Skip to content

Commit

Permalink
[duoyun-ui] Export svelte component
Browse files Browse the repository at this point in the history
  • Loading branch information
mantou132 committed Dec 10, 2023
1 parent 58e90be commit 993c083
Show file tree
Hide file tree
Showing 8 changed files with 90 additions and 35 deletions.
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
packages/*/dist
packages/*/react
packages/*/svelte
packages/*/bin
packages/*/coverage
packages/*/extension
1 change: 1 addition & 0 deletions packages/duoyun-ui/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
/elements/
/react/
/vue/
/svelte/
/locales/
/coverage/

Expand Down
2 changes: 2 additions & 0 deletions packages/duoyun-ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@
"./elements/*": "./elements/*.js",
"./react/*": "./react/*.js",
"./vue/*": "./vue/*",
"./svelte/*": "./svelte/*.js",
"./lib/*": "./lib/*.js",
"./locales/*": "./locales/*.js"
},
"files": [
"/elements/",
"/react/",
"/vue/",
"/svelte/",
"/lib/",
"/locales/"
],
Expand Down
26 changes: 26 additions & 0 deletions packages/gem-port/src/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { readdirSync, readFileSync, statSync } from 'fs';

import { ElementDetail, getElements } from 'gem-analyzer';
import { Project } from 'ts-morph';
import * as ts from 'typescript';

const dev = process.env.MODE === 'dev';
const elements = process.env.ELEMENTS?.split(',');
Expand Down Expand Up @@ -46,3 +47,28 @@ export function getRelativePath(elementFilePath: string, outDir: string) {
const relativePath = path.relative(path.resolve(outDir), path.dirname(elementFilePath)).replace('src/', '');
return `${relativePath}/${basename}`;
}

export function compile(outDir: string, fileSystem: Record<string, string>): void {
const options: ts.CompilerOptions = {
jsx: ts.JsxEmit.React,
target: ts.ScriptTarget.ES2020,
declaration: true,
outDir,
};
const host = ts.createCompilerHost(options);
const originReadFile = host.readFile;
host.readFile = (filename: string) => {
if (filename in fileSystem) return fileSystem[filename];
return originReadFile(filename);
};
const program = ts.createProgram(Object.keys(fileSystem), options, host);
program.emit().diagnostics.forEach((diagnostic) => {
if (diagnostic.file) {
const { line, character } = ts.getLineAndCharacterOfPosition(diagnostic.file, diagnostic.start!);
const message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n');
console.warn(`${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`);
} else {
console.warn(ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n'));
}
});
}
6 changes: 4 additions & 2 deletions packages/gem-port/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import program from 'commander';
import { name, description, version } from '../package.json';

import { compileReact } from './react';
import { compileVue } from './vue';
import { generateVue } from './vue';
import { compileSvelte } from './svelte';

const cliOptions = {
outDir: './',
Expand All @@ -21,7 +22,8 @@ program
.arguments('<dir>')
.action((dir: string) => {
compileReact(dir, path.resolve(cliOptions.outDir, 'react'));
compileVue(dir, path.resolve(cliOptions.outDir, 'vue'));
generateVue(dir, path.resolve(cliOptions.outDir, 'vue'));
compileSvelte(dir, path.resolve(cliOptions.outDir, 'svelte'));
process.exit(0);
});

Expand Down
36 changes: 4 additions & 32 deletions packages/gem-port/src/react.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import * as ts from 'typescript';

import { getElementPathList, getFileElements, getComponentName, getRelativePath } from './common';
import { getElementPathList, getFileElements, getComponentName, getRelativePath, compile } from './common';

function createReactSourceFile(elementFilePath: string, outDir: string) {
const elementDetailList = getFileElements(elementFilePath);
Expand All @@ -22,7 +20,7 @@ function createReactSourceFile(elementFilePath: string, outDir: string) {
${properties
.map(({ name, reactive, event }) =>
event
? [`'on${event}'`, `(arg: CustomEvent<Parameters<${constructorName}['${name}']>[0]>) => void`].join(
? [`'on${event}'`, `(event: CustomEvent<Parameters<${constructorName}['${name}']>[0]>) => void`].join(
'?:',
)
: reactive
Expand Down Expand Up @@ -83,36 +81,10 @@ function createReactSourceFile(elementFilePath: string, outDir: string) {
);
}

function createReactSourceFiles(elementsDir: string, outDir: string) {
export function compileReact(elementsDir: string, outDir: string): void {
const fileSystem: Record<string, string> = {};
getElementPathList(elementsDir).forEach((elementFilePath) => {
Object.assign(fileSystem, createReactSourceFile(elementFilePath, outDir));
});
return fileSystem;
}

export function compileReact(elementsDir: string, outDir: string): void {
const options: ts.CompilerOptions = {
jsx: ts.JsxEmit.React,
target: ts.ScriptTarget.ES2020,
declaration: true,
outDir,
};
const fileSystem = createReactSourceFiles(elementsDir, outDir);
const host = ts.createCompilerHost(options);
const originReadFile = host.readFile;
host.readFile = (filename: string) => {
if (filename in fileSystem) return fileSystem[filename];
return originReadFile(filename);
};
const program = ts.createProgram(Object.keys(fileSystem), options, host);
program.emit().diagnostics.forEach((diagnostic) => {
if (diagnostic.file) {
const { line, character } = ts.getLineAndCharacterOfPosition(diagnostic.file, diagnostic.start!);
const message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n');
console.warn(`${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`);
} else {
console.warn(ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n'));
}
});
compile(outDir, fileSystem);
}
51 changes: 51 additions & 0 deletions packages/gem-port/src/svelte.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import path from 'path';

import { compile, getComponentName, getElementPathList, getFileElements, getRelativePath } from './common';

export function compileSvelte(elementsDir: string, outDir: string): void {
const fileSystem: Record<string, string> = {};
getElementPathList(elementsDir).forEach((elementFilePath) => {
const elementDetailList = getFileElements(elementFilePath);
Object.assign(
fileSystem,
Object.fromEntries(
elementDetailList.map(({ name: tag, constructorName, properties }) => {
const componentName = getComponentName(tag);
const componentPropsName = `${componentName}Props`;
const relativePath = getRelativePath(elementFilePath, outDir);
const basename = path.basename(relativePath);
return [
basename + '.ts',
`
import type { HTMLAttributes } from "svelte/elements";
import { ${constructorName} } from '${relativePath}';
export * from '${relativePath}';
interface ${componentPropsName} extends HTMLAttributes<HTMLElement> {
${properties
.map(({ name, reactive, event }) =>
event
? [
`'on:${event}'`,
`(event: CustomEvent<Parameters<${constructorName}['${name}']>[0]>) => void`,
].join('?:')
: reactive
? [name, `${constructorName}['${name}']`].join('?:')
: '',
)
.join(';')}
};
declare module "svelte/elements" {
interface SvelteHTMLElements {
'${tag}': ${componentPropsName};
}
}
`,
];
}),
),
);
});
compile(outDir, fileSystem);
}
2 changes: 1 addition & 1 deletion packages/gem-port/src/vue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ declare module '@vue/runtime-dom' {
}
*/

export function compileVue(elementsDir: string, outDir: string): void {
export function generateVue(elementsDir: string, outDir: string): void {
mkdirSync(outDir, { recursive: true });
getElementPathList(elementsDir).forEach((elementFilePath) => {
getFileElements(elementFilePath).forEach(({ name: tag, properties, constructorName, methods, events }) => {
Expand Down

0 comments on commit 993c083

Please sign in to comment.