legal-markdown-js 3.3.2 → 3.3.4
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/{browser-modern-wM0F4Tg1.js → browser-modern-BP5EJrCS.js} +1727 -1485
- package/dist/browser-modern-BP5EJrCS.js.map +1 -0
- package/dist/cli/interactive/index.js +4 -46
- package/dist/cli/interactive/index.js.map +1 -1
- package/dist/cli/interactive/prompts/file-selector.d.ts +1 -1
- package/dist/cli/interactive/prompts/file-selector.d.ts.map +1 -1
- package/dist/cli/interactive/prompts/file-selector.js +29 -53
- package/dist/cli/interactive/prompts/file-selector.js.map +1 -1
- package/dist/cli/interactive/service.d.ts +7 -2
- package/dist/cli/interactive/service.d.ts.map +1 -1
- package/dist/cli/interactive/service.js +58 -81
- package/dist/cli/interactive/service.js.map +1 -1
- package/dist/cli/service.d.ts +10 -1
- package/dist/cli/service.d.ts.map +1 -1
- package/dist/cli/service.js +52 -92
- package/dist/cli/service.js.map +1 -1
- package/dist/core/pipeline/context-builder.d.ts +138 -0
- package/dist/core/pipeline/context-builder.d.ts.map +1 -0
- package/dist/core/pipeline/context-builder.js +170 -0
- package/dist/core/pipeline/context-builder.js.map +1 -0
- package/dist/core/pipeline/format-generator.d.ts +158 -0
- package/dist/core/pipeline/format-generator.d.ts.map +1 -0
- package/dist/core/pipeline/format-generator.js +368 -0
- package/dist/core/pipeline/format-generator.js.map +1 -0
- package/dist/core/pipeline/index.d.ts +24 -0
- package/dist/core/pipeline/index.d.ts.map +1 -0
- package/dist/core/pipeline/index.js +27 -0
- package/dist/core/pipeline/index.js.map +1 -0
- package/dist/core/processors/clause-processor.d.ts +5 -0
- package/dist/core/processors/clause-processor.d.ts.map +1 -1
- package/dist/core/processors/clause-processor.js +11 -0
- package/dist/core/processors/clause-processor.js.map +1 -1
- package/dist/core/processors/date-processor.d.ts +5 -0
- package/dist/core/processors/date-processor.d.ts.map +1 -1
- package/dist/core/processors/date-processor.js +11 -0
- package/dist/core/processors/date-processor.js.map +1 -1
- package/dist/core/processors/header-processor.d.ts +5 -0
- package/dist/core/processors/header-processor.d.ts.map +1 -1
- package/dist/core/processors/header-processor.js +11 -0
- package/dist/core/processors/header-processor.js.map +1 -1
- package/dist/core/processors/import-processor.d.ts +10 -0
- package/dist/core/processors/import-processor.d.ts.map +1 -1
- package/dist/core/processors/import-processor.js +22 -0
- package/dist/core/processors/import-processor.js.map +1 -1
- package/dist/core/processors/mixin-processor.d.ts +5 -0
- package/dist/core/processors/mixin-processor.d.ts.map +1 -1
- package/dist/core/processors/mixin-processor.js +11 -0
- package/dist/core/processors/mixin-processor.js.map +1 -1
- package/dist/core/processors/reference-processor.d.ts +5 -0
- package/dist/core/processors/reference-processor.d.ts.map +1 -1
- package/dist/core/processors/reference-processor.js +11 -0
- package/dist/core/processors/reference-processor.js.map +1 -1
- package/dist/examples/imports/frontmatter-merging/output/contract-metadata.json +2 -2
- package/dist/examples/imports/frontmatter-merging/output/contract-metadata.yaml +2 -2
- package/dist/examples/imports/frontmatter-merging/templates/output/enterprise-contract-metadata.json +2 -2
- package/dist/examples/imports/frontmatter-merging/templates/output/enterprise-contract-metadata.yaml +2 -2
- package/dist/extensions/generators/html-generator.d.ts +18 -7
- package/dist/extensions/generators/html-generator.d.ts.map +1 -1
- package/dist/extensions/generators/html-generator.js +32 -23
- package/dist/extensions/generators/html-generator.js.map +1 -1
- package/dist/extensions/generators/pdf-generator.d.ts +60 -2
- package/dist/extensions/generators/pdf-generator.d.ts.map +1 -1
- package/dist/extensions/generators/pdf-generator.js +152 -0
- package/dist/extensions/generators/pdf-generator.js.map +1 -1
- package/dist/extensions/remark/legal-markdown-processor.d.ts +8 -2
- package/dist/extensions/remark/legal-markdown-processor.d.ts.map +1 -1
- package/dist/extensions/remark/legal-markdown-processor.js +57 -5
- package/dist/extensions/remark/legal-markdown-processor.js.map +1 -1
- package/dist/force-commands-parser-DDda8v0G.js +441 -0
- package/dist/force-commands-parser-DDda8v0G.js.map +1 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -5
- package/dist/index.js.map +1 -1
- package/dist/legal-markdown-browser.js +1 -1
- package/dist/legal-markdown.umd.min.js +1 -1
- package/dist/legal-markdown.umd.min.js.map +1 -1
- package/dist/plugins/remark/headers.d.ts.map +1 -1
- package/dist/plugins/remark/headers.js +50 -0
- package/dist/plugins/remark/headers.js.map +1 -1
- package/dist/plugins/remark/imports.d.ts +10 -0
- package/dist/plugins/remark/imports.d.ts.map +1 -1
- package/dist/plugins/remark/imports.js +212 -153
- package/dist/plugins/remark/imports.js.map +1 -1
- package/dist/plugins/remark/legal-headers-parser.d.ts.map +1 -1
- package/dist/plugins/remark/legal-headers-parser.js +5 -2
- package/dist/plugins/remark/legal-headers-parser.js.map +1 -1
- package/dist/plugins/remark/plugin-metadata-registry.d.ts +36 -0
- package/dist/plugins/remark/plugin-metadata-registry.d.ts.map +1 -0
- package/dist/plugins/remark/plugin-metadata-registry.js +141 -0
- package/dist/plugins/remark/plugin-metadata-registry.js.map +1 -0
- package/dist/plugins/remark/plugin-order-validator.d.ts +79 -0
- package/dist/plugins/remark/plugin-order-validator.d.ts.map +1 -0
- package/dist/plugins/remark/plugin-order-validator.js +311 -0
- package/dist/plugins/remark/plugin-order-validator.js.map +1 -0
- package/dist/plugins/remark/types.d.ts +165 -0
- package/dist/plugins/remark/types.d.ts.map +1 -0
- package/dist/plugins/remark/types.js +10 -0
- package/dist/plugins/remark/types.js.map +1 -0
- package/dist/types/content-formats.d.ts +169 -0
- package/dist/types/content-formats.d.ts.map +1 -0
- package/dist/types/content-formats.js +178 -0
- package/dist/types/content-formats.js.map +1 -0
- package/dist/types.d.ts +2 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +1 -1
- package/dist/types.js.map +1 -1
- package/dist/web/{browser-modern-wM0F4Tg1.js → browser-modern-BP5EJrCS.js} +1727 -1485
- package/dist/web/browser-modern-BP5EJrCS.js.map +1 -0
- package/dist/web/force-commands-parser-DDda8v0G.js +441 -0
- package/dist/web/force-commands-parser-DDda8v0G.js.map +1 -0
- package/dist/web/index.js.map +1 -1
- package/dist/web/legal-markdown-browser.js +1 -1
- package/dist/web/legal-markdown.umd.min.js +1 -1
- package/dist/web/legal-markdown.umd.min.js.map +1 -1
- package/dist/web/types.js.map +1 -1
- package/package.json +12 -3
- package/scripts/check-confusable-symbols.cjs +159 -0
- package/dist/browser-modern-wM0F4Tg1.js.map +0 -1
- package/dist/cli/interactive/prompts/ftux-handler.d.ts +0 -20
- package/dist/cli/interactive/prompts/ftux-handler.d.ts.map +0 -1
- package/dist/cli/interactive/prompts/ftux-handler.js +0 -406
- package/dist/cli/interactive/prompts/ftux-handler.js.map +0 -1
- package/dist/force-commands-parser-CkTMgF1y.js +0 -204
- package/dist/force-commands-parser-CkTMgF1y.js.map +0 -1
- package/dist/web/browser-modern-wM0F4Tg1.js.map +0 -1
- package/dist/web/force-commands-parser-CkTMgF1y.js +0 -204
- package/dist/web/force-commands-parser-CkTMgF1y.js.map +0 -1
|
@@ -16720,6 +16720,9 @@ function initializeHeaderState() {
|
|
|
16720
16720
|
customLevels: /* @__PURE__ */ new Map()
|
|
16721
16721
|
};
|
|
16722
16722
|
}
|
|
16723
|
+
function getLevelCssClass(level) {
|
|
16724
|
+
return `legal-header-level-${level}`;
|
|
16725
|
+
}
|
|
16723
16726
|
function processHeader(node, config, state, options) {
|
|
16724
16727
|
const { noReset, noIndent, debug } = options;
|
|
16725
16728
|
const level = node.depth;
|
|
@@ -16727,6 +16730,29 @@ function processHeader(node, config, state, options) {
|
|
|
16727
16730
|
updateHeaderState(level, state, noReset);
|
|
16728
16731
|
const number = getHeaderNumber(level, state);
|
|
16729
16732
|
const headerText = formatHeaderText(node, format, number, state, { noIndent, debug });
|
|
16733
|
+
if (!node.data) {
|
|
16734
|
+
node.data = {};
|
|
16735
|
+
}
|
|
16736
|
+
const nodeData = node.data;
|
|
16737
|
+
if (!nodeData.hProperties) {
|
|
16738
|
+
nodeData.hProperties = {};
|
|
16739
|
+
}
|
|
16740
|
+
const cssClass = getLevelCssClass(level);
|
|
16741
|
+
const existingClass = nodeData.hProperties.className;
|
|
16742
|
+
if (existingClass) {
|
|
16743
|
+
if (Array.isArray(existingClass)) {
|
|
16744
|
+
if (!existingClass.includes(cssClass)) {
|
|
16745
|
+
existingClass.push(cssClass);
|
|
16746
|
+
}
|
|
16747
|
+
} else if (typeof existingClass === "string") {
|
|
16748
|
+
const classes = existingClass.split(" ");
|
|
16749
|
+
if (!classes.includes(cssClass)) {
|
|
16750
|
+
nodeData.hProperties.className = [...classes, cssClass];
|
|
16751
|
+
}
|
|
16752
|
+
}
|
|
16753
|
+
} else {
|
|
16754
|
+
nodeData.hProperties.className = cssClass;
|
|
16755
|
+
}
|
|
16730
16756
|
if (headerText !== null) {
|
|
16731
16757
|
const hasIndentation = headerText.startsWith(" ");
|
|
16732
16758
|
if (hasIndentation) {
|
|
@@ -16737,6 +16763,7 @@ function processHeader(node, config, state, options) {
|
|
|
16737
16763
|
}
|
|
16738
16764
|
if (debug) {
|
|
16739
16765
|
console.log(`[remarkHeaders] Processed level ${level} header:`, headerText);
|
|
16766
|
+
console.log(`[remarkHeaders] Added CSS class:`, cssClass);
|
|
16740
16767
|
}
|
|
16741
16768
|
}
|
|
16742
16769
|
function getHeaderFormat(level, config) {
|
|
@@ -17055,16 +17082,16 @@ const remarkClauses = (options) => {
|
|
|
17055
17082
|
}
|
|
17056
17083
|
visit(tree, (node) => {
|
|
17057
17084
|
if (node.type === "text") {
|
|
17058
|
-
processTextNode$
|
|
17085
|
+
processTextNode$1(node, metadata, debug, enableFieldTracking);
|
|
17059
17086
|
} else if (node.type === "html" && "value" in node) {
|
|
17060
17087
|
processHtmlNode(node, metadata, debug, enableFieldTracking);
|
|
17061
17088
|
} else if (node.type === "paragraph") {
|
|
17062
|
-
processParagraphNode$
|
|
17089
|
+
processParagraphNode$1(node, metadata, debug, enableFieldTracking);
|
|
17063
17090
|
}
|
|
17064
17091
|
});
|
|
17065
17092
|
};
|
|
17066
17093
|
};
|
|
17067
|
-
function processTextNode$
|
|
17094
|
+
function processTextNode$1(node, metadata, debug, enableFieldTracking) {
|
|
17068
17095
|
const originalText = node.value;
|
|
17069
17096
|
const conditionalBlocks = extractConditionalBlocks(originalText);
|
|
17070
17097
|
if (debug && originalText.includes("{{#")) {
|
|
@@ -17109,10 +17136,10 @@ function processHtmlNode(node, metadata, debug, enableFieldTracking) {
|
|
|
17109
17136
|
}
|
|
17110
17137
|
node.value = processedHtml;
|
|
17111
17138
|
}
|
|
17112
|
-
function processParagraphNode$
|
|
17139
|
+
function processParagraphNode$1(node, metadata, debug, enableFieldTracking) {
|
|
17113
17140
|
node.children.forEach((child) => {
|
|
17114
17141
|
if (child.type === "text") {
|
|
17115
|
-
processTextNode$
|
|
17142
|
+
processTextNode$1(child, metadata, debug, enableFieldTracking);
|
|
17116
17143
|
}
|
|
17117
17144
|
});
|
|
17118
17145
|
}
|
|
@@ -17845,14 +17872,14 @@ const remarkMixins = (options) => {
|
|
|
17845
17872
|
};
|
|
17846
17873
|
visit(tree, (node) => {
|
|
17847
17874
|
if (node.type === "text") {
|
|
17848
|
-
processTextNode
|
|
17875
|
+
processTextNode(node, context);
|
|
17849
17876
|
} else if (node.type === "paragraph") {
|
|
17850
|
-
processParagraphNode
|
|
17877
|
+
processParagraphNode(node, context);
|
|
17851
17878
|
}
|
|
17852
17879
|
});
|
|
17853
17880
|
};
|
|
17854
17881
|
};
|
|
17855
|
-
function processTextNode
|
|
17882
|
+
function processTextNode(node, context) {
|
|
17856
17883
|
const originalText = node.value;
|
|
17857
17884
|
const mixinDirectives = extractMixinDirectives(originalText);
|
|
17858
17885
|
if (mixinDirectives.length === 0) {
|
|
@@ -17869,10 +17896,10 @@ function processTextNode$1(node, context) {
|
|
|
17869
17896
|
}
|
|
17870
17897
|
node.value = processedText;
|
|
17871
17898
|
}
|
|
17872
|
-
function processParagraphNode
|
|
17899
|
+
function processParagraphNode(node, context) {
|
|
17873
17900
|
node.children.forEach((child) => {
|
|
17874
17901
|
if (child.type === "text") {
|
|
17875
|
-
processTextNode
|
|
17902
|
+
processTextNode(child, context);
|
|
17876
17903
|
}
|
|
17877
17904
|
});
|
|
17878
17905
|
}
|
|
@@ -21023,1623 +21050,1795 @@ function checkNestedConflicts(key, importedValue, currentFlat, logOperations) {
|
|
|
21023
21050
|
return { hasConflict: false, conflictedField: "" };
|
|
21024
21051
|
}
|
|
21025
21052
|
|
|
21026
|
-
|
|
21027
|
-
|
|
21028
|
-
|
|
21029
|
-
|
|
21030
|
-
|
|
21031
|
-
|
|
21032
|
-
|
|
21033
|
-
|
|
21034
|
-
|
|
21035
|
-
|
|
21036
|
-
|
|
21037
|
-
|
|
21038
|
-
|
|
21053
|
+
const remarkImports = (options) => {
|
|
21054
|
+
const {
|
|
21055
|
+
basePath = ".",
|
|
21056
|
+
mergeMetadata = true,
|
|
21057
|
+
debug = false,
|
|
21058
|
+
maxDepth = 10,
|
|
21059
|
+
timeoutMs = 3e4,
|
|
21060
|
+
filterReserved = true,
|
|
21061
|
+
validateTypes = true,
|
|
21062
|
+
logImportOperations = false,
|
|
21063
|
+
onMetadataMerged,
|
|
21064
|
+
importStack = []
|
|
21065
|
+
} = options;
|
|
21066
|
+
return async (tree) => {
|
|
21067
|
+
const startTime = Date.now();
|
|
21068
|
+
if (debug) {
|
|
21069
|
+
console.log("[remarkImports] Processing imports with options:", {
|
|
21070
|
+
basePath,
|
|
21071
|
+
mergeMetadata,
|
|
21072
|
+
maxDepth,
|
|
21073
|
+
timeoutMs,
|
|
21074
|
+
filterReserved,
|
|
21075
|
+
validateTypes,
|
|
21076
|
+
currentDepth: importStack.length
|
|
21077
|
+
});
|
|
21078
|
+
}
|
|
21079
|
+
const context = {
|
|
21080
|
+
depth: importStack.length,
|
|
21081
|
+
maxDepth,
|
|
21082
|
+
basePath,
|
|
21083
|
+
mergeMetadata,
|
|
21084
|
+
debug,
|
|
21085
|
+
startTime,
|
|
21086
|
+
timeoutMs,
|
|
21087
|
+
filterReserved,
|
|
21088
|
+
validateTypes,
|
|
21089
|
+
logImportOperations,
|
|
21090
|
+
onMetadataMerged,
|
|
21091
|
+
importStack: [...importStack],
|
|
21092
|
+
contentCache: /* @__PURE__ */ new Map(),
|
|
21093
|
+
importedMetadataList: [],
|
|
21094
|
+
importedFiles: [],
|
|
21095
|
+
accumulatedMetadata: {}
|
|
21096
|
+
// Initialize with empty metadata
|
|
21097
|
+
};
|
|
21098
|
+
const replacements = [];
|
|
21099
|
+
visit(tree, "paragraph", (node, index, parent) => {
|
|
21100
|
+
if (!parent || index === void 0) return;
|
|
21101
|
+
for (const child of node.children) {
|
|
21102
|
+
if (child.type === "text") {
|
|
21103
|
+
const directives = extractImportDirectives(child.value);
|
|
21104
|
+
if (directives.length > 0) {
|
|
21105
|
+
replacements.push({
|
|
21106
|
+
parent,
|
|
21107
|
+
index,
|
|
21108
|
+
nodes: []
|
|
21109
|
+
// Will be filled in later
|
|
21110
|
+
});
|
|
21111
|
+
return SKIP;
|
|
21112
|
+
}
|
|
21113
|
+
}
|
|
21114
|
+
}
|
|
21115
|
+
});
|
|
21116
|
+
for (const replacement of replacements) {
|
|
21117
|
+
const paragraph = replacement.parent.children[replacement.index];
|
|
21118
|
+
const processedNodes = await processParagraphWithImports(paragraph, context);
|
|
21119
|
+
replacement.nodes = processedNodes;
|
|
21120
|
+
}
|
|
21121
|
+
for (let i = replacements.length - 1; i >= 0; i--) {
|
|
21122
|
+
const { parent, index, nodes } = replacements[i];
|
|
21123
|
+
parent.children.splice(index, 1, ...nodes);
|
|
21124
|
+
}
|
|
21125
|
+
if (context.mergeMetadata && context.importedMetadataList.length > 0) {
|
|
21126
|
+
const mergedResult = performSequentialMerge(context);
|
|
21127
|
+
tree._importedMetadata = mergedResult.metadata;
|
|
21128
|
+
tree._importStats = mergedResult.stats;
|
|
21129
|
+
}
|
|
21130
|
+
};
|
|
21131
|
+
};
|
|
21132
|
+
async function processParagraphWithImports(paragraph, context) {
|
|
21133
|
+
const results = [];
|
|
21134
|
+
for (const child of paragraph.children) {
|
|
21135
|
+
if (child.type !== "text") {
|
|
21136
|
+
results.push(child);
|
|
21137
|
+
continue;
|
|
21138
|
+
}
|
|
21139
|
+
const text = child.value;
|
|
21140
|
+
const directives = extractImportDirectives(text);
|
|
21141
|
+
if (directives.length === 0) {
|
|
21142
|
+
results.push(child);
|
|
21143
|
+
continue;
|
|
21144
|
+
}
|
|
21145
|
+
if (context.debug) {
|
|
21146
|
+
console.log(`[remarkImports] Found ${directives.length} import directives`);
|
|
21147
|
+
}
|
|
21148
|
+
let lastIndex = 0;
|
|
21149
|
+
for (const directive of directives) {
|
|
21150
|
+
if (directive.start > lastIndex) {
|
|
21151
|
+
const beforeText = text.substring(lastIndex, directive.start);
|
|
21152
|
+
if (beforeText.trim()) {
|
|
21153
|
+
results.push({
|
|
21154
|
+
type: "text",
|
|
21155
|
+
value: beforeText
|
|
21156
|
+
});
|
|
21157
|
+
}
|
|
21158
|
+
}
|
|
21159
|
+
const importedNodes = await processImportDirectiveToAST(directive, context);
|
|
21160
|
+
results.push(...importedNodes);
|
|
21161
|
+
lastIndex = directive.end;
|
|
21162
|
+
}
|
|
21163
|
+
if (lastIndex < text.length) {
|
|
21164
|
+
const afterText = text.substring(lastIndex);
|
|
21165
|
+
if (afterText.trim()) {
|
|
21166
|
+
results.push({
|
|
21167
|
+
type: "text",
|
|
21168
|
+
value: afterText
|
|
21169
|
+
});
|
|
21170
|
+
}
|
|
21171
|
+
}
|
|
21039
21172
|
}
|
|
21040
|
-
return
|
|
21173
|
+
return results;
|
|
21041
21174
|
}
|
|
21042
|
-
function
|
|
21043
|
-
const
|
|
21044
|
-
const
|
|
21045
|
-
const conditionalPattern = /\{\{#if\s*([^}]+)\}\}([\s\S]*?)\{\{\/if\}\}/g;
|
|
21175
|
+
function extractImportDirectives(text) {
|
|
21176
|
+
const directives = [];
|
|
21177
|
+
const importRegex = /@import\s+([^\s#]+)(?:#([^\s]+))?/g;
|
|
21046
21178
|
let match;
|
|
21047
|
-
while ((match =
|
|
21048
|
-
const [fullMatch,
|
|
21049
|
-
|
|
21050
|
-
|
|
21051
|
-
|
|
21052
|
-
start: match.index,
|
|
21053
|
-
end: match.index + fullMatch.length,
|
|
21054
|
-
fullMatch
|
|
21055
|
-
});
|
|
21056
|
-
}
|
|
21057
|
-
while ((match = conditionalPattern.exec(content)) !== null) {
|
|
21058
|
-
const [fullMatch, condition, conditionalContent] = match;
|
|
21059
|
-
loopBlocks.push({
|
|
21060
|
-
variable: `if ${condition}`,
|
|
21061
|
-
// Mark as conditional
|
|
21062
|
-
content: conditionalContent,
|
|
21179
|
+
while ((match = importRegex.exec(text)) !== null) {
|
|
21180
|
+
const [fullMatch, filePath, section] = match;
|
|
21181
|
+
directives.push({
|
|
21182
|
+
filePath: filePath.trim(),
|
|
21183
|
+
section: section?.trim(),
|
|
21063
21184
|
start: match.index,
|
|
21064
21185
|
end: match.index + fullMatch.length,
|
|
21065
21186
|
fullMatch
|
|
21066
21187
|
});
|
|
21067
21188
|
}
|
|
21068
|
-
return
|
|
21189
|
+
return directives;
|
|
21069
21190
|
}
|
|
21070
|
-
function
|
|
21071
|
-
const
|
|
21072
|
-
|
|
21073
|
-
|
|
21074
|
-
|
|
21075
|
-
|
|
21076
|
-
|
|
21077
|
-
|
|
21078
|
-
|
|
21079
|
-
|
|
21080
|
-
|
|
21081
|
-
|
|
21082
|
-
|
|
21083
|
-
|
|
21084
|
-
|
|
21085
|
-
|
|
21086
|
-
|
|
21087
|
-
|
|
21088
|
-
|
|
21089
|
-
|
|
21090
|
-
|
|
21191
|
+
async function parseImportedContentToAST(content) {
|
|
21192
|
+
const processor = unified().use(remarkParse);
|
|
21193
|
+
const tree = processor.parse(content);
|
|
21194
|
+
return tree.children;
|
|
21195
|
+
}
|
|
21196
|
+
async function processImportDirectiveToAST(directive, context) {
|
|
21197
|
+
if (context.depth >= context.maxDepth) {
|
|
21198
|
+
console.warn(
|
|
21199
|
+
`[remarkImports] Maximum import depth (${context.maxDepth}) reached for file "${directive.filePath}"`
|
|
21200
|
+
);
|
|
21201
|
+
return [{ type: "text", value: directive.fullMatch }];
|
|
21202
|
+
}
|
|
21203
|
+
const absolutePath = pathBrowserifyExports.resolve(context.basePath, directive.filePath);
|
|
21204
|
+
const normalizedPath = pathBrowserifyExports.normalize(absolutePath);
|
|
21205
|
+
if (context.importStack.includes(normalizedPath)) {
|
|
21206
|
+
console.warn(`[remarkImports] Circular import detected: ${normalizedPath}`);
|
|
21207
|
+
return [{ type: "text", value: directive.fullMatch }];
|
|
21208
|
+
}
|
|
21209
|
+
if (context.debug) {
|
|
21210
|
+
console.log(
|
|
21211
|
+
`[remarkImports] Processing import "${directive.filePath}" (resolved: ${normalizedPath})`
|
|
21212
|
+
);
|
|
21213
|
+
}
|
|
21214
|
+
const fileContent = loadFileContent(normalizedPath, context);
|
|
21215
|
+
if (!fileContent) {
|
|
21216
|
+
console.warn(`[remarkImports] Import file not found: ${directive.filePath}`);
|
|
21217
|
+
return [{ type: "text", value: directive.fullMatch }];
|
|
21218
|
+
}
|
|
21219
|
+
let contentToImport = fileContent;
|
|
21220
|
+
if (context.mergeMetadata) {
|
|
21221
|
+
const { content, metadata } = parseYamlFrontMatter(fileContent, false);
|
|
21222
|
+
contentToImport = content;
|
|
21223
|
+
if (Object.keys(metadata).length > 0) {
|
|
21224
|
+
context.importedMetadataList.push({
|
|
21225
|
+
metadata,
|
|
21226
|
+
source: normalizedPath
|
|
21227
|
+
});
|
|
21228
|
+
context.accumulatedMetadata = {
|
|
21229
|
+
...context.accumulatedMetadata,
|
|
21230
|
+
...metadata
|
|
21231
|
+
};
|
|
21232
|
+
if (!context.importedFiles.includes(normalizedPath)) {
|
|
21233
|
+
context.importedFiles.push(normalizedPath);
|
|
21234
|
+
}
|
|
21235
|
+
if (context.debug) {
|
|
21236
|
+
console.log(
|
|
21237
|
+
`[remarkImports] Collected metadata from ${directive.filePath}:`,
|
|
21238
|
+
Object.keys(metadata)
|
|
21239
|
+
);
|
|
21091
21240
|
}
|
|
21092
21241
|
}
|
|
21093
21242
|
}
|
|
21094
|
-
|
|
21095
|
-
|
|
21096
|
-
|
|
21097
|
-
|
|
21098
|
-
|
|
21099
|
-
|
|
21100
|
-
|
|
21101
|
-
|
|
21102
|
-
|
|
21103
|
-
|
|
21104
|
-
|
|
21105
|
-
|
|
21106
|
-
|
|
21107
|
-
enableFieldTracking
|
|
21108
|
-
);
|
|
21109
|
-
} else if (loopValue) {
|
|
21110
|
-
return expandConditionalBlock(
|
|
21111
|
-
variable,
|
|
21112
|
-
content,
|
|
21113
|
-
loopValue,
|
|
21114
|
-
metadata,
|
|
21115
|
-
parentContext,
|
|
21116
|
-
enableFieldTracking
|
|
21117
|
-
);
|
|
21118
|
-
} else {
|
|
21119
|
-
return "";
|
|
21243
|
+
if (directive.section) {
|
|
21244
|
+
contentToImport = extractSection(contentToImport, directive.section, context.debug);
|
|
21245
|
+
}
|
|
21246
|
+
const nestedContext = {
|
|
21247
|
+
...context,
|
|
21248
|
+
depth: context.depth + 1,
|
|
21249
|
+
importStack: [...context.importStack, normalizedPath],
|
|
21250
|
+
basePath: pathBrowserifyExports.dirname(normalizedPath)
|
|
21251
|
+
// Update base path for relative imports
|
|
21252
|
+
};
|
|
21253
|
+
const processedContent = await processNestedImportsToAST(contentToImport, nestedContext);
|
|
21254
|
+
if (context.mergeMetadata && Object.keys(context.accumulatedMetadata).length > 0) {
|
|
21255
|
+
return await expandMixinsInAST(processedContent, context.accumulatedMetadata);
|
|
21120
21256
|
}
|
|
21257
|
+
return processedContent;
|
|
21121
21258
|
}
|
|
21122
|
-
function
|
|
21123
|
-
|
|
21124
|
-
|
|
21125
|
-
|
|
21126
|
-
|
|
21127
|
-
variable,
|
|
21128
|
-
item,
|
|
21129
|
-
index: i,
|
|
21130
|
-
total: items.length,
|
|
21131
|
-
parent: parentContext
|
|
21259
|
+
function performSequentialMerge(context) {
|
|
21260
|
+
if (context.importedMetadataList.length === 0) {
|
|
21261
|
+
return {
|
|
21262
|
+
metadata: {},
|
|
21263
|
+
stats: void 0
|
|
21132
21264
|
};
|
|
21133
|
-
|
|
21134
|
-
|
|
21135
|
-
|
|
21136
|
-
|
|
21137
|
-
enhancedMetadata,
|
|
21138
|
-
loopContext,
|
|
21139
|
-
enableFieldTracking
|
|
21265
|
+
}
|
|
21266
|
+
if (Date.now() - context.startTime > context.timeoutMs) {
|
|
21267
|
+
throw new Error(
|
|
21268
|
+
`Import processing timed out after ${context.timeoutMs}ms. This may indicate complex nested imports or slow file operations.`
|
|
21140
21269
|
);
|
|
21141
|
-
processedContent = processItemMixins(
|
|
21142
|
-
processedContent,
|
|
21143
|
-
enhancedMetadata,
|
|
21144
|
-
loopContext,
|
|
21145
|
-
enableFieldTracking
|
|
21146
|
-
);
|
|
21147
|
-
processedContent = convertMarkdownListToHtml(processedContent);
|
|
21148
|
-
expandedParts.push(processedContent);
|
|
21149
21270
|
}
|
|
21150
|
-
|
|
21151
|
-
|
|
21152
|
-
|
|
21153
|
-
|
|
21154
|
-
|
|
21155
|
-
|
|
21271
|
+
const mergeOptions = {
|
|
21272
|
+
filterReserved: context.filterReserved,
|
|
21273
|
+
validateTypes: context.validateTypes,
|
|
21274
|
+
logOperations: context.logImportOperations,
|
|
21275
|
+
includeStats: true,
|
|
21276
|
+
timeoutMs: Math.max(1e3, context.timeoutMs - (Date.now() - context.startTime))
|
|
21156
21277
|
};
|
|
21157
|
-
|
|
21158
|
-
|
|
21159
|
-
|
|
21160
|
-
|
|
21161
|
-
|
|
21162
|
-
);
|
|
21163
|
-
processedContent = processItemMixins(
|
|
21164
|
-
processedContent,
|
|
21165
|
-
enhancedMetadata,
|
|
21166
|
-
parentContext,
|
|
21167
|
-
enableFieldTracking
|
|
21168
|
-
);
|
|
21169
|
-
return processedContent;
|
|
21170
|
-
}
|
|
21171
|
-
function resolveLoopVariable(variable, metadata, parentContext) {
|
|
21172
|
-
const resolvedFromMetadata = resolvePath(metadata, variable);
|
|
21173
|
-
if (resolvedFromMetadata !== void 0) {
|
|
21174
|
-
return resolvedFromMetadata;
|
|
21278
|
+
const metadataList = context.importedMetadataList.map((item) => item.metadata);
|
|
21279
|
+
if (context.debug) {
|
|
21280
|
+
console.log(
|
|
21281
|
+
`[remarkImports] Performing sequential merge of ${metadataList.length} metadata objects`
|
|
21282
|
+
);
|
|
21175
21283
|
}
|
|
21176
|
-
|
|
21177
|
-
const
|
|
21178
|
-
if (
|
|
21179
|
-
|
|
21284
|
+
try {
|
|
21285
|
+
const result = mergeSequentially({}, metadataList, mergeOptions);
|
|
21286
|
+
if (context.onMetadataMerged && Object.keys(result.metadata).length > 0) {
|
|
21287
|
+
context.onMetadataMerged(result.metadata, "merged-imports");
|
|
21180
21288
|
}
|
|
21181
|
-
|
|
21182
|
-
|
|
21183
|
-
|
|
21184
|
-
|
|
21185
|
-
if (ctx.item) {
|
|
21186
|
-
const resolvedFromNestedContext = resolvePath(ctx.item, variable);
|
|
21187
|
-
if (resolvedFromNestedContext !== void 0) {
|
|
21188
|
-
return resolvedFromNestedContext;
|
|
21189
|
-
}
|
|
21289
|
+
return result;
|
|
21290
|
+
} catch (error) {
|
|
21291
|
+
if (context.debug) {
|
|
21292
|
+
console.warn("[remarkImports] Sequential merge failed:", error);
|
|
21190
21293
|
}
|
|
21294
|
+
throw error;
|
|
21191
21295
|
}
|
|
21192
|
-
return void 0;
|
|
21193
21296
|
}
|
|
21194
|
-
function
|
|
21195
|
-
|
|
21196
|
-
|
|
21197
|
-
Object.assign(enhanced, item);
|
|
21297
|
+
function loadFileContent(filePath, context) {
|
|
21298
|
+
if (context.contentCache.has(filePath)) {
|
|
21299
|
+
return context.contentCache.get(filePath);
|
|
21198
21300
|
}
|
|
21199
|
-
enhanced["."] = item;
|
|
21200
|
-
enhanced["@index"] = context.index;
|
|
21201
|
-
enhanced["@total"] = context.total;
|
|
21202
|
-
enhanced["@first"] = context.index === 0;
|
|
21203
|
-
enhanced["@last"] = context.index === context.total - 1;
|
|
21204
|
-
return enhanced;
|
|
21205
|
-
}
|
|
21206
|
-
function evaluateHelperExpression(expression, metadata) {
|
|
21207
21301
|
try {
|
|
21208
|
-
|
|
21209
|
-
if (!match) return void 0;
|
|
21210
|
-
const [, helperName, argsString] = match;
|
|
21211
|
-
const helper = extensionHelpers[helperName];
|
|
21212
|
-
if (!helper || typeof helper !== "function") {
|
|
21213
|
-
return void 0;
|
|
21214
|
-
}
|
|
21215
|
-
const args = argsString ? parseHelperArguments(argsString, metadata) : [];
|
|
21216
|
-
return helper(...args);
|
|
21302
|
+
if (existsSync(filePath)) ;
|
|
21217
21303
|
} catch (error) {
|
|
21218
|
-
|
|
21219
|
-
|
|
21220
|
-
}
|
|
21221
|
-
}
|
|
21222
|
-
function parseHelperArguments(argsString, metadata) {
|
|
21223
|
-
const args = [];
|
|
21224
|
-
let currentArg = "";
|
|
21225
|
-
let parenDepth = 0;
|
|
21226
|
-
let inQuotes = false;
|
|
21227
|
-
let quoteChar = "";
|
|
21228
|
-
for (let i = 0; i < argsString.length; i++) {
|
|
21229
|
-
const char = argsString[i];
|
|
21230
|
-
if ((char === '"' || char === "'") && !inQuotes) {
|
|
21231
|
-
inQuotes = true;
|
|
21232
|
-
quoteChar = char;
|
|
21233
|
-
currentArg += char;
|
|
21234
|
-
} else if (char === quoteChar && inQuotes) {
|
|
21235
|
-
inQuotes = false;
|
|
21236
|
-
quoteChar = "";
|
|
21237
|
-
currentArg += char;
|
|
21238
|
-
} else if (char === "(" && !inQuotes) {
|
|
21239
|
-
parenDepth++;
|
|
21240
|
-
currentArg += char;
|
|
21241
|
-
} else if (char === ")" && !inQuotes) {
|
|
21242
|
-
parenDepth--;
|
|
21243
|
-
currentArg += char;
|
|
21244
|
-
} else if (char === "," && parenDepth === 0 && !inQuotes) {
|
|
21245
|
-
args.push(resolveHelperArgument(currentArg.trim(), metadata));
|
|
21246
|
-
currentArg = "";
|
|
21247
|
-
} else {
|
|
21248
|
-
currentArg += char;
|
|
21304
|
+
if (context.debug) {
|
|
21305
|
+
console.warn(`[remarkImports] Failed to load import file "${filePath}":`, error);
|
|
21249
21306
|
}
|
|
21250
21307
|
}
|
|
21251
|
-
|
|
21252
|
-
args.push(resolveHelperArgument(currentArg.trim(), metadata));
|
|
21253
|
-
}
|
|
21254
|
-
return args;
|
|
21308
|
+
return null;
|
|
21255
21309
|
}
|
|
21256
|
-
function
|
|
21257
|
-
|
|
21258
|
-
|
|
21259
|
-
|
|
21260
|
-
|
|
21261
|
-
|
|
21262
|
-
|
|
21263
|
-
|
|
21264
|
-
|
|
21265
|
-
|
|
21266
|
-
|
|
21310
|
+
function extractSection(content, sectionName, debug) {
|
|
21311
|
+
const lines = content.split("\n");
|
|
21312
|
+
let sectionStart = -1;
|
|
21313
|
+
let sectionEnd = lines.length;
|
|
21314
|
+
let sectionLevel = 0;
|
|
21315
|
+
for (let i = 0; i < lines.length; i++) {
|
|
21316
|
+
const line = lines[i].trim();
|
|
21317
|
+
const headerMatch = line.match(/^(#{1,6})\s+(.+)$/);
|
|
21318
|
+
if (headerMatch) {
|
|
21319
|
+
const [, hashes, title] = headerMatch;
|
|
21320
|
+
const level = hashes.length;
|
|
21321
|
+
if (title.toLowerCase() === sectionName.toLowerCase()) {
|
|
21322
|
+
sectionStart = i + 1;
|
|
21323
|
+
sectionLevel = level;
|
|
21324
|
+
if (debug) {
|
|
21325
|
+
console.log(`[remarkImports] Found section '${sectionName}' at line ${i}`);
|
|
21326
|
+
}
|
|
21327
|
+
break;
|
|
21328
|
+
}
|
|
21329
|
+
}
|
|
21267
21330
|
}
|
|
21268
|
-
if (
|
|
21269
|
-
|
|
21331
|
+
if (sectionStart === -1) {
|
|
21332
|
+
if (debug) {
|
|
21333
|
+
console.warn(`[remarkImports] Section '${sectionName}' not found`);
|
|
21334
|
+
}
|
|
21335
|
+
return content;
|
|
21270
21336
|
}
|
|
21271
|
-
|
|
21272
|
-
const
|
|
21273
|
-
|
|
21274
|
-
|
|
21337
|
+
for (let i = sectionStart; i < lines.length; i++) {
|
|
21338
|
+
const line = lines[i].trim();
|
|
21339
|
+
const headerMatch = line.match(/^(#{1,6})\s+(.+)$/);
|
|
21340
|
+
if (headerMatch) {
|
|
21341
|
+
const [, hashes] = headerMatch;
|
|
21342
|
+
const level = hashes.length;
|
|
21343
|
+
if (level <= sectionLevel) {
|
|
21344
|
+
sectionEnd = i;
|
|
21345
|
+
break;
|
|
21346
|
+
}
|
|
21275
21347
|
}
|
|
21276
21348
|
}
|
|
21277
|
-
return
|
|
21349
|
+
return lines.slice(sectionStart, sectionEnd).join("\n").trim();
|
|
21278
21350
|
}
|
|
21279
|
-
function
|
|
21280
|
-
const
|
|
21281
|
-
|
|
21282
|
-
|
|
21283
|
-
|
|
21284
|
-
|
|
21351
|
+
async function processNestedImportsToAST(content, context) {
|
|
21352
|
+
const nodes = await parseImportedContentToAST(content);
|
|
21353
|
+
const hasImports = nodes.some((node) => {
|
|
21354
|
+
if (node.type === "paragraph") {
|
|
21355
|
+
return node.children.some(
|
|
21356
|
+
(child) => child.type === "text" && extractImportDirectives(child.value).length > 0
|
|
21357
|
+
);
|
|
21358
|
+
}
|
|
21359
|
+
return false;
|
|
21360
|
+
});
|
|
21361
|
+
if (!hasImports) {
|
|
21362
|
+
return nodes;
|
|
21363
|
+
}
|
|
21364
|
+
const processedNodes = [];
|
|
21365
|
+
for (const node of nodes) {
|
|
21366
|
+
if (node.type === "paragraph") {
|
|
21367
|
+
const paragraph = node;
|
|
21368
|
+
const hasDirectives = paragraph.children.some(
|
|
21369
|
+
(child) => child.type === "text" && extractImportDirectives(child.value).length > 0
|
|
21370
|
+
);
|
|
21371
|
+
if (hasDirectives) {
|
|
21372
|
+
const importedNodes = await processParagraphWithImports(paragraph, context);
|
|
21373
|
+
processedNodes.push(...importedNodes);
|
|
21374
|
+
} else {
|
|
21375
|
+
processedNodes.push(node);
|
|
21376
|
+
}
|
|
21285
21377
|
} else {
|
|
21286
|
-
|
|
21378
|
+
processedNodes.push(node);
|
|
21287
21379
|
}
|
|
21288
21380
|
}
|
|
21289
|
-
return
|
|
21381
|
+
return processedNodes;
|
|
21290
21382
|
}
|
|
21291
|
-
function
|
|
21292
|
-
const
|
|
21293
|
-
|
|
21294
|
-
|
|
21295
|
-
|
|
21296
|
-
const
|
|
21297
|
-
|
|
21298
|
-
|
|
21299
|
-
|
|
21300
|
-
|
|
21301
|
-
|
|
21302
|
-
if (trimmedVar.includes("(") && trimmedVar.includes(")")) {
|
|
21303
|
-
const result = evaluateHelperExpression(trimmedVar, metadata);
|
|
21304
|
-
if (result !== void 0) {
|
|
21305
|
-
fieldTracker.trackField(trimmedVar, {
|
|
21306
|
-
value: result,
|
|
21307
|
-
hasLogic: true,
|
|
21308
|
-
mixinUsed: "helper"
|
|
21309
|
-
});
|
|
21310
|
-
if (enableFieldTracking) {
|
|
21311
|
-
const escapedField = escapeHtmlAttribute$1(trimmedVar);
|
|
21312
|
-
const stringResult = String(result);
|
|
21313
|
-
return `<span class="highlight"><span class="imported-value" data-field="${escapedField}">${stringResult}</span></span>`;
|
|
21383
|
+
async function expandMixinsInAST(nodes, metadata) {
|
|
21384
|
+
const processedNodes = [];
|
|
21385
|
+
for (const node of nodes) {
|
|
21386
|
+
if (node.type === "paragraph") {
|
|
21387
|
+
const paragraph = node;
|
|
21388
|
+
const processedChildren = [];
|
|
21389
|
+
for (const child of paragraph.children) {
|
|
21390
|
+
if (child.type === "text") {
|
|
21391
|
+
processedChildren.push(child);
|
|
21392
|
+
} else {
|
|
21393
|
+
processedChildren.push(child);
|
|
21314
21394
|
}
|
|
21315
|
-
return String(result);
|
|
21316
|
-
}
|
|
21317
|
-
}
|
|
21318
|
-
const value = resolveVariablePath(trimmedVar, metadata);
|
|
21319
|
-
if (value === void 0 || value === null) {
|
|
21320
|
-
if (enableFieldTracking) {
|
|
21321
|
-
return `<span class="legal-field missing-value" data-field="${escapeHtmlAttribute$1(trimmedVar)}">[[${trimmedVar}]]</span>`;
|
|
21322
21395
|
}
|
|
21323
|
-
|
|
21324
|
-
|
|
21325
|
-
|
|
21326
|
-
|
|
21327
|
-
}
|
|
21328
|
-
|
|
21329
|
-
});
|
|
21330
|
-
}
|
|
21331
|
-
function processConditionalExpression(expression, metadata, enableFieldTracking = true) {
|
|
21332
|
-
const questionIndex = findOperatorIndex(expression, "?");
|
|
21333
|
-
const colonIndex = findOperatorIndex(expression, ":", questionIndex);
|
|
21334
|
-
if (questionIndex === -1 || colonIndex === -1) {
|
|
21335
|
-
return expression;
|
|
21336
|
-
}
|
|
21337
|
-
const condition = expression.substring(0, questionIndex).trim();
|
|
21338
|
-
const truePart = expression.substring(questionIndex + 1, colonIndex).trim();
|
|
21339
|
-
const falsePart = expression.substring(colonIndex + 1).trim();
|
|
21340
|
-
const conditionValue = resolveVariablePath(condition, metadata);
|
|
21341
|
-
const selectedPart = conditionValue ? truePart : falsePart;
|
|
21342
|
-
if (selectedPart.startsWith('"') && selectedPart.endsWith('"') || // eslint-disable-next-line quotes
|
|
21343
|
-
selectedPart.startsWith("'") && selectedPart.endsWith("'")) {
|
|
21344
|
-
const unquotedValue = selectedPart.slice(1, -1);
|
|
21345
|
-
if (enableFieldTracking) {
|
|
21346
|
-
return `<span class="imported-value" data-field="${escapeHtmlAttribute$1(expression)}">${unquotedValue}</span>`;
|
|
21396
|
+
processedNodes.push({
|
|
21397
|
+
...paragraph,
|
|
21398
|
+
children: processedChildren
|
|
21399
|
+
});
|
|
21400
|
+
} else {
|
|
21401
|
+
processedNodes.push(node);
|
|
21347
21402
|
}
|
|
21348
|
-
return unquotedValue;
|
|
21349
21403
|
}
|
|
21350
|
-
|
|
21351
|
-
if (enableFieldTracking) {
|
|
21352
|
-
return `<span class="imported-value" data-field="${escapeHtmlAttribute$1(expression)}">${processedValue}</span>`;
|
|
21353
|
-
}
|
|
21354
|
-
return processedValue;
|
|
21404
|
+
return processedNodes;
|
|
21355
21405
|
}
|
|
21356
|
-
|
|
21357
|
-
|
|
21358
|
-
|
|
21359
|
-
|
|
21360
|
-
const char = expression[i];
|
|
21361
|
-
if (!inQuotes && (char === '"' || char === "'")) {
|
|
21362
|
-
inQuotes = true;
|
|
21363
|
-
quoteChar = char;
|
|
21364
|
-
} else if (inQuotes && char === quoteChar) {
|
|
21365
|
-
inQuotes = false;
|
|
21366
|
-
quoteChar = "";
|
|
21367
|
-
} else if (!inQuotes && char === operator) {
|
|
21368
|
-
return i;
|
|
21369
|
-
}
|
|
21370
|
-
}
|
|
21371
|
-
return -1;
|
|
21372
|
-
}
|
|
21373
|
-
function processExpression(expression, metadata) {
|
|
21374
|
-
if (expression.includes("+") && (expression.includes('"') || expression.includes("'"))) {
|
|
21375
|
-
return evaluateStringConcatenation(expression, metadata);
|
|
21376
|
-
}
|
|
21377
|
-
if (expression.includes("*") || expression.includes("/") || expression.includes("+") || expression.includes("-")) {
|
|
21378
|
-
return evaluateMathematicalExpression(expression, metadata);
|
|
21379
|
-
}
|
|
21380
|
-
const value = resolveVariablePath(expression, metadata);
|
|
21381
|
-
return value !== void 0 ? String(value) : expression;
|
|
21382
|
-
}
|
|
21383
|
-
function evaluateStringConcatenation(expression, metadata) {
|
|
21384
|
-
try {
|
|
21385
|
-
let processedExpression = expression.trim();
|
|
21386
|
-
const variablePattern = /\b[a-zA-Z_][a-zA-Z0-9_.]*\b/g;
|
|
21387
|
-
const variables = /* @__PURE__ */ new Set();
|
|
21388
|
-
let match;
|
|
21389
|
-
let inQuotes = false;
|
|
21390
|
-
let quoteChar = "";
|
|
21391
|
-
for (let i = 0; i < expression.length; i++) {
|
|
21392
|
-
const char = expression[i];
|
|
21393
|
-
if (!inQuotes && (char === '"' || char === "'")) {
|
|
21394
|
-
inQuotes = true;
|
|
21395
|
-
quoteChar = char;
|
|
21396
|
-
} else if (inQuotes && char === quoteChar) {
|
|
21397
|
-
inQuotes = false;
|
|
21398
|
-
quoteChar = "";
|
|
21399
|
-
}
|
|
21400
|
-
}
|
|
21401
|
-
while ((match = variablePattern.exec(expression)) !== null) {
|
|
21402
|
-
const beforeMatch = expression.substring(0, match.index);
|
|
21403
|
-
const openQuotes = (beforeMatch.match(/"/g) || []).length;
|
|
21404
|
-
const openSingleQuotes = (beforeMatch.match(/'/g) || []).length;
|
|
21405
|
-
if (openQuotes % 2 === 0 && openSingleQuotes % 2 === 0) {
|
|
21406
|
-
variables.add(match[0]);
|
|
21407
|
-
}
|
|
21408
|
-
}
|
|
21409
|
-
for (const variable of variables) {
|
|
21410
|
-
const value = resolveVariablePath(variable, metadata);
|
|
21411
|
-
if (value !== void 0) {
|
|
21412
|
-
const regex = new RegExp(`\\b${variable.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\\b`, "g");
|
|
21413
|
-
if (typeof value === "string") {
|
|
21414
|
-
processedExpression = processedExpression.replace(regex, `"${value}"`);
|
|
21415
|
-
} else {
|
|
21416
|
-
processedExpression = processedExpression.replace(regex, String(value));
|
|
21417
|
-
}
|
|
21418
|
-
} else {
|
|
21419
|
-
return expression;
|
|
21420
|
-
}
|
|
21421
|
-
}
|
|
21422
|
-
const result = new Function(`"use strict"; return (${processedExpression})`)();
|
|
21423
|
-
return String(result);
|
|
21424
|
-
} catch (error) {
|
|
21425
|
-
return expression;
|
|
21426
|
-
}
|
|
21406
|
+
|
|
21407
|
+
const LEGAL_HEADER_PATTERN = /^(l{1,9})\.\s+(.+)$/;
|
|
21408
|
+
function getHeadingLevel(pattern) {
|
|
21409
|
+
return pattern.length;
|
|
21427
21410
|
}
|
|
21428
|
-
function
|
|
21429
|
-
|
|
21430
|
-
|
|
21431
|
-
const
|
|
21432
|
-
|
|
21433
|
-
|
|
21434
|
-
|
|
21435
|
-
|
|
21436
|
-
|
|
21437
|
-
|
|
21438
|
-
const value = resolveVariablePath(variable, metadata);
|
|
21439
|
-
if (value !== void 0 && !isNaN(Number(value))) {
|
|
21440
|
-
const regex = new RegExp(`\\b${variable.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\\b`, "g");
|
|
21441
|
-
processedExpression = processedExpression.replace(regex, String(value));
|
|
21442
|
-
} else {
|
|
21443
|
-
return expression;
|
|
21444
|
-
}
|
|
21445
|
-
}
|
|
21446
|
-
if (!/^[\d\s+\-*/().]+$/.test(processedExpression)) {
|
|
21447
|
-
return expression;
|
|
21411
|
+
function isLegalHeader(node) {
|
|
21412
|
+
if (node.children.length === 1 && node.children[0].type === "text") {
|
|
21413
|
+
const textNode = node.children[0];
|
|
21414
|
+
const match = textNode.value.match(LEGAL_HEADER_PATTERN);
|
|
21415
|
+
if (match) {
|
|
21416
|
+
const [, levelPattern, headerText] = match;
|
|
21417
|
+
return {
|
|
21418
|
+
level: getHeadingLevel(levelPattern),
|
|
21419
|
+
text: headerText.trim()
|
|
21420
|
+
};
|
|
21448
21421
|
}
|
|
21449
|
-
const result = new Function(`"use strict"; return (${processedExpression})`)();
|
|
21450
|
-
return typeof result === "number" && !isNaN(result) ? String(result) : expression;
|
|
21451
|
-
} catch (error) {
|
|
21452
|
-
return expression;
|
|
21453
21422
|
}
|
|
21454
|
-
|
|
21455
|
-
|
|
21456
|
-
|
|
21457
|
-
|
|
21458
|
-
|
|
21459
|
-
|
|
21460
|
-
|
|
21461
|
-
|
|
21462
|
-
|
|
21463
|
-
|
|
21464
|
-
|
|
21465
|
-
return
|
|
21423
|
+
if (node.children.length > 0 && node.children[0].type === "text") {
|
|
21424
|
+
const firstChild = node.children[0];
|
|
21425
|
+
const match = firstChild.value.match(/^(l{1,5})\.\s*/);
|
|
21426
|
+
if (match) {
|
|
21427
|
+
const [fullMatch, levelPattern] = match;
|
|
21428
|
+
const remainingText = firstChild.value.slice(fullMatch.length);
|
|
21429
|
+
const otherText = node.children.slice(1).map((child) => {
|
|
21430
|
+
if (child.type === "text") return child.value;
|
|
21431
|
+
if (child.type === "html") return child.value || "";
|
|
21432
|
+
return "";
|
|
21433
|
+
}).join("");
|
|
21434
|
+
return {
|
|
21435
|
+
level: getHeadingLevel(levelPattern),
|
|
21436
|
+
text: (remainingText + otherText).trim()
|
|
21437
|
+
};
|
|
21466
21438
|
}
|
|
21467
21439
|
}
|
|
21468
|
-
return
|
|
21469
|
-
}
|
|
21470
|
-
function convertMarkdownListToHtml(content) {
|
|
21471
|
-
const trimmedContent = content.trim();
|
|
21472
|
-
if (trimmedContent.startsWith("- ")) {
|
|
21473
|
-
const listItemContent = trimmedContent.substring(2).trim();
|
|
21474
|
-
return `<li>${listItemContent}</li>`;
|
|
21475
|
-
}
|
|
21476
|
-
return content;
|
|
21477
|
-
}
|
|
21478
|
-
function evaluateCondition(condition, metadata) {
|
|
21479
|
-
const value = resolveVariablePath(condition, metadata);
|
|
21480
|
-
if (value === null || value === void 0) return false;
|
|
21481
|
-
if (typeof value === "boolean") return value;
|
|
21482
|
-
if (typeof value === "number") return value !== 0;
|
|
21483
|
-
if (typeof value === "string") return value.length > 0;
|
|
21484
|
-
if (Array.isArray(value)) return value.length > 0;
|
|
21485
|
-
if (typeof value === "object") return Object.keys(value).length > 0;
|
|
21486
|
-
return Boolean(value);
|
|
21487
|
-
}
|
|
21488
|
-
function processTemplateContent(content, metadata, context, enableFieldTracking = true) {
|
|
21489
|
-
let processedContent = processTemplateLoops(content, metadata, context, enableFieldTracking);
|
|
21490
|
-
processedContent = processedContent.replace(/\{\{([^#/][^}]*)\}\}/g, (match, variable) => {
|
|
21491
|
-
const trimmedVar = variable.trim();
|
|
21492
|
-
const value = resolveVariablePath(trimmedVar, metadata);
|
|
21493
|
-
if (value !== void 0) {
|
|
21494
|
-
if (enableFieldTracking) {
|
|
21495
|
-
const isEmptyValue = value === null || value === "" || typeof value === "string" && value.trim() === "";
|
|
21496
|
-
const cssClass = isEmptyValue ? "legal-field missing-value" : "legal-field imported-value";
|
|
21497
|
-
fieldTracker.trackField(trimmedVar, {
|
|
21498
|
-
value,
|
|
21499
|
-
originalValue: match,
|
|
21500
|
-
hasLogic: false
|
|
21501
|
-
});
|
|
21502
|
-
return `<span class="${cssClass}" data-field="${escapeHtmlAttribute$1(trimmedVar)}">${String(value)}</span>`;
|
|
21503
|
-
}
|
|
21504
|
-
return String(value);
|
|
21505
|
-
}
|
|
21506
|
-
return match;
|
|
21507
|
-
});
|
|
21508
|
-
return processedContent;
|
|
21509
|
-
}
|
|
21510
|
-
|
|
21511
|
-
function escapeHtmlAttribute(value) {
|
|
21512
|
-
return value.replace(/&/g, "&").replace(/"/g, """).replace(/'/g, "'").replace(/</g, "<").replace(/>/g, ">");
|
|
21440
|
+
return null;
|
|
21513
21441
|
}
|
|
21514
|
-
function
|
|
21515
|
-
|
|
21516
|
-
|
|
21517
|
-
|
|
21518
|
-
|
|
21519
|
-
|
|
21520
|
-
|
|
21521
|
-
|
|
21522
|
-
}
|
|
21523
|
-
|
|
21524
|
-
|
|
21442
|
+
function convertToHeading(node, level, text) {
|
|
21443
|
+
const heading = {
|
|
21444
|
+
type: "heading",
|
|
21445
|
+
depth: level,
|
|
21446
|
+
children: parseMarkdownInlineFormatting(text)
|
|
21447
|
+
};
|
|
21448
|
+
heading.data = {
|
|
21449
|
+
isLegalHeader: true,
|
|
21450
|
+
hProperties: {}
|
|
21451
|
+
// Initialize for remarkHeaders to add CSS classes
|
|
21452
|
+
};
|
|
21453
|
+
if (node.children.length > 1 || node.children[0].type === "text" && node.children[0].value.includes("<span")) {
|
|
21454
|
+
const firstChild = node.children[0];
|
|
21455
|
+
if (firstChild.type === "text") {
|
|
21456
|
+
const match = firstChild.value.match(/^(l{1,5})\.\s*/);
|
|
21525
21457
|
if (match) {
|
|
21526
|
-
const [
|
|
21527
|
-
|
|
21528
|
-
|
|
21529
|
-
|
|
21530
|
-
|
|
21531
|
-
|
|
21532
|
-
|
|
21533
|
-
|
|
21534
|
-
const match = expression.match(/^(\w+)\((.*)\)$/);
|
|
21535
|
-
if (!match) return void 0;
|
|
21536
|
-
const [, helperName, argsString] = match;
|
|
21537
|
-
const helper = extensionHelpers[helperName];
|
|
21538
|
-
if (!helper || typeof helper !== "function") {
|
|
21539
|
-
return void 0;
|
|
21540
|
-
}
|
|
21541
|
-
const args = parseArguments(argsString, metadata2);
|
|
21542
|
-
return helper(...args);
|
|
21543
|
-
} catch (error) {
|
|
21544
|
-
console.warn(`Error evaluating helper expression: ${expression}`, error);
|
|
21545
|
-
return void 0;
|
|
21546
|
-
}
|
|
21547
|
-
}
|
|
21548
|
-
function parseArguments(argsString, metadata2) {
|
|
21549
|
-
if (!argsString.trim()) return [];
|
|
21550
|
-
const args = [];
|
|
21551
|
-
let current = "";
|
|
21552
|
-
let inQuotes = false;
|
|
21553
|
-
let quoteChar = "";
|
|
21554
|
-
let parenDepth = 0;
|
|
21555
|
-
for (let i = 0; i < argsString.length; i++) {
|
|
21556
|
-
const char = argsString[i];
|
|
21557
|
-
if (!inQuotes && (char === '"' || char === "'")) {
|
|
21558
|
-
inQuotes = true;
|
|
21559
|
-
quoteChar = char;
|
|
21560
|
-
current += char;
|
|
21561
|
-
continue;
|
|
21562
|
-
}
|
|
21563
|
-
if (inQuotes && char === quoteChar) {
|
|
21564
|
-
inQuotes = false;
|
|
21565
|
-
quoteChar = "";
|
|
21566
|
-
current += char;
|
|
21567
|
-
continue;
|
|
21568
|
-
}
|
|
21569
|
-
if (!inQuotes && char === "(") {
|
|
21570
|
-
parenDepth++;
|
|
21571
|
-
current += char;
|
|
21572
|
-
continue;
|
|
21573
|
-
}
|
|
21574
|
-
if (!inQuotes && char === ")") {
|
|
21575
|
-
parenDepth--;
|
|
21576
|
-
current += char;
|
|
21577
|
-
continue;
|
|
21578
|
-
}
|
|
21579
|
-
if (!inQuotes && char === "," && parenDepth === 0) {
|
|
21580
|
-
args.push(parseArgument(current.trim(), metadata2));
|
|
21581
|
-
current = "";
|
|
21582
|
-
continue;
|
|
21583
|
-
}
|
|
21584
|
-
current += char;
|
|
21585
|
-
}
|
|
21586
|
-
if (current.trim()) {
|
|
21587
|
-
args.push(parseArgument(current.trim(), metadata2));
|
|
21588
|
-
}
|
|
21589
|
-
return args;
|
|
21590
|
-
}
|
|
21591
|
-
function parseArgument(arg, metadata2) {
|
|
21592
|
-
if (arg.startsWith('"') && arg.endsWith('"') || arg.startsWith("'") && arg.endsWith("'")) {
|
|
21593
|
-
return arg.slice(1, -1);
|
|
21594
|
-
}
|
|
21595
|
-
if (/^-?\d+(\.\d+)?$/.test(arg)) {
|
|
21596
|
-
return parseFloat(arg);
|
|
21597
|
-
}
|
|
21598
|
-
if (arg === "true") return true;
|
|
21599
|
-
if (arg === "false") return false;
|
|
21600
|
-
if (arg === "null") return null;
|
|
21601
|
-
if (arg === "undefined") return void 0;
|
|
21602
|
-
if (arg === "@today") {
|
|
21603
|
-
return metadata2["@today"] ? new Date(metadata2["@today"]) : /* @__PURE__ */ new Date();
|
|
21604
|
-
}
|
|
21605
|
-
if (arg.includes("(") && arg.includes(")")) {
|
|
21606
|
-
const result = evaluateHelperExpression(arg, metadata2);
|
|
21607
|
-
if (result !== void 0) {
|
|
21608
|
-
return result;
|
|
21609
|
-
}
|
|
21610
|
-
}
|
|
21611
|
-
return resolvePath(metadata2, arg);
|
|
21612
|
-
}
|
|
21613
|
-
function evaluateExpression(expression, metadata2) {
|
|
21614
|
-
try {
|
|
21615
|
-
let cleanExpression = expression.trim();
|
|
21616
|
-
const variables = Object.keys(metadata2);
|
|
21617
|
-
variables.forEach((varName) => {
|
|
21618
|
-
const value = metadata2[varName];
|
|
21619
|
-
const regex = new RegExp(`\\b${varName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\\b`, "g");
|
|
21620
|
-
if (typeof value === "string") {
|
|
21621
|
-
cleanExpression = cleanExpression.replace(regex, `"${value}"`);
|
|
21622
|
-
} else if (typeof value === "number") {
|
|
21623
|
-
cleanExpression = cleanExpression.replace(regex, String(value));
|
|
21624
|
-
} else if (value === null || value === void 0) {
|
|
21625
|
-
cleanExpression = cleanExpression.replace(regex, "null");
|
|
21626
|
-
} else {
|
|
21627
|
-
cleanExpression = cleanExpression.replace(regex, JSON.stringify(value));
|
|
21628
|
-
}
|
|
21629
|
-
});
|
|
21630
|
-
if (cleanExpression.includes("+") && cleanExpression.includes('"')) {
|
|
21631
|
-
const result = Function(`"use strict"; return (${cleanExpression})`)();
|
|
21632
|
-
return String(result);
|
|
21633
|
-
} else if (/^[\d\s+\-*/().]+$/.test(cleanExpression)) {
|
|
21634
|
-
const result = Function(`"use strict"; return (${cleanExpression})`)();
|
|
21635
|
-
return String(result);
|
|
21458
|
+
const [fullMatch] = match;
|
|
21459
|
+
firstChild.value = firstChild.value.slice(fullMatch.length);
|
|
21460
|
+
heading.children = node.children.filter((child) => {
|
|
21461
|
+
if (child.type === "text" && child.value.trim() === "") {
|
|
21462
|
+
return false;
|
|
21463
|
+
}
|
|
21464
|
+
return true;
|
|
21465
|
+
});
|
|
21636
21466
|
}
|
|
21637
|
-
return expression;
|
|
21638
|
-
} catch (error) {
|
|
21639
|
-
return expression;
|
|
21640
21467
|
}
|
|
21641
21468
|
}
|
|
21642
|
-
|
|
21643
|
-
|
|
21644
|
-
|
|
21645
|
-
|
|
21646
|
-
|
|
21647
|
-
|
|
21648
|
-
|
|
21649
|
-
}
|
|
21650
|
-
function processVariable(match, variable, depth) {
|
|
21651
|
-
const trimmedVar = variable.trim();
|
|
21652
|
-
if (trimmedVar.includes("(") && trimmedVar.includes(")")) {
|
|
21653
|
-
const result = evaluateHelperExpression(trimmedVar, metadata);
|
|
21654
|
-
if (result !== void 0) {
|
|
21655
|
-
fieldTracker.trackField(trimmedVar, {
|
|
21656
|
-
value: result,
|
|
21657
|
-
hasLogic: true,
|
|
21658
|
-
mixinUsed: "helper"
|
|
21659
|
-
});
|
|
21660
|
-
if (options.enableFieldTrackingInMarkdown) {
|
|
21661
|
-
return `<span class="highlight"><span class="imported-value" data-field="${escapeHtmlAttribute(trimmedVar)}">${String(result)}</span></span>`;
|
|
21662
|
-
}
|
|
21663
|
-
return String(result);
|
|
21664
|
-
}
|
|
21665
|
-
if (options.enableFieldTrackingInMarkdown) {
|
|
21666
|
-
return `<span class="legal-field highlight"><span class="legal-field missing-value" data-field="${escapeHtmlAttribute(trimmedVar)}">[[${trimmedVar}]]</span></span>`;
|
|
21667
|
-
}
|
|
21668
|
-
return `{{${trimmedVar}}}`;
|
|
21469
|
+
return heading;
|
|
21470
|
+
}
|
|
21471
|
+
const remarkLegalHeadersParser = (options = {}) => {
|
|
21472
|
+
const { debug = false } = options;
|
|
21473
|
+
return (tree) => {
|
|
21474
|
+
if (debug) {
|
|
21475
|
+
console.log("🔍 [remarkLegalHeadersParser] Parsing legal header syntax");
|
|
21669
21476
|
}
|
|
21670
|
-
|
|
21671
|
-
|
|
21672
|
-
|
|
21673
|
-
if (
|
|
21674
|
-
|
|
21675
|
-
|
|
21676
|
-
|
|
21677
|
-
|
|
21678
|
-
|
|
21679
|
-
|
|
21680
|
-
|
|
21681
|
-
|
|
21682
|
-
|
|
21683
|
-
|
|
21684
|
-
|
|
21685
|
-
|
|
21686
|
-
|
|
21687
|
-
|
|
21688
|
-
|
|
21689
|
-
|
|
21477
|
+
let convertedCount = 0;
|
|
21478
|
+
const nodesToReplace = [];
|
|
21479
|
+
visit(tree, "paragraph", (node, index, parent) => {
|
|
21480
|
+
if (parent && typeof index === "number") {
|
|
21481
|
+
if (node.children.length === 1 && node.children[0].type === "text") {
|
|
21482
|
+
const textNode = node.children[0];
|
|
21483
|
+
const lines = textNode.value.split("\n");
|
|
21484
|
+
const hasLegalHeaders = lines.some((line) => LEGAL_HEADER_PATTERN.test(line));
|
|
21485
|
+
if (hasLegalHeaders) {
|
|
21486
|
+
const newNodes = [];
|
|
21487
|
+
const nonHeaderLines = [];
|
|
21488
|
+
for (const line of lines) {
|
|
21489
|
+
const match = line.match(LEGAL_HEADER_PATTERN);
|
|
21490
|
+
if (match) {
|
|
21491
|
+
if (nonHeaderLines.length > 0) {
|
|
21492
|
+
newNodes.push({
|
|
21493
|
+
type: "paragraph",
|
|
21494
|
+
children: [
|
|
21495
|
+
{
|
|
21496
|
+
type: "text",
|
|
21497
|
+
value: nonHeaderLines.join("\n")
|
|
21498
|
+
}
|
|
21499
|
+
]
|
|
21500
|
+
});
|
|
21501
|
+
nonHeaderLines.length = 0;
|
|
21502
|
+
}
|
|
21503
|
+
const [, levelPattern, headerText] = match;
|
|
21504
|
+
const level = getHeadingLevel(levelPattern);
|
|
21505
|
+
if (debug) {
|
|
21506
|
+
console.log(
|
|
21507
|
+
`🔄 [remarkLegalHeadersParser] Converting "${line.substring(0, 50)}..." to level ${level} heading`
|
|
21508
|
+
);
|
|
21509
|
+
}
|
|
21510
|
+
const headingNode = {
|
|
21511
|
+
type: "heading",
|
|
21512
|
+
depth: level,
|
|
21513
|
+
children: parseMarkdownInlineFormatting(headerText.trim())
|
|
21514
|
+
};
|
|
21515
|
+
headingNode.data = { isLegalHeader: true };
|
|
21516
|
+
newNodes.push(headingNode);
|
|
21517
|
+
convertedCount++;
|
|
21518
|
+
} else {
|
|
21519
|
+
nonHeaderLines.push(line);
|
|
21520
|
+
}
|
|
21690
21521
|
}
|
|
21691
|
-
|
|
21692
|
-
|
|
21522
|
+
if (nonHeaderLines.length > 0) {
|
|
21523
|
+
newNodes.push({
|
|
21524
|
+
type: "paragraph",
|
|
21525
|
+
children: [
|
|
21526
|
+
{
|
|
21527
|
+
type: "text",
|
|
21528
|
+
value: nonHeaderLines.join("\n")
|
|
21529
|
+
}
|
|
21530
|
+
]
|
|
21531
|
+
});
|
|
21532
|
+
}
|
|
21533
|
+
if (newNodes.length > 0) {
|
|
21534
|
+
nodesToReplace.push({ parent, index, newNodes });
|
|
21535
|
+
}
|
|
21536
|
+
}
|
|
21537
|
+
} else if (node.children.length > 1) {
|
|
21538
|
+
let fullText = "";
|
|
21539
|
+
const childrenMap = /* @__PURE__ */ new Map();
|
|
21540
|
+
for (let i = 0; i < node.children.length; i++) {
|
|
21541
|
+
const child = node.children[i];
|
|
21542
|
+
const start = fullText.length;
|
|
21543
|
+
if (child.type === "text") {
|
|
21544
|
+
fullText += child.value;
|
|
21545
|
+
} else if (child.type === "emphasis") {
|
|
21546
|
+
const emphasisText = child.children.map((c) => c.value || "").join("");
|
|
21547
|
+
fullText += `_${emphasisText}_`;
|
|
21548
|
+
} else if (child.type === "strong") {
|
|
21549
|
+
const strongText = child.children.map((c) => c.value || "").join("");
|
|
21550
|
+
fullText += `__${strongText}__`;
|
|
21551
|
+
} else if (child.type === "link") {
|
|
21552
|
+
const linkText = child.children.map((c) => c.value || "").join("");
|
|
21553
|
+
const url = child.url || "";
|
|
21554
|
+
fullText += `[${linkText}](${url})`;
|
|
21555
|
+
} else if (child.type === "inlineCode") {
|
|
21556
|
+
fullText += `\`${child.value || ""}\``;
|
|
21557
|
+
} else {
|
|
21558
|
+
fullText += child.value || "";
|
|
21559
|
+
}
|
|
21560
|
+
const end = fullText.length;
|
|
21561
|
+
childrenMap.set(i, { start, end, child });
|
|
21693
21562
|
}
|
|
21694
|
-
|
|
21695
|
-
|
|
21563
|
+
const lines = fullText.split("\n");
|
|
21564
|
+
const hasLegalHeaders = lines.some((line) => LEGAL_HEADER_PATTERN.test(line));
|
|
21565
|
+
if (hasLegalHeaders) {
|
|
21566
|
+
const newNodes = [];
|
|
21567
|
+
const nonHeaderLines = [];
|
|
21568
|
+
for (const line of lines) {
|
|
21569
|
+
const match = line.match(LEGAL_HEADER_PATTERN);
|
|
21570
|
+
if (match) {
|
|
21571
|
+
if (nonHeaderLines.length > 0) {
|
|
21572
|
+
newNodes.push({
|
|
21573
|
+
type: "paragraph",
|
|
21574
|
+
children: [
|
|
21575
|
+
{
|
|
21576
|
+
type: "text",
|
|
21577
|
+
value: nonHeaderLines.join("\n")
|
|
21578
|
+
}
|
|
21579
|
+
]
|
|
21580
|
+
});
|
|
21581
|
+
nonHeaderLines.length = 0;
|
|
21582
|
+
}
|
|
21583
|
+
const [, levelPattern, headerText] = match;
|
|
21584
|
+
const level = getHeadingLevel(levelPattern);
|
|
21585
|
+
if (debug) {
|
|
21586
|
+
console.log(
|
|
21587
|
+
`🔄 [remarkLegalHeadersParser] Converting complex "${line.substring(0, 50)}..." to level ${level} heading`
|
|
21588
|
+
);
|
|
21589
|
+
}
|
|
21590
|
+
const headingNode = {
|
|
21591
|
+
type: "heading",
|
|
21592
|
+
depth: level,
|
|
21593
|
+
children: parseMarkdownInlineFormatting(headerText.trim())
|
|
21594
|
+
};
|
|
21595
|
+
headingNode.data = { isLegalHeader: true };
|
|
21596
|
+
newNodes.push(headingNode);
|
|
21597
|
+
convertedCount++;
|
|
21598
|
+
} else {
|
|
21599
|
+
nonHeaderLines.push(line);
|
|
21600
|
+
}
|
|
21601
|
+
}
|
|
21602
|
+
if (nonHeaderLines.length > 0) {
|
|
21603
|
+
newNodes.push({
|
|
21604
|
+
type: "paragraph",
|
|
21605
|
+
children: [
|
|
21606
|
+
{
|
|
21607
|
+
type: "text",
|
|
21608
|
+
value: nonHeaderLines.join("\n")
|
|
21609
|
+
}
|
|
21610
|
+
]
|
|
21611
|
+
});
|
|
21612
|
+
}
|
|
21613
|
+
if (newNodes.length > 0) {
|
|
21614
|
+
nodesToReplace.push({ parent, index, newNodes });
|
|
21615
|
+
}
|
|
21696
21616
|
}
|
|
21697
|
-
|
|
21617
|
+
}
|
|
21618
|
+
} else {
|
|
21619
|
+
if (debug) {
|
|
21620
|
+
const firstChildText = node.children[0]?.type === "text" ? node.children[0].value : "<non-text>";
|
|
21621
|
+
console.log(`🔍 [remarkLegalHeadersParser] Single-line paragraph: "${firstChildText}"`);
|
|
21622
|
+
}
|
|
21623
|
+
const headerInfo = isLegalHeader(node);
|
|
21624
|
+
if (headerInfo && parent && typeof index === "number") {
|
|
21625
|
+
if (debug) {
|
|
21626
|
+
const firstChildText = node.children[0].type === "text" ? node.children[0].value : "";
|
|
21627
|
+
console.log(
|
|
21628
|
+
`🔄 [remarkLegalHeadersParser] Converting "${firstChildText.substring(0, 50)}..." to level ${headerInfo.level} heading`
|
|
21629
|
+
);
|
|
21630
|
+
}
|
|
21631
|
+
const heading = convertToHeading(node, headerInfo.level, headerInfo.text);
|
|
21632
|
+
nodesToReplace.push({ parent, index, newNodes: [heading] });
|
|
21633
|
+
convertedCount++;
|
|
21698
21634
|
}
|
|
21699
21635
|
}
|
|
21700
|
-
if (options.enableFieldTrackingInMarkdown) {
|
|
21701
|
-
return `<span class="legal-field highlight"><span class="legal-field missing-value" data-field="${escapeHtmlAttribute(trimmedVar)}">[[${trimmedVar}]]</span></span>`;
|
|
21702
|
-
}
|
|
21703
|
-
return `{{${trimmedVar}}}`;
|
|
21704
|
-
}
|
|
21705
|
-
const value = resolvePath(metadata, trimmedVar);
|
|
21706
|
-
if (value === void 0 || value === null) {
|
|
21707
|
-
fieldTracker.trackField(trimmedVar, {
|
|
21708
|
-
value: void 0,
|
|
21709
|
-
hasLogic: false
|
|
21710
|
-
});
|
|
21711
|
-
if (options.enableFieldTrackingInMarkdown) {
|
|
21712
|
-
return `<span class="legal-field missing-value" data-field="${escapeHtmlAttribute(trimmedVar)}">[[${trimmedVar}]]</span>`;
|
|
21713
|
-
}
|
|
21714
|
-
return `{{${trimmedVar}}}`;
|
|
21715
|
-
}
|
|
21716
|
-
fieldTracker.trackField(trimmedVar, {
|
|
21717
|
-
value,
|
|
21718
|
-
hasLogic: false
|
|
21719
21636
|
});
|
|
21720
|
-
|
|
21721
|
-
|
|
21722
|
-
|
|
21723
|
-
if (options.enableFieldTrackingInMarkdown) {
|
|
21724
|
-
return `<span class="imported-value" data-field="${escapeHtmlAttribute(trimmedVar)}">${nestedResult}</span>`;
|
|
21725
|
-
}
|
|
21726
|
-
return nestedResult;
|
|
21727
|
-
}
|
|
21728
|
-
if (options.enableFieldTrackingInMarkdown) {
|
|
21729
|
-
return `<span class="imported-value" data-field="${escapeHtmlAttribute(trimmedVar)}">${stringValue}</span>`;
|
|
21637
|
+
for (let i = nodesToReplace.length - 1; i >= 0; i--) {
|
|
21638
|
+
const { parent, index, newNodes } = nodesToReplace[i];
|
|
21639
|
+
parent.children.splice(index, 1, ...newNodes);
|
|
21730
21640
|
}
|
|
21731
|
-
return stringValue;
|
|
21732
|
-
}
|
|
21733
|
-
const loopProcessedContent = processTemplateLoops(
|
|
21734
|
-
content,
|
|
21735
|
-
metadata,
|
|
21736
|
-
void 0,
|
|
21737
|
-
options.enableFieldTrackingInMarkdown || false
|
|
21738
|
-
);
|
|
21739
|
-
return replaceMixins(loopProcessedContent);
|
|
21740
|
-
}
|
|
21741
|
-
|
|
21742
|
-
const MAX_HEADER_LEVEL = 9;
|
|
21743
|
-
const FUNCTION_CALL_PATTERN = /^[a-zA-Z_][a-zA-Z0-9_]*\s*\(/;
|
|
21744
|
-
const CONDITIONAL_PATTERN = /\?.*:/;
|
|
21745
|
-
const remarkImports = (options) => {
|
|
21746
|
-
const {
|
|
21747
|
-
basePath = ".",
|
|
21748
|
-
mergeMetadata = true,
|
|
21749
|
-
debug = false,
|
|
21750
|
-
maxDepth = 10,
|
|
21751
|
-
timeoutMs = 3e4,
|
|
21752
|
-
filterReserved = true,
|
|
21753
|
-
validateTypes = true,
|
|
21754
|
-
logImportOperations = false,
|
|
21755
|
-
onMetadataMerged,
|
|
21756
|
-
importStack = []
|
|
21757
|
-
} = options;
|
|
21758
|
-
return (tree) => {
|
|
21759
|
-
const startTime = Date.now();
|
|
21760
21641
|
if (debug) {
|
|
21761
|
-
console.log(
|
|
21762
|
-
basePath,
|
|
21763
|
-
mergeMetadata,
|
|
21764
|
-
maxDepth,
|
|
21765
|
-
timeoutMs,
|
|
21766
|
-
filterReserved,
|
|
21767
|
-
validateTypes,
|
|
21768
|
-
currentDepth: importStack.length
|
|
21769
|
-
});
|
|
21770
|
-
}
|
|
21771
|
-
const context = {
|
|
21772
|
-
depth: importStack.length,
|
|
21773
|
-
maxDepth,
|
|
21774
|
-
basePath,
|
|
21775
|
-
mergeMetadata,
|
|
21776
|
-
debug,
|
|
21777
|
-
startTime,
|
|
21778
|
-
timeoutMs,
|
|
21779
|
-
filterReserved,
|
|
21780
|
-
validateTypes,
|
|
21781
|
-
logImportOperations,
|
|
21782
|
-
onMetadataMerged,
|
|
21783
|
-
importStack: [...importStack],
|
|
21784
|
-
contentCache: /* @__PURE__ */ new Map(),
|
|
21785
|
-
importedMetadataList: [],
|
|
21786
|
-
importedFiles: [],
|
|
21787
|
-
accumulatedMetadata: {}
|
|
21788
|
-
// Initialize with empty metadata
|
|
21789
|
-
};
|
|
21790
|
-
visit(tree, (node) => {
|
|
21791
|
-
if (node.type === "text") {
|
|
21792
|
-
processTextNode(node, context);
|
|
21793
|
-
} else if (node.type === "paragraph") {
|
|
21794
|
-
processParagraphNode(node, context);
|
|
21795
|
-
}
|
|
21796
|
-
});
|
|
21797
|
-
if (context.mergeMetadata && context.importedMetadataList.length > 0) {
|
|
21798
|
-
const mergedResult = performSequentialMerge(context);
|
|
21799
|
-
tree._importedMetadata = mergedResult.metadata;
|
|
21800
|
-
tree._importStats = mergedResult.stats;
|
|
21642
|
+
console.log(`✅ [remarkLegalHeadersParser] Converted ${convertedCount} legal headers`);
|
|
21801
21643
|
}
|
|
21802
21644
|
};
|
|
21803
21645
|
};
|
|
21804
|
-
function
|
|
21805
|
-
const
|
|
21806
|
-
const
|
|
21807
|
-
|
|
21808
|
-
|
|
21809
|
-
|
|
21810
|
-
|
|
21811
|
-
|
|
21812
|
-
|
|
21813
|
-
|
|
21814
|
-
|
|
21815
|
-
|
|
21816
|
-
|
|
21817
|
-
|
|
21818
|
-
|
|
21819
|
-
|
|
21820
|
-
|
|
21821
|
-
|
|
21822
|
-
|
|
21823
|
-
|
|
21824
|
-
|
|
21825
|
-
|
|
21826
|
-
|
|
21827
|
-
|
|
21828
|
-
|
|
21829
|
-
|
|
21830
|
-
|
|
21831
|
-
let match;
|
|
21832
|
-
while ((match = importRegex.exec(text)) !== null) {
|
|
21833
|
-
const [fullMatch, filePath, section] = match;
|
|
21834
|
-
directives.push({
|
|
21835
|
-
filePath: filePath.trim(),
|
|
21836
|
-
section: section?.trim(),
|
|
21837
|
-
start: match.index,
|
|
21838
|
-
end: match.index + fullMatch.length,
|
|
21839
|
-
fullMatch
|
|
21840
|
-
});
|
|
21841
|
-
}
|
|
21842
|
-
return directives;
|
|
21843
|
-
}
|
|
21844
|
-
function processImportDirective(directive, context) {
|
|
21845
|
-
if (context.depth >= context.maxDepth) {
|
|
21846
|
-
console.warn(
|
|
21847
|
-
`[remarkImports] Maximum import depth (${context.maxDepth}) reached for file "${directive.filePath}"`
|
|
21848
|
-
);
|
|
21849
|
-
return directive.fullMatch;
|
|
21850
|
-
}
|
|
21851
|
-
const absolutePath = pathBrowserifyExports.resolve(context.basePath, directive.filePath);
|
|
21852
|
-
const normalizedPath = pathBrowserifyExports.normalize(absolutePath);
|
|
21853
|
-
if (context.importStack.includes(normalizedPath)) {
|
|
21854
|
-
console.warn(`[remarkImports] Circular import detected: ${normalizedPath}`);
|
|
21855
|
-
return directive.fullMatch;
|
|
21646
|
+
function parseMarkdownInlineFormatting(text) {
|
|
21647
|
+
const children = [];
|
|
21648
|
+
const patterns = [
|
|
21649
|
+
{ regex: /\[([^\]]+)\]\([^)]+\)/g, type: "link" },
|
|
21650
|
+
// [text](url) - extract just the text
|
|
21651
|
+
{ regex: /`([^`]+)`/g, type: "inlineCode" },
|
|
21652
|
+
// `code`
|
|
21653
|
+
{ regex: /\*\*(.+?)\*\*/g, type: "strong" },
|
|
21654
|
+
// **bold**
|
|
21655
|
+
{ regex: /__(.+?)__/g, type: "strong" },
|
|
21656
|
+
// __bold__
|
|
21657
|
+
{ regex: /\*(.+?)\*/g, type: "emphasis" },
|
|
21658
|
+
// *italic*
|
|
21659
|
+
{ regex: /_(.+?)_/g, type: "emphasis" }
|
|
21660
|
+
// _italic_
|
|
21661
|
+
];
|
|
21662
|
+
const allMatches = [];
|
|
21663
|
+
for (const pattern of patterns) {
|
|
21664
|
+
let match;
|
|
21665
|
+
while ((match = pattern.regex.exec(text)) !== null) {
|
|
21666
|
+
allMatches.push({
|
|
21667
|
+
start: match.index,
|
|
21668
|
+
end: match.index + match[0].length,
|
|
21669
|
+
type: pattern.type,
|
|
21670
|
+
content: match[1]
|
|
21671
|
+
});
|
|
21672
|
+
}
|
|
21856
21673
|
}
|
|
21857
|
-
|
|
21858
|
-
|
|
21859
|
-
|
|
21860
|
-
|
|
21674
|
+
allMatches.sort((a, b) => a.start - b.start);
|
|
21675
|
+
const validMatches = [];
|
|
21676
|
+
let lastEnd = 0;
|
|
21677
|
+
for (const match of allMatches) {
|
|
21678
|
+
if (match.start >= lastEnd) {
|
|
21679
|
+
validMatches.push(match);
|
|
21680
|
+
lastEnd = match.end;
|
|
21681
|
+
}
|
|
21861
21682
|
}
|
|
21862
|
-
|
|
21863
|
-
|
|
21864
|
-
|
|
21865
|
-
|
|
21683
|
+
let pos = 0;
|
|
21684
|
+
for (const match of validMatches) {
|
|
21685
|
+
if (pos < match.start) {
|
|
21686
|
+
const beforeText = text.slice(pos, match.start);
|
|
21687
|
+
if (beforeText) {
|
|
21688
|
+
children.push({
|
|
21689
|
+
type: "text",
|
|
21690
|
+
value: beforeText
|
|
21691
|
+
});
|
|
21692
|
+
}
|
|
21693
|
+
}
|
|
21694
|
+
if (match.type === "inlineCode") {
|
|
21695
|
+
children.push({
|
|
21696
|
+
type: "inlineCode",
|
|
21697
|
+
value: match.content
|
|
21698
|
+
});
|
|
21699
|
+
} else if (match.type === "link") {
|
|
21700
|
+
children.push({
|
|
21701
|
+
type: "text",
|
|
21702
|
+
value: match.content
|
|
21703
|
+
});
|
|
21704
|
+
} else {
|
|
21705
|
+
children.push({
|
|
21706
|
+
type: match.type,
|
|
21707
|
+
children: [
|
|
21708
|
+
{
|
|
21709
|
+
type: "text",
|
|
21710
|
+
value: match.content
|
|
21711
|
+
}
|
|
21712
|
+
]
|
|
21713
|
+
});
|
|
21714
|
+
}
|
|
21715
|
+
pos = match.end;
|
|
21866
21716
|
}
|
|
21867
|
-
|
|
21868
|
-
|
|
21869
|
-
|
|
21870
|
-
|
|
21871
|
-
|
|
21872
|
-
|
|
21873
|
-
metadata,
|
|
21874
|
-
source: normalizedPath
|
|
21717
|
+
if (pos < text.length) {
|
|
21718
|
+
const remainingText = text.slice(pos);
|
|
21719
|
+
if (remainingText) {
|
|
21720
|
+
children.push({
|
|
21721
|
+
type: "text",
|
|
21722
|
+
value: remainingText
|
|
21875
21723
|
});
|
|
21876
|
-
context.accumulatedMetadata = {
|
|
21877
|
-
...context.accumulatedMetadata,
|
|
21878
|
-
...metadata
|
|
21879
|
-
};
|
|
21880
|
-
if (!context.importedFiles.includes(normalizedPath)) {
|
|
21881
|
-
context.importedFiles.push(normalizedPath);
|
|
21882
|
-
}
|
|
21883
|
-
if (context.debug) {
|
|
21884
|
-
console.log(
|
|
21885
|
-
`[remarkImports] Collected metadata from ${directive.filePath}:`,
|
|
21886
|
-
Object.keys(metadata)
|
|
21887
|
-
);
|
|
21888
|
-
}
|
|
21889
21724
|
}
|
|
21890
21725
|
}
|
|
21891
|
-
if (
|
|
21892
|
-
|
|
21726
|
+
if (children.length === 0) {
|
|
21727
|
+
return [
|
|
21728
|
+
{
|
|
21729
|
+
type: "text",
|
|
21730
|
+
value: text
|
|
21731
|
+
}
|
|
21732
|
+
];
|
|
21893
21733
|
}
|
|
21894
|
-
|
|
21895
|
-
...context,
|
|
21896
|
-
depth: context.depth + 1,
|
|
21897
|
-
importStack: [...context.importStack, normalizedPath],
|
|
21898
|
-
basePath: pathBrowserifyExports.dirname(normalizedPath)
|
|
21899
|
-
// Update base path for relative imports
|
|
21900
|
-
};
|
|
21901
|
-
return processNestedImports(contentToImport, nestedContext);
|
|
21734
|
+
return children;
|
|
21902
21735
|
}
|
|
21903
|
-
|
|
21904
|
-
|
|
21905
|
-
|
|
21906
|
-
|
|
21907
|
-
|
|
21908
|
-
};
|
|
21909
|
-
}
|
|
21910
|
-
if (Date.now() - context.startTime > context.timeoutMs) {
|
|
21911
|
-
throw new Error(
|
|
21912
|
-
`Import processing timed out after ${context.timeoutMs}ms. This may indicate complex nested imports or slow file operations.`
|
|
21913
|
-
);
|
|
21914
|
-
}
|
|
21915
|
-
const mergeOptions = {
|
|
21916
|
-
filterReserved: context.filterReserved,
|
|
21917
|
-
validateTypes: context.validateTypes,
|
|
21918
|
-
logOperations: context.logImportOperations,
|
|
21919
|
-
includeStats: true,
|
|
21920
|
-
timeoutMs: Math.max(1e3, context.timeoutMs - (Date.now() - context.startTime))
|
|
21921
|
-
};
|
|
21922
|
-
const metadataList = context.importedMetadataList.map((item) => item.metadata);
|
|
21923
|
-
if (context.debug) {
|
|
21924
|
-
console.log(
|
|
21925
|
-
`[remarkImports] Performing sequential merge of ${metadataList.length} metadata objects`
|
|
21926
|
-
);
|
|
21736
|
+
|
|
21737
|
+
const EXTENDED_DATE_PATTERN = /@today((?:[+-]\d+[dmy]?(?:\[[^\]]+\])?)|(?:[+-]\d+[dmy]?)|(?:\[[^\]]+\]))?/g;
|
|
21738
|
+
function parseDateToken(token) {
|
|
21739
|
+
if (!token) return { arithmetic: null, format: null, isValid: true };
|
|
21740
|
+
if (!/^[+-]?\d*[dmy]?(\[[^\]]+\])?$/.test(token)) {
|
|
21741
|
+
return { arithmetic: null, format: null, isValid: false };
|
|
21927
21742
|
}
|
|
21928
|
-
|
|
21929
|
-
|
|
21930
|
-
|
|
21931
|
-
|
|
21932
|
-
|
|
21933
|
-
|
|
21934
|
-
|
|
21935
|
-
|
|
21936
|
-
|
|
21743
|
+
const formatMatch = token.match(/\[([^\]]+)\]/);
|
|
21744
|
+
const format = formatMatch ? formatMatch[1] : null;
|
|
21745
|
+
const arithmeticPart = token.replace(/\[([^\]]+)\]/, "");
|
|
21746
|
+
let arithmetic = null;
|
|
21747
|
+
if (arithmeticPart) {
|
|
21748
|
+
const arithmeticMatch = arithmeticPart.match(/^([+-])(\d+)([dmy]?)$/);
|
|
21749
|
+
if (arithmeticMatch) {
|
|
21750
|
+
const [, sign, amount, suffix] = arithmeticMatch;
|
|
21751
|
+
const numAmount = parseInt(amount) * (sign === "-" ? -1 : 1);
|
|
21752
|
+
switch (suffix) {
|
|
21753
|
+
case "d":
|
|
21754
|
+
case "":
|
|
21755
|
+
arithmetic = { type: "days", amount: numAmount };
|
|
21756
|
+
break;
|
|
21757
|
+
case "m":
|
|
21758
|
+
arithmetic = { type: "months", amount: numAmount };
|
|
21759
|
+
break;
|
|
21760
|
+
case "y":
|
|
21761
|
+
arithmetic = { type: "years", amount: numAmount };
|
|
21762
|
+
break;
|
|
21763
|
+
default:
|
|
21764
|
+
arithmetic = { type: "days", amount: numAmount };
|
|
21765
|
+
}
|
|
21766
|
+
} else if (arithmeticPart !== "") {
|
|
21767
|
+
return { arithmetic: null, format: null, isValid: false };
|
|
21937
21768
|
}
|
|
21938
|
-
throw error;
|
|
21939
21769
|
}
|
|
21770
|
+
return { arithmetic, format, isValid: true };
|
|
21940
21771
|
}
|
|
21941
|
-
function
|
|
21942
|
-
if (
|
|
21943
|
-
|
|
21944
|
-
|
|
21945
|
-
|
|
21946
|
-
|
|
21947
|
-
|
|
21948
|
-
|
|
21949
|
-
|
|
21950
|
-
|
|
21772
|
+
function applyDateArithmetic(baseDate, arithmetic) {
|
|
21773
|
+
if (!arithmetic) return baseDate;
|
|
21774
|
+
switch (arithmetic.type) {
|
|
21775
|
+
case "days":
|
|
21776
|
+
return addDays(baseDate, arithmetic.amount);
|
|
21777
|
+
case "months":
|
|
21778
|
+
return addMonths(baseDate, arithmetic.amount);
|
|
21779
|
+
case "years":
|
|
21780
|
+
return addYears(baseDate, arithmetic.amount);
|
|
21781
|
+
default:
|
|
21782
|
+
return baseDate;
|
|
21951
21783
|
}
|
|
21952
|
-
return null;
|
|
21953
21784
|
}
|
|
21954
|
-
function
|
|
21955
|
-
|
|
21956
|
-
|
|
21957
|
-
let sectionEnd = lines.length;
|
|
21958
|
-
let sectionLevel = 0;
|
|
21959
|
-
for (let i = 0; i < lines.length; i++) {
|
|
21960
|
-
const line = lines[i].trim();
|
|
21961
|
-
const headerMatch = line.match(/^(#{1,6})\s+(.+)$/);
|
|
21962
|
-
if (headerMatch) {
|
|
21963
|
-
const [, hashes, title] = headerMatch;
|
|
21964
|
-
const level = hashes.length;
|
|
21965
|
-
if (title.toLowerCase() === sectionName.toLowerCase()) {
|
|
21966
|
-
sectionStart = i + 1;
|
|
21967
|
-
sectionLevel = level;
|
|
21968
|
-
if (debug) {
|
|
21969
|
-
console.log(`[remarkImports] Found section '${sectionName}' at line ${i}`);
|
|
21970
|
-
}
|
|
21971
|
-
break;
|
|
21972
|
-
}
|
|
21973
|
-
}
|
|
21785
|
+
function getOrdinalSuffix(day) {
|
|
21786
|
+
if (day >= 11 && day <= 13) {
|
|
21787
|
+
return "th";
|
|
21974
21788
|
}
|
|
21975
|
-
|
|
21976
|
-
|
|
21977
|
-
|
|
21978
|
-
|
|
21979
|
-
|
|
21789
|
+
switch (day % 10) {
|
|
21790
|
+
case 1:
|
|
21791
|
+
return "st";
|
|
21792
|
+
case 2:
|
|
21793
|
+
return "nd";
|
|
21794
|
+
case 3:
|
|
21795
|
+
return "rd";
|
|
21796
|
+
default:
|
|
21797
|
+
return "th";
|
|
21980
21798
|
}
|
|
21981
|
-
|
|
21982
|
-
|
|
21983
|
-
|
|
21984
|
-
|
|
21985
|
-
|
|
21986
|
-
|
|
21987
|
-
|
|
21988
|
-
|
|
21989
|
-
|
|
21990
|
-
|
|
21799
|
+
}
|
|
21800
|
+
function formatDateBasic(date, format) {
|
|
21801
|
+
const year = date.getFullYear();
|
|
21802
|
+
const month = String(date.getMonth() + 1).padStart(2, "0");
|
|
21803
|
+
const day = String(date.getDate()).padStart(2, "0");
|
|
21804
|
+
const dayNumber = date.getDate();
|
|
21805
|
+
const monthNames = [
|
|
21806
|
+
"January",
|
|
21807
|
+
"February",
|
|
21808
|
+
"March",
|
|
21809
|
+
"April",
|
|
21810
|
+
"May",
|
|
21811
|
+
"June",
|
|
21812
|
+
"July",
|
|
21813
|
+
"August",
|
|
21814
|
+
"September",
|
|
21815
|
+
"October",
|
|
21816
|
+
"November",
|
|
21817
|
+
"December"
|
|
21818
|
+
];
|
|
21819
|
+
switch (format.toLowerCase()) {
|
|
21820
|
+
case "iso":
|
|
21821
|
+
case "yyyy-mm-dd":
|
|
21822
|
+
return `${year}-${month}-${day}`;
|
|
21823
|
+
case "us":
|
|
21824
|
+
case "mm/dd/yyyy":
|
|
21825
|
+
return `${month}/${day}/${year}`;
|
|
21826
|
+
case "eu":
|
|
21827
|
+
case "european":
|
|
21828
|
+
case "dd/mm/yyyy":
|
|
21829
|
+
return `${day}/${month}/${year}`;
|
|
21830
|
+
case "long":
|
|
21831
|
+
return `${monthNames[date.getMonth()]} ${dayNumber}, ${year}`;
|
|
21832
|
+
case "medium":
|
|
21833
|
+
return `${monthNames[date.getMonth()].substring(0, 3)} ${dayNumber}, ${year}`;
|
|
21834
|
+
case "short":
|
|
21835
|
+
return `${monthNames[date.getMonth()].substring(0, 3)} ${dayNumber}, ${String(year).substring(2)}`;
|
|
21836
|
+
case "legal": {
|
|
21837
|
+
const suffix = getOrdinalSuffix(dayNumber);
|
|
21838
|
+
return `${monthNames[date.getMonth()]} ${dayNumber}${suffix}, ${year}`;
|
|
21991
21839
|
}
|
|
21840
|
+
default:
|
|
21841
|
+
return `${year}-${month}-${day}`;
|
|
21992
21842
|
}
|
|
21993
|
-
return lines.slice(sectionStart, sectionEnd).join("\n").trim();
|
|
21994
|
-
}
|
|
21995
|
-
function expandMixinsWithTracking(content, metadata) {
|
|
21996
|
-
const mixinPattern = /\{\{([^}]+)\}\}/g;
|
|
21997
|
-
return content.replace(mixinPattern, (match, fieldExpression) => {
|
|
21998
|
-
const trimmedField = fieldExpression.trim();
|
|
21999
|
-
let value;
|
|
22000
|
-
let hasValue = false;
|
|
22001
|
-
try {
|
|
22002
|
-
const expandedValue = processMixins(match, metadata, {});
|
|
22003
|
-
if (expandedValue !== match) {
|
|
22004
|
-
value = expandedValue;
|
|
22005
|
-
hasValue = true;
|
|
22006
|
-
}
|
|
22007
|
-
} catch (error) {
|
|
22008
|
-
}
|
|
22009
|
-
if (hasValue) {
|
|
22010
|
-
const hasLogic = FUNCTION_CALL_PATTERN.test(trimmedField) || // Function call: formatPercent(...)
|
|
22011
|
-
CONDITIONAL_PATTERN.test(trimmedField);
|
|
22012
|
-
const cssClass = hasLogic ? "legal-field highlight" : "legal-field imported-value";
|
|
22013
|
-
return `<span class="${cssClass}" data-field="${trimmedField}">${value}</span>`;
|
|
22014
|
-
} else {
|
|
22015
|
-
return match;
|
|
22016
|
-
}
|
|
22017
|
-
});
|
|
22018
21843
|
}
|
|
22019
|
-
function
|
|
22020
|
-
|
|
22021
|
-
processed = processed.replace(/<!--[\s\S]*?-->/g, "");
|
|
22022
|
-
const headerPattern = `l{1,${MAX_HEADER_LEVEL}}`;
|
|
22023
|
-
processed = processed.replace(
|
|
22024
|
-
new RegExp(
|
|
22025
|
-
`<(p|div|span)(?!\\s+[a-z])\\s*>\\s*(${headerPattern}\\.\\s+[^\\n]+)\\s*<\\/\\1>`,
|
|
22026
|
-
"gi"
|
|
22027
|
-
),
|
|
22028
|
-
"$2"
|
|
22029
|
-
);
|
|
22030
|
-
processed = processed.replace(
|
|
22031
|
-
new RegExp(`<(p|div|span)(?!\\s+[a-z])\\s*>(${headerPattern}\\.\\s+[^<]+)<\\/\\1>`, "gi"),
|
|
22032
|
-
"$2"
|
|
22033
|
-
);
|
|
22034
|
-
return processed;
|
|
21844
|
+
function getDateFieldCssClass(hasArithmetic) {
|
|
21845
|
+
return hasArithmetic ? "legal-field highlight" : "legal-field imported-value";
|
|
22035
21846
|
}
|
|
22036
|
-
function
|
|
22037
|
-
|
|
22038
|
-
|
|
22039
|
-
if (importDirectives.length > 0) {
|
|
22040
|
-
for (let i = importDirectives.length - 1; i >= 0; i--) {
|
|
22041
|
-
const directive = importDirectives[i];
|
|
22042
|
-
const result = processImportDirective(directive, context);
|
|
22043
|
-
processedContent = processedContent.substring(0, directive.start) + result + processedContent.substring(directive.end);
|
|
22044
|
-
}
|
|
22045
|
-
}
|
|
22046
|
-
if (context.mergeMetadata && Object.keys(context.accumulatedMetadata).length > 0) {
|
|
22047
|
-
processedContent = expandMixinsWithTracking(processedContent, context.accumulatedMetadata);
|
|
21847
|
+
function formatDateValue(value, originalToken, enableFieldTracking = false, hasArithmetic = false) {
|
|
21848
|
+
if (!enableFieldTracking) {
|
|
21849
|
+
return value;
|
|
22048
21850
|
}
|
|
22049
|
-
|
|
22050
|
-
}
|
|
22051
|
-
|
|
22052
|
-
const LEGAL_HEADER_PATTERN = /^(l{1,9})\.\s+(.+)$/;
|
|
22053
|
-
function getHeadingLevel(pattern) {
|
|
22054
|
-
return pattern.length;
|
|
21851
|
+
const cssClass = getDateFieldCssClass(hasArithmetic);
|
|
21852
|
+
const fieldName = `date.${originalToken.replace(/[@[\]]/g, "")}`;
|
|
21853
|
+
return `<span class="${cssClass}" data-field="${fieldName.replace(/"/g, """)}">${value}</span>`;
|
|
22055
21854
|
}
|
|
22056
|
-
function
|
|
22057
|
-
|
|
22058
|
-
const
|
|
22059
|
-
|
|
22060
|
-
|
|
22061
|
-
|
|
22062
|
-
|
|
22063
|
-
|
|
22064
|
-
|
|
22065
|
-
|
|
21855
|
+
function processDateReferencesInAST(root, metadata, enableFieldTracking = false) {
|
|
21856
|
+
visit(root, "text", (node, index, parent) => {
|
|
21857
|
+
const originalValue = node.value;
|
|
21858
|
+
let modifiedValue = originalValue;
|
|
21859
|
+
let hasChanges = false;
|
|
21860
|
+
modifiedValue = modifiedValue.replace(EXTENDED_DATE_PATTERN, (match, token) => {
|
|
21861
|
+
try {
|
|
21862
|
+
const { arithmetic, format: tokenFormat, isValid } = parseDateToken(token);
|
|
21863
|
+
if (!isValid) {
|
|
21864
|
+
return match;
|
|
21865
|
+
}
|
|
21866
|
+
let date = /* @__PURE__ */ new Date();
|
|
21867
|
+
const hasArithmetic = !!arithmetic;
|
|
21868
|
+
if (arithmetic) {
|
|
21869
|
+
date = applyDateArithmetic(date, arithmetic);
|
|
21870
|
+
}
|
|
21871
|
+
const format = tokenFormat || metadata["date-format"] || "YYYY-MM-DD";
|
|
21872
|
+
const formattedDate = formatDateBasic(date, format);
|
|
21873
|
+
fieldTracker.trackField(`date.${match.replace(/[@[\]]/g, "")}`, {
|
|
21874
|
+
value: formattedDate,
|
|
21875
|
+
originalValue: match,
|
|
21876
|
+
hasLogic: hasArithmetic
|
|
21877
|
+
});
|
|
21878
|
+
hasChanges = true;
|
|
21879
|
+
return formatDateValue(formattedDate, match, enableFieldTracking, hasArithmetic);
|
|
21880
|
+
} catch (error) {
|
|
21881
|
+
console.warn(`Error processing date reference ${match}:`, error);
|
|
21882
|
+
return match;
|
|
21883
|
+
}
|
|
21884
|
+
});
|
|
21885
|
+
if (hasChanges) {
|
|
21886
|
+
if (enableFieldTracking && modifiedValue.includes("<span")) {
|
|
21887
|
+
if (parent && typeof index === "number") {
|
|
21888
|
+
const htmlNode = {
|
|
21889
|
+
type: "html",
|
|
21890
|
+
value: modifiedValue
|
|
21891
|
+
};
|
|
21892
|
+
parent.children[index] = htmlNode;
|
|
21893
|
+
}
|
|
21894
|
+
} else {
|
|
21895
|
+
node.value = modifiedValue;
|
|
21896
|
+
}
|
|
22066
21897
|
}
|
|
22067
|
-
}
|
|
22068
|
-
|
|
22069
|
-
|
|
22070
|
-
|
|
22071
|
-
if (match) {
|
|
22072
|
-
const [fullMatch, levelPattern] = match;
|
|
22073
|
-
const remainingText = firstChild.value.slice(fullMatch.length);
|
|
22074
|
-
const otherText = node.children.slice(1).map((child) => {
|
|
22075
|
-
if (child.type === "text") return child.value;
|
|
22076
|
-
if (child.type === "html") return child.value || "";
|
|
22077
|
-
return "";
|
|
22078
|
-
}).join("");
|
|
22079
|
-
return {
|
|
22080
|
-
level: getHeadingLevel(levelPattern),
|
|
22081
|
-
text: (remainingText + otherText).trim()
|
|
22082
|
-
};
|
|
21898
|
+
});
|
|
21899
|
+
visit(root, "html", (node) => {
|
|
21900
|
+
if (!node.value || !node.value.includes("@today")) {
|
|
21901
|
+
return;
|
|
22083
21902
|
}
|
|
22084
|
-
|
|
22085
|
-
|
|
22086
|
-
|
|
22087
|
-
|
|
22088
|
-
|
|
22089
|
-
|
|
22090
|
-
|
|
22091
|
-
|
|
22092
|
-
|
|
22093
|
-
|
|
22094
|
-
|
|
22095
|
-
|
|
22096
|
-
|
|
22097
|
-
|
|
22098
|
-
|
|
22099
|
-
|
|
22100
|
-
|
|
22101
|
-
|
|
22102
|
-
|
|
22103
|
-
|
|
21903
|
+
let modifiedValue = node.value;
|
|
21904
|
+
let hasChanges = false;
|
|
21905
|
+
modifiedValue = modifiedValue.replace(
|
|
21906
|
+
EXTENDED_DATE_PATTERN,
|
|
21907
|
+
(match, formatOverride) => {
|
|
21908
|
+
try {
|
|
21909
|
+
const date = /* @__PURE__ */ new Date();
|
|
21910
|
+
const format = formatOverride || metadata["date-format"] || "YYYY-MM-DD";
|
|
21911
|
+
const formattedDate = formatDateBasic(date, format);
|
|
21912
|
+
fieldTracker.trackField(`date.${match.replace(/[@[\]]/g, "")}`, {
|
|
21913
|
+
value: formattedDate,
|
|
21914
|
+
originalValue: match,
|
|
21915
|
+
hasLogic: false
|
|
21916
|
+
});
|
|
21917
|
+
hasChanges = true;
|
|
21918
|
+
if (enableFieldTracking) {
|
|
21919
|
+
const cssClass = getDateFieldCssClass(false);
|
|
21920
|
+
const fieldName = `date.${match.replace(/[@[\]]/g, "")}`;
|
|
21921
|
+
return `<span class="${cssClass}" data-field="${fieldName.replace(/"/g, """)}">${formattedDate}</span>`;
|
|
21922
|
+
} else {
|
|
21923
|
+
return formattedDate;
|
|
22104
21924
|
}
|
|
22105
|
-
|
|
22106
|
-
|
|
21925
|
+
} catch (error) {
|
|
21926
|
+
console.warn(`Error processing date reference ${match}:`, error);
|
|
21927
|
+
return match;
|
|
21928
|
+
}
|
|
22107
21929
|
}
|
|
21930
|
+
);
|
|
21931
|
+
if (hasChanges) {
|
|
21932
|
+
node.value = modifiedValue;
|
|
22108
21933
|
}
|
|
22109
|
-
}
|
|
22110
|
-
return heading;
|
|
21934
|
+
});
|
|
22111
21935
|
}
|
|
22112
|
-
const
|
|
22113
|
-
const { debug = false } = options;
|
|
21936
|
+
const remarkDates = (options) => {
|
|
21937
|
+
const { metadata, debug = false, enableFieldTracking = false } = options;
|
|
22114
21938
|
return (tree) => {
|
|
22115
21939
|
if (debug) {
|
|
22116
|
-
console.log("
|
|
21940
|
+
console.log("📅 Processing date references with remark plugin");
|
|
22117
21941
|
}
|
|
22118
|
-
|
|
22119
|
-
|
|
22120
|
-
|
|
22121
|
-
|
|
22122
|
-
|
|
22123
|
-
|
|
22124
|
-
|
|
22125
|
-
|
|
22126
|
-
|
|
22127
|
-
|
|
22128
|
-
|
|
22129
|
-
|
|
22130
|
-
|
|
22131
|
-
|
|
22132
|
-
|
|
22133
|
-
|
|
22134
|
-
|
|
22135
|
-
|
|
22136
|
-
|
|
22137
|
-
|
|
22138
|
-
|
|
22139
|
-
|
|
22140
|
-
|
|
22141
|
-
|
|
22142
|
-
|
|
22143
|
-
|
|
22144
|
-
|
|
22145
|
-
|
|
22146
|
-
|
|
22147
|
-
|
|
22148
|
-
|
|
22149
|
-
|
|
22150
|
-
|
|
22151
|
-
|
|
22152
|
-
|
|
22153
|
-
|
|
22154
|
-
|
|
22155
|
-
|
|
22156
|
-
|
|
22157
|
-
|
|
22158
|
-
|
|
22159
|
-
|
|
22160
|
-
|
|
22161
|
-
|
|
22162
|
-
|
|
22163
|
-
|
|
22164
|
-
|
|
22165
|
-
|
|
22166
|
-
|
|
22167
|
-
|
|
22168
|
-
|
|
22169
|
-
|
|
22170
|
-
|
|
22171
|
-
|
|
22172
|
-
}
|
|
22173
|
-
}
|
|
22174
|
-
if (newNodes.length > 0) {
|
|
22175
|
-
nodesToReplace.push({ parent, index, newNodes });
|
|
22176
|
-
}
|
|
21942
|
+
processDateReferencesInAST(tree, metadata, enableFieldTracking);
|
|
21943
|
+
if (debug) {
|
|
21944
|
+
console.log("✅ Date reference processing completed");
|
|
21945
|
+
}
|
|
21946
|
+
};
|
|
21947
|
+
};
|
|
21948
|
+
|
|
21949
|
+
class PluginOrderValidator {
|
|
21950
|
+
registry;
|
|
21951
|
+
constructor(registry) {
|
|
21952
|
+
this.registry = registry;
|
|
21953
|
+
}
|
|
21954
|
+
/**
|
|
21955
|
+
* Validate plugin execution order
|
|
21956
|
+
*
|
|
21957
|
+
* @param pluginNames - List of plugin names in execution order
|
|
21958
|
+
* @param options - Validation options
|
|
21959
|
+
* @returns Validation result with errors and warnings
|
|
21960
|
+
*/
|
|
21961
|
+
validate(pluginNames, options = {}) {
|
|
21962
|
+
const { throwOnError = true, logWarnings = true, strictMode = false, debug = false } = options;
|
|
21963
|
+
const errors = [];
|
|
21964
|
+
const warnings = [];
|
|
21965
|
+
if (debug) {
|
|
21966
|
+
console.log("[PluginOrderValidator] Validating plugin order:", pluginNames);
|
|
21967
|
+
}
|
|
21968
|
+
const positions = /* @__PURE__ */ new Map();
|
|
21969
|
+
pluginNames.forEach((name, index) => {
|
|
21970
|
+
positions.set(name, index);
|
|
21971
|
+
});
|
|
21972
|
+
for (let i = 0; i < pluginNames.length; i++) {
|
|
21973
|
+
const pluginName = pluginNames[i];
|
|
21974
|
+
const metadata = this.registry.get(pluginName);
|
|
21975
|
+
if (!metadata) {
|
|
21976
|
+
if (strictMode) {
|
|
21977
|
+
warnings.push({
|
|
21978
|
+
type: "unknown-plugin",
|
|
21979
|
+
plugin: pluginName,
|
|
21980
|
+
message: `Plugin "${pluginName}" has no metadata declaration`
|
|
21981
|
+
});
|
|
21982
|
+
}
|
|
21983
|
+
continue;
|
|
21984
|
+
}
|
|
21985
|
+
if (debug) {
|
|
21986
|
+
console.log(`[PluginOrderValidator] Checking constraints for ${pluginName}`);
|
|
21987
|
+
}
|
|
21988
|
+
if (metadata.runBefore) {
|
|
21989
|
+
for (const beforePlugin of metadata.runBefore) {
|
|
21990
|
+
const beforePos = positions.get(beforePlugin);
|
|
21991
|
+
if (beforePos !== void 0 && beforePos <= i) {
|
|
21992
|
+
errors.push({
|
|
21993
|
+
type: "dependency-violation",
|
|
21994
|
+
plugin: pluginName,
|
|
21995
|
+
relatedPlugin: beforePlugin,
|
|
21996
|
+
message: `"${pluginName}" must run BEFORE "${beforePlugin}", but it appears after it in the pipeline`
|
|
21997
|
+
});
|
|
22177
21998
|
}
|
|
22178
|
-
}
|
|
22179
|
-
|
|
22180
|
-
|
|
22181
|
-
|
|
22182
|
-
|
|
22183
|
-
|
|
22184
|
-
|
|
22185
|
-
|
|
22186
|
-
|
|
22187
|
-
|
|
22188
|
-
|
|
22189
|
-
}
|
|
22190
|
-
const strongText = child.children.map((c) => c.value || "").join("");
|
|
22191
|
-
fullText += `__${strongText}__`;
|
|
22192
|
-
} else if (child.type === "link") {
|
|
22193
|
-
const linkText = child.children.map((c) => c.value || "").join("");
|
|
22194
|
-
const url = child.url || "";
|
|
22195
|
-
fullText += `[${linkText}](${url})`;
|
|
22196
|
-
} else if (child.type === "inlineCode") {
|
|
22197
|
-
fullText += `\`${child.value || ""}\``;
|
|
22198
|
-
} else {
|
|
22199
|
-
fullText += child.value || "";
|
|
22200
|
-
}
|
|
22201
|
-
const end = fullText.length;
|
|
22202
|
-
childrenMap.set(i, { start, end, child });
|
|
21999
|
+
}
|
|
22000
|
+
}
|
|
22001
|
+
if (metadata.runAfter) {
|
|
22002
|
+
for (const afterPlugin of metadata.runAfter) {
|
|
22003
|
+
const afterPos = positions.get(afterPlugin);
|
|
22004
|
+
if (afterPos !== void 0 && afterPos >= i) {
|
|
22005
|
+
errors.push({
|
|
22006
|
+
type: "dependency-violation",
|
|
22007
|
+
plugin: pluginName,
|
|
22008
|
+
relatedPlugin: afterPlugin,
|
|
22009
|
+
message: `"${pluginName}" must run AFTER "${afterPlugin}", but it appears before it in the pipeline`
|
|
22010
|
+
});
|
|
22203
22011
|
}
|
|
22204
|
-
|
|
22205
|
-
|
|
22206
|
-
|
|
22207
|
-
|
|
22208
|
-
|
|
22209
|
-
|
|
22210
|
-
|
|
22211
|
-
|
|
22212
|
-
|
|
22213
|
-
|
|
22214
|
-
|
|
22215
|
-
|
|
22216
|
-
|
|
22217
|
-
|
|
22218
|
-
|
|
22219
|
-
|
|
22220
|
-
|
|
22221
|
-
|
|
22222
|
-
|
|
22223
|
-
|
|
22224
|
-
|
|
22225
|
-
|
|
22226
|
-
|
|
22227
|
-
|
|
22228
|
-
|
|
22229
|
-
|
|
22230
|
-
|
|
22231
|
-
|
|
22232
|
-
|
|
22233
|
-
|
|
22234
|
-
|
|
22235
|
-
|
|
22236
|
-
|
|
22237
|
-
|
|
22238
|
-
|
|
22239
|
-
|
|
22240
|
-
|
|
22012
|
+
}
|
|
22013
|
+
}
|
|
22014
|
+
if (metadata.conflicts) {
|
|
22015
|
+
for (const conflictPlugin of metadata.conflicts) {
|
|
22016
|
+
if (positions.has(conflictPlugin)) {
|
|
22017
|
+
errors.push({
|
|
22018
|
+
type: "conflict",
|
|
22019
|
+
plugin: pluginName,
|
|
22020
|
+
relatedPlugin: conflictPlugin,
|
|
22021
|
+
message: `"${pluginName}" conflicts with "${conflictPlugin}" - they cannot be used together`
|
|
22022
|
+
});
|
|
22023
|
+
}
|
|
22024
|
+
}
|
|
22025
|
+
}
|
|
22026
|
+
}
|
|
22027
|
+
for (const [name, metadata] of this.registry.entries()) {
|
|
22028
|
+
if (metadata.required && !positions.has(name)) {
|
|
22029
|
+
warnings.push({
|
|
22030
|
+
type: "missing-required",
|
|
22031
|
+
plugin: name,
|
|
22032
|
+
message: `Required plugin "${name}" is missing from the pipeline`
|
|
22033
|
+
});
|
|
22034
|
+
}
|
|
22035
|
+
}
|
|
22036
|
+
const circularErrors = this.detectCircularDependencies(pluginNames);
|
|
22037
|
+
errors.push(...circularErrors);
|
|
22038
|
+
if (logWarnings && warnings.length > 0) {
|
|
22039
|
+
for (const warning of warnings) {
|
|
22040
|
+
console.warn(`[PluginOrderValidator] WARNING: ${warning.message}`);
|
|
22041
|
+
}
|
|
22042
|
+
}
|
|
22043
|
+
const valid = errors.length === 0;
|
|
22044
|
+
let suggestedOrder;
|
|
22045
|
+
if (!valid) {
|
|
22046
|
+
try {
|
|
22047
|
+
suggestedOrder = this.topologicalSort(pluginNames);
|
|
22048
|
+
if (debug) {
|
|
22049
|
+
console.log("[PluginOrderValidator] Suggested order:", suggestedOrder);
|
|
22050
|
+
}
|
|
22051
|
+
} catch (error) {
|
|
22052
|
+
if (debug) {
|
|
22053
|
+
console.error("[PluginOrderValidator] Failed to generate suggested order:", error);
|
|
22054
|
+
}
|
|
22055
|
+
}
|
|
22056
|
+
}
|
|
22057
|
+
const result = {
|
|
22058
|
+
valid,
|
|
22059
|
+
errors,
|
|
22060
|
+
warnings,
|
|
22061
|
+
suggestedOrder
|
|
22062
|
+
};
|
|
22063
|
+
if (!valid && throwOnError) {
|
|
22064
|
+
const errorMessages = errors.map((e) => e.message).join("\n - ");
|
|
22065
|
+
throw new Error(
|
|
22066
|
+
`Plugin order validation failed:
|
|
22067
|
+
- ${errorMessages}${suggestedOrder ? `
|
|
22068
|
+
|
|
22069
|
+
Suggested order: ${suggestedOrder.join(" → ")}` : ""}`
|
|
22070
|
+
);
|
|
22071
|
+
}
|
|
22072
|
+
return result;
|
|
22073
|
+
}
|
|
22074
|
+
/**
|
|
22075
|
+
* Detect circular dependencies in plugin metadata
|
|
22076
|
+
*
|
|
22077
|
+
* @param pluginNames - List of plugin names
|
|
22078
|
+
* @returns List of errors for circular dependencies found
|
|
22079
|
+
*/
|
|
22080
|
+
detectCircularDependencies(pluginNames) {
|
|
22081
|
+
const errors = [];
|
|
22082
|
+
const visited = /* @__PURE__ */ new Set();
|
|
22083
|
+
const recursionStack = /* @__PURE__ */ new Set();
|
|
22084
|
+
const hasCycle = (plugin, path) => {
|
|
22085
|
+
if (recursionStack.has(plugin)) {
|
|
22086
|
+
const cyclePath = [...path, plugin].join(" → ");
|
|
22087
|
+
errors.push({
|
|
22088
|
+
type: "circular-dependency",
|
|
22089
|
+
plugin,
|
|
22090
|
+
message: `Circular dependency detected: ${cyclePath}`
|
|
22091
|
+
});
|
|
22092
|
+
return true;
|
|
22093
|
+
}
|
|
22094
|
+
if (visited.has(plugin)) {
|
|
22095
|
+
return false;
|
|
22096
|
+
}
|
|
22097
|
+
visited.add(plugin);
|
|
22098
|
+
recursionStack.add(plugin);
|
|
22099
|
+
const metadata = this.registry.get(plugin);
|
|
22100
|
+
if (metadata) {
|
|
22101
|
+
if (metadata.runAfter) {
|
|
22102
|
+
for (const dep of metadata.runAfter) {
|
|
22103
|
+
if (pluginNames.includes(dep)) {
|
|
22104
|
+
if (hasCycle(dep, [...path, plugin])) {
|
|
22105
|
+
recursionStack.delete(plugin);
|
|
22106
|
+
return true;
|
|
22241
22107
|
}
|
|
22242
22108
|
}
|
|
22243
|
-
if (nonHeaderLines.length > 0) {
|
|
22244
|
-
newNodes.push({
|
|
22245
|
-
type: "paragraph",
|
|
22246
|
-
children: [
|
|
22247
|
-
{
|
|
22248
|
-
type: "text",
|
|
22249
|
-
value: nonHeaderLines.join("\n")
|
|
22250
|
-
}
|
|
22251
|
-
]
|
|
22252
|
-
});
|
|
22253
|
-
}
|
|
22254
|
-
if (newNodes.length > 0) {
|
|
22255
|
-
nodesToReplace.push({ parent, index, newNodes });
|
|
22256
|
-
}
|
|
22257
22109
|
}
|
|
22258
22110
|
}
|
|
22259
|
-
}
|
|
22260
|
-
|
|
22261
|
-
|
|
22262
|
-
|
|
22111
|
+
}
|
|
22112
|
+
recursionStack.delete(plugin);
|
|
22113
|
+
return false;
|
|
22114
|
+
};
|
|
22115
|
+
for (const plugin of pluginNames) {
|
|
22116
|
+
if (!visited.has(plugin)) {
|
|
22117
|
+
hasCycle(plugin, []);
|
|
22118
|
+
}
|
|
22119
|
+
}
|
|
22120
|
+
return errors;
|
|
22121
|
+
}
|
|
22122
|
+
/**
|
|
22123
|
+
* Perform topological sort on plugins to find a valid execution order
|
|
22124
|
+
*
|
|
22125
|
+
* Uses Kahn's algorithm for topological sorting.
|
|
22126
|
+
*
|
|
22127
|
+
* @param pluginNames - List of plugin names to sort
|
|
22128
|
+
* @returns Sorted list of plugin names
|
|
22129
|
+
* @throws Error if plugins have circular dependencies
|
|
22130
|
+
*/
|
|
22131
|
+
topologicalSort(pluginNames) {
|
|
22132
|
+
const adjList = /* @__PURE__ */ new Map();
|
|
22133
|
+
const inDegree = /* @__PURE__ */ new Map();
|
|
22134
|
+
for (const plugin of pluginNames) {
|
|
22135
|
+
adjList.set(plugin, /* @__PURE__ */ new Set());
|
|
22136
|
+
inDegree.set(plugin, 0);
|
|
22137
|
+
}
|
|
22138
|
+
for (const plugin of pluginNames) {
|
|
22139
|
+
const metadata = this.registry.get(plugin);
|
|
22140
|
+
if (!metadata) continue;
|
|
22141
|
+
if (metadata.runBefore) {
|
|
22142
|
+
for (const beforePlugin of metadata.runBefore) {
|
|
22143
|
+
if (pluginNames.includes(beforePlugin)) {
|
|
22144
|
+
adjList.get(plugin).add(beforePlugin);
|
|
22145
|
+
inDegree.set(beforePlugin, inDegree.get(beforePlugin) + 1);
|
|
22146
|
+
}
|
|
22263
22147
|
}
|
|
22264
|
-
|
|
22265
|
-
|
|
22266
|
-
|
|
22267
|
-
|
|
22268
|
-
|
|
22269
|
-
|
|
22270
|
-
);
|
|
22148
|
+
}
|
|
22149
|
+
if (metadata.runAfter) {
|
|
22150
|
+
for (const afterPlugin of metadata.runAfter) {
|
|
22151
|
+
if (pluginNames.includes(afterPlugin)) {
|
|
22152
|
+
adjList.get(afterPlugin).add(plugin);
|
|
22153
|
+
inDegree.set(plugin, inDegree.get(plugin) + 1);
|
|
22271
22154
|
}
|
|
22272
|
-
const heading = convertToHeading(node, headerInfo.level, headerInfo.text);
|
|
22273
|
-
nodesToReplace.push({ parent, index, newNodes: [heading] });
|
|
22274
|
-
convertedCount++;
|
|
22275
22155
|
}
|
|
22276
22156
|
}
|
|
22277
|
-
});
|
|
22278
|
-
for (let i = nodesToReplace.length - 1; i >= 0; i--) {
|
|
22279
|
-
const { parent, index, newNodes } = nodesToReplace[i];
|
|
22280
|
-
parent.children.splice(index, 1, ...newNodes);
|
|
22281
22157
|
}
|
|
22282
|
-
|
|
22283
|
-
|
|
22158
|
+
const queue = [];
|
|
22159
|
+
const result = [];
|
|
22160
|
+
for (const [plugin, degree] of inDegree.entries()) {
|
|
22161
|
+
if (degree === 0) {
|
|
22162
|
+
queue.push(plugin);
|
|
22163
|
+
}
|
|
22284
22164
|
}
|
|
22285
|
-
|
|
22165
|
+
while (queue.length > 0) {
|
|
22166
|
+
const current = queue.shift();
|
|
22167
|
+
result.push(current);
|
|
22168
|
+
for (const neighbor of adjList.get(current)) {
|
|
22169
|
+
const newDegree = inDegree.get(neighbor) - 1;
|
|
22170
|
+
inDegree.set(neighbor, newDegree);
|
|
22171
|
+
if (newDegree === 0) {
|
|
22172
|
+
queue.push(neighbor);
|
|
22173
|
+
}
|
|
22174
|
+
}
|
|
22175
|
+
}
|
|
22176
|
+
if (result.length !== pluginNames.length) {
|
|
22177
|
+
throw new Error("Cannot generate topological sort: circular dependencies detected");
|
|
22178
|
+
}
|
|
22179
|
+
return result;
|
|
22180
|
+
}
|
|
22181
|
+
/**
|
|
22182
|
+
* Get metadata for a plugin
|
|
22183
|
+
*
|
|
22184
|
+
* @param pluginName - Name of the plugin
|
|
22185
|
+
* @returns Plugin metadata or undefined if not found
|
|
22186
|
+
*/
|
|
22187
|
+
getMetadata(pluginName) {
|
|
22188
|
+
return this.registry.get(pluginName);
|
|
22189
|
+
}
|
|
22190
|
+
/**
|
|
22191
|
+
* Add or update metadata for a plugin
|
|
22192
|
+
*
|
|
22193
|
+
* @param metadata - Plugin metadata to add/update
|
|
22194
|
+
*/
|
|
22195
|
+
registerPlugin(metadata) {
|
|
22196
|
+
this.registry.set(metadata.name, metadata);
|
|
22197
|
+
}
|
|
22198
|
+
}
|
|
22199
|
+
function createPluginRegistry(metadataList) {
|
|
22200
|
+
const registry = /* @__PURE__ */ new Map();
|
|
22201
|
+
for (const metadata of metadataList) {
|
|
22202
|
+
registry.set(metadata.name, metadata);
|
|
22203
|
+
}
|
|
22204
|
+
return registry;
|
|
22205
|
+
}
|
|
22206
|
+
|
|
22207
|
+
const PLUGIN_METADATA_LIST = [
|
|
22208
|
+
// Phase 1: Import Processing
|
|
22209
|
+
{
|
|
22210
|
+
name: "remarkImports",
|
|
22211
|
+
description: "Process @import directives and insert content as AST nodes",
|
|
22212
|
+
runBefore: [
|
|
22213
|
+
"remarkTemplateFields",
|
|
22214
|
+
"remarkLegalHeadersParser",
|
|
22215
|
+
"remarkFieldTracking",
|
|
22216
|
+
"remarkMixins"
|
|
22217
|
+
],
|
|
22218
|
+
required: false,
|
|
22219
|
+
version: "2.0.0"
|
|
22220
|
+
// Version 2.0 uses AST-based insertion
|
|
22221
|
+
},
|
|
22222
|
+
// Phase 2: Mixin and Field Processing
|
|
22223
|
+
{
|
|
22224
|
+
name: "remarkMixins",
|
|
22225
|
+
description: "Process mixin definitions and expansions",
|
|
22226
|
+
runAfter: ["remarkImports"],
|
|
22227
|
+
runBefore: ["remarkTemplateFields"],
|
|
22228
|
+
required: false
|
|
22229
|
+
},
|
|
22230
|
+
{
|
|
22231
|
+
name: "remarkTemplateFields",
|
|
22232
|
+
description: "Process {{field}} template patterns and resolve values",
|
|
22233
|
+
runAfter: ["remarkImports", "remarkMixins"],
|
|
22234
|
+
runBefore: ["remarkFieldTracking"],
|
|
22235
|
+
required: true
|
|
22236
|
+
},
|
|
22237
|
+
// Phase 3: Header Processing
|
|
22238
|
+
{
|
|
22239
|
+
name: "remarkLegalHeadersParser",
|
|
22240
|
+
description: "Parse legal header markers (l., ll., lll.) into structured headers",
|
|
22241
|
+
runAfter: ["remarkImports"],
|
|
22242
|
+
runBefore: ["remarkHeaders"],
|
|
22243
|
+
required: true
|
|
22244
|
+
},
|
|
22245
|
+
{
|
|
22246
|
+
name: "remarkHeaders",
|
|
22247
|
+
description: "Process headers and add CSS classes (legal-header-level-X)",
|
|
22248
|
+
runAfter: ["remarkLegalHeadersParser"],
|
|
22249
|
+
required: true
|
|
22250
|
+
},
|
|
22251
|
+
// Phase 4: Field Tracking
|
|
22252
|
+
{
|
|
22253
|
+
name: "remarkFieldTracking",
|
|
22254
|
+
description: "Track template fields for highlighting and analysis",
|
|
22255
|
+
runAfter: ["remarkTemplateFields"],
|
|
22256
|
+
required: false
|
|
22257
|
+
},
|
|
22258
|
+
// Phase 5: Cross-References and Clauses
|
|
22259
|
+
{
|
|
22260
|
+
name: "remarkCrossReferences",
|
|
22261
|
+
description: "Process cross-references between document sections",
|
|
22262
|
+
// Must run BEFORE remarkHeaders to extract |key| patterns before headers removes them
|
|
22263
|
+
runBefore: ["remarkHeaders"],
|
|
22264
|
+
runAfter: ["remarkLegalHeadersParser"],
|
|
22265
|
+
// After headers are parsed, before they're processed
|
|
22266
|
+
required: false
|
|
22267
|
+
},
|
|
22268
|
+
{
|
|
22269
|
+
name: "remarkCrossReferencesAst",
|
|
22270
|
+
description: "AST-based cross-reference processing (alternative to remarkCrossReferences)",
|
|
22271
|
+
runAfter: ["remarkHeaders", "remarkLegalHeadersParser"],
|
|
22272
|
+
conflicts: ["remarkCrossReferences"],
|
|
22273
|
+
// Can't use both
|
|
22274
|
+
required: false
|
|
22275
|
+
},
|
|
22276
|
+
{
|
|
22277
|
+
name: "remarkClauses",
|
|
22278
|
+
description: "Process conditional clauses ({{#if}}, {{#unless}})",
|
|
22279
|
+
// Note: Can run before or after remarkTemplateFields depending on use case
|
|
22280
|
+
required: false
|
|
22281
|
+
},
|
|
22282
|
+
// Phase 6: Date Processing
|
|
22283
|
+
{
|
|
22284
|
+
name: "remarkDates",
|
|
22285
|
+
description: "Process date fields and formatting",
|
|
22286
|
+
// Note: Can run before or after remarkTemplateFields depending on use case
|
|
22287
|
+
required: false
|
|
22288
|
+
},
|
|
22289
|
+
// Phase 7: Signature Lines
|
|
22290
|
+
{
|
|
22291
|
+
name: "remarkSignatureLines",
|
|
22292
|
+
description: "Process signature line markers",
|
|
22293
|
+
required: false
|
|
22294
|
+
},
|
|
22295
|
+
// Utility Plugins
|
|
22296
|
+
{
|
|
22297
|
+
name: "remarkDebugAst",
|
|
22298
|
+
description: "Debug plugin for visualizing AST structure",
|
|
22299
|
+
required: false
|
|
22300
|
+
}
|
|
22301
|
+
];
|
|
22302
|
+
const GLOBAL_PLUGIN_REGISTRY = createPluginRegistry(PLUGIN_METADATA_LIST);
|
|
22303
|
+
|
|
22304
|
+
const DEFAULT_OPTIONS = {
|
|
22305
|
+
minUnderscores: 10,
|
|
22306
|
+
addCssClass: true,
|
|
22307
|
+
cssClassName: "signature-line",
|
|
22308
|
+
debug: false
|
|
22286
22309
|
};
|
|
22287
|
-
function
|
|
22288
|
-
const
|
|
22289
|
-
|
|
22290
|
-
|
|
22291
|
-
|
|
22292
|
-
|
|
22293
|
-
|
|
22294
|
-
|
|
22295
|
-
|
|
22296
|
-
|
|
22297
|
-
|
|
22298
|
-
|
|
22299
|
-
|
|
22300
|
-
|
|
22301
|
-
|
|
22302
|
-
|
|
22303
|
-
|
|
22304
|
-
|
|
22305
|
-
|
|
22306
|
-
|
|
22307
|
-
|
|
22308
|
-
|
|
22309
|
-
|
|
22310
|
-
|
|
22311
|
-
|
|
22310
|
+
function sanitizeCssClassName(className) {
|
|
22311
|
+
const validPattern = /^[a-zA-Z_][\w-]*$/;
|
|
22312
|
+
if (!className || !validPattern.test(className)) {
|
|
22313
|
+
console.warn(
|
|
22314
|
+
`[signature-lines] Invalid CSS class name "${className}", using default "signature-line"`
|
|
22315
|
+
);
|
|
22316
|
+
return "signature-line";
|
|
22317
|
+
}
|
|
22318
|
+
return className;
|
|
22319
|
+
}
|
|
22320
|
+
const remarkSignatureLines = (options = {}) => {
|
|
22321
|
+
const config = { ...DEFAULT_OPTIONS, ...options };
|
|
22322
|
+
const safeCssClassName = sanitizeCssClassName(config.cssClassName);
|
|
22323
|
+
return (tree) => {
|
|
22324
|
+
if (config.debug) {
|
|
22325
|
+
console.log("[signature-lines] Processing tree...");
|
|
22326
|
+
}
|
|
22327
|
+
visit(tree, "text", (node, index, parent) => {
|
|
22328
|
+
if (index === void 0 || !parent) return;
|
|
22329
|
+
const text = node.value;
|
|
22330
|
+
const underscorePattern = new RegExp(`_{${config.minUnderscores},}`, "g");
|
|
22331
|
+
if (!underscorePattern.test(text)) {
|
|
22332
|
+
return;
|
|
22333
|
+
}
|
|
22334
|
+
if (config.debug) {
|
|
22335
|
+
console.log("[signature-lines] Found signature line in text:", text);
|
|
22336
|
+
}
|
|
22337
|
+
if (!config.addCssClass) {
|
|
22338
|
+
return;
|
|
22339
|
+
}
|
|
22340
|
+
const processedText = text.replace(underscorePattern, (match) => {
|
|
22341
|
+
if (config.debug) {
|
|
22342
|
+
console.log(`[signature-lines] Wrapping ${match.length} underscores`);
|
|
22343
|
+
}
|
|
22344
|
+
return `<span class="${safeCssClassName}">${match}</span>`;
|
|
22312
22345
|
});
|
|
22346
|
+
const htmlNode = {
|
|
22347
|
+
type: "html",
|
|
22348
|
+
value: processedText
|
|
22349
|
+
};
|
|
22350
|
+
parent.children[index] = htmlNode;
|
|
22351
|
+
});
|
|
22352
|
+
if (config.debug) {
|
|
22353
|
+
console.log("[signature-lines] Processing complete");
|
|
22313
22354
|
}
|
|
22355
|
+
};
|
|
22356
|
+
};
|
|
22357
|
+
|
|
22358
|
+
function escapeHtmlAttribute(value) {
|
|
22359
|
+
return value.replace(/&/g, "&").replace(/"/g, """).replace(/'/g, "'").replace(/</g, "<").replace(/>/g, ">");
|
|
22360
|
+
}
|
|
22361
|
+
function processTemplateLoops(content, metadata, context, enableFieldTracking = true) {
|
|
22362
|
+
const loopBlocks = findLoopBlocks(content);
|
|
22363
|
+
if (loopBlocks.length === 0) {
|
|
22364
|
+
return content;
|
|
22314
22365
|
}
|
|
22315
|
-
|
|
22316
|
-
|
|
22317
|
-
|
|
22318
|
-
|
|
22319
|
-
|
|
22320
|
-
validMatches.push(match);
|
|
22321
|
-
lastEnd = match.end;
|
|
22322
|
-
}
|
|
22366
|
+
let processedContent = content;
|
|
22367
|
+
for (let i = loopBlocks.length - 1; i >= 0; i--) {
|
|
22368
|
+
const loopBlock = loopBlocks[i];
|
|
22369
|
+
const expandedContent = expandLoopBlock(loopBlock, metadata, context, enableFieldTracking);
|
|
22370
|
+
processedContent = processedContent.slice(0, loopBlock.start) + expandedContent + processedContent.slice(loopBlock.end);
|
|
22323
22371
|
}
|
|
22324
|
-
|
|
22325
|
-
|
|
22326
|
-
|
|
22327
|
-
|
|
22328
|
-
|
|
22329
|
-
|
|
22330
|
-
|
|
22331
|
-
|
|
22332
|
-
|
|
22333
|
-
|
|
22334
|
-
|
|
22335
|
-
|
|
22336
|
-
|
|
22337
|
-
|
|
22338
|
-
|
|
22339
|
-
|
|
22340
|
-
|
|
22341
|
-
|
|
22342
|
-
|
|
22343
|
-
|
|
22344
|
-
}
|
|
22372
|
+
return processedContent;
|
|
22373
|
+
}
|
|
22374
|
+
function findLoopBlocks(content) {
|
|
22375
|
+
const loopBlocks = [];
|
|
22376
|
+
const loopPattern = /\{\{#([\w.]+)\}\}([\s\S]*?)\{\{\/\1\}\}/g;
|
|
22377
|
+
const conditionalPattern = /\{\{#if\s*([^}]+)\}\}([\s\S]*?)\{\{\/if\}\}/g;
|
|
22378
|
+
let match;
|
|
22379
|
+
while ((match = loopPattern.exec(content)) !== null) {
|
|
22380
|
+
const [fullMatch, variable, loopContent] = match;
|
|
22381
|
+
loopBlocks.push({
|
|
22382
|
+
variable,
|
|
22383
|
+
content: loopContent,
|
|
22384
|
+
start: match.index,
|
|
22385
|
+
end: match.index + fullMatch.length,
|
|
22386
|
+
fullMatch
|
|
22387
|
+
});
|
|
22388
|
+
}
|
|
22389
|
+
while ((match = conditionalPattern.exec(content)) !== null) {
|
|
22390
|
+
const [fullMatch, condition, conditionalContent] = match;
|
|
22391
|
+
loopBlocks.push({
|
|
22392
|
+
variable: `if ${condition}`,
|
|
22393
|
+
// Mark as conditional
|
|
22394
|
+
content: conditionalContent,
|
|
22395
|
+
start: match.index,
|
|
22396
|
+
end: match.index + fullMatch.length,
|
|
22397
|
+
fullMatch
|
|
22398
|
+
});
|
|
22399
|
+
}
|
|
22400
|
+
return loopBlocks;
|
|
22401
|
+
}
|
|
22402
|
+
function expandLoopBlock(loopBlock, metadata, parentContext, enableFieldTracking = true) {
|
|
22403
|
+
const { variable, content } = loopBlock;
|
|
22404
|
+
if (variable.startsWith("if ")) {
|
|
22405
|
+
const condition = variable.substring(3).trim();
|
|
22406
|
+
const conditionValue = evaluateCondition(condition, metadata);
|
|
22407
|
+
fieldTracker.trackField(`if ${condition}`, {
|
|
22408
|
+
value: conditionValue,
|
|
22409
|
+
hasLogic: true,
|
|
22410
|
+
mixinUsed: "conditional"
|
|
22411
|
+
});
|
|
22412
|
+
const elseIndex = content.indexOf("{{else}}");
|
|
22413
|
+
if (elseIndex !== -1) {
|
|
22414
|
+
const ifContent = content.substring(0, elseIndex);
|
|
22415
|
+
const elseContent = content.substring(elseIndex + 8);
|
|
22416
|
+
const selectedContent = conditionValue ? ifContent : elseContent;
|
|
22417
|
+
return processTemplateContent(selectedContent, metadata, parentContext, enableFieldTracking);
|
|
22345
22418
|
} else {
|
|
22346
|
-
|
|
22347
|
-
|
|
22348
|
-
|
|
22349
|
-
|
|
22350
|
-
|
|
22351
|
-
value: match.content
|
|
22352
|
-
}
|
|
22353
|
-
]
|
|
22354
|
-
});
|
|
22419
|
+
if (conditionValue) {
|
|
22420
|
+
return processTemplateContent(content, metadata, parentContext, enableFieldTracking);
|
|
22421
|
+
} else {
|
|
22422
|
+
return "";
|
|
22423
|
+
}
|
|
22355
22424
|
}
|
|
22356
|
-
pos = match.end;
|
|
22357
22425
|
}
|
|
22358
|
-
|
|
22359
|
-
|
|
22360
|
-
|
|
22361
|
-
|
|
22362
|
-
|
|
22363
|
-
|
|
22364
|
-
|
|
22365
|
-
|
|
22426
|
+
const loopValue = resolveLoopVariable(variable, metadata, parentContext);
|
|
22427
|
+
fieldTracker.trackField(variable, {
|
|
22428
|
+
value: loopValue,
|
|
22429
|
+
hasLogic: true,
|
|
22430
|
+
mixinUsed: "loop"
|
|
22431
|
+
});
|
|
22432
|
+
if (Array.isArray(loopValue)) {
|
|
22433
|
+
return expandArrayLoop(
|
|
22434
|
+
variable,
|
|
22435
|
+
content,
|
|
22436
|
+
loopValue,
|
|
22437
|
+
metadata,
|
|
22438
|
+
parentContext,
|
|
22439
|
+
enableFieldTracking
|
|
22440
|
+
);
|
|
22441
|
+
} else if (loopValue) {
|
|
22442
|
+
return expandConditionalBlock(
|
|
22443
|
+
variable,
|
|
22444
|
+
content,
|
|
22445
|
+
loopValue,
|
|
22446
|
+
metadata,
|
|
22447
|
+
parentContext,
|
|
22448
|
+
enableFieldTracking
|
|
22449
|
+
);
|
|
22450
|
+
} else {
|
|
22451
|
+
return "";
|
|
22366
22452
|
}
|
|
22367
|
-
|
|
22368
|
-
|
|
22369
|
-
|
|
22370
|
-
|
|
22371
|
-
|
|
22372
|
-
|
|
22373
|
-
|
|
22453
|
+
}
|
|
22454
|
+
function expandArrayLoop(variable, content, items, metadata, parentContext, enableFieldTracking = true) {
|
|
22455
|
+
const expandedParts = [];
|
|
22456
|
+
for (let i = 0; i < items.length; i++) {
|
|
22457
|
+
const item = items[i];
|
|
22458
|
+
const loopContext = {
|
|
22459
|
+
variable,
|
|
22460
|
+
item,
|
|
22461
|
+
index: i,
|
|
22462
|
+
total: items.length,
|
|
22463
|
+
parent: parentContext
|
|
22464
|
+
};
|
|
22465
|
+
const enhancedMetadata = createEnhancedMetadata(metadata, item, loopContext);
|
|
22466
|
+
let processedContent = content;
|
|
22467
|
+
processedContent = processTemplateLoops(
|
|
22468
|
+
processedContent,
|
|
22469
|
+
enhancedMetadata,
|
|
22470
|
+
loopContext,
|
|
22471
|
+
enableFieldTracking
|
|
22472
|
+
);
|
|
22473
|
+
processedContent = processItemMixins(
|
|
22474
|
+
processedContent,
|
|
22475
|
+
enhancedMetadata,
|
|
22476
|
+
loopContext,
|
|
22477
|
+
enableFieldTracking
|
|
22478
|
+
);
|
|
22479
|
+
processedContent = convertMarkdownListToHtml(processedContent);
|
|
22480
|
+
expandedParts.push(processedContent);
|
|
22374
22481
|
}
|
|
22375
|
-
return
|
|
22482
|
+
return expandedParts.join("\n");
|
|
22376
22483
|
}
|
|
22377
|
-
|
|
22378
|
-
const
|
|
22379
|
-
|
|
22380
|
-
|
|
22381
|
-
|
|
22382
|
-
|
|
22484
|
+
function expandConditionalBlock(variable, content, value, metadata, parentContext, enableFieldTracking = true) {
|
|
22485
|
+
const enhancedMetadata = {
|
|
22486
|
+
...metadata,
|
|
22487
|
+
[variable]: value
|
|
22488
|
+
};
|
|
22489
|
+
let processedContent = processTemplateLoops(
|
|
22490
|
+
content,
|
|
22491
|
+
enhancedMetadata,
|
|
22492
|
+
parentContext,
|
|
22493
|
+
enableFieldTracking
|
|
22494
|
+
);
|
|
22495
|
+
processedContent = processItemMixins(
|
|
22496
|
+
processedContent,
|
|
22497
|
+
enhancedMetadata,
|
|
22498
|
+
parentContext,
|
|
22499
|
+
enableFieldTracking
|
|
22500
|
+
);
|
|
22501
|
+
return processedContent;
|
|
22502
|
+
}
|
|
22503
|
+
function resolveLoopVariable(variable, metadata, parentContext) {
|
|
22504
|
+
const resolvedFromMetadata = resolvePath(metadata, variable);
|
|
22505
|
+
if (resolvedFromMetadata !== void 0) {
|
|
22506
|
+
return resolvedFromMetadata;
|
|
22383
22507
|
}
|
|
22384
|
-
|
|
22385
|
-
|
|
22386
|
-
|
|
22387
|
-
|
|
22388
|
-
|
|
22389
|
-
|
|
22390
|
-
|
|
22391
|
-
|
|
22392
|
-
|
|
22393
|
-
|
|
22394
|
-
|
|
22395
|
-
|
|
22396
|
-
|
|
22397
|
-
break;
|
|
22398
|
-
case "m":
|
|
22399
|
-
arithmetic = { type: "months", amount: numAmount };
|
|
22400
|
-
break;
|
|
22401
|
-
case "y":
|
|
22402
|
-
arithmetic = { type: "years", amount: numAmount };
|
|
22403
|
-
break;
|
|
22404
|
-
default:
|
|
22405
|
-
arithmetic = { type: "days", amount: numAmount };
|
|
22508
|
+
if (parentContext && parentContext.item) {
|
|
22509
|
+
const resolvedFromContext = resolvePath(parentContext.item, variable);
|
|
22510
|
+
if (resolvedFromContext !== void 0) {
|
|
22511
|
+
return resolvedFromContext;
|
|
22512
|
+
}
|
|
22513
|
+
}
|
|
22514
|
+
let ctx = parentContext;
|
|
22515
|
+
while (ctx && ctx.parent) {
|
|
22516
|
+
ctx = ctx.parent;
|
|
22517
|
+
if (ctx.item) {
|
|
22518
|
+
const resolvedFromNestedContext = resolvePath(ctx.item, variable);
|
|
22519
|
+
if (resolvedFromNestedContext !== void 0) {
|
|
22520
|
+
return resolvedFromNestedContext;
|
|
22406
22521
|
}
|
|
22407
|
-
} else if (arithmeticPart !== "") {
|
|
22408
|
-
return { arithmetic: null, format: null, isValid: false };
|
|
22409
22522
|
}
|
|
22410
22523
|
}
|
|
22411
|
-
return
|
|
22524
|
+
return void 0;
|
|
22412
22525
|
}
|
|
22413
|
-
function
|
|
22414
|
-
|
|
22415
|
-
|
|
22416
|
-
|
|
22417
|
-
return addDays(baseDate, arithmetic.amount);
|
|
22418
|
-
case "months":
|
|
22419
|
-
return addMonths(baseDate, arithmetic.amount);
|
|
22420
|
-
case "years":
|
|
22421
|
-
return addYears(baseDate, arithmetic.amount);
|
|
22422
|
-
default:
|
|
22423
|
-
return baseDate;
|
|
22526
|
+
function createEnhancedMetadata(metadata, item, context) {
|
|
22527
|
+
const enhanced = { ...metadata };
|
|
22528
|
+
if (item && typeof item === "object" && !Array.isArray(item)) {
|
|
22529
|
+
Object.assign(enhanced, item);
|
|
22424
22530
|
}
|
|
22531
|
+
enhanced["."] = item;
|
|
22532
|
+
enhanced["@index"] = context.index;
|
|
22533
|
+
enhanced["@total"] = context.total;
|
|
22534
|
+
enhanced["@first"] = context.index === 0;
|
|
22535
|
+
enhanced["@last"] = context.index === context.total - 1;
|
|
22536
|
+
return enhanced;
|
|
22425
22537
|
}
|
|
22426
|
-
function
|
|
22427
|
-
|
|
22428
|
-
|
|
22429
|
-
|
|
22430
|
-
|
|
22431
|
-
|
|
22432
|
-
|
|
22433
|
-
|
|
22434
|
-
|
|
22435
|
-
|
|
22436
|
-
|
|
22437
|
-
|
|
22438
|
-
|
|
22538
|
+
function evaluateHelperExpression(expression, metadata) {
|
|
22539
|
+
try {
|
|
22540
|
+
const match = expression.match(/^(\w+)\((.*)\)$/);
|
|
22541
|
+
if (!match) return void 0;
|
|
22542
|
+
const [, helperName, argsString] = match;
|
|
22543
|
+
const helper = extensionHelpers[helperName];
|
|
22544
|
+
if (!helper || typeof helper !== "function") {
|
|
22545
|
+
return void 0;
|
|
22546
|
+
}
|
|
22547
|
+
const args = argsString ? parseHelperArguments(argsString, metadata) : [];
|
|
22548
|
+
return helper(...args);
|
|
22549
|
+
} catch (error) {
|
|
22550
|
+
console.error(`Error evaluating helper expression: ${expression}`, error);
|
|
22551
|
+
return void 0;
|
|
22439
22552
|
}
|
|
22440
22553
|
}
|
|
22441
|
-
function
|
|
22442
|
-
const
|
|
22443
|
-
|
|
22444
|
-
|
|
22445
|
-
|
|
22446
|
-
|
|
22447
|
-
|
|
22448
|
-
|
|
22449
|
-
"
|
|
22450
|
-
|
|
22451
|
-
|
|
22452
|
-
|
|
22453
|
-
|
|
22454
|
-
|
|
22455
|
-
|
|
22456
|
-
|
|
22457
|
-
"
|
|
22458
|
-
|
|
22459
|
-
|
|
22460
|
-
|
|
22461
|
-
|
|
22462
|
-
|
|
22463
|
-
|
|
22464
|
-
|
|
22465
|
-
|
|
22466
|
-
|
|
22467
|
-
|
|
22468
|
-
case "european":
|
|
22469
|
-
case "dd/mm/yyyy":
|
|
22470
|
-
return `${day}/${month}/${year}`;
|
|
22471
|
-
case "long":
|
|
22472
|
-
return `${monthNames[date.getMonth()]} ${dayNumber}, ${year}`;
|
|
22473
|
-
case "medium":
|
|
22474
|
-
return `${monthNames[date.getMonth()].substring(0, 3)} ${dayNumber}, ${year}`;
|
|
22475
|
-
case "short":
|
|
22476
|
-
return `${monthNames[date.getMonth()].substring(0, 3)} ${dayNumber}, ${String(year).substring(2)}`;
|
|
22477
|
-
case "legal": {
|
|
22478
|
-
const suffix = getOrdinalSuffix(dayNumber);
|
|
22479
|
-
return `${monthNames[date.getMonth()]} ${dayNumber}${suffix}, ${year}`;
|
|
22554
|
+
function parseHelperArguments(argsString, metadata) {
|
|
22555
|
+
const args = [];
|
|
22556
|
+
let currentArg = "";
|
|
22557
|
+
let parenDepth = 0;
|
|
22558
|
+
let inQuotes = false;
|
|
22559
|
+
let quoteChar = "";
|
|
22560
|
+
for (let i = 0; i < argsString.length; i++) {
|
|
22561
|
+
const char = argsString[i];
|
|
22562
|
+
if ((char === '"' || char === "'") && !inQuotes) {
|
|
22563
|
+
inQuotes = true;
|
|
22564
|
+
quoteChar = char;
|
|
22565
|
+
currentArg += char;
|
|
22566
|
+
} else if (char === quoteChar && inQuotes) {
|
|
22567
|
+
inQuotes = false;
|
|
22568
|
+
quoteChar = "";
|
|
22569
|
+
currentArg += char;
|
|
22570
|
+
} else if (char === "(" && !inQuotes) {
|
|
22571
|
+
parenDepth++;
|
|
22572
|
+
currentArg += char;
|
|
22573
|
+
} else if (char === ")" && !inQuotes) {
|
|
22574
|
+
parenDepth--;
|
|
22575
|
+
currentArg += char;
|
|
22576
|
+
} else if (char === "," && parenDepth === 0 && !inQuotes) {
|
|
22577
|
+
args.push(resolveHelperArgument(currentArg.trim(), metadata));
|
|
22578
|
+
currentArg = "";
|
|
22579
|
+
} else {
|
|
22580
|
+
currentArg += char;
|
|
22480
22581
|
}
|
|
22481
|
-
default:
|
|
22482
|
-
return `${year}-${month}-${day}`;
|
|
22483
22582
|
}
|
|
22583
|
+
if (currentArg.trim()) {
|
|
22584
|
+
args.push(resolveHelperArgument(currentArg.trim(), metadata));
|
|
22585
|
+
}
|
|
22586
|
+
return args;
|
|
22484
22587
|
}
|
|
22485
|
-
function
|
|
22486
|
-
|
|
22588
|
+
function resolveHelperArgument(arg, metadata) {
|
|
22589
|
+
if (arg.startsWith('"') && arg.endsWith('"') || arg.startsWith("'") && arg.endsWith("'")) {
|
|
22590
|
+
return arg.slice(1, -1);
|
|
22591
|
+
}
|
|
22592
|
+
if (arg === "true") return true;
|
|
22593
|
+
if (arg === "false") return false;
|
|
22594
|
+
if (/^\d+$/.test(arg)) {
|
|
22595
|
+
return parseInt(arg, 10);
|
|
22596
|
+
}
|
|
22597
|
+
if (/^\d+\.\d+$/.test(arg)) {
|
|
22598
|
+
return parseFloat(arg);
|
|
22599
|
+
}
|
|
22600
|
+
if (arg === "@today") {
|
|
22601
|
+
return metadata["@today"] ? new Date(metadata["@today"]) : /* @__PURE__ */ new Date();
|
|
22602
|
+
}
|
|
22603
|
+
if (arg.includes("(") && arg.includes(")")) {
|
|
22604
|
+
const result = evaluateHelperExpression(arg, metadata);
|
|
22605
|
+
if (result !== void 0) {
|
|
22606
|
+
return result;
|
|
22607
|
+
}
|
|
22608
|
+
}
|
|
22609
|
+
return resolvePath(metadata, arg);
|
|
22487
22610
|
}
|
|
22488
|
-
function
|
|
22489
|
-
|
|
22490
|
-
|
|
22611
|
+
function resolvePath(obj, path) {
|
|
22612
|
+
const keys = path.split(".");
|
|
22613
|
+
let current = obj;
|
|
22614
|
+
for (const key of keys) {
|
|
22615
|
+
if (current && typeof current === "object" && key in current) {
|
|
22616
|
+
current = current[key];
|
|
22617
|
+
} else {
|
|
22618
|
+
return void 0;
|
|
22619
|
+
}
|
|
22491
22620
|
}
|
|
22492
|
-
|
|
22493
|
-
const fieldName = `date.${originalToken.replace(/[@[\]]/g, "")}`;
|
|
22494
|
-
return `<span class="${cssClass}" data-field="${fieldName.replace(/"/g, """)}">${value}</span>`;
|
|
22621
|
+
return current;
|
|
22495
22622
|
}
|
|
22496
|
-
function
|
|
22497
|
-
|
|
22498
|
-
|
|
22499
|
-
|
|
22500
|
-
|
|
22501
|
-
|
|
22502
|
-
|
|
22503
|
-
|
|
22504
|
-
if (!isValid) {
|
|
22505
|
-
return match;
|
|
22506
|
-
}
|
|
22507
|
-
let date = /* @__PURE__ */ new Date();
|
|
22508
|
-
const hasArithmetic = !!arithmetic;
|
|
22509
|
-
if (arithmetic) {
|
|
22510
|
-
date = applyDateArithmetic(date, arithmetic);
|
|
22511
|
-
}
|
|
22512
|
-
const format = tokenFormat || metadata["date-format"] || "YYYY-MM-DD";
|
|
22513
|
-
const formattedDate = formatDateBasic(date, format);
|
|
22514
|
-
fieldTracker.trackField(`date.${match.replace(/[@[\]]/g, "")}`, {
|
|
22515
|
-
value: formattedDate,
|
|
22516
|
-
originalValue: match,
|
|
22517
|
-
hasLogic: hasArithmetic
|
|
22518
|
-
});
|
|
22519
|
-
hasChanges = true;
|
|
22520
|
-
return formatDateValue(formattedDate, match, enableFieldTracking, hasArithmetic);
|
|
22521
|
-
} catch (error) {
|
|
22522
|
-
console.warn(`Error processing date reference ${match}:`, error);
|
|
22523
|
-
return match;
|
|
22524
|
-
}
|
|
22525
|
-
});
|
|
22526
|
-
if (hasChanges) {
|
|
22527
|
-
if (enableFieldTracking && modifiedValue.includes("<span")) {
|
|
22528
|
-
if (parent && typeof index === "number") {
|
|
22529
|
-
const htmlNode = {
|
|
22530
|
-
type: "html",
|
|
22531
|
-
value: modifiedValue
|
|
22532
|
-
};
|
|
22533
|
-
parent.children[index] = htmlNode;
|
|
22534
|
-
}
|
|
22535
|
-
} else {
|
|
22536
|
-
node.value = modifiedValue;
|
|
22623
|
+
function processItemMixins(content, metadata, context, enableFieldTracking = true) {
|
|
22624
|
+
const mixinPattern = /\{\{([^}]+)\}\}/g;
|
|
22625
|
+
return content.replace(mixinPattern, (match, variable) => {
|
|
22626
|
+
const trimmedVar = variable.trim();
|
|
22627
|
+
if (trimmedVar.includes("?") && trimmedVar.includes(":")) {
|
|
22628
|
+
const result = processConditionalExpression(trimmedVar, metadata, enableFieldTracking);
|
|
22629
|
+
if (enableFieldTracking) {
|
|
22630
|
+
return `<span class="highlight">${result}</span>`;
|
|
22537
22631
|
}
|
|
22632
|
+
return result;
|
|
22538
22633
|
}
|
|
22539
|
-
|
|
22540
|
-
|
|
22541
|
-
|
|
22542
|
-
|
|
22543
|
-
|
|
22544
|
-
|
|
22545
|
-
|
|
22546
|
-
|
|
22547
|
-
|
|
22548
|
-
|
|
22549
|
-
|
|
22550
|
-
|
|
22551
|
-
const format = formatOverride || metadata["date-format"] || "YYYY-MM-DD";
|
|
22552
|
-
const formattedDate = formatDateBasic(date, format);
|
|
22553
|
-
fieldTracker.trackField(`date.${match.replace(/[@[\]]/g, "")}`, {
|
|
22554
|
-
value: formattedDate,
|
|
22555
|
-
originalValue: match,
|
|
22556
|
-
hasLogic: false
|
|
22557
|
-
});
|
|
22558
|
-
hasChanges = true;
|
|
22559
|
-
if (enableFieldTracking) {
|
|
22560
|
-
const cssClass = getDateFieldCssClass(false);
|
|
22561
|
-
const fieldName = `date.${match.replace(/[@[\]]/g, "")}`;
|
|
22562
|
-
return `<span class="${cssClass}" data-field="${fieldName.replace(/"/g, """)}">${formattedDate}</span>`;
|
|
22563
|
-
} else {
|
|
22564
|
-
return formattedDate;
|
|
22565
|
-
}
|
|
22566
|
-
} catch (error) {
|
|
22567
|
-
console.warn(`Error processing date reference ${match}:`, error);
|
|
22568
|
-
return match;
|
|
22634
|
+
if (trimmedVar.includes("(") && trimmedVar.includes(")")) {
|
|
22635
|
+
const result = evaluateHelperExpression(trimmedVar, metadata);
|
|
22636
|
+
if (result !== void 0) {
|
|
22637
|
+
fieldTracker.trackField(trimmedVar, {
|
|
22638
|
+
value: result,
|
|
22639
|
+
hasLogic: true,
|
|
22640
|
+
mixinUsed: "helper"
|
|
22641
|
+
});
|
|
22642
|
+
if (enableFieldTracking) {
|
|
22643
|
+
const escapedField = escapeHtmlAttribute(trimmedVar);
|
|
22644
|
+
const stringResult = String(result);
|
|
22645
|
+
return `<span class="highlight"><span class="imported-value" data-field="${escapedField}">${stringResult}</span></span>`;
|
|
22569
22646
|
}
|
|
22647
|
+
return String(result);
|
|
22570
22648
|
}
|
|
22571
|
-
);
|
|
22572
|
-
if (hasChanges) {
|
|
22573
|
-
node.value = modifiedValue;
|
|
22574
22649
|
}
|
|
22650
|
+
const value = resolveVariablePath(trimmedVar, metadata);
|
|
22651
|
+
if (value === void 0 || value === null) {
|
|
22652
|
+
if (enableFieldTracking) {
|
|
22653
|
+
return `<span class="legal-field missing-value" data-field="${escapeHtmlAttribute(trimmedVar)}">[[${trimmedVar}]]</span>`;
|
|
22654
|
+
}
|
|
22655
|
+
return `{{${trimmedVar}}}`;
|
|
22656
|
+
}
|
|
22657
|
+
if (enableFieldTracking) {
|
|
22658
|
+
return `<span class="imported-value" data-field="${escapeHtmlAttribute(trimmedVar)}">${String(value)}</span>`;
|
|
22659
|
+
}
|
|
22660
|
+
return String(value);
|
|
22575
22661
|
});
|
|
22576
22662
|
}
|
|
22577
|
-
|
|
22578
|
-
const
|
|
22579
|
-
|
|
22580
|
-
|
|
22581
|
-
|
|
22663
|
+
function processConditionalExpression(expression, metadata, enableFieldTracking = true) {
|
|
22664
|
+
const questionIndex = findOperatorIndex(expression, "?");
|
|
22665
|
+
const colonIndex = findOperatorIndex(expression, ":", questionIndex);
|
|
22666
|
+
if (questionIndex === -1 || colonIndex === -1) {
|
|
22667
|
+
return expression;
|
|
22668
|
+
}
|
|
22669
|
+
const condition = expression.substring(0, questionIndex).trim();
|
|
22670
|
+
const truePart = expression.substring(questionIndex + 1, colonIndex).trim();
|
|
22671
|
+
const falsePart = expression.substring(colonIndex + 1).trim();
|
|
22672
|
+
const conditionValue = resolveVariablePath(condition, metadata);
|
|
22673
|
+
const selectedPart = conditionValue ? truePart : falsePart;
|
|
22674
|
+
if (selectedPart.startsWith('"') && selectedPart.endsWith('"') || // eslint-disable-next-line quotes
|
|
22675
|
+
selectedPart.startsWith("'") && selectedPart.endsWith("'")) {
|
|
22676
|
+
const unquotedValue = selectedPart.slice(1, -1);
|
|
22677
|
+
if (enableFieldTracking) {
|
|
22678
|
+
return `<span class="imported-value" data-field="${escapeHtmlAttribute(expression)}">${unquotedValue}</span>`;
|
|
22582
22679
|
}
|
|
22583
|
-
|
|
22584
|
-
|
|
22585
|
-
|
|
22680
|
+
return unquotedValue;
|
|
22681
|
+
}
|
|
22682
|
+
const processedValue = processExpression(selectedPart, metadata);
|
|
22683
|
+
if (enableFieldTracking) {
|
|
22684
|
+
return `<span class="imported-value" data-field="${escapeHtmlAttribute(expression)}">${processedValue}</span>`;
|
|
22685
|
+
}
|
|
22686
|
+
return processedValue;
|
|
22687
|
+
}
|
|
22688
|
+
function findOperatorIndex(expression, operator, startIndex = 0) {
|
|
22689
|
+
let inQuotes = false;
|
|
22690
|
+
let quoteChar = "";
|
|
22691
|
+
for (let i = startIndex; i < expression.length; i++) {
|
|
22692
|
+
const char = expression[i];
|
|
22693
|
+
if (!inQuotes && (char === '"' || char === "'")) {
|
|
22694
|
+
inQuotes = true;
|
|
22695
|
+
quoteChar = char;
|
|
22696
|
+
} else if (inQuotes && char === quoteChar) {
|
|
22697
|
+
inQuotes = false;
|
|
22698
|
+
quoteChar = "";
|
|
22699
|
+
} else if (!inQuotes && char === operator) {
|
|
22700
|
+
return i;
|
|
22586
22701
|
}
|
|
22587
|
-
};
|
|
22588
|
-
};
|
|
22589
|
-
|
|
22590
|
-
const DEFAULT_OPTIONS = {
|
|
22591
|
-
minUnderscores: 10,
|
|
22592
|
-
addCssClass: true,
|
|
22593
|
-
cssClassName: "signature-line",
|
|
22594
|
-
debug: false
|
|
22595
|
-
};
|
|
22596
|
-
function sanitizeCssClassName(className) {
|
|
22597
|
-
const validPattern = /^[a-zA-Z_][\w-]*$/;
|
|
22598
|
-
if (!className || !validPattern.test(className)) {
|
|
22599
|
-
console.warn(
|
|
22600
|
-
`[signature-lines] Invalid CSS class name "${className}", using default "signature-line"`
|
|
22601
|
-
);
|
|
22602
|
-
return "signature-line";
|
|
22603
22702
|
}
|
|
22604
|
-
return
|
|
22703
|
+
return -1;
|
|
22605
22704
|
}
|
|
22606
|
-
|
|
22607
|
-
|
|
22608
|
-
|
|
22609
|
-
|
|
22610
|
-
|
|
22611
|
-
|
|
22705
|
+
function processExpression(expression, metadata) {
|
|
22706
|
+
if (expression.includes("+") && (expression.includes('"') || expression.includes("'"))) {
|
|
22707
|
+
return evaluateStringConcatenation(expression, metadata);
|
|
22708
|
+
}
|
|
22709
|
+
if (expression.includes("*") || expression.includes("/") || expression.includes("+") || expression.includes("-")) {
|
|
22710
|
+
return evaluateMathematicalExpression(expression, metadata);
|
|
22711
|
+
}
|
|
22712
|
+
const value = resolveVariablePath(expression, metadata);
|
|
22713
|
+
return value !== void 0 ? String(value) : expression;
|
|
22714
|
+
}
|
|
22715
|
+
function evaluateStringConcatenation(expression, metadata) {
|
|
22716
|
+
try {
|
|
22717
|
+
let processedExpression = expression.trim();
|
|
22718
|
+
const variablePattern = /\b[a-zA-Z_][a-zA-Z0-9_.]*\b/g;
|
|
22719
|
+
const variables = /* @__PURE__ */ new Set();
|
|
22720
|
+
let match;
|
|
22721
|
+
let inQuotes = false;
|
|
22722
|
+
let quoteChar = "";
|
|
22723
|
+
for (let i = 0; i < expression.length; i++) {
|
|
22724
|
+
const char = expression[i];
|
|
22725
|
+
if (!inQuotes && (char === '"' || char === "'")) {
|
|
22726
|
+
inQuotes = true;
|
|
22727
|
+
quoteChar = char;
|
|
22728
|
+
} else if (inQuotes && char === quoteChar) {
|
|
22729
|
+
inQuotes = false;
|
|
22730
|
+
quoteChar = "";
|
|
22731
|
+
}
|
|
22612
22732
|
}
|
|
22613
|
-
|
|
22614
|
-
|
|
22615
|
-
const
|
|
22616
|
-
const
|
|
22617
|
-
if (
|
|
22618
|
-
|
|
22733
|
+
while ((match = variablePattern.exec(expression)) !== null) {
|
|
22734
|
+
const beforeMatch = expression.substring(0, match.index);
|
|
22735
|
+
const openQuotes = (beforeMatch.match(/"/g) || []).length;
|
|
22736
|
+
const openSingleQuotes = (beforeMatch.match(/'/g) || []).length;
|
|
22737
|
+
if (openQuotes % 2 === 0 && openSingleQuotes % 2 === 0) {
|
|
22738
|
+
variables.add(match[0]);
|
|
22619
22739
|
}
|
|
22620
|
-
|
|
22621
|
-
|
|
22740
|
+
}
|
|
22741
|
+
for (const variable of variables) {
|
|
22742
|
+
const value = resolveVariablePath(variable, metadata);
|
|
22743
|
+
if (value !== void 0) {
|
|
22744
|
+
const regex = new RegExp(`\\b${variable.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\\b`, "g");
|
|
22745
|
+
if (typeof value === "string") {
|
|
22746
|
+
processedExpression = processedExpression.replace(regex, `"${value}"`);
|
|
22747
|
+
} else {
|
|
22748
|
+
processedExpression = processedExpression.replace(regex, String(value));
|
|
22749
|
+
}
|
|
22750
|
+
} else {
|
|
22751
|
+
return expression;
|
|
22622
22752
|
}
|
|
22623
|
-
|
|
22624
|
-
|
|
22753
|
+
}
|
|
22754
|
+
const result = new Function(`"use strict"; return (${processedExpression})`)();
|
|
22755
|
+
return String(result);
|
|
22756
|
+
} catch (error) {
|
|
22757
|
+
return expression;
|
|
22758
|
+
}
|
|
22759
|
+
}
|
|
22760
|
+
function evaluateMathematicalExpression(expression, metadata) {
|
|
22761
|
+
try {
|
|
22762
|
+
let processedExpression = expression;
|
|
22763
|
+
const variablePattern = /[a-zA-Z_][a-zA-Z0-9_.]*(?![a-zA-Z0-9_.])/g;
|
|
22764
|
+
const variables = /* @__PURE__ */ new Set();
|
|
22765
|
+
let match;
|
|
22766
|
+
while ((match = variablePattern.exec(expression)) !== null) {
|
|
22767
|
+
variables.add(match[0]);
|
|
22768
|
+
}
|
|
22769
|
+
for (const variable of variables) {
|
|
22770
|
+
const value = resolveVariablePath(variable, metadata);
|
|
22771
|
+
if (value !== void 0 && !isNaN(Number(value))) {
|
|
22772
|
+
const regex = new RegExp(`\\b${variable.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\\b`, "g");
|
|
22773
|
+
processedExpression = processedExpression.replace(regex, String(value));
|
|
22774
|
+
} else {
|
|
22775
|
+
return expression;
|
|
22625
22776
|
}
|
|
22626
|
-
const processedText = text.replace(underscorePattern, (match) => {
|
|
22627
|
-
if (config.debug) {
|
|
22628
|
-
console.log(`[signature-lines] Wrapping ${match.length} underscores`);
|
|
22629
|
-
}
|
|
22630
|
-
return `<span class="${safeCssClassName}">${match}</span>`;
|
|
22631
|
-
});
|
|
22632
|
-
const htmlNode = {
|
|
22633
|
-
type: "html",
|
|
22634
|
-
value: processedText
|
|
22635
|
-
};
|
|
22636
|
-
parent.children[index] = htmlNode;
|
|
22637
|
-
});
|
|
22638
|
-
if (config.debug) {
|
|
22639
|
-
console.log("[signature-lines] Processing complete");
|
|
22640
22777
|
}
|
|
22641
|
-
|
|
22642
|
-
|
|
22778
|
+
if (!/^[\d\s+\-*/().]+$/.test(processedExpression)) {
|
|
22779
|
+
return expression;
|
|
22780
|
+
}
|
|
22781
|
+
const result = new Function(`"use strict"; return (${processedExpression})`)();
|
|
22782
|
+
return typeof result === "number" && !isNaN(result) ? String(result) : expression;
|
|
22783
|
+
} catch (error) {
|
|
22784
|
+
return expression;
|
|
22785
|
+
}
|
|
22786
|
+
}
|
|
22787
|
+
function resolveVariablePath(path, metadata, context) {
|
|
22788
|
+
if (path === ".") {
|
|
22789
|
+
return metadata["."];
|
|
22790
|
+
}
|
|
22791
|
+
const parts = path.split(".");
|
|
22792
|
+
let current = metadata;
|
|
22793
|
+
for (const part of parts) {
|
|
22794
|
+
if (current && typeof current === "object" && Object.prototype.hasOwnProperty.call(current, part)) {
|
|
22795
|
+
current = current[part];
|
|
22796
|
+
} else {
|
|
22797
|
+
return void 0;
|
|
22798
|
+
}
|
|
22799
|
+
}
|
|
22800
|
+
return current;
|
|
22801
|
+
}
|
|
22802
|
+
function convertMarkdownListToHtml(content) {
|
|
22803
|
+
const trimmedContent = content.trim();
|
|
22804
|
+
if (trimmedContent.startsWith("- ")) {
|
|
22805
|
+
const listItemContent = trimmedContent.substring(2).trim();
|
|
22806
|
+
return `<li>${listItemContent}</li>`;
|
|
22807
|
+
}
|
|
22808
|
+
return content;
|
|
22809
|
+
}
|
|
22810
|
+
function evaluateCondition(condition, metadata) {
|
|
22811
|
+
const value = resolveVariablePath(condition, metadata);
|
|
22812
|
+
if (value === null || value === void 0) return false;
|
|
22813
|
+
if (typeof value === "boolean") return value;
|
|
22814
|
+
if (typeof value === "number") return value !== 0;
|
|
22815
|
+
if (typeof value === "string") return value.length > 0;
|
|
22816
|
+
if (Array.isArray(value)) return value.length > 0;
|
|
22817
|
+
if (typeof value === "object") return Object.keys(value).length > 0;
|
|
22818
|
+
return Boolean(value);
|
|
22819
|
+
}
|
|
22820
|
+
function processTemplateContent(content, metadata, context, enableFieldTracking = true) {
|
|
22821
|
+
let processedContent = processTemplateLoops(content, metadata, context, enableFieldTracking);
|
|
22822
|
+
processedContent = processedContent.replace(/\{\{([^#/][^}]*)\}\}/g, (match, variable) => {
|
|
22823
|
+
const trimmedVar = variable.trim();
|
|
22824
|
+
const value = resolveVariablePath(trimmedVar, metadata);
|
|
22825
|
+
if (value !== void 0) {
|
|
22826
|
+
if (enableFieldTracking) {
|
|
22827
|
+
const isEmptyValue = value === null || value === "" || typeof value === "string" && value.trim() === "";
|
|
22828
|
+
const cssClass = isEmptyValue ? "legal-field missing-value" : "legal-field imported-value";
|
|
22829
|
+
fieldTracker.trackField(trimmedVar, {
|
|
22830
|
+
value,
|
|
22831
|
+
originalValue: match,
|
|
22832
|
+
hasLogic: false
|
|
22833
|
+
});
|
|
22834
|
+
return `<span class="${cssClass}" data-field="${escapeHtmlAttribute(trimmedVar)}">${String(value)}</span>`;
|
|
22835
|
+
}
|
|
22836
|
+
return String(value);
|
|
22837
|
+
}
|
|
22838
|
+
return match;
|
|
22839
|
+
});
|
|
22840
|
+
return processedContent;
|
|
22841
|
+
}
|
|
22643
22842
|
|
|
22644
22843
|
var define_process_default = { env: { NODE_ENV: "production", DEBUG: false } };
|
|
22645
22844
|
function exportMetadata(metadata, format, outputPath) {
|
|
@@ -22707,6 +22906,10 @@ function filterMetadataForExport(metadata) {
|
|
|
22707
22906
|
return result;
|
|
22708
22907
|
}
|
|
22709
22908
|
|
|
22909
|
+
function asMarkdown(content) {
|
|
22910
|
+
return content;
|
|
22911
|
+
}
|
|
22912
|
+
|
|
22710
22913
|
const unsafeWithoutUnderscores = [
|
|
22711
22914
|
{ character: " ", after: "[\\r\\n]", inConstruct: "phrasing" },
|
|
22712
22915
|
{ character: " ", before: "[\\r\\n]", inConstruct: "phrasing" },
|
|
@@ -22848,6 +23051,7 @@ function escapeTemplateUnderscores(content) {
|
|
|
22848
23051
|
}
|
|
22849
23052
|
function createLegalMarkdownProcessor(metadata, options) {
|
|
22850
23053
|
const processor = unified().use(remarkParse);
|
|
23054
|
+
const pluginOrder = [];
|
|
22851
23055
|
if (!options.noImports) {
|
|
22852
23056
|
processor.use(remarkImports, {
|
|
22853
23057
|
basePath: options.basePath || ".",
|
|
@@ -22932,6 +23136,42 @@ function createLegalMarkdownProcessor(metadata, options) {
|
|
|
22932
23136
|
unsafe: unsafeWithoutUnderscores
|
|
22933
23137
|
// Use filtered unsafe patterns without underscores
|
|
22934
23138
|
});
|
|
23139
|
+
if (!options.noImports) pluginOrder.push("remarkImports");
|
|
23140
|
+
if (!options.noHeaders) pluginOrder.push("remarkLegalHeadersParser");
|
|
23141
|
+
if (!options.noMixins) pluginOrder.push("remarkMixins");
|
|
23142
|
+
if (!options.noClauses) pluginOrder.push("remarkClauses");
|
|
23143
|
+
pluginOrder.push("remarkDates");
|
|
23144
|
+
pluginOrder.push("remarkSignatureLines");
|
|
23145
|
+
pluginOrder.push("remarkTemplateFields");
|
|
23146
|
+
if (!options.disableCrossReferences && !options.noReferences) {
|
|
23147
|
+
pluginOrder.push("remarkCrossReferences");
|
|
23148
|
+
}
|
|
23149
|
+
if (!options.noHeaders) pluginOrder.push("remarkHeaders");
|
|
23150
|
+
if (options.debug || options.validatePluginOrder) {
|
|
23151
|
+
try {
|
|
23152
|
+
const validator = new PluginOrderValidator(GLOBAL_PLUGIN_REGISTRY);
|
|
23153
|
+
const result = validator.validate(pluginOrder, {
|
|
23154
|
+
throwOnError: false,
|
|
23155
|
+
// Don't throw, just log warnings
|
|
23156
|
+
logWarnings: options.debug || options.validatePluginOrder,
|
|
23157
|
+
strictMode: false,
|
|
23158
|
+
debug: options.debug
|
|
23159
|
+
});
|
|
23160
|
+
if (!result.valid && options.debug) {
|
|
23161
|
+
console.warn("[LegalMarkdownProcessor] Plugin order validation warnings detected");
|
|
23162
|
+
for (const error of result.errors) {
|
|
23163
|
+
console.warn(` - ${error.message}`);
|
|
23164
|
+
}
|
|
23165
|
+
if (result.suggestedOrder) {
|
|
23166
|
+
console.warn(" Suggested order:", result.suggestedOrder.join(" → "));
|
|
23167
|
+
}
|
|
23168
|
+
}
|
|
23169
|
+
} catch (error) {
|
|
23170
|
+
if (options.debug) {
|
|
23171
|
+
console.warn("[LegalMarkdownProcessor] Plugin order validation failed:", error);
|
|
23172
|
+
}
|
|
23173
|
+
}
|
|
23174
|
+
}
|
|
22935
23175
|
return processor;
|
|
22936
23176
|
}
|
|
22937
23177
|
async function processLegalMarkdownWithRemark(content, options = {}) {
|
|
@@ -22979,7 +23219,7 @@ async function processLegalMarkdownWithRemark(content, options = {}) {
|
|
|
22979
23219
|
);
|
|
22980
23220
|
}
|
|
22981
23221
|
return {
|
|
22982
|
-
content: contentWithEscapedTemplates,
|
|
23222
|
+
content: asMarkdown(contentWithEscapedTemplates),
|
|
22983
23223
|
metadata: { ...yamlMetadata, ...options.additionalMetadata },
|
|
22984
23224
|
stats: {
|
|
22985
23225
|
processingTime: Date.now() - startTime,
|
|
@@ -22992,7 +23232,7 @@ async function processLegalMarkdownWithRemark(content, options = {}) {
|
|
|
22992
23232
|
}
|
|
22993
23233
|
if (options.yamlOnly) {
|
|
22994
23234
|
return {
|
|
22995
|
-
content: contentWithEscapedTemplates,
|
|
23235
|
+
content: asMarkdown(contentWithEscapedTemplates),
|
|
22996
23236
|
metadata: yamlMetadata,
|
|
22997
23237
|
stats: {
|
|
22998
23238
|
processingTime: Date.now() - startTime,
|
|
@@ -23007,7 +23247,7 @@ async function processLegalMarkdownWithRemark(content, options = {}) {
|
|
|
23007
23247
|
...yamlMetadata,
|
|
23008
23248
|
...options.additionalMetadata
|
|
23009
23249
|
};
|
|
23010
|
-
const { parseForceCommands, applyForceCommands } = await import('./force-commands-parser-
|
|
23250
|
+
const { parseForceCommands, applyForceCommands } = await import('./force-commands-parser-DDda8v0G.js');
|
|
23011
23251
|
let updatedOptions = { ...options };
|
|
23012
23252
|
if (combinedMetadata.force_commands && typeof combinedMetadata.force_commands === "string") {
|
|
23013
23253
|
const forceCommands = parseForceCommands(combinedMetadata.force_commands, combinedMetadata);
|
|
@@ -23087,8 +23327,8 @@ async function processLegalMarkdownWithRemark(content, options = {}) {
|
|
|
23087
23327
|
}
|
|
23088
23328
|
const result = await processor.process(preprocessedContent);
|
|
23089
23329
|
const processedContent = String(result);
|
|
23090
|
-
const processedTree = result.
|
|
23091
|
-
const importedMetadata =
|
|
23330
|
+
const processedTree = result.value;
|
|
23331
|
+
const importedMetadata = result.history[0]?._importedMetadata || {};
|
|
23092
23332
|
const finalMetadata = {
|
|
23093
23333
|
...importedMetadata,
|
|
23094
23334
|
...combinedMetadata
|
|
@@ -23136,8 +23376,10 @@ async function processLegalMarkdownWithRemark(content, options = {}) {
|
|
|
23136
23376
|
console.log(`📋 Fields tracked: ${fieldsTracked}`);
|
|
23137
23377
|
}
|
|
23138
23378
|
return {
|
|
23139
|
-
content: processedContent,
|
|
23379
|
+
content: asMarkdown(processedContent),
|
|
23140
23380
|
metadata: finalMetadata,
|
|
23381
|
+
ast: processedTree,
|
|
23382
|
+
// Cached AST for Phase 3
|
|
23141
23383
|
exportedFiles: exportedFiles.length > 0 ? exportedFiles : void 0,
|
|
23142
23384
|
fieldReport,
|
|
23143
23385
|
stats: {
|
|
@@ -23196,5 +23438,5 @@ if (typeof window !== "undefined" && window.DEBUG_LEGAL_MARKDOWN) {
|
|
|
23196
23438
|
});
|
|
23197
23439
|
}
|
|
23198
23440
|
|
|
23199
|
-
export { LegalMarkdown as L, processLegalMarkdown as a, processLegalMarkdownSync as b, logger as l,
|
|
23200
|
-
//# sourceMappingURL=browser-modern-
|
|
23441
|
+
export { LegalMarkdown as L, processLegalMarkdown as a, processLegalMarkdownSync as b, extensionHelpers as e, fieldTracker as f, logger as l, processTemplateLoops as p };
|
|
23442
|
+
//# sourceMappingURL=browser-modern-BP5EJrCS.js.map
|