Skip to content

Commit

Permalink
feat: add defineTechStack api (#2042)
Browse files Browse the repository at this point in the history
* feat: add createTechStack api

* refactor: change to defineTechStack, restore built-in ReactTechStack

* refactor: remain consistent with the original interface

---------

Co-authored-by: Peach <scdzwyxst@gmail.com>
  • Loading branch information
jeffwcx and PeachScript authored Mar 24, 2024
1 parent e227b15 commit 4859310
Show file tree
Hide file tree
Showing 5 changed files with 116 additions and 116 deletions.
26 changes: 26 additions & 0 deletions src/techStacks/utils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { ParserConfig } from '@swc/core';
import { transformSync } from '@swc/core';
import { IDumiTechStack } from '../types';

export {
IDumiTechStack,
Expand Down Expand Up @@ -59,3 +60,28 @@ export function wrapDemoWithFn(code: string, opts: IWrapDemoWithFnOptions) {
${result.code}
}`;
}

export type IDefineTechStackOptions = IDumiTechStack;

/**
* Define a tech stack
* @param options techstack options
* @returns function that returns {@link IDumiTechStack}, can be used to register a techstack
*
* @example
* const ReactTechStack = defineTechStack({
* name: 'jsx',
* isSupported(_, lang) {
* return ['jsx', 'tsx'].includes(lang);
* },
* transformCode() {
* // ...
* return '';
* },
* });
*
* api.registerTechStack(() => ReactTechStack);
*/
export function defineTechStack(options: IDefineTechStackOptions) {
return options;
}
4 changes: 3 additions & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,9 @@ export abstract class IDumiTechStack {
*/
abstract runtimeOpts?: IDumiTechStackRuntimeOpts;
/**
* transform code
* Is the lang supported by the current tech stack?
* @param lang
* @param node hast Element https://github.com/syntax-tree/hast?tab=readme-ov-file#element
*/
abstract isSupported(node: Element, lang: string): boolean;
/**
Expand Down
8 changes: 4 additions & 4 deletions suites/preset-vue/src/vue/techStack/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { BABEL_STANDALONE_CDN, getPkgPath, getPluginPath } from '@/shared';
import type { IApi } from 'dumi';
import { fsExtra } from 'dumi/plugin-utils';
import { join } from 'path';
import VueJSXTechStack from './jsx';
import VueSfcTechStack from './sfc';
import { VueJSXTechStack } from './jsx';
import { VueSfcTechStack } from './sfc';

const COMPILE_FILENAME = 'compiler.mjs';
const RENDERER_FILENAME = 'renderer.mjs';
Expand Down Expand Up @@ -54,12 +54,12 @@ export default function registerTechStack(api: IApi) {
api.register({
key: 'registerTechStack',
stage: 0,
fn: () => new VueJSXTechStack(runtimeOpts),
fn: () => VueJSXTechStack(runtimeOpts),
});

api.register({
key: 'registerTechStack',
stage: 1,
fn: () => new VueSfcTechStack(runtimeOpts),
fn: () => VueSfcTechStack(runtimeOpts),
});
}
100 changes: 43 additions & 57 deletions suites/preset-vue/src/vue/techStack/jsx.ts
Original file line number Diff line number Diff line change
@@ -1,62 +1,48 @@
import { compile } from '@/compiler/node';
import type {
IDumiTechStack,
IDumiTechStackOnBlockLoadArgs,
IDumiTechStackOnBlockLoadResult,
IDumiTechStackRuntimeOpts,
} from 'dumi/tech-stack-utils';
import { wrapDemoWithFn } from 'dumi/tech-stack-utils';
import type { IDumiTechStackRuntimeOpts } from 'dumi/tech-stack-utils';
import { defineTechStack, wrapDemoWithFn } from 'dumi/tech-stack-utils';
import hashId from 'hash-sum';
import type { Element } from 'hast';

export default class VueJSXTechStack implements IDumiTechStack {
name = 'vue3-tsx';

runtimeOpts!: IDumiTechStackRuntimeOpts;

constructor(runtimeOpts: IDumiTechStackRuntimeOpts) {
this.runtimeOpts = runtimeOpts;
}

isSupported(_: Element, lang: string) {
return ['jsx', 'tsx'].includes(lang);
}

onBlockLoad(
args: IDumiTechStackOnBlockLoadArgs,
): IDumiTechStackOnBlockLoadResult | null {
if (!args.path.endsWith('.tsx') && !args.path.endsWith('.jsx')) return null;
const { filename } = args;
return {
type: 'tsx',
content: compile({
id: filename,
filename,
code: args.entryPointCode,
}) as string,
};
}

transformCode(...[raw, opts]: Parameters<IDumiTechStack['transformCode']>) {
if (opts.type === 'code-block') {
const filename = opts.fileAbsPath;

const result = compile({
id: hashId(raw),
filename,
code: raw,
}) as string;

if (result) {
const code = wrapDemoWithFn(result, {
export const VueJSXTechStack = (runtimeOpts: IDumiTechStackRuntimeOpts) =>
defineTechStack({
name: 'vue3-tsx',
runtimeOpts,
isSupported(_, lang: string) {
return ['jsx', 'tsx'].includes(lang);
},
onBlockLoad(args) {
if (!args.path.endsWith('.tsx') && !args.path.endsWith('.jsx'))
return null;
const { filename } = args;
return {
type: 'tsx',
content: compile({
id: filename,
filename,
code: args.entryPointCode,
}) as string,
};
},
transformCode(raw, opts) {
if (opts.type === 'code-block') {
const filename = opts.fileAbsPath;

const result = compile({
id: hashId(raw),
filename,
parserConfig: {
syntax: 'ecmascript',
},
});
return `(${code})()`;
code: raw,
}) as string;

if (result) {
const code = wrapDemoWithFn(result, {
filename,
parserConfig: {
syntax: 'ecmascript',
},
});
return `(${code})()`;
}
}
}
return raw;
}
}
return raw;
},
});
94 changes: 40 additions & 54 deletions suites/preset-vue/src/vue/techStack/sfc.ts
Original file line number Diff line number Diff line change
@@ -1,61 +1,47 @@
import { compile, compiler } from '@/compiler/node';
import type {
IDumiTechStack,
IDumiTechStackOnBlockLoadArgs,
IDumiTechStackOnBlockLoadResult,
IDumiTechStackRuntimeOpts,
} from 'dumi/tech-stack-utils';
import { wrapDemoWithFn } from 'dumi/tech-stack-utils';
import type { IDumiTechStackRuntimeOpts } from 'dumi/tech-stack-utils';
import { defineTechStack, wrapDemoWithFn } from 'dumi/tech-stack-utils';
import hashId from 'hash-sum';
import type { Element } from 'hast';
import { logger } from 'umi/plugin-utils';

export default class VueSfcTechStack implements IDumiTechStack {
name = 'vue3-sfc';
runtimeOpts!: IDumiTechStackRuntimeOpts;

constructor(runtimeOpts: IDumiTechStackRuntimeOpts) {
this.runtimeOpts = runtimeOpts;
}

isSupported(_: Element, lang: string) {
return ['vue'].includes(lang);
}

onBlockLoad(
args: IDumiTechStackOnBlockLoadArgs,
): IDumiTechStackOnBlockLoadResult | null {
if (!args.path.endsWith('.vue')) return null;
const result = compiler.compileSFC({
id: args.path,
code: args.entryPointCode,
filename: args.filename,
});
return {
type: 'tsx',
content: Array.isArray(result) ? '' : result.js,
};
}
export const VueSfcTechStack = (runtimeOpts: IDumiTechStackRuntimeOpts) =>
defineTechStack({
name: 'vue3-sfc',
runtimeOpts,
isSupported(_, lang: string) {
return ['vue'].includes(lang);
},
onBlockLoad(args) {
if (!args.path.endsWith('.vue')) return null;
const result = compiler.compileSFC({
id: args.path,
code: args.entryPointCode,
filename: args.filename,
});
return {
type: 'tsx',
content: Array.isArray(result) ? '' : result.js,
};
},
transformCode(raw, opts) {
if (opts.type === 'code-block') {
const filename = opts.fileAbsPath;
const id = hashId(raw);

transformCode(...[raw, opts]: Parameters<IDumiTechStack['transformCode']>) {
if (opts.type === 'code-block') {
const filename = opts.fileAbsPath;
const id = hashId(raw);
const js = compile({ id, filename, code: raw });
if (Array.isArray(js)) {
logger.error(js);
return '';
}

const js = compile({ id, filename, code: raw });
if (Array.isArray(js)) {
logger.error(js);
return '';
const code = wrapDemoWithFn(js, {
filename,
parserConfig: {
syntax: 'ecmascript',
},
});
return `(${code})()`;
}

const code = wrapDemoWithFn(js, {
filename,
parserConfig: {
syntax: 'ecmascript',
},
});
return `(${code})()`;
}
return raw;
}
}
return raw;
},
});

0 comments on commit 4859310

Please sign in to comment.