@hmg-report-editor/template-converter 1.0.1

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.
@@ -0,0 +1,4 @@
1
+ import type { CurrentReportTemplateVersion, TemplateConversionOptions, TemplateConversionResult } from './types.js';
2
+ export declare const CURRENT_REPORT_TEMPLATE_VERSION: CurrentReportTemplateVersion;
3
+ /** 将指定版本模板数据转换为当前报告模板格式。 */
4
+ export declare function convertReportTemplate(data: unknown, sourceVersion: string, options?: TemplateConversionOptions): TemplateConversionResult;
@@ -0,0 +1,8 @@
1
+ import type { TemplateConversionErrorCode } from './types.js';
2
+ /** 模板转换失败时抛出的结构化错误。 */
3
+ export declare class TemplateConversionError extends Error {
4
+ readonly code: TemplateConversionErrorCode;
5
+ readonly detail?: unknown | undefined;
6
+ /** 创建包含错误码和原始明细的转换错误。 */
7
+ constructor(code: TemplateConversionErrorCode, message: string, detail?: unknown | undefined);
8
+ }
package/dist/index.cjs ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const V=require("parse5");class d extends Error{constructor(t,i,r){super(i),this.code=t,this.detail=r,this.name="TemplateConversionError"}}const O=new Set(["article","aside","blockquote","dd","div","dl","dt","figcaption","figure","footer","h1","h2","h3","h4","h5","h6","header","li","main","nav","ol","section","table","tbody","td","tfoot","th","thead","tr","ul"]),$=new Set(["a","abbr","b","code","em","i","label","small","span","strong","sub","sup","u"]);function j(e,t){if(!Array.isArray(e))throw new d("INVALID_TEMPLATE_DATA","Legacy 1.0.0 template data must be an array of sections.",e);const i=e.map((r,n)=>G(r,n,t));return{version:t.targetVersion,sourceVersion:t.sourceVersion,sections:i,warnings:t.warnings}}function G(e,t,i){if(!te(e))throw new d("INVALID_TEMPLATE_DATA",`Legacy 1.0.0 section at index ${t} must be an object.`,e);const r=w(e.field,`section_${t+1}`),n=l(e.title),s=l(e.id),a=typeof e.value=="string"?e.value:"",u={sectionField:r,sectionIndex:t,templateId:i.templateId,controlIndex:0,warn:i.warn},c=a.trim()?B(a,u):[_()];return a.trim()||i.warn({code:"EMPTY_LEGACY_SECTION",message:`Legacy section has no HTML content: ${r}.`,sectionField:r}),{field:r,title:n,id:s,template:{version:i.targetVersion,title:n,content:c.length>0?c:[_()]}}}function B(e,t){const i=V.parseFragment(e);return R(i.childNodes,t)}function R(e,t){const i=[];let r=[];const n=()=>{r.length!==0&&(i.push(F(r,!1)),r=[])};for(const s of e)if(!(ie(s)&&r.length===0)){if(p(s)&&s.tagName.toLowerCase()==="p"){n(),i.push(H(s,t));continue}if(p(s)&&O.has(s.tagName.toLowerCase())){n(),i.push(...R(s.childNodes,t));continue}N(r,U(s,t,[]))}return n(),i}function H(e,t){const i=b(e.childNodes,t,[]);return F(i,!1)}function b(e,t,i){const r=[];for(let n=0;n<e.length;n+=1){const s=e[n],a=q(e,n,t,i);if(a){N(r,[a.node]),n=a.endIndex;continue}N(r,U(s,t,i))}return r}function U(e,t,i){if(L(e))return e.value?[C(e.value,i)]:[];if(!p(e))return t.warn({code:"UNSUPPORTED_HTML_NODE",message:`Unsupported legacy HTML node ignored: ${e.nodeName}.`,sectionField:t.sectionField,detail:{nodeName:e.nodeName}}),[];const r=e.tagName.toLowerCase();switch(r){case"input":return z(e,t);case"select":return k(e,t);case"img":return W(e,t);case"br":return[C(`
2
+ `,i)];case"script":case"style":return t.warn({code:"UNSUPPORTED_HTML_TAG",message:`Unsupported legacy HTML tag ignored: <${r}>.`,sectionField:t.sectionField,detail:{tagName:r}}),[];default:return!$.has(r)&&!O.has(r)&&t.warn({code:"UNSUPPORTED_HTML_TAG",message:`Unsupported legacy HTML tag flattened: <${r}>.`,sectionField:t.sectionField,detail:{tagName:r}}),b(e.childNodes,t,X(e,i))}}function z(e,t){const i=(o(e,"type")??"text").toLowerCase();i!=="text"&&t.warn({code:"UNSUPPORTED_HTML_TAG",message:`Unsupported input type converted as text field: ${i}.`,sectionField:t.sectionField,detail:{type:i}});const r=g(e,t);return[{type:"structuredField",attrs:{...P(e,r,t,"input"),value:E(o(e,"value"),r==null?void 0:r.default,"")}}]}function k(e,t){const i=g(e,t),r=Q(i==null?void 0:i.options),n=K(e),s=r.options.length>0?r.options:n.options;return[{type:"dropdownField",attrs:{...P(e,i,t,"select"),value:E(n.selectedValue,r.defaultValue,i==null?void 0:i.default,""),options:s,allowCustomText:!1}}]}function W(e,t){const i=g(e,t);return v(e,i)?[]:(t.warn({code:"UNSUPPORTED_HTML_TAG",message:"Unsupported legacy image ignored.",sectionField:t.sectionField,detail:{src:o(e,"src")}}),[])}function q(e,t,i,r){const n=e[t];if(!p(n)||n.tagName.toLowerCase()!=="img")return;const s=g(n,i);if(!v(n,s))return;const a=J(e,t,s,i);if(a===-1){i.warn({code:"UNSUPPORTED_HTML_TAG",message:"Legacy visibility group marker has no matching closing marker.",sectionField:i.sectionField,detail:{serialId:s==null?void 0:s.serialId}});return}const u=b(e.slice(t+1,a),i,r);if(u.length===0){i.warn({code:"UNSUPPORTED_HTML_NODE",message:"Legacy visibility group marker range has no convertible content.",sectionField:i.sectionField,detail:{serialId:s==null?void 0:s.serialId}});return}return{endIndex:a,node:{type:"visibilityGroup",attrs:{condition:"all-controls-empty"},content:u}}}function J(e,t,i,r){const n=l(i==null?void 0:i.serialId);for(let s=t+1;s<e.length;s+=1){const a=e[s];if(!p(a)||a.tagName.toLowerCase()!=="img")continue;const u=g(a,r);if(!v(a,u))continue;const c=l(u==null?void 0:u.serialId);if(!n||!c||n===c)return s}return-1}function v(e,t){var n;if(e.tagName.toLowerCase()!=="img")return!1;const i=l(t==null?void 0:t.type),r=((n=l(o(e,"src")))==null?void 0:n.toLowerCase())??"";return i==="段落隐藏"||r.includes("tiny-left-icon")||r.includes("tiny-right-icon")}function P(e,t,i,r){const n=w(t==null?void 0:t.field,t==null?void 0:t.id,t==null?void 0:t.serialId,o(e,"id"),re(i,r)),s=w(t==null?void 0:t.label,t==null?void 0:t.title,o(e,"title"),n),a=l(o(e,"placeholder"),t==null?void 0:t.title,t==null?void 0:t.label),u=l(t==null?void 0:t.serialId),c=x(t==null?void 0:t.rule),A=l(t==null?void 0:t.nextItem);return{templateId:i.templateId,...u?{widgetNumber:u}:{},fieldId:n,fieldName:s,value:"",defaultValue:E(t==null?void 0:t.default,""),placeholder:a,required:y(t==null?void 0:t.isRequired),hideWhenEmpty:y(t==null?void 0:t.isNeedHide),noMatchDefault:y(t==null?void 0:t.noMatchDefault),...c.length>0?{rules:c}:{},...A?{nextWidgetNumber:A}:{}}}function x(e){return Array.isArray(e)?e.filter(t=>!!(t&&typeof t=="object")).map(t=>({title:l(t.title)??"规则",contents:Y(t.list)})):[]}function Y(e){return Array.isArray(e)?e.filter(t=>!!(t&&typeof t=="object")).filter(t=>!!(t.result&&typeof t.result=="object")).map(t=>({premises:Array.isArray(t.premiss)?t.premiss:[],result:t.result})):[]}function g(e,t){const i=o(e,"data-controlinfo");if(i)try{const r=JSON.parse(i.replace(/&quot;/g,'"'));return r&&typeof r=="object"?r:void 0}catch(r){t.warn({code:"CONTROL_INFO_PARSE_FAILED",message:"Legacy control info JSON parse failed.",sectionField:t.sectionField,detail:{raw:i,error:r}});return}}function K(e){const t=[];let i;for(const r of e.childNodes){if(!p(r)||r.tagName.toLowerCase()!=="option")continue;const n=M(r),s=o(r,"value")??n,a=o(r,"label")??n;t.push({value:s,label:a}),o(r,"selected")!==void 0&&i===void 0&&(i=s)}return{options:t,selectedValue:i}}function Q(e){if(!Array.isArray(e))return{options:[]};const t=[];let i;for(const r of e){if(r&&typeof r=="object"){const s=r,a=T(s.value??s.label??""),u=T(s.label??s.value??"");t.push({value:a,label:u}),i===void 0&&y(s.defaultFlag)&&(i=a);continue}const n=T(r);t.push({value:n,label:n})}return{options:t,defaultValue:i}}function X(e,t){const i=e.tagName.toLowerCase();let r=t;(i==="strong"||i==="b")&&(r=m(r,{type:"bold"})),(i==="em"||i==="i")&&(r=m(r,{type:"italic"})),i==="u"&&(r=m(r,{type:"underline"})),(i==="s"||i==="strike"||i==="del")&&(r=m(r,{type:"strike"}));const n=Z(o(e,"style"));return n&&(r=I(r,n)),r}function Z(e){if(!e)return;const t={};for(const i of e.split(";")){const[r,...n]=i.split(":"),s=r==null?void 0:r.trim().toLowerCase(),a=n.join(":").trim();!s||!a||(s==="font-family"?t.fontFamily=a:s==="font-size"?t.fontSize=a:s==="color"&&(t.color=a))}return Object.keys(t).length>0?t:void 0}function m(e,t){return e.some(i=>i.type===t.type)?e:[...e,t]}function I(e,t){return e.find(r=>r.type==="textStyle")?e.map(r=>r.type==="textStyle"?{...r,attrs:{...r.attrs??{},...t}}:r):[...e,{type:"textStyle",attrs:t}]}function N(e,t){for(const i of t){const r=e[e.length-1];S(r)&&S(i)&&ee(r.marks,i.marks)?r.text+=i.text:e.push(i)}}function S(e){return(e==null?void 0:e.type)==="text"&&typeof e.text=="string"}function ee(e,t){return JSON.stringify(e??[])===JSON.stringify(t??[])}function F(e,t){return{type:"paragraph",hidden:t,...e.length>0?{content:e}:{}}}function _(){return{type:"paragraph",hidden:!1,content:[]}}function C(e,t){return{type:"text",text:e,...t.length>0?{marks:t}:{}}}function te(e){return!!(e&&typeof e=="object")}function p(e){return"tagName"in e&&typeof e.tagName=="string"}function L(e){return e.nodeName==="#text"&&"value"in e}function ie(e){return L(e)&&/^\s*$/.test(e.value)}function o(e,t){const i=e.attrs.find(r=>r.name.toLowerCase()===t.toLowerCase());return i==null?void 0:i.value}function M(e){return L(e)?e.value:"childNodes"in e?e.childNodes.map(t=>M(t)).join(""):""}function re(e,t){return e.controlIndex+=1,`${e.sectionField}_${t}_${e.controlIndex}`}function w(...e){for(const t of e){const i=l(t);if(i)return i}return"field"}function l(...e){for(const t of e){if(t==null)continue;const i=String(t).trim();if(i)return i}}function E(...e){for(const t of e)if(t!==void 0)return ne(t);return""}function ne(e){return e===null||typeof e=="string"||typeof e=="number"||typeof e=="boolean"?e:String(e)}function T(e){return e==null?"":String(e)}function y(e){return typeof e=="boolean"?e:typeof e=="number"?e!==0:typeof e=="string"?["1","true","yes"].includes(e.trim().toLowerCase()):!1}const f="1.0.3";function se(e,t,i={}){const r=i.targetVersion??f;if(r!==f)throw new d("UNSUPPORTED_TARGET_VERSION",`Unsupported target template version: ${r}.`,{targetVersion:r});const n=ue(i);if(t==="1.0.0")return j(e,{targetVersion:r,sourceVersion:t,templateId:i.templateId??ae(),warn:n.warn,warnings:n.warnings});if(t===f)return oe(e,t,r,n.warnings);throw new d("UNSUPPORTED_TEMPLATE_VERSION",`Unsupported source template version: ${t}.`,{sourceVersion:t})}function ae(){const e=globalThis.crypto;return e!=null&&e.randomUUID?`template_${e.randomUUID()}`:`template_${Date.now().toString(36)}_${Math.random().toString(36).slice(2)}`}function ue(e){const t=[];return{warnings:t,warn(i){var r;t.push(i),(r=e.onWarning)==null||r.call(e,i)}}}function oe(e,t,i,r){if(D(e))return h(e.version),{version:i,sourceVersion:t,sections:[{field:"template",title:e.title,template:{...e,version:i}}],warnings:r};if(le(e)){h(e.version);for(const s of e.sections)h(s.template.version);const n=Array.isArray(e.warnings)?e.warnings.filter(ce):[];return{version:i,sourceVersion:t,sections:e.sections.map(s=>({...s,template:{...s.template,version:i}})),warnings:[...n,...r]}}throw new d("INVALID_TEMPLATE_DATA","Current template data must be a ReportTemplate or TemplateConversionResult.",e)}function h(e){if(e!==f)throw new d("UNSUPPORTED_TEMPLATE_VERSION",`Unsupported source template version: ${String(e??"")}.`,{sourceVersion:e})}function D(e){return!!(e&&typeof e=="object"&&"version"in e&&"content"in e&&Array.isArray(e.content))}function le(e){return!!(e&&typeof e=="object"&&"sections"in e&&Array.isArray(e.sections)&&e.sections.every(t=>!!(t&&typeof t=="object"&&"field"in t&&"template"in t&&D(t.template))))}function ce(e){return!!(e&&typeof e=="object"&&"code"in e&&typeof e.code=="string"&&"message"in e&&typeof e.message=="string")}exports.CURRENT_REPORT_TEMPLATE_VERSION=f;exports.TemplateConversionError=d;exports.convertReportTemplate=se;
@@ -0,0 +1,4 @@
1
+ /** 模板转换包公共出口,暴露转换入口、错误类型和转换相关类型。 */
2
+ export { CURRENT_REPORT_TEMPLATE_VERSION, convertReportTemplate } from './converter.js';
3
+ export { TemplateConversionError } from './errors.js';
4
+ export type * from './types.js';
package/dist/index.js ADDED
@@ -0,0 +1,596 @@
1
+ import { parseFragment as V } from "parse5";
2
+ class d extends Error {
3
+ /** 创建包含错误码和原始明细的转换错误。 */
4
+ constructor(t, i, r) {
5
+ super(i), this.code = t, this.detail = r, this.name = "TemplateConversionError";
6
+ }
7
+ }
8
+ const O = /* @__PURE__ */ new Set([
9
+ "article",
10
+ "aside",
11
+ "blockquote",
12
+ "dd",
13
+ "div",
14
+ "dl",
15
+ "dt",
16
+ "figcaption",
17
+ "figure",
18
+ "footer",
19
+ "h1",
20
+ "h2",
21
+ "h3",
22
+ "h4",
23
+ "h5",
24
+ "h6",
25
+ "header",
26
+ "li",
27
+ "main",
28
+ "nav",
29
+ "ol",
30
+ "section",
31
+ "table",
32
+ "tbody",
33
+ "td",
34
+ "tfoot",
35
+ "th",
36
+ "thead",
37
+ "tr",
38
+ "ul"
39
+ ]), $ = /* @__PURE__ */ new Set([
40
+ "a",
41
+ "abbr",
42
+ "b",
43
+ "code",
44
+ "em",
45
+ "i",
46
+ "label",
47
+ "small",
48
+ "span",
49
+ "strong",
50
+ "sub",
51
+ "sup",
52
+ "u"
53
+ ]);
54
+ function G(e, t) {
55
+ if (!Array.isArray(e))
56
+ throw new d(
57
+ "INVALID_TEMPLATE_DATA",
58
+ "Legacy 1.0.0 template data must be an array of sections.",
59
+ e
60
+ );
61
+ const i = e.map((r, n) => j(r, n, t));
62
+ return {
63
+ version: t.targetVersion,
64
+ sourceVersion: t.sourceVersion,
65
+ sections: i,
66
+ warnings: t.warnings
67
+ };
68
+ }
69
+ function j(e, t, i) {
70
+ if (!te(e))
71
+ throw new d(
72
+ "INVALID_TEMPLATE_DATA",
73
+ `Legacy 1.0.0 section at index ${t} must be an object.`,
74
+ e
75
+ );
76
+ const r = w(e.field, `section_${t + 1}`), n = l(e.title), s = l(e.id), a = typeof e.value == "string" ? e.value : "", u = {
77
+ sectionField: r,
78
+ sectionIndex: t,
79
+ templateId: i.templateId,
80
+ controlIndex: 0,
81
+ warn: i.warn
82
+ }, c = a.trim() ? B(a, u) : [_()];
83
+ return a.trim() || i.warn({
84
+ code: "EMPTY_LEGACY_SECTION",
85
+ message: `Legacy section has no HTML content: ${r}.`,
86
+ sectionField: r
87
+ }), {
88
+ field: r,
89
+ title: n,
90
+ id: s,
91
+ template: {
92
+ version: i.targetVersion,
93
+ title: n,
94
+ content: c.length > 0 ? c : [_()]
95
+ }
96
+ };
97
+ }
98
+ function B(e, t) {
99
+ const i = V(e);
100
+ return U(i.childNodes, t);
101
+ }
102
+ function U(e, t) {
103
+ const i = [];
104
+ let r = [];
105
+ const n = () => {
106
+ r.length !== 0 && (i.push(R(r, !1)), r = []);
107
+ };
108
+ for (const s of e)
109
+ if (!(ie(s) && r.length === 0)) {
110
+ if (p(s) && s.tagName.toLowerCase() === "p") {
111
+ n(), i.push(H(s, t));
112
+ continue;
113
+ }
114
+ if (p(s) && O.has(s.tagName.toLowerCase())) {
115
+ n(), i.push(...U(s.childNodes, t));
116
+ continue;
117
+ }
118
+ N(
119
+ r,
120
+ F(
121
+ s,
122
+ t,
123
+ []
124
+ )
125
+ );
126
+ }
127
+ return n(), i;
128
+ }
129
+ function H(e, t) {
130
+ const i = b(
131
+ e.childNodes,
132
+ t,
133
+ []
134
+ );
135
+ return R(i, !1);
136
+ }
137
+ function b(e, t, i) {
138
+ const r = [];
139
+ for (let n = 0; n < e.length; n += 1) {
140
+ const s = e[n], a = q(e, n, t, i);
141
+ if (a) {
142
+ N(r, [a.node]), n = a.endIndex;
143
+ continue;
144
+ }
145
+ N(r, F(s, t, i));
146
+ }
147
+ return r;
148
+ }
149
+ function F(e, t, i) {
150
+ if (v(e))
151
+ return e.value ? [C(e.value, i)] : [];
152
+ if (!p(e))
153
+ return t.warn({
154
+ code: "UNSUPPORTED_HTML_NODE",
155
+ message: `Unsupported legacy HTML node ignored: ${e.nodeName}.`,
156
+ sectionField: t.sectionField,
157
+ detail: { nodeName: e.nodeName }
158
+ }), [];
159
+ const r = e.tagName.toLowerCase();
160
+ switch (r) {
161
+ case "input":
162
+ return z(e, t);
163
+ case "select":
164
+ return k(e, t);
165
+ case "img":
166
+ return W(e, t);
167
+ case "br":
168
+ return [C(`
169
+ `, i)];
170
+ case "script":
171
+ case "style":
172
+ return t.warn({
173
+ code: "UNSUPPORTED_HTML_TAG",
174
+ message: `Unsupported legacy HTML tag ignored: <${r}>.`,
175
+ sectionField: t.sectionField,
176
+ detail: { tagName: r }
177
+ }), [];
178
+ default:
179
+ return !$.has(r) && !O.has(r) && t.warn({
180
+ code: "UNSUPPORTED_HTML_TAG",
181
+ message: `Unsupported legacy HTML tag flattened: <${r}>.`,
182
+ sectionField: t.sectionField,
183
+ detail: { tagName: r }
184
+ }), b(e.childNodes, t, X(e, i));
185
+ }
186
+ }
187
+ function z(e, t) {
188
+ const i = (o(e, "type") ?? "text").toLowerCase();
189
+ i !== "text" && t.warn({
190
+ code: "UNSUPPORTED_HTML_TAG",
191
+ message: `Unsupported input type converted as text field: ${i}.`,
192
+ sectionField: t.sectionField,
193
+ detail: { type: i }
194
+ });
195
+ const r = f(e, t);
196
+ return [
197
+ {
198
+ type: "structuredField",
199
+ attrs: {
200
+ ...P(e, r, t, "input"),
201
+ value: A(o(e, "value"), r == null ? void 0 : r.default, "")
202
+ }
203
+ }
204
+ ];
205
+ }
206
+ function k(e, t) {
207
+ const i = f(e, t), r = Q(i == null ? void 0 : i.options), n = K(e), s = r.options.length > 0 ? r.options : n.options;
208
+ return [
209
+ {
210
+ type: "dropdownField",
211
+ attrs: {
212
+ ...P(e, i, t, "select"),
213
+ value: A(n.selectedValue, r.defaultValue, i == null ? void 0 : i.default, ""),
214
+ options: s,
215
+ allowCustomText: !1
216
+ }
217
+ }
218
+ ];
219
+ }
220
+ function W(e, t) {
221
+ const i = f(e, t);
222
+ return L(e, i) ? [] : (t.warn({
223
+ code: "UNSUPPORTED_HTML_TAG",
224
+ message: "Unsupported legacy image ignored.",
225
+ sectionField: t.sectionField,
226
+ detail: {
227
+ src: o(e, "src")
228
+ }
229
+ }), []);
230
+ }
231
+ function q(e, t, i, r) {
232
+ const n = e[t];
233
+ if (!p(n) || n.tagName.toLowerCase() !== "img")
234
+ return;
235
+ const s = f(n, i);
236
+ if (!L(n, s))
237
+ return;
238
+ const a = J(e, t, s, i);
239
+ if (a === -1) {
240
+ i.warn({
241
+ code: "UNSUPPORTED_HTML_TAG",
242
+ message: "Legacy visibility group marker has no matching closing marker.",
243
+ sectionField: i.sectionField,
244
+ detail: { serialId: s == null ? void 0 : s.serialId }
245
+ });
246
+ return;
247
+ }
248
+ const u = b(e.slice(t + 1, a), i, r);
249
+ if (u.length === 0) {
250
+ i.warn({
251
+ code: "UNSUPPORTED_HTML_NODE",
252
+ message: "Legacy visibility group marker range has no convertible content.",
253
+ sectionField: i.sectionField,
254
+ detail: { serialId: s == null ? void 0 : s.serialId }
255
+ });
256
+ return;
257
+ }
258
+ return {
259
+ endIndex: a,
260
+ node: {
261
+ type: "visibilityGroup",
262
+ attrs: {
263
+ condition: "all-controls-empty"
264
+ },
265
+ content: u
266
+ }
267
+ };
268
+ }
269
+ function J(e, t, i, r) {
270
+ const n = l(i == null ? void 0 : i.serialId);
271
+ for (let s = t + 1; s < e.length; s += 1) {
272
+ const a = e[s];
273
+ if (!p(a) || a.tagName.toLowerCase() !== "img")
274
+ continue;
275
+ const u = f(a, r);
276
+ if (!L(a, u))
277
+ continue;
278
+ const c = l(u == null ? void 0 : u.serialId);
279
+ if (!n || !c || n === c)
280
+ return s;
281
+ }
282
+ return -1;
283
+ }
284
+ function L(e, t) {
285
+ var n;
286
+ if (e.tagName.toLowerCase() !== "img")
287
+ return !1;
288
+ const i = l(t == null ? void 0 : t.type), r = ((n = l(o(e, "src"))) == null ? void 0 : n.toLowerCase()) ?? "";
289
+ return i === "段落隐藏" || r.includes("tiny-left-icon") || r.includes("tiny-right-icon");
290
+ }
291
+ function P(e, t, i, r) {
292
+ const n = w(
293
+ t == null ? void 0 : t.field,
294
+ t == null ? void 0 : t.id,
295
+ t == null ? void 0 : t.serialId,
296
+ o(e, "id"),
297
+ re(i, r)
298
+ ), s = w(
299
+ t == null ? void 0 : t.label,
300
+ t == null ? void 0 : t.title,
301
+ o(e, "title"),
302
+ n
303
+ ), a = l(o(e, "placeholder"), t == null ? void 0 : t.title, t == null ? void 0 : t.label), u = l(t == null ? void 0 : t.serialId), c = x(t == null ? void 0 : t.rule), E = l(t == null ? void 0 : t.nextItem);
304
+ return {
305
+ templateId: i.templateId,
306
+ ...u ? { widgetNumber: u } : {},
307
+ fieldId: n,
308
+ fieldName: s,
309
+ value: "",
310
+ defaultValue: A(t == null ? void 0 : t.default, ""),
311
+ placeholder: a,
312
+ required: m(t == null ? void 0 : t.isRequired),
313
+ hideWhenEmpty: m(t == null ? void 0 : t.isNeedHide),
314
+ noMatchDefault: m(t == null ? void 0 : t.noMatchDefault),
315
+ ...c.length > 0 ? { rules: c } : {},
316
+ ...E ? { nextWidgetNumber: E } : {}
317
+ };
318
+ }
319
+ function x(e) {
320
+ return Array.isArray(e) ? e.filter((t) => !!(t && typeof t == "object")).map((t) => ({
321
+ title: l(t.title) ?? "规则",
322
+ contents: Y(t.list)
323
+ })) : [];
324
+ }
325
+ function Y(e) {
326
+ return Array.isArray(e) ? e.filter((t) => !!(t && typeof t == "object")).filter((t) => !!(t.result && typeof t.result == "object")).map((t) => ({
327
+ premises: Array.isArray(t.premiss) ? t.premiss : [],
328
+ result: t.result
329
+ })) : [];
330
+ }
331
+ function f(e, t) {
332
+ const i = o(e, "data-controlinfo");
333
+ if (i)
334
+ try {
335
+ const r = JSON.parse(i.replace(/&quot;/g, '"'));
336
+ return r && typeof r == "object" ? r : void 0;
337
+ } catch (r) {
338
+ t.warn({
339
+ code: "CONTROL_INFO_PARSE_FAILED",
340
+ message: "Legacy control info JSON parse failed.",
341
+ sectionField: t.sectionField,
342
+ detail: { raw: i, error: r }
343
+ });
344
+ return;
345
+ }
346
+ }
347
+ function K(e) {
348
+ const t = [];
349
+ let i;
350
+ for (const r of e.childNodes) {
351
+ if (!p(r) || r.tagName.toLowerCase() !== "option")
352
+ continue;
353
+ const n = D(r), s = o(r, "value") ?? n, a = o(r, "label") ?? n;
354
+ t.push({ value: s, label: a }), o(r, "selected") !== void 0 && i === void 0 && (i = s);
355
+ }
356
+ return { options: t, selectedValue: i };
357
+ }
358
+ function Q(e) {
359
+ if (!Array.isArray(e))
360
+ return { options: [] };
361
+ const t = [];
362
+ let i;
363
+ for (const r of e) {
364
+ if (r && typeof r == "object") {
365
+ const s = r, a = h(s.value ?? s.label ?? ""), u = h(s.label ?? s.value ?? "");
366
+ t.push({ value: a, label: u }), i === void 0 && m(s.defaultFlag) && (i = a);
367
+ continue;
368
+ }
369
+ const n = h(r);
370
+ t.push({ value: n, label: n });
371
+ }
372
+ return { options: t, defaultValue: i };
373
+ }
374
+ function X(e, t) {
375
+ const i = e.tagName.toLowerCase();
376
+ let r = t;
377
+ (i === "strong" || i === "b") && (r = g(r, { type: "bold" })), (i === "em" || i === "i") && (r = g(r, { type: "italic" })), i === "u" && (r = g(r, { type: "underline" })), (i === "s" || i === "strike" || i === "del") && (r = g(r, { type: "strike" }));
378
+ const n = Z(o(e, "style"));
379
+ return n && (r = I(r, n)), r;
380
+ }
381
+ function Z(e) {
382
+ if (!e)
383
+ return;
384
+ const t = {};
385
+ for (const i of e.split(";")) {
386
+ const [r, ...n] = i.split(":"), s = r == null ? void 0 : r.trim().toLowerCase(), a = n.join(":").trim();
387
+ !s || !a || (s === "font-family" ? t.fontFamily = a : s === "font-size" ? t.fontSize = a : s === "color" && (t.color = a));
388
+ }
389
+ return Object.keys(t).length > 0 ? t : void 0;
390
+ }
391
+ function g(e, t) {
392
+ return e.some((i) => i.type === t.type) ? e : [...e, t];
393
+ }
394
+ function I(e, t) {
395
+ return e.find((r) => r.type === "textStyle") ? e.map(
396
+ (r) => r.type === "textStyle" ? {
397
+ ...r,
398
+ attrs: {
399
+ ...r.attrs ?? {},
400
+ ...t
401
+ }
402
+ } : r
403
+ ) : [...e, { type: "textStyle", attrs: t }];
404
+ }
405
+ function N(e, t) {
406
+ for (const i of t) {
407
+ const r = e[e.length - 1];
408
+ S(r) && S(i) && ee(r.marks, i.marks) ? r.text += i.text : e.push(i);
409
+ }
410
+ }
411
+ function S(e) {
412
+ return (e == null ? void 0 : e.type) === "text" && typeof e.text == "string";
413
+ }
414
+ function ee(e, t) {
415
+ return JSON.stringify(e ?? []) === JSON.stringify(t ?? []);
416
+ }
417
+ function R(e, t) {
418
+ return {
419
+ type: "paragraph",
420
+ hidden: t,
421
+ ...e.length > 0 ? { content: e } : {}
422
+ };
423
+ }
424
+ function _() {
425
+ return {
426
+ type: "paragraph",
427
+ hidden: !1,
428
+ content: []
429
+ };
430
+ }
431
+ function C(e, t) {
432
+ return {
433
+ type: "text",
434
+ text: e,
435
+ ...t.length > 0 ? { marks: t } : {}
436
+ };
437
+ }
438
+ function te(e) {
439
+ return !!(e && typeof e == "object");
440
+ }
441
+ function p(e) {
442
+ return "tagName" in e && typeof e.tagName == "string";
443
+ }
444
+ function v(e) {
445
+ return e.nodeName === "#text" && "value" in e;
446
+ }
447
+ function ie(e) {
448
+ return v(e) && /^\s*$/.test(e.value);
449
+ }
450
+ function o(e, t) {
451
+ const i = e.attrs.find((r) => r.name.toLowerCase() === t.toLowerCase());
452
+ return i == null ? void 0 : i.value;
453
+ }
454
+ function D(e) {
455
+ return v(e) ? e.value : "childNodes" in e ? e.childNodes.map((t) => D(t)).join("") : "";
456
+ }
457
+ function re(e, t) {
458
+ return e.controlIndex += 1, `${e.sectionField}_${t}_${e.controlIndex}`;
459
+ }
460
+ function w(...e) {
461
+ for (const t of e) {
462
+ const i = l(t);
463
+ if (i)
464
+ return i;
465
+ }
466
+ return "field";
467
+ }
468
+ function l(...e) {
469
+ for (const t of e) {
470
+ if (t == null)
471
+ continue;
472
+ const i = String(t).trim();
473
+ if (i)
474
+ return i;
475
+ }
476
+ }
477
+ function A(...e) {
478
+ for (const t of e)
479
+ if (t !== void 0)
480
+ return ne(t);
481
+ return "";
482
+ }
483
+ function ne(e) {
484
+ return e === null || typeof e == "string" || typeof e == "number" || typeof e == "boolean" ? e : String(e);
485
+ }
486
+ function h(e) {
487
+ return e == null ? "" : String(e);
488
+ }
489
+ function m(e) {
490
+ return typeof e == "boolean" ? e : typeof e == "number" ? e !== 0 : typeof e == "string" ? ["1", "true", "yes"].includes(e.trim().toLowerCase()) : !1;
491
+ }
492
+ const y = "1.0.3";
493
+ function de(e, t, i = {}) {
494
+ const r = i.targetVersion ?? y;
495
+ if (r !== y)
496
+ throw new d(
497
+ "UNSUPPORTED_TARGET_VERSION",
498
+ `Unsupported target template version: ${r}.`,
499
+ { targetVersion: r }
500
+ );
501
+ const n = ae(i);
502
+ if (t === "1.0.0")
503
+ return G(e, {
504
+ targetVersion: r,
505
+ sourceVersion: t,
506
+ templateId: i.templateId ?? se(),
507
+ warn: n.warn,
508
+ warnings: n.warnings
509
+ });
510
+ if (t === y)
511
+ return ue(e, t, r, n.warnings);
512
+ throw new d(
513
+ "UNSUPPORTED_TEMPLATE_VERSION",
514
+ `Unsupported source template version: ${t}.`,
515
+ { sourceVersion: t }
516
+ );
517
+ }
518
+ function se() {
519
+ const e = globalThis.crypto;
520
+ return e != null && e.randomUUID ? `template_${e.randomUUID()}` : `template_${Date.now().toString(36)}_${Math.random().toString(36).slice(2)}`;
521
+ }
522
+ function ae(e) {
523
+ const t = [];
524
+ return {
525
+ warnings: t,
526
+ warn(i) {
527
+ var r;
528
+ t.push(i), (r = e.onWarning) == null || r.call(e, i);
529
+ }
530
+ };
531
+ }
532
+ function ue(e, t, i, r) {
533
+ if (M(e))
534
+ return T(e.version), {
535
+ version: i,
536
+ sourceVersion: t,
537
+ sections: [
538
+ {
539
+ field: "template",
540
+ title: e.title,
541
+ template: {
542
+ ...e,
543
+ version: i
544
+ }
545
+ }
546
+ ],
547
+ warnings: r
548
+ };
549
+ if (oe(e)) {
550
+ T(e.version);
551
+ for (const s of e.sections)
552
+ T(s.template.version);
553
+ const n = Array.isArray(e.warnings) ? e.warnings.filter(le) : [];
554
+ return {
555
+ version: i,
556
+ sourceVersion: t,
557
+ sections: e.sections.map((s) => ({
558
+ ...s,
559
+ template: {
560
+ ...s.template,
561
+ version: i
562
+ }
563
+ })),
564
+ warnings: [...n, ...r]
565
+ };
566
+ }
567
+ throw new d(
568
+ "INVALID_TEMPLATE_DATA",
569
+ "Current template data must be a ReportTemplate or TemplateConversionResult.",
570
+ e
571
+ );
572
+ }
573
+ function T(e) {
574
+ if (e !== y)
575
+ throw new d(
576
+ "UNSUPPORTED_TEMPLATE_VERSION",
577
+ `Unsupported source template version: ${String(e ?? "")}.`,
578
+ { sourceVersion: e }
579
+ );
580
+ }
581
+ function M(e) {
582
+ return !!(e && typeof e == "object" && "version" in e && "content" in e && Array.isArray(e.content));
583
+ }
584
+ function oe(e) {
585
+ return !!(e && typeof e == "object" && "sections" in e && Array.isArray(e.sections) && e.sections.every(
586
+ (t) => !!(t && typeof t == "object" && "field" in t && "template" in t && M(t.template))
587
+ ));
588
+ }
589
+ function le(e) {
590
+ return !!(e && typeof e == "object" && "code" in e && typeof e.code == "string" && "message" in e && typeof e.message == "string");
591
+ }
592
+ export {
593
+ y as CURRENT_REPORT_TEMPLATE_VERSION,
594
+ d as TemplateConversionError,
595
+ de as convertReportTemplate
596
+ };
@@ -0,0 +1,11 @@
1
+ import type { CurrentReportTemplateVersion, TemplateConversionResult, TemplateConversionWarning } from './types.js';
2
+ type LegacyConversionContext = {
3
+ sourceVersion: string;
4
+ targetVersion: CurrentReportTemplateVersion;
5
+ templateId: string;
6
+ warnings: TemplateConversionWarning[];
7
+ warn: (warning: TemplateConversionWarning) => void;
8
+ };
9
+ /** 转换 v1.0.0 历史模板数组为当前分段模板结果。 */
10
+ export declare function convertLegacyTemplateV100(data: unknown, context: LegacyConversionContext): TemplateConversionResult;
11
+ export {};
@@ -0,0 +1,42 @@
1
+ /** 模板转换包共享类型,描述版本、错误、警告和转换结果。 */
2
+ import type { ReportTemplate } from '@hmg-report-editor/core';
3
+ /** 当前可输出的报告模板版本。 */
4
+ export type CurrentReportTemplateVersion = '1.0.3';
5
+ /** 模板转换错误码。 */
6
+ export type TemplateConversionErrorCode = 'INVALID_TEMPLATE_DATA' | 'UNSUPPORTED_TARGET_VERSION' | 'UNSUPPORTED_TEMPLATE_VERSION';
7
+ /** 模板转换警告码。 */
8
+ export type TemplateConversionWarningCode = 'CONTROL_INFO_PARSE_FAILED' | 'EMPTY_LEGACY_SECTION' | 'UNSUPPORTED_HTML_NODE' | 'UNSUPPORTED_HTML_TAG';
9
+ /** 模板转换过程中的非阻断警告。 */
10
+ export type TemplateConversionWarning = {
11
+ code: TemplateConversionWarningCode;
12
+ message: string;
13
+ sectionField?: string;
14
+ detail?: unknown;
15
+ };
16
+ /** 模板转换选项。 */
17
+ export type TemplateConversionOptions = {
18
+ targetVersion?: CurrentReportTemplateVersion;
19
+ templateId?: string;
20
+ onWarning?: (warning: TemplateConversionWarning) => void;
21
+ };
22
+ /** 转换结果中的单个报告片段。 */
23
+ export type ConvertedTemplateSection = {
24
+ field: string;
25
+ title?: string;
26
+ id?: string;
27
+ template: ReportTemplate;
28
+ };
29
+ /** 模板转换的完整结果。 */
30
+ export type TemplateConversionResult = {
31
+ version: CurrentReportTemplateVersion;
32
+ sourceVersion: string;
33
+ sections: ConvertedTemplateSection[];
34
+ warnings: TemplateConversionWarning[];
35
+ };
36
+ /** v1.0.0 历史模板中的原始分段。 */
37
+ export type LegacyTemplateSectionV100 = {
38
+ field?: unknown;
39
+ title?: unknown;
40
+ value?: unknown;
41
+ id?: unknown;
42
+ } & Record<string, unknown>;
package/package.json ADDED
@@ -0,0 +1,26 @@
1
+ {
2
+ "name": "@hmg-report-editor/template-converter",
3
+ "version": "1.0.1",
4
+ "type": "module",
5
+ "files": [
6
+ "dist"
7
+ ],
8
+ "main": "./dist/index.cjs",
9
+ "module": "./dist/index.js",
10
+ "types": "./dist/index.d.ts",
11
+ "exports": {
12
+ ".": {
13
+ "types": "./dist/index.d.ts",
14
+ "import": "./dist/index.js",
15
+ "require": "./dist/index.cjs"
16
+ }
17
+ },
18
+ "scripts": {
19
+ "build": "vite build && tsc -p tsconfig.build.json && node ../../scripts/finalize-package-types.mjs .",
20
+ "typecheck": "tsc -p tsconfig.json --noEmit"
21
+ },
22
+ "dependencies": {
23
+ "@hmg-report-editor/core": "^1.0.1",
24
+ "parse5": "^7.3.0"
25
+ }
26
+ }