新增: - 书库导入导出(library_import/library_export)及测试 - 图片变体生成(image_variants)与响应式图片(responsiveImage) - 书籍搜索(bookSearch)+ BookSearch/LibrarySearchGrid 组件 - 小组件运行时(widgetRuntime)与静态检查(widgetLint) - 上传缓存中间件(upload_cache)与字体 CSS 提取脚本 其它: - 后端 handlers/services 全量调整 - 前端页面、组件、库函数与配置更新
53 lines
2.0 KiB
TypeScript
53 lines
2.0 KiB
TypeScript
// 自定义侧栏工具代码处理:
|
||
// parseMixedWidgetCode / mergeWidgetCode:「混写一框」(内联 <style>/<script>)与分栏三字段互转;
|
||
// 三字段存储结构不变,拆分仅发生在管理端提交/切换视图时。
|
||
// 工具的样式隔离由渲染端 Shadow DOM 负责(见 widgetRuntime.ts),本模块不再做 CSS 作用域改写。
|
||
|
||
export interface WidgetCodeParts {
|
||
html: string;
|
||
css: string;
|
||
js: string;
|
||
}
|
||
|
||
const STYLE_RE = /<style\b[^>]*>([\s\S]*?)<\/style>/gi;
|
||
const SCRIPT_RE = /<script\b([^>]*)>([\s\S]*?)<\/script>/gi;
|
||
const TYPE_RE = /\btype\s*=\s*(?:"([^"]*)"|'([^']*)')/i;
|
||
|
||
const JS_TYPES = new Set(["", "text/javascript", "application/javascript", "module"]);
|
||
|
||
function isNonJsScript(attrs: string): boolean {
|
||
const m = attrs.match(TYPE_RE);
|
||
if (!m) return false;
|
||
return !JS_TYPES.has((m[1] ?? m[2] ?? "").toLowerCase());
|
||
}
|
||
|
||
/** 混写代码 → 三字段:<style>/<script> 段被摘出,剩余全部视为 HTML */
|
||
export function parseMixedWidgetCode(code: string): WidgetCodeParts {
|
||
const cssParts: string[] = [];
|
||
const jsParts: string[] = [];
|
||
let html = code.replace(STYLE_RE, (_m, body: string) => {
|
||
cssParts.push(body);
|
||
return "";
|
||
});
|
||
html = html.replace(SCRIPT_RE, (m: string, attrs: string, body: string) => {
|
||
// 外链脚本、模板/数据脚本(type 非 JS)原样留在 HTML 中
|
||
if (/\bsrc\s*=/i.test(attrs) || isNonJsScript(attrs)) return m;
|
||
jsParts.push(body);
|
||
return "";
|
||
});
|
||
return {
|
||
html: html.trim(),
|
||
css: cssParts.join("\n\n").trim(),
|
||
js: jsParts.join("\n\n").trim(),
|
||
};
|
||
}
|
||
|
||
/** 三字段 → 混写视图:HTML 在前,CSS/JS 分别以标准标签包裹 */
|
||
export function mergeWidgetCode(parts: WidgetCodeParts): string {
|
||
const out: string[] = [];
|
||
if (parts.html.trim()) out.push(parts.html.trim());
|
||
if (parts.css.trim()) out.push(`<style>\n${parts.css.trim()}\n</style>`);
|
||
if (parts.js.trim()) out.push(`<script>\n${parts.js.trim()}\n</script>`);
|
||
return out.join("\n\n");
|
||
}
|