@oeyoews/tiddlywiki-plugin-dev
Version:
[](https://github.com/tiddly-gittly)
184 lines (179 loc) • 5.77 kB
text/typescript
import { basename, resolve } from 'path';
import { writeFileSync, readFileSync } from 'fs';
import chalk from 'chalk';
import { ITiddlerFields } from 'tw5-typed';
import { minify as htmlMinify } from 'html-minifier-terser';
import { rebuild } from './packup';
import { tiddlywiki, mkdirsForFileSync, waitForFile } from './utils';
const printPlugins = (plugins: Map<string, string>) => {
// eslint-disable-next-line no-console
console.log(chalk.bgCyan.black.bold(' Minimized plugins '));
plugins.forEach((plugin, title) => {
let size = plugin.length;
let unit = 'B ';
if (size > 1024) {
size /= 1024;
unit = 'KiB';
}
if (size > 1024) {
size /= 1024;
unit = 'MiB';
}
const sizeFormatted = `${size.toFixed(2)} ${unit}`.padStart(11);
// eslint-disable-next-line no-console
console.log(chalk.cyan(`${sizeFormatted} ${title}`));
});
// eslint-disable-next-line no-console
console.log('');
};
/**
* 构建插件
*
* @async
* @param {string} [output] 插件输出的路径,不填则只构建但不保存
* @param {string} [excludeFilter] 排除构建的插件
* @param {string} [srcPath='src'] 插件工程根路径
* @return {Promise<ITiddlerFields[]>} 构建好的插件
*/
export const build = async (
output?: string,
excludeFilter?: string,
srcPath = 'src',
) => {
const $tw = tiddlywiki();
const plugins = await rebuild($tw, srcPath, undefined, false, excludeFilter);
const pluginJsons = new Map<string, string>();
plugins.forEach(plugin => {
const pluginTiddlerName = `${basename(
$tw.utils.generateTiddlerFilepath(plugin.title, {}),
)}.json`;
const jsonStr = JSON.stringify(plugin);
pluginJsons.set(plugin.title, jsonStr);
if (output) {
const path = resolve(output, pluginTiddlerName);
mkdirsForFileSync(path);
writeFileSync(path, jsonStr);
}
});
printPlugins(pluginJsons);
return plugins;
};
/**
* 构建插件库
*
* @async
* @param {string} output 插件库输出的路径
* @param {string} [excludeFilter] 排除构建的插件
* @param {string} [srcPath='src'] 插件工程根路径
* @param {string} [wikiPath='wiki'] wiki 路径
* @return {Promise<ITiddlerFields[]>} 构建好的插件
*/
export const buildLibrary = async (
output: string,
excludeFilter?: string,
srcPath = 'src',
wikiPath = 'wiki',
) => {
const $tw = tiddlywiki();
const plugins: Record<string, ITiddlerFields> = {};
const pluginJsons = new Map<string, string>();
(await rebuild($tw, srcPath, undefined, false, excludeFilter)).forEach(
plugin => {
const jsonStr = JSON.stringify(plugin);
pluginJsons.set(plugin.title, jsonStr);
plugins[plugin.title] = plugin;
},
);
printPlugins(pluginJsons);
const pluginPaths = $tw.getLibraryItemSearchPaths($tw.config.pluginsPath);
// eslint-disable-next-line no-console
console.log(chalk.green.bold('Generating plugin library...'));
tiddlywiki(
[
/* 收集所有已安装插件 */
{
title: '$:/UpgradeLibrary',
type: 'application/json',
'plugin-type': 'library',
text: JSON.stringify({ tiddlers: plugins }),
},
...[
'tiddlywiki/filesystem',
'tiddlywiki/tiddlyweb',
'tiddlywiki/pluginlibrary',
].map(
pluginName =>
$tw.loadPluginFolder(
$tw.findLibraryItem(pluginName, pluginPaths as any)!,
)!,
),
],
wikiPath,
[
...['--output', resolve(output)] /* 指定输出路径 */,
...[
'--savelibrarytiddlers',
'$:/UpgradeLibrary',
'',
'recipes/library/tiddlers/',
'$:/UpgradeLibrary/List',
] /* 导出指定的插件 */,
...[
'--savetiddler',
'$:/UpgradeLibrary/List',
'recipes/library/tiddlers.json',
] /* 生成插件集合JSON文件 */,
...[
'--rendertiddler',
'$:/plugins/tiddlywiki/pluginlibrary/library.template.html',
'index.html',
'text/plain',
] /* 生成插件库HTML文件 */,
...[
'--deletetiddlers',
'[[$:/UpgradeLibrary]] [[$:/UpgradeLibrary/List]]',
] /* 删掉中间内容 */,
],
);
// 最小化:HTML
const HTMLPath = resolve(output, 'index.html');
// index.html 的生成是异步而无法控制,很烦
await waitForFile(HTMLPath);
const result = await htmlMinify(readFileSync(HTMLPath, 'utf-8'), {
caseSensitive: true,
collapseBooleanAttributes: false,
collapseInlineTagWhitespace: false,
collapseWhitespace: true,
conservativeCollapse: true,
continueOnParseError: true,
customAttrCollapse: /.*/,
decodeEntities: true,
html5: true,
ignoreCustomFragments: [/<#[\s\S]*?#>/, /<%[\s\S]*?%>/, /<\?[\s\S]*?\?>/],
includeAutoGeneratedTags: false,
keepClosingSlash: false,
maxLineLength: 0,
minifyCSS: true,
minifyJS: true,
minifyURLs: true,
preserveLineBreaks: false,
preventAttributesEscaping: false,
processConditionalComments: true,
processScripts: ['text/html'],
removeAttributeQuotes: true,
removeComments: true,
removeEmptyAttributes: true,
removeEmptyElements: false,
removeOptionalTags: true,
removeRedundantAttributes: true,
removeScriptTypeAttributes: true,
removeStyleLinkTypeAttributes: true,
removeTagWhitespace: true,
sortAttributes: true,
sortClassName: true,
trimCustomFragments: true,
useShortDoctype: true,
});
writeFileSync(HTMLPath, result);
return plugins;
};