Skip to content

Commit

Permalink
refactor: opensource
Browse files Browse the repository at this point in the history
  • Loading branch information
ikkz committed Nov 20, 2024
1 parent f2cfa47 commit 487b2a8
Show file tree
Hide file tree
Showing 56 changed files with 7,828 additions and 0 deletions.
26 changes: 26 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*

node_modules
dist
dist-ssr
*.local

# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

stats.html
5 changes: 5 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"singleQuote": true,
"trailingComma": "all",
"plugins": ["prettier-plugin-tailwindcss"]
}
1 change: 1 addition & 0 deletions .python-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3.13
204 changes: 204 additions & 0 deletions build.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
import packageJson from './package.json' with { type: 'json' };
import { visualizer } from 'rollup-plugin-visualizer';
import templates from './templates.json' with { type: 'json' };
import release from './release.json' with { type: 'json' };
import autoprefixer from 'autoprefixer';
import tailwindcss from 'tailwindcss';
import cssnano from 'cssnano';
import alias from '@rollup/plugin-alias';
import terser from '@rollup/plugin-terser';
import commonjs from '@rollup/plugin-commonjs';
import html from '@rollup/plugin-html';
import json from '@rollup/plugin-json';
import nodeResolve from '@rollup/plugin-node-resolve';
import replace from '@rollup/plugin-replace';
import url from '@rollup/plugin-url';
import virtual from '@rollup/plugin-virtual';
import { dataToEsm } from '@rollup/pluginutils';
import postcss from 'rollup-plugin-postcss';
import { swc } from 'rollup-plugin-swc3';
import { resolve, extname } from 'node:path';
import fs from 'node:fs/promises';

export async function rollupOptions(config) {
async function buildInputOptions() {
/** @type {import('rollup').InputOptions} */
return {
input: 'entry',
plugins: [
virtual({
'at/options': dataToEsm(templates[config.id]),
'at/locale': dataToEsm({
map: JSON.parse(
await fs.readFile(`./src/locales/${config.locale}.json`, {
encoding: 'utf-8',
}),
),
locale: config.locale,
}),
entry: buildEntry(),
}),
replace({
'process.env.NODE_ENV': JSON.stringify(
envValue('production', 'development'),
),
preventAssignment: true,
}),
json(),
alias({
entries: [
{
find: 'lodash/isPlainObject',
replacement: resolve(
import.meta.dirname,
'src/polyfills/is-plain-object',
),
},
{ find: '@', replacement: resolve(import.meta.dirname, 'src') },
{ find: 'react', replacement: 'preact/compat' },
{ find: 'react-dom/test-utils', replacement: 'preact/test-utils' },
{ find: 'react-dom', replacement: 'preact/compat' },
{ find: 'react/jsx-runtime', replacement: 'preact/jsx-runtime' },
],
customResolver: nodeResolve({
extensions: ['.mjs', '.js', '.json', '.ts', '.tsx'],
}),
}),
nodeResolve({
extensions: ['.mjs', '.js', '.json', '.ts', '.tsx'],
}),
commonjs(),
swc({
jsc: {
target: 'es5',
parser: {
tsx: true,
},
transform: {
react: {
pragma: 'h',
pragmaFrag: 'Fragment',
importSource: 'preact',
runtime: 'automatic',
},
},
minify: false,
},
}),
postcss({
extract: true,
plugins: [
autoprefixer(),
tailwindcss(),
envValue(
cssnano({
preset: [
'default',
{
discardComments: {
removeAll: true,
},
},
],
}),
false,
),
].filter(Boolean),
}),
url(),
visualizer(),
],
onwarn(warning, warn) {
if (warning.code === 'MODULE_LEVEL_DIRECTIVE') {
return;
}
warn(warning);
},
};
}
/** @return {import('rollup').OutputOptions} */
function buildOutputOptions() {
return {
format: 'iife',
dir: `dist/${config.id}/${config.locale}`,
plugins: [
envValue(
() =>
terser({
compress: {
drop_console: true,
},
}),
false,
),
html({
fileName: `front.html`,
template({ files }) {
let frontHtml = '';
frontHtml += `<div data-at-version="${packageJson.version}" id="at-root"></div>`;
frontHtml += `<style>${files?.css?.map(({ source }) => source).join('')}</style>`;
frontHtml += `<div id="at-fields" style="display:none;">${buildFields()}</div>`;
frontHtml +=
files.js
?.map(({ code }) => `<script>${code}</script>`)
.join('') || '';
return frontHtml;
},
}),
{
name: 'generate-template',
generateBundle(_, bundle) {
Object.keys(bundle)
.filter((fileName) => extname(fileName) !== '.html')
.forEach((fileName) => {
delete bundle[fileName];
});
this.emitFile({
type: 'asset',
fileName: `style.css`,
source: ``,
});
this.emitFile({
type: 'asset',
fileName: `back.html`,
source: `<div id="at-back-indicator"></div>{{FrontSide}}`,
});
},
},
],
};
}

return {
inputOptions: await buildInputOptions(),
outputOptions: buildOutputOptions(),
};

function envValue(prodValue, devValue) {
return config.dev ? ensureValue(devValue) : ensureValue(prodValue);
}

function buildFields() {
const options = templates[config.id];
return options.fields
.map(
(field) =>
`<div id="at-field-${field}">${envValue(
`{{${field}}}`,
release[config.id].notes[0].fields[field] || '',
)}</div>`,
)
.join('');
}

function buildEntry() {
return `${envValue('', 'import "preact/debug";')}
import App from '@/entries/${config.id}.tsx';
import { setup } from '@/entries';
setup(App);`;
}
}

