@crypto512/jicon-mcp 0.7.1 → 1.0.0

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.
Files changed (129) hide show
  1. package/README.md +128 -395
  2. package/TOOL_LIST.md +810 -120
  3. package/dist/config/constants.d.ts +1 -0
  4. package/dist/config/constants.d.ts.map +1 -1
  5. package/dist/config/constants.js +1 -0
  6. package/dist/config/constants.js.map +1 -1
  7. package/dist/config/loader.d.ts +1 -0
  8. package/dist/config/loader.d.ts.map +1 -1
  9. package/dist/config/loader.js +27 -1
  10. package/dist/config/loader.js.map +1 -1
  11. package/dist/config/types.d.ts +8 -0
  12. package/dist/config/types.d.ts.map +1 -1
  13. package/dist/config/types.js +2 -0
  14. package/dist/config/types.js.map +1 -1
  15. package/dist/confluence/client.d.ts +38 -0
  16. package/dist/confluence/client.d.ts.map +1 -1
  17. package/dist/confluence/client.js +117 -0
  18. package/dist/confluence/client.js.map +1 -1
  19. package/dist/confluence/tools.d.ts +102 -75
  20. package/dist/confluence/tools.d.ts.map +1 -1
  21. package/dist/confluence/tools.js +510 -151
  22. package/dist/confluence/tools.js.map +1 -1
  23. package/dist/confluence/types.d.ts +55 -1
  24. package/dist/confluence/types.d.ts.map +1 -1
  25. package/dist/index.js +88 -2
  26. package/dist/index.js.map +1 -1
  27. package/dist/jira/tools.d.ts +0 -5
  28. package/dist/jira/tools.d.ts.map +1 -1
  29. package/dist/jira/tools.js +40 -87
  30. package/dist/jira/tools.js.map +1 -1
  31. package/dist/permissions/filter.d.ts +5 -0
  32. package/dist/permissions/filter.d.ts.map +1 -1
  33. package/dist/permissions/filter.js +29 -12
  34. package/dist/permissions/filter.js.map +1 -1
  35. package/dist/permissions/tool-registry.d.ts +23 -25
  36. package/dist/permissions/tool-registry.d.ts.map +1 -1
  37. package/dist/permissions/tool-registry.js +41 -45
  38. package/dist/permissions/tool-registry.js.map +1 -1
  39. package/dist/permissions/write-home-validator.d.ts +35 -0
  40. package/dist/permissions/write-home-validator.d.ts.map +1 -0
  41. package/dist/permissions/write-home-validator.js +140 -0
  42. package/dist/permissions/write-home-validator.js.map +1 -0
  43. package/dist/tempo/tools.d.ts.map +1 -1
  44. package/dist/tempo/tools.js +43 -44
  45. package/dist/tempo/tools.js.map +1 -1
  46. package/dist/utils/buffer-tools.d.ts +119 -1
  47. package/dist/utils/buffer-tools.d.ts.map +1 -1
  48. package/dist/utils/buffer-tools.js +610 -3
  49. package/dist/utils/buffer-tools.js.map +1 -1
  50. package/dist/utils/content-buffer.d.ts +34 -0
  51. package/dist/utils/content-buffer.d.ts.map +1 -1
  52. package/dist/utils/content-buffer.js +79 -0
  53. package/dist/utils/content-buffer.js.map +1 -1
  54. package/dist/utils/http-client.d.ts.map +1 -1
  55. package/dist/utils/http-client.js +4 -4
  56. package/dist/utils/http-client.js.map +1 -1
  57. package/dist/utils/jicon-help.d.ts +29 -0
  58. package/dist/utils/jicon-help.d.ts.map +1 -0
  59. package/dist/utils/jicon-help.js +873 -0
  60. package/dist/utils/jicon-help.js.map +1 -0
  61. package/dist/utils/plantuml/client.d.ts +40 -0
  62. package/dist/utils/plantuml/client.d.ts.map +1 -0
  63. package/dist/utils/plantuml/client.js +306 -0
  64. package/dist/utils/plantuml/client.js.map +1 -0
  65. package/dist/utils/plantuml/docker-manager.d.ts +35 -0
  66. package/dist/utils/plantuml/docker-manager.d.ts.map +1 -0
  67. package/dist/utils/plantuml/docker-manager.js +280 -0
  68. package/dist/utils/plantuml/docker-manager.js.map +1 -0
  69. package/dist/utils/plantuml/index.d.ts +11 -0
  70. package/dist/utils/plantuml/index.d.ts.map +1 -0
  71. package/dist/utils/plantuml/index.js +16 -0
  72. package/dist/utils/plantuml/index.js.map +1 -0
  73. package/dist/utils/plantuml/service.d.ts +46 -0
  74. package/dist/utils/plantuml/service.d.ts.map +1 -0
  75. package/dist/utils/plantuml/service.js +96 -0
  76. package/dist/utils/plantuml/service.js.map +1 -0
  77. package/dist/utils/plantuml/tools.d.ts +65 -0
  78. package/dist/utils/plantuml/tools.d.ts.map +1 -0
  79. package/dist/utils/plantuml/tools.js +272 -0
  80. package/dist/utils/plantuml/tools.js.map +1 -0
  81. package/dist/utils/plantuml/types.d.ts +130 -0
  82. package/dist/utils/plantuml/types.d.ts.map +1 -0
  83. package/dist/utils/plantuml/types.js +66 -0
  84. package/dist/utils/plantuml/types.js.map +1 -0
  85. package/dist/utils/response-formatter.d.ts +14 -0
  86. package/dist/utils/response-formatter.d.ts.map +1 -1
  87. package/dist/utils/response-formatter.js +84 -1
  88. package/dist/utils/response-formatter.js.map +1 -1
  89. package/dist/utils/url-tools.d.ts +49 -0
  90. package/dist/utils/url-tools.d.ts.map +1 -0
  91. package/dist/utils/url-tools.js +141 -0
  92. package/dist/utils/url-tools.js.map +1 -0
  93. package/dist/utils/xhtml/confluence-schema.d.ts +55 -0
  94. package/dist/utils/xhtml/confluence-schema.d.ts.map +1 -0
  95. package/dist/utils/xhtml/confluence-schema.js +215 -0
  96. package/dist/utils/xhtml/confluence-schema.js.map +1 -0
  97. package/dist/utils/xhtml/index.d.ts +17 -0
  98. package/dist/utils/xhtml/index.d.ts.map +1 -0
  99. package/dist/utils/xhtml/index.js +21 -0
  100. package/dist/utils/xhtml/index.js.map +1 -0
  101. package/dist/utils/xhtml/operations.d.ts +100 -0
  102. package/dist/utils/xhtml/operations.d.ts.map +1 -0
  103. package/dist/utils/xhtml/operations.js +596 -0
  104. package/dist/utils/xhtml/operations.js.map +1 -0
  105. package/dist/utils/xhtml/parser.d.ts +64 -0
  106. package/dist/utils/xhtml/parser.d.ts.map +1 -0
  107. package/dist/utils/xhtml/parser.js +180 -0
  108. package/dist/utils/xhtml/parser.js.map +1 -0
  109. package/dist/utils/xhtml/plantuml.d.ts +112 -0
  110. package/dist/utils/xhtml/plantuml.d.ts.map +1 -0
  111. package/dist/utils/xhtml/plantuml.js +251 -0
  112. package/dist/utils/xhtml/plantuml.js.map +1 -0
  113. package/dist/utils/xhtml/selector.d.ts +35 -0
  114. package/dist/utils/xhtml/selector.d.ts.map +1 -0
  115. package/dist/utils/xhtml/selector.js +358 -0
  116. package/dist/utils/xhtml/selector.js.map +1 -0
  117. package/dist/utils/xhtml/serializer.d.ts +26 -0
  118. package/dist/utils/xhtml/serializer.d.ts.map +1 -0
  119. package/dist/utils/xhtml/serializer.js +170 -0
  120. package/dist/utils/xhtml/serializer.js.map +1 -0
  121. package/dist/utils/xhtml/types.d.ts +134 -0
  122. package/dist/utils/xhtml/types.d.ts.map +1 -0
  123. package/dist/utils/xhtml/types.js +65 -0
  124. package/dist/utils/xhtml/types.js.map +1 -0
  125. package/dist/utils/xhtml/validator.d.ts +67 -0
  126. package/dist/utils/xhtml/validator.d.ts.map +1 -0
  127. package/dist/utils/xhtml/validator.js +300 -0
  128. package/dist/utils/xhtml/validator.js.map +1 -0
  129. package/package.json +5 -1
