@ptengine/lp-editor-core 1.0.0-alpha.4 → 1.0.0-alpha.7
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/dist/golden/manifest.json +56 -0
- package/dist/golden/verify.mjs +15 -2
- package/dist/index.d.ts +52 -4
- package/dist/index.js +182 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -679,6 +679,62 @@
|
|
|
679
679
|
"input": "component-cases.json#tabs-underline",
|
|
680
680
|
"inputSha256": "3aa1efdf74f74cdf3e263650e5b57eba197755f4c34ee546f43b671d4a82ffa6",
|
|
681
681
|
"sha256": "50a2f3a06efb2d231d14c81f7cfe1f8eae4601c850dccd0b0453023996465ea0"
|
|
682
|
+
},
|
|
683
|
+
{
|
|
684
|
+
"fixture": "export/01-etvos-article-lp.css.txt",
|
|
685
|
+
"kind": "export",
|
|
686
|
+
"input": "fixtures/page/01-etvos-article-lp.html#css",
|
|
687
|
+
"inputSha256": "363c2748670245a1fe44f4eb4bf30ee9ceed07dbcb72b8ef79a6d8f40f74161a",
|
|
688
|
+
"sha256": "8b013b036685b0ac2007604d76bff452df4abaef94e5b41f20a3aab8ce6dce4c"
|
|
689
|
+
},
|
|
690
|
+
{
|
|
691
|
+
"fixture": "export/01-etvos-article-lp.document.txt",
|
|
692
|
+
"kind": "export",
|
|
693
|
+
"input": "fixtures/page/01-etvos-article-lp.html#document",
|
|
694
|
+
"inputSha256": "363c2748670245a1fe44f4eb4bf30ee9ceed07dbcb72b8ef79a6d8f40f74161a",
|
|
695
|
+
"sha256": "7cb7aba645c6d3c682c29694a6c78ad91a74944afc6d2ed9591724167ba9b9d0"
|
|
696
|
+
},
|
|
697
|
+
{
|
|
698
|
+
"fixture": "export/01-etvos-article-lp.html.txt",
|
|
699
|
+
"kind": "export",
|
|
700
|
+
"input": "fixtures/page/01-etvos-article-lp.html#html",
|
|
701
|
+
"inputSha256": "363c2748670245a1fe44f4eb4bf30ee9ceed07dbcb72b8ef79a6d8f40f74161a",
|
|
702
|
+
"sha256": "466d649a03de2c3a3362a43c60b8a5d98840f9f8804c6940777557a36c716688"
|
|
703
|
+
},
|
|
704
|
+
{
|
|
705
|
+
"fixture": "export/01-etvos-article-lp.js.txt",
|
|
706
|
+
"kind": "export",
|
|
707
|
+
"input": "fixtures/page/01-etvos-article-lp.html#js",
|
|
708
|
+
"inputSha256": "363c2748670245a1fe44f4eb4bf30ee9ceed07dbcb72b8ef79a6d8f40f74161a",
|
|
709
|
+
"sha256": "0e8cff7792046224b5530d50d2fed0673368147d32efd8baff44f96a51156413"
|
|
710
|
+
},
|
|
711
|
+
{
|
|
712
|
+
"fixture": "export/02-vivaia-campaign-lp.css.txt",
|
|
713
|
+
"kind": "export",
|
|
714
|
+
"input": "fixtures/page/02-vivaia-campaign-lp.html#css",
|
|
715
|
+
"inputSha256": "7584711561c7a7dd5e8d7541f0dc9492b4d02fdc797c09692e26d1a9e29fae09",
|
|
716
|
+
"sha256": "b2b91f39fecf92b68639937361a214b0f6ea922a86f3cc313bc206d20ed80494"
|
|
717
|
+
},
|
|
718
|
+
{
|
|
719
|
+
"fixture": "export/02-vivaia-campaign-lp.document.txt",
|
|
720
|
+
"kind": "export",
|
|
721
|
+
"input": "fixtures/page/02-vivaia-campaign-lp.html#document",
|
|
722
|
+
"inputSha256": "7584711561c7a7dd5e8d7541f0dc9492b4d02fdc797c09692e26d1a9e29fae09",
|
|
723
|
+
"sha256": "b82ad94ef75d7abfe0e8271c3ed9d25ef39d4a827cf3801d65d42a1d5c881ce1"
|
|
724
|
+
},
|
|
725
|
+
{
|
|
726
|
+
"fixture": "export/02-vivaia-campaign-lp.html.txt",
|
|
727
|
+
"kind": "export",
|
|
728
|
+
"input": "fixtures/page/02-vivaia-campaign-lp.html#html",
|
|
729
|
+
"inputSha256": "7584711561c7a7dd5e8d7541f0dc9492b4d02fdc797c09692e26d1a9e29fae09",
|
|
730
|
+
"sha256": "03e958eee10e1a837fbb5de8dbdd60ed945b8e6c24b1cc881038f3915b677655"
|
|
731
|
+
},
|
|
732
|
+
{
|
|
733
|
+
"fixture": "export/02-vivaia-campaign-lp.js.txt",
|
|
734
|
+
"kind": "export",
|
|
735
|
+
"input": "fixtures/page/02-vivaia-campaign-lp.html#js",
|
|
736
|
+
"inputSha256": "7584711561c7a7dd5e8d7541f0dc9492b4d02fdc797c09692e26d1a9e29fae09",
|
|
737
|
+
"sha256": "77a3cd919aadd139235a298de9cf460eaee77e462dbed43f18d2e70ceb46abf2"
|
|
682
738
|
}
|
|
683
739
|
]
|
|
684
740
|
}
|
package/dist/golden/verify.mjs
CHANGED
|
@@ -53,7 +53,11 @@ const fragmentSha = new Map(
|
|
|
53
53
|
manifest.fixtures.filter(f => f.kind === 'fragment').map(f => [f.input, f.sha256])
|
|
54
54
|
);
|
|
55
55
|
|
|
56
|
-
|
|
56
|
+
/**
|
|
57
|
+
* `async` 不是可选的:成品拼装那一条要跑 Tailwind 编译。其余分支同步返回也无妨,
|
|
58
|
+
* 外面统一 await。
|
|
59
|
+
*/
|
|
60
|
+
async function compute(entry) {
|
|
57
61
|
if (entry.kind === 'document') {
|
|
58
62
|
return core.serialize(parse(readFileSync(join(here, entry.input), 'utf8')));
|
|
59
63
|
}
|
|
@@ -89,6 +93,15 @@ function compute(entry) {
|
|
|
89
93
|
if (!c) throw new Error(`component-cases.json 里找不到用例 ${name}`);
|
|
90
94
|
return core.components.renderHtml(c.type, c.settings, c.id);
|
|
91
95
|
}
|
|
96
|
+
// 成品拼装。一份输入出四件,`input` 的 # 段说的是取哪一件。
|
|
97
|
+
if (entry.kind === 'export') {
|
|
98
|
+
const [file, part] = entry.input.split('#');
|
|
99
|
+
const doc = parse(readFileSync(join(here, file), 'utf8'));
|
|
100
|
+
core.normalize(doc);
|
|
101
|
+
const out = await core.exportDocument(doc);
|
|
102
|
+
if (!(part in out)) throw new Error(`成品里没有 ${part} 这一件`);
|
|
103
|
+
return out[part];
|
|
104
|
+
}
|
|
92
105
|
if (entry.kind === 'apply') {
|
|
93
106
|
const name = entry.input.split('#')[1];
|
|
94
107
|
const c = opsByName.get(name);
|
|
@@ -106,7 +119,7 @@ let failed = 0;
|
|
|
106
119
|
for (const entry of manifest.fixtures) {
|
|
107
120
|
let actual;
|
|
108
121
|
try {
|
|
109
|
-
actual = sha(compute(entry));
|
|
122
|
+
actual = sha(await compute(entry));
|
|
110
123
|
} catch (e) {
|
|
111
124
|
console.error(`✗ ${entry.fixture} — ${e.message}`);
|
|
112
125
|
failed++;
|
package/dist/index.d.ts
CHANGED
|
@@ -104,7 +104,7 @@ declare function unwrap(doc: Document): DocumentFragment;
|
|
|
104
104
|
* iam 发布拒绝按 `rule` 出后端文案,mastra 回给模型的结构化报错复用同一枚举。
|
|
105
105
|
* 三处各一份措辞,但没有两份真源 —— 这也是 core 能作为公开包发布的前提之一。
|
|
106
106
|
*/
|
|
107
|
-
declare const ERROR_CODES: readonly ["FORMAT_MISSING", "ID_DUPLICATE", "ID_CONFLICT", "ID_FORMAT", "ID_NOT_FOUND", "SCRIPT_FORBIDDEN", "INLINE_STYLE", "NATIVE_PALETTE", "UNIT_FORBIDDEN", "CLASS_UNCOMPILABLE", "VARIANT_FORBIDDEN", "STRUCTURE", "MULTI_ROOT", "REPLACE_ID_CHANGED", "STALE_BASE_VERSION", "FRAGMENT_NOT_CANONICAL", "PLACEHOLDER_UNRESOLVED", "COMPONENT_UNKNOWN", "COMPONENT_RENDER_FAILED", "COMPONENT_SETTING_UNKNOWN", "COMPONENT_SETTING_INVALID"];
|
|
107
|
+
declare const ERROR_CODES: readonly ["FORMAT_MISSING", "ID_DUPLICATE", "ID_CONFLICT", "ID_FORMAT", "ID_NOT_FOUND", "SCRIPT_FORBIDDEN", "STYLE_FORBIDDEN", "INLINE_STYLE", "NATIVE_PALETTE", "UNIT_FORBIDDEN", "CLASS_UNCOMPILABLE", "VARIANT_FORBIDDEN", "STRUCTURE", "MULTI_ROOT", "REPLACE_ID_CHANGED", "STALE_BASE_VERSION", "FRAGMENT_NOT_CANONICAL", "PLACEHOLDER_UNRESOLVED", "COMPONENT_UNKNOWN", "COMPONENT_RENDER_FAILED", "COMPONENT_SETTING_UNKNOWN", "COMPONENT_SETTING_INVALID"];
|
|
108
108
|
type ErrorCode = (typeof ERROR_CODES)[number];
|
|
109
109
|
declare function isErrorCode(value: unknown): value is ErrorCode;
|
|
110
110
|
/** 校验条目。**不带 message** —— 文案归消费端。 */
|
|
@@ -354,6 +354,21 @@ declare function warm(theme?: Theme): Promise<void>;
|
|
|
354
354
|
* 判定器同样只在这一处。
|
|
355
355
|
*/
|
|
356
356
|
declare function canCompile(classes: readonly string[], theme?: Theme): Promise<Map<string, boolean>>;
|
|
357
|
+
/**
|
|
358
|
+
* 按当前主题解析一个 token 的取值。
|
|
359
|
+
*
|
|
360
|
+
* 一条入口,两个消费者:成品的**组件 token 补丁**(组件 CSS 里 `var(--radius-lg)`
|
|
361
|
+
* 这类引用不带兜底,而 Tailwind 按用量裁剪 token —— 缺了整条声明作废,圆角与
|
|
362
|
+
* `calc()` 里的内边距一起归 0)与 **base 开关层的断点**(页面可以覆写
|
|
363
|
+
* `--breakpoint-md`,写死 48rem 会让开关与页面自己的 `md:` 在不同宽度上切换)。
|
|
364
|
+
*
|
|
365
|
+
* 取值走 design system 而不是从 `generated/tw-css.ts` 里抠字面量:**页面 `@theme`
|
|
366
|
+
* 覆写了就返回覆写值**,与 Tailwind 自己用的是同一个来源。抠字面量会让页面改了
|
|
367
|
+
* 主题、组件却还用默认值 —— 又是一条静默不一致。
|
|
368
|
+
*
|
|
369
|
+
* 解析不出返回 `undefined`,由调用方决定怎么办(成品拼装那一侧是抛)。
|
|
370
|
+
*/
|
|
371
|
+
declare function themeValue(name: string, theme?: Theme): Promise<string | undefined>;
|
|
357
372
|
/** 同属性互斥:按当前主题派生的冲突表合并 class 列表。 */
|
|
358
373
|
declare function mergeClasses(classes: readonly string[], theme?: Theme): string;
|
|
359
374
|
/** 测试与宿主重载主题时用。 */
|
|
@@ -370,9 +385,10 @@ declare const compile_mergeClasses: typeof mergeClasses;
|
|
|
370
385
|
declare const compile_themeFromSource: typeof themeFromSource;
|
|
371
386
|
declare const compile_themeOf: typeof themeOf;
|
|
372
387
|
declare const compile_themeTokens: typeof themeTokens;
|
|
388
|
+
declare const compile_themeValue: typeof themeValue;
|
|
373
389
|
declare const compile_warm: typeof warm;
|
|
374
390
|
declare namespace compile {
|
|
375
|
-
export { compile_EMPTY_THEME as EMPTY_THEME, type compile_Theme as Theme, type compile_ThemeTokens as ThemeTokens, compile_canCompile as canCompile, compile_clearCompileCache as clearCompileCache, compile_fresh as fresh, compile_incremental as incremental, compile_mergeClasses as mergeClasses, compile_themeFromSource as themeFromSource, compile_themeOf as themeOf, compile_themeTokens as themeTokens, compile_warm as warm };
|
|
391
|
+
export { compile_EMPTY_THEME as EMPTY_THEME, type compile_Theme as Theme, type compile_ThemeTokens as ThemeTokens, compile_canCompile as canCompile, compile_clearCompileCache as clearCompileCache, compile_fresh as fresh, compile_incremental as incremental, compile_mergeClasses as mergeClasses, compile_themeFromSource as themeFromSource, compile_themeOf as themeOf, compile_themeTokens as themeTokens, compile_themeValue as themeValue, compile_warm as warm };
|
|
376
392
|
}
|
|
377
393
|
|
|
378
394
|
/**
|
|
@@ -760,6 +776,37 @@ declare namespace components {
|
|
|
760
776
|
*/
|
|
761
777
|
declare function collectClasses(root: Document | DocumentFragment | Element): Set<string>;
|
|
762
778
|
|
|
779
|
+
/**
|
|
780
|
+
* 成品拼装:把一份 v4 文档拼成「自包含静态文档」。
|
|
781
|
+
*
|
|
782
|
+
* ```
|
|
783
|
+
* exportDocument(doc) → { html, css, js, document }
|
|
784
|
+
* ```
|
|
785
|
+
*
|
|
786
|
+
* **顶层导出名是 `exportDocument` 而不是 `export`。** 后者语法上其实可以
|
|
787
|
+
* (`export { x as export }` 合法),但消费方就得写 `import { export as … }` ——
|
|
788
|
+
* d.ts、IDE 重命名、文档引用全要绕,收益为零。`LpEditorHandle.export()` 是
|
|
789
|
+
* React 包上的**方法名**,属性名用保留字没有成本,那一侧不改。
|
|
790
|
+
*
|
|
791
|
+
* **不接任何选项。** §8 已经把「弹窗的成品形态」(rem→px、`:host`、去 Preflight)
|
|
792
|
+
* 判给弹窗宿主了。这里留一个 `preflight?: false` 或 `scope?: 'shadow'`,就是把刚
|
|
793
|
+
* 拆掉的宿主档位换个形状装回来。加选项在将来是非破坏性的,删选项不是。
|
|
794
|
+
*
|
|
795
|
+
* **不跑 `validate`。** 裁决与拼装分家:issues 要随 `lpxSaveVersion` 上送 iam 落
|
|
796
|
+
* `publish_blockers`,宿主自己调。在这里再跑一遍等于同一个判断两处实现。
|
|
797
|
+
*/
|
|
798
|
+
interface ExportResult {
|
|
799
|
+
/** 完整文档,已剥、已展开、已去主题块,**不含** css 与 js 两段。 */
|
|
800
|
+
html: string;
|
|
801
|
+
/** Tailwind fresh 输出 + 组件 token 补丁 + 组件 CSS + base 开关层。 */
|
|
802
|
+
css: string;
|
|
803
|
+
/** 组件脚本,按类型各一份;无组件时为空串。 */
|
|
804
|
+
js: string;
|
|
805
|
+
/** 在 `html` 的 `<head>` 末尾补上 `<style>` 与 `<script>` 之后的单文件。 */
|
|
806
|
+
document: string;
|
|
807
|
+
}
|
|
808
|
+
declare function exportDocument(doc: Document): Promise<ExportResult>;
|
|
809
|
+
|
|
763
810
|
/**
|
|
764
811
|
* 宿主注入的 DOM 契约。
|
|
765
812
|
*
|
|
@@ -933,7 +980,7 @@ declare function checkVariants(className: string): VariantCheck;
|
|
|
933
980
|
* 护栏:export golden 断言「输出变了而 COMPILER_VERSION 没变就红」。
|
|
934
981
|
* 递增它是一次显式动作,不要顺手跟着包版本一起改。
|
|
935
982
|
*/
|
|
936
|
-
declare const VERSION = "1.0.0-alpha.
|
|
983
|
+
declare const VERSION = "1.0.0-alpha.7";
|
|
937
984
|
declare const COMPILER_VERSION = "2";
|
|
938
985
|
|
|
939
986
|
/**
|
|
@@ -956,6 +1003,7 @@ declare function createCore(options: CoreOptions): {
|
|
|
956
1003
|
compile: typeof compile;
|
|
957
1004
|
components: typeof components;
|
|
958
1005
|
collectClasses: typeof collectClasses;
|
|
1006
|
+
exportDocument: typeof exportDocument;
|
|
959
1007
|
rules: {
|
|
960
1008
|
readonly deviceVariants: readonly ["md", "max-md"];
|
|
961
1009
|
readonly stateVariants: readonly ["hover", "focus-visible", "active", "disabled"];
|
|
@@ -1014,4 +1062,4 @@ declare function createCore(options: CoreOptions): {
|
|
|
1014
1062
|
};
|
|
1015
1063
|
type Core = ReturnType<typeof createCore>;
|
|
1016
1064
|
|
|
1017
|
-
export { type ApplyResult, COMPILER_VERSION, type Core, type CoreOptions, type DOMParserCtor, type DOMParserLike, type DeleteOp, type DeviceVariant, EMPTY_THEME, ERROR_CODES, type EditOp, type EditorError, type ErrorCode, type InsertOp, type Issue, type LayerName, type LeafType, MAX_CONTAINER_DEPTH, type MoveOp, type NormalizeOptions, type OpaqueMode, PUBLISH_BLOCKING_RULES, type PropertySlot, type ReplaceOp, type Rules, type SetOp, type StateVariant, type StructureRejection, type Theme, type ThemeTokens, type Transaction, VERSION, type ValidateOptions, type ValidateResult$1 as ValidateResult, apply, canContain, checkVariants, collectClasses, compile, components, containerDepth, createCore, deleteTarget, editorError, fragmentElementRoots, guards, isErrorCode, isNativePaletteClass, isPublishBlocking, isWrapLayer, layerOf, normalize, normalizeClassValue, parseFragment, rules, serialize, themeFromSource, themeOf, themeTokens, unwrap, validate };
|
|
1065
|
+
export { type ApplyResult, COMPILER_VERSION, type Core, type CoreOptions, type DOMParserCtor, type DOMParserLike, type DeleteOp, type DeviceVariant, EMPTY_THEME, ERROR_CODES, type EditOp, type EditorError, type ErrorCode, type ExportResult, type InsertOp, type Issue, type LayerName, type LeafType, MAX_CONTAINER_DEPTH, type MoveOp, type NormalizeOptions, type OpaqueMode, PUBLISH_BLOCKING_RULES, type PropertySlot, type ReplaceOp, type Rules, type SetOp, type StateVariant, type StructureRejection, type Theme, type ThemeTokens, type Transaction, VERSION, type ValidateOptions, type ValidateResult$1 as ValidateResult, apply, canContain, checkVariants, collectClasses, compile, components, containerDepth, createCore, deleteTarget, editorError, exportDocument, fragmentElementRoots, guards, isErrorCode, isNativePaletteClass, isPublishBlocking, isWrapLayer, layerOf, normalize, normalizeClassValue, parseFragment, rules, serialize, themeFromSource, themeOf, themeTokens, unwrap, validate };
|
package/dist/index.js
CHANGED
|
@@ -369,7 +369,7 @@ var rules = {
|
|
|
369
369
|
};
|
|
370
370
|
|
|
371
371
|
// src/version.ts
|
|
372
|
-
var VERSION = "1.0.0-alpha.
|
|
372
|
+
var VERSION = "1.0.0-alpha.7";
|
|
373
373
|
var COMPILER_VERSION = "2";
|
|
374
374
|
|
|
375
375
|
// src/validate/tree.ts
|
|
@@ -1133,6 +1133,7 @@ function checkIds(root, issues) {
|
|
|
1133
1133
|
}
|
|
1134
1134
|
function checkElements(root, options, issues) {
|
|
1135
1135
|
const all = root.querySelectorAll("*");
|
|
1136
|
+
let themeSeen = 0;
|
|
1136
1137
|
for (let i = 0; i < all.length; i++) {
|
|
1137
1138
|
const el = all[i];
|
|
1138
1139
|
const name = tag(el);
|
|
@@ -1150,6 +1151,17 @@ function checkElements(root, options, issues) {
|
|
|
1150
1151
|
if (name === "script") {
|
|
1151
1152
|
issues.push({ ptId, rule: "SCRIPT_FORBIDDEN", params: { tag: name } });
|
|
1152
1153
|
}
|
|
1154
|
+
if (name === "style") {
|
|
1155
|
+
if (!isThemeStyle(el)) {
|
|
1156
|
+
issues.push({ ptId, rule: "STYLE_FORBIDDEN", params: { reason: "not-theme" } });
|
|
1157
|
+
} else if (++themeSeen > 1) {
|
|
1158
|
+
issues.push({
|
|
1159
|
+
ptId,
|
|
1160
|
+
rule: "STYLE_FORBIDDEN",
|
|
1161
|
+
params: { reason: "duplicate-theme" }
|
|
1162
|
+
});
|
|
1163
|
+
}
|
|
1164
|
+
}
|
|
1153
1165
|
checkAttributes(el, ptId, issues);
|
|
1154
1166
|
checkClasses(el, ptId, options, issues);
|
|
1155
1167
|
checkComponentSettings(el, ptId, options, issues);
|
|
@@ -1241,6 +1253,16 @@ var ERROR_CODES = [
|
|
|
1241
1253
|
"ID_NOT_FOUND",
|
|
1242
1254
|
/** 出现 <script> 或 on* 事件属性。 */
|
|
1243
1255
|
"SCRIPT_FORBIDDEN",
|
|
1256
|
+
/**
|
|
1257
|
+
* 出现了不该有的 <style>。`params.reason` 区分两种越界:
|
|
1258
|
+
* `not-theme` 不是主题块(`type` 不是 `text/tailwindcss`),位置不限
|
|
1259
|
+
* `duplicate-theme` 主题块多于一个,第二个起逐个报
|
|
1260
|
+
*
|
|
1261
|
+
* 两者处置相同(删掉它),没有消费端需要按 reason 分流,所以共用一个码——
|
|
1262
|
+
* 每多一个码,三个消费端就各多一处要认的分支。同码多 reason 的先例见
|
|
1263
|
+
* `PLACEHOLDER_UNRESOLVED`。
|
|
1264
|
+
*/
|
|
1265
|
+
"STYLE_FORBIDDEN",
|
|
1244
1266
|
/** 出现内联 style(动效变量除外)。 */
|
|
1245
1267
|
"INLINE_STYLE",
|
|
1246
1268
|
/** 使用了 Tailwind 内置色板。它本身可编译,所以必须由独立规则拦。 */
|
|
@@ -1754,6 +1776,7 @@ __export(compile_exports, {
|
|
|
1754
1776
|
themeFromSource: () => themeFromSource,
|
|
1755
1777
|
themeOf: () => themeOf,
|
|
1756
1778
|
themeTokens: () => themeTokens,
|
|
1779
|
+
themeValue: () => themeValue,
|
|
1757
1780
|
warm: () => warm
|
|
1758
1781
|
});
|
|
1759
1782
|
|
|
@@ -1893,6 +1916,10 @@ async function canCompile(classes, theme = EMPTY_THEME) {
|
|
|
1893
1916
|
for (const c of classes) out.set(c, e.compilable.get(c) ?? false);
|
|
1894
1917
|
return out;
|
|
1895
1918
|
}
|
|
1919
|
+
async function themeValue(name, theme = EMPTY_THEME) {
|
|
1920
|
+
const ds = await designSystemOf(theme);
|
|
1921
|
+
return ds.theme.get([name]) ?? void 0;
|
|
1922
|
+
}
|
|
1896
1923
|
function mergeClasses(classes, theme = EMPTY_THEME) {
|
|
1897
1924
|
return twMergeOf(theme)(...classes);
|
|
1898
1925
|
}
|
|
@@ -2360,6 +2387,158 @@ function collectClasses(root) {
|
|
|
2360
2387
|
return out;
|
|
2361
2388
|
}
|
|
2362
2389
|
|
|
2390
|
+
// src/export/baseCss.ts
|
|
2391
|
+
var FALLBACK_MD = "48rem";
|
|
2392
|
+
function rules2(md) {
|
|
2393
|
+
return [
|
|
2394
|
+
`@media (width < ${md}) {`,
|
|
2395
|
+
' [data-pt-hide="mobile"] { display: none }',
|
|
2396
|
+
' [data-pt-layout-mobile="stack"] { flex-direction: column; overflow-x: visible; scroll-snap-type: none }',
|
|
2397
|
+
' [data-pt-layout-mobile="scroll"] { display: flex; flex-wrap: nowrap; overflow-x: auto; scroll-snap-type: x mandatory }',
|
|
2398
|
+
' [data-pt-layout-mobile="scroll"] > * { flex: 0 0 auto; scroll-snap-align: start }',
|
|
2399
|
+
"}",
|
|
2400
|
+
`@media (width >= ${md}) {`,
|
|
2401
|
+
' [data-pt-hide="pc"] { display: none }',
|
|
2402
|
+
"}"
|
|
2403
|
+
].join("\n");
|
|
2404
|
+
}
|
|
2405
|
+
async function baseCss(resolve) {
|
|
2406
|
+
const md = await resolve("--breakpoint-md") ?? FALLBACK_MD;
|
|
2407
|
+
return rules2(md);
|
|
2408
|
+
}
|
|
2409
|
+
|
|
2410
|
+
// src/export/components.ts
|
|
2411
|
+
var COMPONENT_ATTR = "data-pt-component";
|
|
2412
|
+
var SETTINGS_ATTR2 = "data-pt-component-settings";
|
|
2413
|
+
function settingsOf(el) {
|
|
2414
|
+
const raw = el.getAttribute(SETTINGS_ATTR2);
|
|
2415
|
+
if (!raw) return {};
|
|
2416
|
+
try {
|
|
2417
|
+
const parsed = JSON.parse(raw);
|
|
2418
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) return {};
|
|
2419
|
+
return parsed;
|
|
2420
|
+
} catch {
|
|
2421
|
+
return {};
|
|
2422
|
+
}
|
|
2423
|
+
}
|
|
2424
|
+
function expandComponents(doc) {
|
|
2425
|
+
const nodes = doc.querySelectorAll(`[${COMPONENT_ATTR}]`);
|
|
2426
|
+
const types = /* @__PURE__ */ new Set();
|
|
2427
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
2428
|
+
const el = nodes[i];
|
|
2429
|
+
const type = el.getAttribute(COMPONENT_ATTR);
|
|
2430
|
+
if (!type) continue;
|
|
2431
|
+
const instanceId = el.getAttribute("data-pt-id") ?? "";
|
|
2432
|
+
const markup = renderHtml(type, settingsOf(el), instanceId);
|
|
2433
|
+
el.append(...parseFragment(doc, markup).childNodes);
|
|
2434
|
+
types.add(type);
|
|
2435
|
+
}
|
|
2436
|
+
const sorted = [...types].sort();
|
|
2437
|
+
return {
|
|
2438
|
+
types: sorted,
|
|
2439
|
+
css: sorted.map((t) => renderCss(t)).join("\n"),
|
|
2440
|
+
// 五件都是自闭合 IIFE(`})();` 收尾),换行拼接不会有 ASI 事故。
|
|
2441
|
+
js: sorted.map((t) => renderJs(t)).join("\n")
|
|
2442
|
+
};
|
|
2443
|
+
}
|
|
2444
|
+
|
|
2445
|
+
// src/export/componentTokens.ts
|
|
2446
|
+
function scanTokens(css) {
|
|
2447
|
+
const found = /* @__PURE__ */ new Set();
|
|
2448
|
+
const re = /var\(\s*(--[a-zA-Z0-9_-]+)\s*([,)])/g;
|
|
2449
|
+
let m;
|
|
2450
|
+
while ((m = re.exec(css)) !== null) {
|
|
2451
|
+
const [, name, delim] = m;
|
|
2452
|
+
if (delim === ",") continue;
|
|
2453
|
+
if (name.startsWith("--pt-")) continue;
|
|
2454
|
+
found.add(name);
|
|
2455
|
+
}
|
|
2456
|
+
return [...found].sort();
|
|
2457
|
+
}
|
|
2458
|
+
function requiredTokens(types) {
|
|
2459
|
+
const all = /* @__PURE__ */ new Set();
|
|
2460
|
+
for (const type of types) {
|
|
2461
|
+
for (const token of scanTokens(renderCss(type))) all.add(token);
|
|
2462
|
+
}
|
|
2463
|
+
return [...all].sort();
|
|
2464
|
+
}
|
|
2465
|
+
async function componentTokenCss(types, resolve) {
|
|
2466
|
+
const tokens = requiredTokens(types);
|
|
2467
|
+
if (tokens.length === 0) return "";
|
|
2468
|
+
const decls = [];
|
|
2469
|
+
for (const name of tokens) {
|
|
2470
|
+
const value = await resolve(name);
|
|
2471
|
+
if (value === void 0) {
|
|
2472
|
+
throw editorError("COMPONENT_RENDER_FAILED", { params: { token: name } });
|
|
2473
|
+
}
|
|
2474
|
+
decls.push(` ${name}: ${value};`);
|
|
2475
|
+
}
|
|
2476
|
+
return `:root {
|
|
2477
|
+
${decls.join("\n")}
|
|
2478
|
+
}`;
|
|
2479
|
+
}
|
|
2480
|
+
|
|
2481
|
+
// src/export/placeholder.ts
|
|
2482
|
+
var PLACEHOLDER_ATTR = "data-pt-placeholder";
|
|
2483
|
+
var PROMPT_ATTR = "data-pt-image-prompt";
|
|
2484
|
+
var SVG = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 4 3" preserveAspectRatio="none"><rect width="4" height="3" fill="#e5e7eb"/></svg>';
|
|
2485
|
+
var PLACEHOLDER_SRC = `data:image/svg+xml,${encodeURIComponent(SVG)}`;
|
|
2486
|
+
function renderPlaceholders(doc) {
|
|
2487
|
+
const nodes = doc.querySelectorAll(`img[${PLACEHOLDER_ATTR}]`);
|
|
2488
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
2489
|
+
const img = nodes[i];
|
|
2490
|
+
img.setAttribute("src", PLACEHOLDER_SRC);
|
|
2491
|
+
img.removeAttribute(PLACEHOLDER_ATTR);
|
|
2492
|
+
img.removeAttribute(PROMPT_ATTR);
|
|
2493
|
+
}
|
|
2494
|
+
}
|
|
2495
|
+
|
|
2496
|
+
// src/export/strip.ts
|
|
2497
|
+
var STRIPPED_ATTRS = [
|
|
2498
|
+
"data-pt-name",
|
|
2499
|
+
"data-pt-description",
|
|
2500
|
+
"data-pt-image-prompt",
|
|
2501
|
+
"data-pt-placeholder"
|
|
2502
|
+
];
|
|
2503
|
+
function stripEditorState(doc) {
|
|
2504
|
+
for (const attr of STRIPPED_ATTRS) {
|
|
2505
|
+
const nodes = doc.querySelectorAll(`[${attr}]`);
|
|
2506
|
+
for (let i = 0; i < nodes.length; i++) nodes[i].removeAttribute(attr);
|
|
2507
|
+
}
|
|
2508
|
+
const styles = doc.querySelectorAll("style");
|
|
2509
|
+
for (let i = 0; i < styles.length; i++) {
|
|
2510
|
+
const style = styles[i];
|
|
2511
|
+
if (isThemeStyle(style)) style.remove();
|
|
2512
|
+
}
|
|
2513
|
+
}
|
|
2514
|
+
|
|
2515
|
+
// src/export/index.ts
|
|
2516
|
+
async function exportDocument(doc) {
|
|
2517
|
+
const out = doc.cloneNode(true);
|
|
2518
|
+
renderPlaceholders(out);
|
|
2519
|
+
stripEditorState(out);
|
|
2520
|
+
const theme = themeOf(doc);
|
|
2521
|
+
const classes = collectClasses(out);
|
|
2522
|
+
const components = expandComponents(out);
|
|
2523
|
+
const resolve = (name) => themeValue(name, theme);
|
|
2524
|
+
const tokenCss = await componentTokenCss(components.types, resolve);
|
|
2525
|
+
const tailwind = await fresh(classes, theme);
|
|
2526
|
+
const css = [tailwind, tokenCss, components.css, await baseCss(resolve)].filter(Boolean).join("\n");
|
|
2527
|
+
const html = serialize(out);
|
|
2528
|
+
const head = out.head;
|
|
2529
|
+
if (head) {
|
|
2530
|
+
const style = out.createElement("style");
|
|
2531
|
+
style.textContent = css;
|
|
2532
|
+
head.append(style);
|
|
2533
|
+
if (components.js) {
|
|
2534
|
+
const script = out.createElement("script");
|
|
2535
|
+
script.textContent = components.js;
|
|
2536
|
+
head.append(script);
|
|
2537
|
+
}
|
|
2538
|
+
}
|
|
2539
|
+
return { html, css, js: components.js, document: serialize(out) };
|
|
2540
|
+
}
|
|
2541
|
+
|
|
2363
2542
|
// src/index.ts
|
|
2364
2543
|
function createCore(options) {
|
|
2365
2544
|
if (!options || typeof options.DOMParser !== "function") {
|
|
@@ -2379,12 +2558,13 @@ function createCore(options) {
|
|
|
2379
2558
|
compile: compile_exports,
|
|
2380
2559
|
components: components_exports,
|
|
2381
2560
|
collectClasses,
|
|
2561
|
+
exportDocument,
|
|
2382
2562
|
rules,
|
|
2383
2563
|
VERSION,
|
|
2384
2564
|
COMPILER_VERSION
|
|
2385
2565
|
};
|
|
2386
2566
|
}
|
|
2387
2567
|
|
|
2388
|
-
export { COMPILER_VERSION, EMPTY_THEME, ERROR_CODES, MAX_CONTAINER_DEPTH, PUBLISH_BLOCKING_RULES, VERSION, apply, canContain, checkVariants, collectClasses, compile_exports as compile, components_exports as components, containerDepth, createCore, deleteTarget, editorError, fragmentElementRoots, guards_exports as guards, isErrorCode, isNativePaletteClass, isPublishBlocking, isWrapLayer, layerOf, normalize, normalizeClassValue, parseFragment, rules, serialize, themeFromSource, themeOf, themeTokens, unwrap, validate };
|
|
2568
|
+
export { COMPILER_VERSION, EMPTY_THEME, ERROR_CODES, MAX_CONTAINER_DEPTH, PUBLISH_BLOCKING_RULES, VERSION, apply, canContain, checkVariants, collectClasses, compile_exports as compile, components_exports as components, containerDepth, createCore, deleteTarget, editorError, exportDocument, fragmentElementRoots, guards_exports as guards, isErrorCode, isNativePaletteClass, isPublishBlocking, isWrapLayer, layerOf, normalize, normalizeClassValue, parseFragment, rules, serialize, themeFromSource, themeOf, themeTokens, unwrap, validate };
|
|
2389
2569
|
//# sourceMappingURL=index.js.map
|
|
2390
2570
|
//# sourceMappingURL=index.js.map
|