@moneko/core 3.2.1-beta.0 → 3.2.1-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/app-entry.js +32 -1
- package/lib/app.js +40 -2
- package/lib/cleanup.js +19 -1
- package/lib/common.js +248 -1
- package/lib/config.js +234 -1
- package/lib/coverage.js +33 -2
- package/lib/dev.js +89 -5
- package/lib/docs.js +120 -2
- package/lib/done.js +12 -1
- package/lib/esm.js +7 -1
- package/lib/fallback.js +6 -1
- package/lib/generate-api.d.ts +1 -1
- package/lib/generate-api.js +345 -3
- package/lib/has-pkg.js +12 -1
- package/lib/html-add-entry-attr.js +32 -10
- package/lib/html-plugin-option.js +45 -1
- package/lib/index.js +4 -1
- package/lib/locales.js +93 -3
- package/lib/merge-router.js +1 -1
- package/lib/minify.js +47 -2
- package/lib/modify-vars.js +11 -1
- package/lib/module-federation.js +46 -1
- package/lib/module.config.js +273 -3
- package/lib/net.js +33 -1
- package/lib/normalize-css.js +6 -1
- package/lib/paths.js +21 -1
- package/lib/polyfills/replace-children.js +26 -3
- package/lib/polyfills.js +15 -3
- package/lib/prefix-router.js +6 -1
- package/lib/process-env.js +33 -2
- package/lib/prod.js +65 -5
- package/lib/reactive-object.js +47 -8
- package/lib/rem.js +6 -1
- package/lib/resolver-sync.js +27 -1
- package/lib/routes.js +196 -4
- package/lib/seo.js +41 -2
- package/lib/swcrc.js +100 -2
- package/lib/tsloader.config.js +26 -2
- package/lib/utils.js +71 -7
- package/lib/virtual-module-plugin.js +49 -1
- package/lib/virtual-modules.js +37 -1
- package/lib/yarn-argv.js +9 -1
- package/package.json +6 -2
- package/typings/global.d.ts +1 -2
package/lib/normalize-css.js
CHANGED
|
@@ -1 +1,6 @@
|
|
|
1
|
-
import{CONFIG
|
|
1
|
+
import { CONFIG } from './config.js';
|
|
2
|
+
let normalizeCss = '';
|
|
3
|
+
if (CONFIG.normalizeCss) {
|
|
4
|
+
normalizeCss = 'html,body{margin:0;padding:0;line-height:1.8}input,textarea{caret-color:inherit}h1{margin:0.67em 0;font-size:2em}hr{overflow:visible;block-size:0;box-sizing:content-box}pre{font-size:1em;font-family:monospace}a{text-decoration:none;background-color:transparent;cursor:pointer}abbr[title]{border-block-end:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-size:1em;font-family:monospace}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{inset-block-end:-0.25em}sup{inset-block-start:-0.5em}img{border-style:none}img,button{outline:1px solid transparent}button,input,optgroup,select,textarea{margin:0;font-size:100%;font-family:inherit;line-height:1.15}button,input{overflow:visible}button,select{text-transform:none}button,[type="button"],[type="reset"],[type="submit"]{appearance:button}button::-moz-focus-inner,[type="button"]::-moz-focus-inner,[type="reset"]::-moz-focus-inner,[type="submit"]::-moz-focus-inner{border-style:none;padding:0}button:-moz-focusring,[type="button"]:-moz-focusring,[type="reset"]:-moz-focusring,[type="submit"]:-moz-focusring{outline:1px dotted var(--primary-outline)}fieldset{padding:0.35em 0.75em 0.625em}legend{display:table;padding:0;max-inline-size:100%;white-space:normal;color:inherit;box-sizing:border-box}progress{vertical-align:baseline}textarea{overflow:auto}details{display:block}summary{display:list-item}template,[hidden]{display:none}[type="checkbox"],[type="radio"]{box-sizing:border-box;padding:0}[type="number"]::-webkit-inner-spin-button,[type="number"]::-webkit-outer-spin-button{block-size:auto}[type="search"]{appearance:textfield;outline-offset:-2px}[type="search"]::-webkit-search-decoration{appearance:none}::-webkit-file-upload-button{appearance:button;font:inherit}::-webkit-scrollbar{inline-size:5px;block-size:5px}::-webkit-scrollbar-track,::-webkit-scrollbar-thumb{background-color:transparent}:hover::-webkit-scrollbar-thumb{background-color:var(--primary-selection)}::-webkit-scrollbar-thumb:hover{background-color:var(--primary-hover)}::-webkit-scrollbar-thumb:active{background-color:var(--primary-active)}::-webkit-scrollbar-button{display:none}';
|
|
5
|
+
}
|
|
6
|
+
export default normalizeCss;
|
package/lib/paths.js
CHANGED
|
@@ -1 +1,21 @@
|
|
|
1
|
-
import{existsSync
|
|
1
|
+
import { existsSync, mkdirSync } from 'fs';
|
|
2
|
+
import url from 'url';
|
|
3
|
+
const programPath = process.cwd();
|
|
4
|
+
const cachePath = `${programPath}/node_modules/.cache/.mo`;
|
|
5
|
+
if (!existsSync(cachePath)) {
|
|
6
|
+
mkdirSync(cachePath, {
|
|
7
|
+
recursive: true
|
|
8
|
+
});
|
|
9
|
+
}
|
|
10
|
+
export default {
|
|
11
|
+
corePath: url.fileURLToPath(new URL('.', import.meta.url)),
|
|
12
|
+
programPath: programPath,
|
|
13
|
+
webpackCachePath: `${programPath}/node_modules/.temp_cache`,
|
|
14
|
+
cachePath: cachePath,
|
|
15
|
+
httpCachePath: `${programPath}/node_modules/.cache/http`,
|
|
16
|
+
swcCachePath: `${programPath}/node_modules/.swc`,
|
|
17
|
+
defaultConfigPath: `${programPath}/config/index.ts`,
|
|
18
|
+
coveragePath: `${programPath}/coverage/clover.xml`,
|
|
19
|
+
pagesPath: `${programPath}/src/pages`,
|
|
20
|
+
componentsPath: `${programPath}/components`
|
|
21
|
+
};
|
|
@@ -1,3 +1,26 @@
|
|
|
1
|
-
function
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
function replaceChildrenPolyfill(...nodes) {
|
|
2
|
+
/**
|
|
3
|
+
* @ts-ignore */ // eslint-disable-next-line consistent-this, no-invalid-this, @typescript-eslint/no-this-alias
|
|
4
|
+
const self = this;
|
|
5
|
+
const l = nodes.length;
|
|
6
|
+
const newChildren = new Array(l);
|
|
7
|
+
for(let k = 0; k < l; k++){
|
|
8
|
+
newChildren[k] = nodes[k];
|
|
9
|
+
}
|
|
10
|
+
while(self.firstChild){
|
|
11
|
+
self.removeChild(self.firstChild);
|
|
12
|
+
}
|
|
13
|
+
newChildren.forEach(function(child) {
|
|
14
|
+
if (typeof child === 'string') {
|
|
15
|
+
self.appendChild(document.createTextNode(child));
|
|
16
|
+
} else {
|
|
17
|
+
self.appendChild(child);
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
if (!Element.prototype.replaceChildren) {
|
|
22
|
+
Element.prototype.replaceChildren = replaceChildrenPolyfill;
|
|
23
|
+
}
|
|
24
|
+
if (!ShadowRoot.prototype.replaceChildren) {
|
|
25
|
+
ShadowRoot.prototype.replaceChildren = replaceChildrenPolyfill;
|
|
26
|
+
}
|
package/lib/polyfills.js
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import browserslist from 'browserslist';
|
|
2
|
+
import compat from 'core-js-compat';
|
|
3
|
+
import paths from './paths.js';
|
|
4
|
+
function polyfills() {
|
|
5
|
+
return compat({
|
|
6
|
+
// 从项目的根目录自动寻找 browserslistrc 配置
|
|
7
|
+
targets: browserslist(void 0, {
|
|
8
|
+
path: paths.programPath,
|
|
9
|
+
env: process.env.NODE_ENV
|
|
10
|
+
}).filter((e)=>!e.endsWith(' TP')),
|
|
11
|
+
// 须指定 core-js 前两位具体版本,如 `3.20`,否则 polyfill 会不全
|
|
12
|
+
version: '3.32.2'
|
|
13
|
+
}).list;
|
|
14
|
+
}
|
|
15
|
+
export default polyfills;
|
package/lib/prefix-router.js
CHANGED
|
@@ -1 +1,6 @@
|
|
|
1
|
-
import{isReact
|
|
1
|
+
import { isReact } from './process-env.js';
|
|
2
|
+
let prefixRouter = '';
|
|
3
|
+
if (isReact) {
|
|
4
|
+
prefixRouter = 'import { createElement, isValidElement } from "react";import { Outlet } from "react-router-dom";function prefix(e){return e.map(function(e){var n=Object.assign({key:e.path},e);return n.element?isValidElement(n.element)||(n.element=createElement(n.element,n.meta)):n.element=createElement(Outlet,null),Array.isArray(n.children)&&(n.children=prefix(n.children)),n})}export default prefix;';
|
|
5
|
+
}
|
|
6
|
+
export default prefixRouter;
|
package/lib/process-env.js
CHANGED
|
@@ -1,7 +1,38 @@
|
|
|
1
|
-
import{readFileSync
|
|
1
|
+
import { readFileSync } from 'fs';
|
|
2
|
+
import paths from './paths.js';
|
|
3
|
+
import yarnArgv from './yarn-argv.js';
|
|
4
|
+
export const APPTYPE = process.env.APPTYPE;
|
|
5
|
+
export const FRAMEWORK = process.env.FRAMEWORK;
|
|
6
|
+
export const isLibrary = APPTYPE === 'library';
|
|
7
|
+
export const isMicro = APPTYPE === 'micro';
|
|
8
|
+
export const isReact = FRAMEWORK === 'react';
|
|
9
|
+
export const isSolid = FRAMEWORK === 'solid';
|
|
10
|
+
export const jsxImportSource = {
|
|
11
|
+
react: 'react',
|
|
12
|
+
solid: 'solid-js/h'
|
|
13
|
+
}[FRAMEWORK];
|
|
14
|
+
export const createElement = {
|
|
15
|
+
react: 'createElement',
|
|
16
|
+
solid: 'createComponent'
|
|
17
|
+
}[FRAMEWORK];
|
|
18
|
+
/** 框架名称 */ export const FRAMEWORKNAME = {
|
|
19
|
+
react: 'react',
|
|
20
|
+
solid: 'solid-js'
|
|
21
|
+
}[FRAMEWORK];
|
|
22
|
+
/** 应用名称 */ export const PACKAGENAME = process.env.npm_package_name;
|
|
23
|
+
/** 版本号 */ export const PACKAGEVERSION = process.env.npm_package_version;
|
|
24
|
+
const pkg = readFileSync(`${paths.corePath}/../package.json`, {
|
|
25
|
+
encoding: 'utf-8'
|
|
26
|
+
});
|
|
27
|
+
/** core 包名 */ export const coreName = JSON.parse(pkg).name;
|
|
28
|
+
/** 是否为本地开发环境 */ export const isDev = process.env.NODE_ENV === 'development';
|
|
29
|
+
/** 附加启动配置名称
|
|
2
30
|
* @example
|
|
3
31
|
* 当通过以下命令启动时, 此时 CUSTOMCONFIG 为 test
|
|
4
32
|
* ```sh
|
|
5
33
|
* npm run start --config=test
|
|
6
34
|
* ```
|
|
7
|
-
*/export const CUSTOMCONFIG=process.env.npm_config_config||
|
|
35
|
+
*/ export const CUSTOMCONFIG = process.env.npm_config_config || yarnArgv.config;
|
|
36
|
+
const envKeys = Object.keys(process.env);
|
|
37
|
+
export const hasEslintConfig = envKeys.findIndex((k)=>k.startsWith('npm_package_eslintConfig_')) !== -1;
|
|
38
|
+
export const hasStylelintConfig = envKeys.findIndex((k)=>k.startsWith('npm_package_stylelint_')) !== -1;
|
package/lib/prod.js
CHANGED
|
@@ -1,5 +1,65 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
import CssMinimizerPlugin from 'css-minimizer-webpack-plugin';
|
|
2
|
+
import MiniCssExtractPlugin from 'mini-css-extract-plugin';
|
|
3
|
+
import TerserPlugin from 'terser-webpack-plugin';
|
|
4
|
+
import webpack from 'webpack';
|
|
5
|
+
import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer';
|
|
6
|
+
import { merge } from 'webpack-merge';
|
|
7
|
+
import { clientConfig } from './common.js';
|
|
8
|
+
import { CONFIG } from './config.js';
|
|
9
|
+
import { getMinifyOption } from './minify.js';
|
|
10
|
+
const { optimize: { MinChunkSizePlugin } } = webpack;
|
|
11
|
+
const { cssnanoMinify, swcMinify } = CssMinimizerPlugin;
|
|
12
|
+
const swcCompiler = CONFIG.compiler === 'swc';
|
|
13
|
+
const defaultJsMiniify = swcCompiler ? 'swc' : 'terser';
|
|
14
|
+
const defaultCssMiniify = swcCompiler ? 'swc' : 'cssnano';
|
|
15
|
+
const cssMinify = {
|
|
16
|
+
swc: swcMinify,
|
|
17
|
+
cssnano: cssnanoMinify
|
|
18
|
+
};
|
|
19
|
+
const minimizer = [];
|
|
20
|
+
if (CONFIG.minifier) {
|
|
21
|
+
if (CONFIG.minifier.js) {
|
|
22
|
+
minimizer.push(new TerserPlugin(getMinifyOption(CONFIG.minifier.js?.type || defaultJsMiniify, CONFIG.minifier.js?.options)));
|
|
23
|
+
}
|
|
24
|
+
if (CONFIG.minifier.css) {
|
|
25
|
+
minimizer.push(new CssMinimizerPlugin({
|
|
26
|
+
minify: cssMinify[CONFIG.minifier.css?.type || defaultCssMiniify],
|
|
27
|
+
minimizerOptions: CONFIG.minifier.css?.options
|
|
28
|
+
}));
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
const optimization = {
|
|
32
|
+
splitChunks: CONFIG.splitChunk,
|
|
33
|
+
runtimeChunk: CONFIG.runtimeChunk,
|
|
34
|
+
chunkIds: 'named',
|
|
35
|
+
moduleIds: 'named',
|
|
36
|
+
// parent chunk中解决了的chunk会被删除
|
|
37
|
+
removeAvailableModules: true,
|
|
38
|
+
// 删除空的chunks
|
|
39
|
+
removeEmptyChunks: true,
|
|
40
|
+
// 合并重复的chunk
|
|
41
|
+
mergeDuplicateChunks: true,
|
|
42
|
+
mangleWasmImports: true,
|
|
43
|
+
minimize: true,
|
|
44
|
+
minimizer: minimizer
|
|
45
|
+
};
|
|
46
|
+
const client = merge(clientConfig, {
|
|
47
|
+
devtool: CONFIG.devtool === false || CONFIG.devtool ? CONFIG.devtool : 'cheap-module-source-map',
|
|
48
|
+
mode: 'production',
|
|
49
|
+
optimization: optimization,
|
|
50
|
+
plugins: [
|
|
51
|
+
// 压缩 css
|
|
52
|
+
new MiniCssExtractPlugin({
|
|
53
|
+
filename: 'style/[name].bundle.css',
|
|
54
|
+
chunkFilename: 'style/[name].chunk.css',
|
|
55
|
+
experimentalUseImportModule: true
|
|
56
|
+
}),
|
|
57
|
+
CONFIG.bundleAnalyzer && new BundleAnalyzerPlugin(CONFIG.bundleAnalyzer),
|
|
58
|
+
CONFIG.splitChunk && new MinChunkSizePlugin({
|
|
59
|
+
minChunkSize: 10000
|
|
60
|
+
})
|
|
61
|
+
].filter(Boolean)
|
|
62
|
+
});
|
|
63
|
+
export default [
|
|
64
|
+
client
|
|
65
|
+
];
|
package/lib/reactive-object.js
CHANGED
|
@@ -1,8 +1,47 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
import EventEmitter from 'events';
|
|
2
|
+
class ReactiveObject extends EventEmitter {
|
|
3
|
+
data;
|
|
4
|
+
constructor(props = {}){
|
|
5
|
+
super();
|
|
6
|
+
this.data = props;
|
|
7
|
+
}
|
|
8
|
+
setData(key, value) {
|
|
9
|
+
if (value !== this.data[key]) {
|
|
10
|
+
this.data[key] = value;
|
|
11
|
+
this.emit('change', key, value);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
getData(key) {
|
|
15
|
+
return this.data[key];
|
|
16
|
+
}
|
|
17
|
+
// removeData(key: keyof T) {
|
|
18
|
+
// if (Object.prototype.hasOwnProperty.call(this.data, key)) {
|
|
19
|
+
// delete this.data[key];
|
|
20
|
+
// this.emit('change', key, null);
|
|
21
|
+
// }
|
|
22
|
+
// }
|
|
23
|
+
// 实现迭代器接口
|
|
24
|
+
[Symbol.iterator]() {
|
|
25
|
+
const keys = Object.keys(this.data);
|
|
26
|
+
let index = 0;
|
|
27
|
+
return {
|
|
28
|
+
next: ()=>{
|
|
29
|
+
if (index < keys.length) {
|
|
30
|
+
const key = keys[index++];
|
|
31
|
+
return {
|
|
32
|
+
value: [
|
|
33
|
+
key,
|
|
34
|
+
this.data[key]
|
|
35
|
+
],
|
|
36
|
+
done: false
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
return {
|
|
40
|
+
value: void 0,
|
|
41
|
+
done: true
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
export default ReactiveObject;
|
package/lib/rem.js
CHANGED
|
@@ -1 +1,6 @@
|
|
|
1
|
-
import{CONFIG
|
|
1
|
+
import { CONFIG } from './config.js';
|
|
2
|
+
let rem = '';
|
|
3
|
+
if (CONFIG.rem.designSize) {
|
|
4
|
+
rem = `!function(e,n){function t(){let n=e.documentElement,t=n.clientWidth||e.body.clientWidth,i=t<=375?375:${CONFIG.rem.designSize},o=t;o=t<=375?t:t<=${CONFIG.rem.designSize}?i:t;let d=16/i*o+"px";d!==n.style.fontSize&&(n.style.fontSize=d)}t(),"addEventListener"in e&&n.addEventListener("orientationchange"in n?"orientationchange":"resize",t,!1)}(document,window);`;
|
|
5
|
+
}
|
|
6
|
+
export default rem;
|
package/lib/resolver-sync.js
CHANGED
|
@@ -1 +1,27 @@
|
|
|
1
|
-
import*as
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
import enhancedResolve from 'enhanced-resolve';
|
|
3
|
+
const { CachedInputFileSystem, ResolverFactory } = enhancedResolve;
|
|
4
|
+
/**
|
|
5
|
+
* @examples
|
|
6
|
+
* ```javascript
|
|
7
|
+
* // 获取 react 包入口路径,优先 esm,兜底 cjs
|
|
8
|
+
* resolverSync.resolveSync({}, process.cwd(), "react")
|
|
9
|
+
* ```
|
|
10
|
+
*/ const resolverSync = ResolverFactory.createResolver({
|
|
11
|
+
fileSystem: new CachedInputFileSystem(fs, 4000),
|
|
12
|
+
conditionNames: [
|
|
13
|
+
'node'
|
|
14
|
+
],
|
|
15
|
+
extensions: [
|
|
16
|
+
'.js',
|
|
17
|
+
'.json',
|
|
18
|
+
'.node'
|
|
19
|
+
],
|
|
20
|
+
useSyncFileSystemCalls: true,
|
|
21
|
+
mainFields: [
|
|
22
|
+
'esm',
|
|
23
|
+
'module',
|
|
24
|
+
'main'
|
|
25
|
+
]
|
|
26
|
+
});
|
|
27
|
+
export default resolverSync;
|
package/lib/routes.js
CHANGED
|
@@ -1,4 +1,196 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import { readFileSync, readdirSync, statSync } from 'fs';
|
|
2
|
+
import { join, relative } from 'path';
|
|
3
|
+
import { watch } from 'chokidar';
|
|
4
|
+
import { load } from 'js-yaml';
|
|
5
|
+
import { hasCustomRouter } from './config.js';
|
|
6
|
+
import paths from './paths.js';
|
|
7
|
+
import { FRAMEWORK, FRAMEWORKNAME, createElement, isLibrary, isReact, isSolid } from './process-env.js';
|
|
8
|
+
import ReactiveObject from './reactive-object.js';
|
|
9
|
+
const frontmatterRegex = /^---\n([\s\S]+?)\n---\n/;
|
|
10
|
+
function extractFrontmatter(md) {
|
|
11
|
+
const matches = md.match(frontmatterRegex);
|
|
12
|
+
return matches && matches[1] ? matches[1].trim() : null;
|
|
13
|
+
}
|
|
14
|
+
const elename = isSolid ? 'component' : 'element';
|
|
15
|
+
function extractCode(codeStr) {
|
|
16
|
+
const codes = {};
|
|
17
|
+
const regex = /```(.+?)\n([\s\S]*?)\n```/g;
|
|
18
|
+
let match;
|
|
19
|
+
while((match = regex.exec(codeStr)) !== null){
|
|
20
|
+
const [, language = 'jsx', source] = match;
|
|
21
|
+
const lang = language.split(' ').pop() || 'jsx';
|
|
22
|
+
codes[lang] = source.trim();
|
|
23
|
+
}
|
|
24
|
+
return Object.keys(codes).length ? codes : {
|
|
25
|
+
jsx: codeStr
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
function prefixPath(src) {
|
|
29
|
+
return src.replace(/\$/g, ':').replace(/^index\.tsx?$/, '/').replace(/^README\.mdx?$/, '/');
|
|
30
|
+
}
|
|
31
|
+
function getTree(directory, option) {
|
|
32
|
+
const { regex, alia, base = directory, outputSource } = option;
|
|
33
|
+
const files = readdirSync(directory);
|
|
34
|
+
return files.reduce((tree, file)=>{
|
|
35
|
+
const filePath = join(directory, file);
|
|
36
|
+
const stats = statSync(filePath);
|
|
37
|
+
if (stats.isDirectory()) {
|
|
38
|
+
const children = getTree(filePath, {
|
|
39
|
+
...option,
|
|
40
|
+
base
|
|
41
|
+
});
|
|
42
|
+
if (children.length > 0) {
|
|
43
|
+
const item = {};
|
|
44
|
+
const baseItem = {
|
|
45
|
+
path: prefixPath(file),
|
|
46
|
+
key: prefixPath(relative(base, filePath))
|
|
47
|
+
};
|
|
48
|
+
if (outputSource) {
|
|
49
|
+
Object.assign(item, {
|
|
50
|
+
children
|
|
51
|
+
});
|
|
52
|
+
} else {
|
|
53
|
+
const baseIdx = children.findIndex((c)=>c.path === '/' || baseItem.path === c.path);
|
|
54
|
+
const frist = children.splice(baseIdx, 1)[0];
|
|
55
|
+
if (children.length) {
|
|
56
|
+
Object.assign(item, !isSolid && frist, {
|
|
57
|
+
children: [
|
|
58
|
+
isSolid && {
|
|
59
|
+
...frist,
|
|
60
|
+
path: baseItem.path === frist.path ? '/' : frist.path
|
|
61
|
+
},
|
|
62
|
+
...children
|
|
63
|
+
].filter(Boolean)
|
|
64
|
+
});
|
|
65
|
+
} else {
|
|
66
|
+
Object.assign(item, frist);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
tree.push(Object.assign(item, baseItem));
|
|
70
|
+
}
|
|
71
|
+
} else if (regex.test(filePath)) {
|
|
72
|
+
const source = readFileSync(filePath, {
|
|
73
|
+
encoding: 'utf-8'
|
|
74
|
+
});
|
|
75
|
+
const frontmatter = extractFrontmatter(source);
|
|
76
|
+
const meta = frontmatter ? load(frontmatter) : {};
|
|
77
|
+
const reslove = relative(base, filePath);
|
|
78
|
+
const realPath = prefixPath(reslove);
|
|
79
|
+
tree.push(Object.assign({
|
|
80
|
+
path: realPath.split('/').slice(-2, -1)?.join('') || '/',
|
|
81
|
+
key: realPath.replace(/\/?index.tsx?$/, '/').replace(/\/?README.mdx?$/, '/').split('/').filter(Boolean).join('/'),
|
|
82
|
+
meta: {
|
|
83
|
+
...meta
|
|
84
|
+
}
|
|
85
|
+
}, alia && {
|
|
86
|
+
[elename]: `rr(() => import(/* webpackChunkName: '${reslove}' */'${join(alia, reslove)}'))rr`
|
|
87
|
+
}, outputSource && {
|
|
88
|
+
codes: extractCode(source.replace(frontmatterRegex, '').replace(/^\n+|\n+$/g, ''))
|
|
89
|
+
}));
|
|
90
|
+
}
|
|
91
|
+
return tree;
|
|
92
|
+
}, []);
|
|
93
|
+
}
|
|
94
|
+
export const routesModuleName = '@app/routes';
|
|
95
|
+
export const route = new ReactiveObject({
|
|
96
|
+
[routesModuleName]: 'export default []'
|
|
97
|
+
});
|
|
98
|
+
export const exampleModuleName = '@app/example';
|
|
99
|
+
export const examples = new ReactiveObject();
|
|
100
|
+
let replaceStr = `${isSolid ? '() => ' : ''}${createElement}(SuspenseComp, { comp: $1 })`;
|
|
101
|
+
let prefixStr = `import { ${createElement} } from "${FRAMEWORKNAME}";import SuspenseComp from "@app/suspense";${isReact ? 'import prefix from "@app/prefix-router";' : ''}`;
|
|
102
|
+
if (hasCustomRouter) {
|
|
103
|
+
prefixStr += 'import merge from "@app/merge-router";import customRouter from "@/router";';
|
|
104
|
+
}
|
|
105
|
+
if (![
|
|
106
|
+
'react',
|
|
107
|
+
'solid'
|
|
108
|
+
].includes(FRAMEWORK)) {
|
|
109
|
+
replaceStr = '$1';
|
|
110
|
+
prefixStr = '';
|
|
111
|
+
}
|
|
112
|
+
export let routes = [];
|
|
113
|
+
let timerRoutes;
|
|
114
|
+
function updateData(tree) {
|
|
115
|
+
return `${prefixStr}const routes = [{ path: "/", children: [${isSolid ? '{ path: "/" },' : ''} ${tree}] }];const _routes = ${hasCustomRouter ? 'merge([...routes, ...customRouter], "path")' : 'routes'};export default ${isReact ? 'prefix(_routes)' : '_routes'};`;
|
|
116
|
+
}
|
|
117
|
+
function generatorLibraryRouter() {
|
|
118
|
+
clearTimeout(timerRoutes);
|
|
119
|
+
timerRoutes = setTimeout(()=>{
|
|
120
|
+
clearTimeout(timerRoutes);
|
|
121
|
+
routes = getTree(paths.componentsPath, {
|
|
122
|
+
regex: /README\.mdx?$/,
|
|
123
|
+
alia: '@pkg'
|
|
124
|
+
});
|
|
125
|
+
route.setData(routesModuleName, updateData(JSON.stringify(routes).replace(/"rr\((.+?)\)rr"/g, replaceStr).slice(1, -1)));
|
|
126
|
+
}, 100);
|
|
127
|
+
}
|
|
128
|
+
let timerExample;
|
|
129
|
+
function generatorLibraryDemo() {
|
|
130
|
+
clearTimeout(timerExample);
|
|
131
|
+
timerExample = setTimeout(()=>{
|
|
132
|
+
clearTimeout(timerExample);
|
|
133
|
+
getTree(paths.componentsPath, {
|
|
134
|
+
regex: /\/examples\/(.+)\.md$/,
|
|
135
|
+
outputSource: true
|
|
136
|
+
}).forEach((item)=>{
|
|
137
|
+
const _name = [
|
|
138
|
+
exampleModuleName,
|
|
139
|
+
item.key
|
|
140
|
+
].filter(Boolean).join('/');
|
|
141
|
+
const data = item.children?.[0].children?.filter((e)=>e.codes)?.map((e)=>({
|
|
142
|
+
title: e.path.replace(/.md$/, ''),
|
|
143
|
+
order: 0,
|
|
144
|
+
...e.meta,
|
|
145
|
+
codes: e.codes
|
|
146
|
+
})).sort((a, b)=>a.order - b.order) || [];
|
|
147
|
+
examples.setData(_name, `export default ${JSON.stringify(data)};`);
|
|
148
|
+
});
|
|
149
|
+
}, 100);
|
|
150
|
+
}
|
|
151
|
+
function watchFiles(root, ignored, call) {
|
|
152
|
+
const ignoredRouter = (src, stats)=>{
|
|
153
|
+
if (stats) {
|
|
154
|
+
if (stats.isDirectory()) {
|
|
155
|
+
return false;
|
|
156
|
+
}
|
|
157
|
+
return ignored.test(src);
|
|
158
|
+
}
|
|
159
|
+
return void 0;
|
|
160
|
+
};
|
|
161
|
+
const watcher = watch(root, {
|
|
162
|
+
ignored: ignoredRouter,
|
|
163
|
+
persistent: true,
|
|
164
|
+
ignoreInitial: false
|
|
165
|
+
});
|
|
166
|
+
watcher.on('add', ()=>{
|
|
167
|
+
call();
|
|
168
|
+
}).on('change', ()=>{
|
|
169
|
+
call();
|
|
170
|
+
}).on('unlink', ()=>{
|
|
171
|
+
call();
|
|
172
|
+
});
|
|
173
|
+
process.on('SIGINT', function() {
|
|
174
|
+
watcher.close();
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
function generatorRouter() {
|
|
178
|
+
clearTimeout(timerRoutes);
|
|
179
|
+
timerRoutes = setTimeout(()=>{
|
|
180
|
+
clearTimeout(timerRoutes);
|
|
181
|
+
routes = getTree(paths.pagesPath, {
|
|
182
|
+
regex: /index\.tsx?$/,
|
|
183
|
+
alia: '@/pages'
|
|
184
|
+
});
|
|
185
|
+
route.setData(routesModuleName, updateData(JSON.stringify(routes).replace(/"rr\((.+?)\)rr"/g, replaceStr).slice(1, -1)));
|
|
186
|
+
}, 100);
|
|
187
|
+
}
|
|
188
|
+
if (isLibrary) {
|
|
189
|
+
// router
|
|
190
|
+
watchFiles(paths.componentsPath, /(?<!README\.mdx?)$/, generatorLibraryRouter);
|
|
191
|
+
// demos
|
|
192
|
+
watchFiles(paths.componentsPath, /(?<!\/examples\/(.+)\.md)$/, generatorLibraryDemo);
|
|
193
|
+
} else {
|
|
194
|
+
// router
|
|
195
|
+
watchFiles(paths.pagesPath, /(?<!index\.tsx?)$/, generatorRouter);
|
|
196
|
+
}
|
package/lib/seo.js
CHANGED
|
@@ -1,2 +1,41 @@
|
|
|
1
|
-
import{existsSync
|
|
2
|
-
|
|
1
|
+
import { existsSync, mkdirSync, writeFileSync } from 'fs';
|
|
2
|
+
import { join } from 'path';
|
|
3
|
+
import { outputConfig } from './common.js';
|
|
4
|
+
import { CONFIG } from './config.js';
|
|
5
|
+
import { routes } from './routes.js';
|
|
6
|
+
import { resolveProgramPath } from './utils.js';
|
|
7
|
+
function writeFile(path, data) {
|
|
8
|
+
try {
|
|
9
|
+
writeFileSync(path, data, 'utf-8');
|
|
10
|
+
} catch (error) {
|
|
11
|
+
//
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
export const seo = ()=>{
|
|
15
|
+
const { domain, nojekyll, path } = CONFIG.seo || {};
|
|
16
|
+
const baseDir = path && resolveProgramPath(path) || outputConfig?.path;
|
|
17
|
+
if (!domain || !baseDir) {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
if (!existsSync(baseDir)) {
|
|
21
|
+
mkdirSync(baseDir);
|
|
22
|
+
}
|
|
23
|
+
const routeBase = CONFIG.basename;
|
|
24
|
+
const base = routeBase.endsWith('/') ? routeBase : `${routeBase}/`;
|
|
25
|
+
writeFile(join(baseDir, 'CNAME'), domain);
|
|
26
|
+
writeFile(join(baseDir, 'robots'), `Sitemap: https://${domain}${base}sitemap.txt`);
|
|
27
|
+
const sitemap = [];
|
|
28
|
+
function getSiteMap(list) {
|
|
29
|
+
list.forEach((item)=>{
|
|
30
|
+
sitemap.push(`https://${domain}${base}${item.key}`);
|
|
31
|
+
if (Array.isArray(item.children)) {
|
|
32
|
+
getSiteMap(item.children);
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
getSiteMap(routes);
|
|
37
|
+
writeFile(join(baseDir, 'sitemap.txt'), sitemap.join('\n'));
|
|
38
|
+
if (nojekyll) {
|
|
39
|
+
writeFile(join(baseDir, '.nojekyll'), '');
|
|
40
|
+
}
|
|
41
|
+
};
|