@@ -0,0 +1,358 @@
1
+ /**
2
+ * CSS-like Selector Engine for Confluence XHTML
3
+ *
4
+ * Supports:
5
+ * - Tag name: p, h1, table
6
+ * - Namespaced: ac:structured-macro, ri:page
7
+ * - Attributes: [ac:name="plantuml"], ac:structured-macro[ac:name="code"]
8
+ * - Pseudo-selectors: :nth-child(2), :first-child, :last-child
9
+ * - Descendants: table tbody tr
10
+ * - Direct children: ul > li
11
+ */
12
+ import { getContentRoot } from "./parser.js";
13
+ /**
14
+ * Parse a single simple selector (tag[attr]:pseudo)
15
+ */
16
+ function parseSimpleSelector(selector) {
17
+ const token = {};
18
+ let remaining = selector;
19
+ // First, extract pseudo-selectors (they always have a pattern like :name or :name(...))
20
+ // Distinguish from namespace prefixes: ac:structured-macro vs h2:first-child
21
+ // - Pseudo-selectors: :first-child, :nth-child(2), :contains("text")
22
+ // - Namespace prefix: ac:structured-macro, ri:page (part of the tag name)
23
+ //
24
+ // Key insight: Pseudo-selectors either:
25
+ // 1. Have () immediately after: :contains(...), :nth-child(...)
26
+ // 2. Are at the end or followed by more pseudo/attr: :first-child, :empty
27
+ // Namespace prefixes are part of the tag and followed by more tag-name characters, [ or end
28
+ // Match pseudo-selectors with arguments first: :name(arg) or :name-name(arg)
29
+ const pseudoWithArgRegex = /:([\w-]+)\(([^)]+)\)/g;
30
+ let pseudoMatch;
31
+ while ((pseudoMatch = pseudoWithArgRegex.exec(remaining)) !== null) {
32
+ if (!token.pseudos) {
33
+ token.pseudos = [];
34
+ }
35
+ const arg = pseudoMatch[2];
36
+ token.pseudos.push({
37
+ name: pseudoMatch[1],
38
+ arg: isNaN(Number(arg)) ? arg : Number(arg),
39
+ });
40
+ }
41
+ // Remove matched pseudos with args from remaining
42
+ remaining = remaining.replace(pseudoWithArgRegex, "");
43
+ // Match pseudo-selectors without arguments: :first-child, :empty
44
+ // Only match KNOWN pseudo-selectors to avoid confusion with namespace prefixes
45
+ // (e.g., ac:structured-macro should NOT treat :structured-macro as a pseudo)
46
+ const knownPseudos = ["first-child", "last-child", "only-child", "empty"];
47
+ for (const pseudoName of knownPseudos) {
48
+ const pseudoPattern = new RegExp(`:${pseudoName}(?=$|[:\\[])`);
49
+ if (pseudoPattern.test(remaining)) {
50
+ if (!token.pseudos) {
51
+ token.pseudos = [];
52
+ }
53
+ token.pseudos.push({
54
+ name: pseudoName,
55
+ arg: undefined,
56
+ });
57
+ remaining = remaining.replace(`:${pseudoName}`, "");
58
+ }
59
+ }
60
+ // Match tag name (including namespace prefix like ac:structured-macro)
61
+ const tagMatch = remaining.match(/^([\w:-]+)/);
62
+ if (tagMatch) {
63
+ token.tag = tagMatch[1].toLowerCase();
64
+ remaining = remaining.slice(tagMatch[0].length);
65
+ }
66
+ // Match attribute selectors [name="value"]
67
+ const attrRegex = /\[([^\]=]+)(?:="([^"]*)")?\]/g;
68
+ let attrMatch;
69
+ while ((attrMatch = attrRegex.exec(remaining)) !== null) {
70
+ if (!token.attributes) {
71
+ token.attributes = new Map();
72
+ }
73
+ const attrName = attrMatch[1];
74
+ const attrValue = attrMatch[2] ?? ""; // Empty string means "has attribute"
75
+ token.attributes.set(attrName, attrValue);
76
+ }
77
+ return token;
78
+ }
79
+ /**
80
+ * Parse a full selector string into tokens
81
+ */
82
+ function parseSelector(selector) {
83
+ const tokens = [];
84
+ const parts = selector.trim().split(/\s+/);
85
+ for (let i = 0; i < parts.length; i++) {
86
+ const part = parts[i];
87
+ if (part === ">") {
88
+ // Direct child combinator
89
+ if (tokens.length > 0) {
90
+ tokens[tokens.length - 1].combinator = "child";
91
+ }
92
+ continue;
93
+ }
94
+ // Check for > attached to the selector
95
+ if (part.endsWith(">")) {
96
+ const actualPart = part.slice(0, -1);
97
+ if (actualPart) {
98
+ const token = parseSimpleSelector(actualPart);
99
+ token.combinator = "child";
100
+ tokens.push(token);
101
+ }
102
+ continue;
103
+ }
104
+ if (part.startsWith(">")) {
105
+ // > attached to next selector
106
+ if (tokens.length > 0) {
107
+ tokens[tokens.length - 1].combinator = "child";
108
+ }
109
+ const actualPart = part.slice(1);
110
+ if (actualPart) {
111
+ tokens.push(parseSimpleSelector(actualPart));
112
+ }
113
+ continue;
114
+ }
115
+ const token = parseSimpleSelector(part);
116
+ if (i < parts.length - 1 && parts[i + 1] !== ">") {
117
+ token.combinator = "descendant";
118
+ }
119
+ tokens.push(token);
120
+ }
121
+ return tokens;
122
+ }
123
+ /**
124
+ * Check if an element matches a selector token
125
+ */
126
+ function matchesToken(element, token) {
127
+ // Check tag name
128
+ if (token.tag) {
129
+ const tagName = element.tagName.toLowerCase();
130
+ if (tagName !== token.tag) {
131
+ return false;
132
+ }
133
+ }
134
+ // Check attributes
135
+ if (token.attributes) {
136
+ for (const [name, value] of token.attributes) {
137
+ const attrValue = element.getAttribute(name);
138
+ if (attrValue === null) {
139
+ return false;
140
+ }
141
+ // If value is specified, must match exactly
142
+ if (value !== "" && attrValue !== value) {
143
+ return false;
144
+ }
145
+ }
146
+ }
147
+ // Check pseudo-selectors
148
+ if (token.pseudos) {
149
+ for (const pseudo of token.pseudos) {
150
+ if (!matchesPseudo(element, pseudo)) {
151
+ return false;
152
+ }
153
+ }
154
+ }
155
+ return true;
156
+ }
157
+ // Unsupported pseudo-selectors that LLMs commonly try to use
158
+ const UNSUPPORTED_PSEUDOS = new Set([
159
+ "has-text", // jQuery-style, not standard CSS
160
+ "contains", // jQuery-style (we'll add our own :contains())
161
+ "has", // CSS :has() is complex, not implemented
162
+ "not", // CSS :not() requires full selector parsing
163
+ "matches", // CSS :matches() / :is()
164
+ "where", // CSS :where()
165
+ ]);
166
+ /**
167
+ * Check if a selector contains unsupported pseudo-selectors
168
+ * Returns the unsupported pseudo name or null
169
+ */
170
+ export function findUnsupportedPseudo(selector) {
171
+ const pseudoRegex = /:(\w+)(?:\([^)]*\))?/g;
172
+ let match;
173
+ while ((match = pseudoRegex.exec(selector)) !== null) {
174
+ const pseudoName = match[1].toLowerCase();
175
+ // Check if it's unsupported (but not our supported ones)
176
+ if (UNSUPPORTED_PSEUDOS.has(pseudoName) && pseudoName !== "contains") {
177
+ return pseudoName;
178
+ }
179
+ }
180
+ return null;
181
+ }
182
+ /**
183
+ * Check if element matches a pseudo-selector
184
+ */
185
+ function matchesPseudo(element, pseudo) {
186
+ const parent = element.parentElement;
187
+ switch (pseudo.name) {
188
+ case "first-child":
189
+ if (!parent)
190
+ return false;
191
+ return Array.from(parent.children).indexOf(element) === 0;
192
+ case "last-child":
193
+ if (!parent)
194
+ return false;
195
+ const siblings = Array.from(parent.children);
196
+ return siblings.indexOf(element) === siblings.length - 1;
197
+ case "nth-child": {
198
+ if (!parent)
199
+ return false;
200
+ const n = typeof pseudo.arg === "number" ? pseudo.arg : parseInt(pseudo.arg || "0", 10);
201
+ return Array.from(parent.children).indexOf(element) === n - 1; // nth-child is 1-based
202
+ }
203
+ case "only-child":
204
+ if (!parent)
205
+ return false;
206
+ return parent.children.length === 1;
207
+ case "empty":
208
+ return element.children.length === 0 && (element.textContent || "").trim() === "";
209
+ case "contains": {
210
+ // :contains("text") - matches if element contains the text
211
+ let searchText = typeof pseudo.arg === "string" ? pseudo.arg : String(pseudo.arg || "");
212
+ // Strip surrounding quotes if present
213
+ if ((searchText.startsWith('"') && searchText.endsWith('"')) ||
214
+ (searchText.startsWith("'") && searchText.endsWith("'"))) {
215
+ searchText = searchText.slice(1, -1);
216
+ }
217
+ const elementText = element.textContent || "";
218
+ return elementText.toLowerCase().includes(searchText.toLowerCase());
219
+ }
220
+ case "has-text": {
221
+ // Alias for :contains() - jQuery-style syntax that LLMs often try
222
+ let searchText = typeof pseudo.arg === "string" ? pseudo.arg : String(pseudo.arg || "");
223
+ // Strip surrounding quotes if present
224
+ if ((searchText.startsWith('"') && searchText.endsWith('"')) ||
225
+ (searchText.startsWith("'") && searchText.endsWith("'"))) {
226
+ searchText = searchText.slice(1, -1);
227
+ }
228
+ const elementText = element.textContent || "";
229
+ return elementText.toLowerCase().includes(searchText.toLowerCase());
230
+ }
231
+ default:
232
+ // Unknown pseudo-selector - ignore (don't fail, just don't filter)
233
+ return true;
234
+ }
235
+ }
236
+ /**
237
+ * Find all elements matching a selector token within a root
238
+ */
239
+ function findMatchingElements(root, token, combinator, startFrom) {
240
+ const matches = [];
241
+ if (combinator === "child" && startFrom) {
242
+ // Direct children only
243
+ for (const child of startFrom.children) {
244
+ if (matchesToken(child, token)) {
245
+ matches.push(child);
246
+ }
247
+ }
248
+ }
249
+ else if (startFrom) {
250
+ // Descendants - use recursive traversal (no TreeWalker in linkedom Node.js)
251
+ const traverse = (el) => {
252
+ for (const child of el.children) {
253
+ if (matchesToken(child, token)) {
254
+ matches.push(child);
255
+ }
256
+ traverse(child);
257
+ }
258
+ };
259
+ traverse(startFrom);
260
+ }
261
+ else {
262
+ // Search from root
263
+ const traverse = (el) => {
264
+ if (matchesToken(el, token)) {
265
+ matches.push(el);
266
+ }
267
+ for (const child of el.children) {
268
+ traverse(child);
269
+ }
270
+ };
271
+ traverse(root);
272
+ }
273
+ return matches;
274
+ }
275
+ /**
276
+ * Execute a selector query on a document
277
+ *
278
+ * @param document - DOM Document to search
279
+ * @param selector - CSS-like selector string
280
+ * @returns SelectorResult with matches
281
+ */
282
+ export function querySelector(document, selector) {
283
+ const root = getContentRoot(document);
284
+ if (!root) {
285
+ return { matches: [], totalCount: 0 };
286
+ }
287
+ const tokens = parseSelector(selector);
288
+ if (tokens.length === 0) {
289
+ return { matches: [], totalCount: 0 };
290
+ }
291
+ // Start with first token
292
+ let currentMatches = findMatchingElements(root, tokens[0], undefined, undefined);
293
+ // Process remaining tokens
294
+ for (let i = 1; i < tokens.length; i++) {
295
+ const token = tokens[i];
296
+ const combinator = tokens[i - 1].combinator;
297
+ const nextMatches = [];
298
+ for (const match of currentMatches) {
299
+ const descendants = findMatchingElements(root, token, combinator, match);
300
+ nextMatches.push(...descendants);
301
+ }
302
+ currentMatches = nextMatches;
303
+ }
304
+ // Convert to SelectorMatch array
305
+ const matches = currentMatches.map((element, index) => ({
306
+ element,
307
+ index,
308
+ }));
309
+ return {
310
+ matches,
311
+ totalCount: matches.length,
312
+ };
313
+ }
314
+ /**
315
+ * Check if a selector is valid
316
+ */
317
+ export function isValidSelector(selector) {
318
+ try {
319
+ const tokens = parseSelector(selector);
320
+ return tokens.length > 0;
321
+ }
322
+ catch {
323
+ return false;
324
+ }
325
+ }
326
+ /**
327
+ * Get a human-readable description of a selector
328
+ */
329
+ export function describeSelector(selector) {
330
+ const tokens = parseSelector(selector);
331
+ const parts = [];
332
+ for (const token of tokens) {
333
+ let desc = token.tag || "*";
334
+ if (token.attributes) {
335
+ for (const [name, value] of token.attributes) {
336
+ if (value) {
337
+ desc += `[${name}="${value}"]`;
338
+ }
339
+ else {
340
+ desc += `[${name}]`;
341
+ }
342
+ }
343
+ }
344
+ if (token.pseudos) {
345
+ for (const pseudo of token.pseudos) {
346
+ if (pseudo.arg !== undefined) {
347
+ desc += `:${pseudo.name}(${pseudo.arg})`;
348
+ }
349
+ else {
350
+ desc += `:${pseudo.name}`;
351
+ }
352
+ }
353
+ }
354
+ parts.push(desc);
355
+ }
356
+ return parts.join(" ");
357
+ }
358
+ //# sourceMappingURL=selector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"selector.js","sourceRoot":"","sources":["../../../src/utils/xhtml/selector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * XHTML Serializer
3
+ *
4
+ * Serializes DOM back to XHTML string with proper handling of:
5
+ * - Namespace prefixes (ac:, ri:)
6
+ * - CDATA sections
7
+ * - Self-closing tags
8
+ * - Attribute order preservation
9
+ */
10
+ import type { Document, Element } from "linkedom";
11
+ /**
12
+ * Serialize a DOM Document back to XHTML string
13
+ *
14
+ * @param document - DOM Document to serialize
15
+ * @returns XHTML string (Confluence storage format)
16
+ */
17
+ export declare function serializeXhtml(document: Document): string;
18
+ /**
19
+ * Serialize an element fragment (not a full document)
20
+ */
21
+ export declare function serializeFragment(element: Element): string;
22
+ /**
23
+ * Pretty-print XHTML with consistent indentation
24
+ */
25
+ export declare function prettyPrint(content: string): string;
26
+ //# sourceMappingURL=serializer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serializer.d.ts","sourceRoot":"","sources":["../../../src/utils/xhtml/serializer.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AA6HlD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM,CA4BzD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAE1D;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAQnD"}
@@ -0,0 +1,170 @@
1
+ /**
2
+ * XHTML Serializer
3
+ *
4
+ * Serializes DOM back to XHTML string with proper handling of:
5
+ * - Namespace prefixes (ac:, ri:)
6
+ * - CDATA sections
7
+ * - Self-closing tags
8
+ * - Attribute order preservation
9
+ */
10
+ import { getContentRoot } from "./parser.js";
11
+ // Elements that should always be self-closing when empty
12
+ const VOID_ELEMENTS = new Set([
13
+ "br", "hr", "img", "input", "meta", "link", "area", "base", "col", "embed",
14
+ "param", "source", "track", "wbr",
15
+ ]);
16
+ // Elements that should preserve their content format (CDATA)
17
+ const CDATA_ELEMENTS = new Set([
18
+ "ac:plain-text-body",
19
+ ]);
20
+ /**
21
+ * Escape XML special characters in text content
22
+ */
23
+ function escapeXml(text) {
24
+ return text
25
+ .replace(/&/g, "&amp;")
26
+ .replace(/</g, "&lt;")
27
+ .replace(/>/g, "&gt;")
28
+ .replace(/"/g, "&quot;")
29
+ .replace(/'/g, "&apos;");
30
+ }
31
+ /**
32
+ * Check if text contains CDATA content
33
+ */
34
+ function containsCData(text) {
35
+ return text.includes("<![CDATA[");
36
+ }
37
+ /**
38
+ * Serialize element attributes to string
39
+ */
40
+ function serializeAttributes(element) {
41
+ const attrs = [];
42
+ for (const attr of element.attributes) {
43
+ // Skip xmlns declarations for our wrapper
44
+ if (attr.name.startsWith("xmlns:") && element.tagName.toLowerCase() === "xhtml-root") {
45
+ continue;
46
+ }
47
+ attrs.push(`${attr.name}="${escapeXml(attr.value)}"`);
48
+ }
49
+ return attrs.length > 0 ? " " + attrs.join(" ") : "";
50
+ }
51
+ /**
52
+ * Serialize a single element to XHTML string
53
+ */
54
+ function serializeElement(element, indent = "", preserveWhitespace = false) {
55
+ const tagName = element.tagName.toLowerCase();
56
+ const attrs = serializeAttributes(element);
57
+ // Check if this is a CDATA-containing element
58
+ const isCDataElement = CDATA_ELEMENTS.has(tagName);
59
+ // Check if element has children
60
+ const hasChildren = element.childNodes.length > 0;
61
+ // Void elements
62
+ if (!hasChildren && VOID_ELEMENTS.has(tagName)) {
63
+ return `${indent}<${tagName}${attrs} />`;
64
+ }
65
+ // Empty non-void elements
66
+ if (!hasChildren) {
67
+ return `${indent}<${tagName}${attrs}></${tagName}>`;
68
+ }
69
+ // Serialize children
70
+ const children = [];
71
+ let hasElementChildren = false;
72
+ for (const child of element.childNodes) {
73
+ if (child.nodeType === 1) {
74
+ // Element node
75
+ hasElementChildren = true;
76
+ const childElement = child;
77
+ const childPreserve = preserveWhitespace ||
78
+ tagName === "pre" || tagName === "code" ||
79
+ isCDataElement;
80
+ children.push(serializeElement(childElement, preserveWhitespace ? "" : indent + " ", childPreserve));
81
+ }
82
+ else if (child.nodeType === 3) {
83
+ // Text node
84
+ const text = child.textContent || "";
85
+ // Handle CDATA content
86
+ if (isCDataElement && containsCData(text)) {
87
+ // Preserve CDATA as-is
88
+ children.push(text);
89
+ }
90
+ else if (isCDataElement || preserveWhitespace || tagName === "pre" || tagName === "code") {
91
+ // Preserve whitespace in these elements
92
+ children.push(text);
93
+ }
94
+ else {
95
+ // Normal text - trim if only whitespace
96
+ const trimmed = text.trim();
97
+ if (trimmed) {
98
+ children.push(escapeXml(trimmed));
99
+ }
100
+ }
101
+ }
102
+ else if (child.nodeType === 4) {
103
+ // CDATA section node
104
+ const cdataContent = child.textContent || "";
105
+ children.push(`<![CDATA[${cdataContent}]]>`);
106
+ }
107
+ else if (child.nodeType === 8) {
108
+ // Comment node
109
+ children.push(`<!--${child.textContent || ""}-->`);
110
+ }
111
+ }
112
+ // Format output
113
+ if (preserveWhitespace || isCDataElement || !hasElementChildren) {
114
+ // Inline format for text-heavy content
115
+ return `${indent}<${tagName}${attrs}>${children.join("")}</${tagName}>`;
116
+ }
117
+ // Multi-line format for structured content
118
+ const childContent = children.join("\n");
119
+ return `${indent}<${tagName}${attrs}>\n${childContent}\n${indent}</${tagName}>`;
120
+ }
121
+ /**
122
+ * Serialize a DOM Document back to XHTML string
123
+ *
124
+ * @param document - DOM Document to serialize
125
+ * @returns XHTML string (Confluence storage format)
126
+ */
127
+ export function serializeXhtml(document) {
128
+ const needsUnwrap = document.__needsUnwrap;
129
+ const root = getContentRoot(document);
130
+ if (!root) {
131
+ return "";
132
+ }
133
+ if (needsUnwrap) {
134
+ // Serialize children of our wrapper, not the wrapper itself
135
+ const children = [];
136
+ for (const child of root.childNodes) {
137
+ if (child.nodeType === 1) {
138
+ children.push(serializeElement(child));
139
+ }
140
+ else if (child.nodeType === 3) {
141
+ const text = (child.textContent || "").trim();
142
+ if (text) {
143
+ children.push(escapeXml(text));
144
+ }
145
+ }
146
+ }
147
+ return children.join("\n");
148
+ }
149
+ // Serialize the entire document
150
+ return serializeElement(root);
151
+ }
152
+ /**
153
+ * Serialize an element fragment (not a full document)
154
+ */
155
+ export function serializeFragment(element) {
156
+ return serializeElement(element);
157
+ }
158
+ /**
159
+ * Pretty-print XHTML with consistent indentation
160
+ */
161
+ export function prettyPrint(content) {
162
+ // This is a simple implementation - for more complex formatting,
163
+ // we would parse and re-serialize
164
+ return content
165
+ .replace(/>\s*</g, ">\n<")
166
+ .split("\n")
167
+ .map((line) => line)
168
+ .join("\n");
169
+ }
170
+ //# sourceMappingURL=serializer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serializer.js","sourceRoot":"","sources":["../../../src/utils/xhtml/serializer.ts"],"names":[],"mappings":"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"}