function ensureValue(value) {
return typeof value === 'function' ? value() : value;
}
82 changes: 82 additions & 0 deletions cli.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#!/usr/bin/env node

import Koa from 'koa';
import templates from './templates.json' with { type: 'json' };
import { rollup } from 'rollup';
import { watch } from 'rollup';
import { extname } from 'node:path';
import { parseArgs } from 'node:util';
import { rollupOptions } from './build.js';

const { values: args } = parseArgs({
options: {
dev: {
type: 'string',
},
locale: {
type: 'string',
default: 'en',
},
},
});

if (!args.dev) {
const ids = Object.keys(templates);
const locales = ['en', 'zh'];
for (const id of ids) {
for (const locale of locales) {
console.log(`build id:${id} locale:${locale}`);
const { inputOptions, outputOptions } = await rollupOptions({
id,
locale,
});
const bundle = await rollup(inputOptions);
bundle.write(outputOptions);
bundle.close();
}
}
} else {
const { inputOptions, outputOptions } = await rollupOptions({
id: args.dev,
locale: args.locale,
dev: true,
});
let html = '';
const koa = new Koa();
koa.use(async (ctx) => {
ctx.body = html;
});
koa.listen(3000);
console.log('listen 3000');
const watcher = watch({
...inputOptions,
watch: {
buildDelay: 1000,
clearScreen: false,
exclude: ['node_modules/**', 'dist/**'],
skipWrite: true,
},
});
watcher.on('event', (args) => {
if (args.code === 'BUNDLE_END') {
console.log('BUNDLE_END');
args.result.generate(outputOptions).then(({ output }) => {
html =
'<!DOCTYPE html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"></head>';
output.reverse().forEach((file) => {
if (
extname(file.fileName) === '.html' &&
!file.fileName.endsWith('back.html')
) {
html += file.source;
}
});
});
}
});
watcher.on('event', ({ result }) => {
if (result) {
result.close();
}
});
}
28 changes: 28 additions & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import globals from 'globals';
import pluginJs from '@eslint/js';
import tseslint from 'typescript-eslint';
import pluginReact from 'eslint-plugin-react';
import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended';

export default [
{ files: ['**/*.{js,mjs,cjs,ts,jsx,tsx}'] },
{ languageOptions: { globals: globals.browser } },
pluginJs.configs.recommended,
...tseslint.configs.recommended,
pluginReact.configs.flat.recommended,
eslintPluginPrettierRecommended,
{
rules: {
'react/jsx-uses-react': 'off',
'react/react-in-jsx-scope': 'off',
'react/prop-types': 'off',
'react/display-name': 'off',
'@typescript-eslint/no-explicit-any': 'off',
},
settings: {
react: {
version: '17',
},
},
},
];
Loading

0 comments on commit 487b2a8

Please sign in to comment.