@miliastry/quasar 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +119 -0
- package/README.md +45 -0
- package/dist/Visuals/lyne.css +1027 -0
- package/dist/Visuals/osu.css +257 -0
- package/dist/index.d.mts +4563 -0
- package/dist/index.d.ts +4563 -0
- package/dist/index.js +11291 -0
- package/dist/index.mjs +11197 -0
- package/package.json +51 -0
- package/src/Analysis/Contracts/AnalysisReport.ts +26 -0
- package/src/Analysis/Contracts/Contribution.ts +76 -0
- package/src/Analysis/Contracts/Pass.ts +76 -0
- package/src/Analysis/Contracts/PipelineContext.ts +48 -0
- package/src/Analysis/Passes/Analysis/GradientAnalyzer.ts +292 -0
- package/src/Analysis/Passes/Analysis/MergeableColorAnalyzer.ts +112 -0
- package/src/Analysis/Passes/Analysis/RainbowAnalyzer.ts +233 -0
- package/src/Analysis/Passes/Analysis/WaveAnalyzer.ts +211 -0
- package/src/Analysis/Passes/Analysis/__tests__/GradientAnalyzer.test.ts +135 -0
- package/src/Analysis/Passes/Analysis/__tests__/MergeableColorAnalyzer.test.ts +84 -0
- package/src/Analysis/Passes/Analysis/__tests__/RainbowAnalyzer.test.ts +99 -0
- package/src/Analysis/Passes/Analysis/__tests__/WaveAnalyzer.test.ts +119 -0
- package/src/Analysis/Passes/Decision/DefaultDecision.ts +139 -0
- package/src/Analysis/Passes/Decision/__tests__/DefaultDecision.test.ts +179 -0
- package/src/Analysis/Passes/Transform/CollapseGradientTransform.ts +176 -0
- package/src/Analysis/Passes/Transform/MergeColorsTransform.ts +126 -0
- package/src/Analysis/Passes/Transform/RainbowCollapseTransform.ts +83 -0
- package/src/Analysis/Passes/Transform/WaveCollapseTransform.ts +88 -0
- package/src/Analysis/Passes/Utility/CharacterCountAnalyzer.ts +45 -0
- package/src/Analysis/Pipeline/Pipeline.ts +133 -0
- package/src/Analysis/Pipeline/PipelineBuilder.ts +55 -0
- package/src/Analysis/Pipeline/PipelineStage.ts +19 -0
- package/src/Analysis/Utils/color-utils.ts +132 -0
- package/src/Analysis/__tests__/Integration.test.ts +162 -0
- package/src/Analysis/__tests__/Pipeline.test.ts +133 -0
- package/src/Analysis/index.ts +52 -0
- package/src/BBCode/BBCodeDocumentModel.ts +175 -0
- package/src/BBCode/BBCodeToGreenNode.ts +755 -0
- package/src/BBCode/Parser.ts +384 -0
- package/src/BBCode/index.ts +12 -0
- package/src/Collab/positions.ts +91 -0
- package/src/Commands/Command.ts +44 -0
- package/src/Commands/CommandRegistry.ts +78 -0
- package/src/Commands/DeleteNode.ts +20 -0
- package/src/Commands/InsertText.ts +21 -0
- package/src/Commands/SplitMerge.ts +28 -0
- package/src/Commands/WrapInTag.ts +21 -0
- package/src/Commands/index.ts +6 -0
- package/src/Diff/TreeDiffer.ts +264 -0
- package/src/Diff/__tests__/TreeDiffer.test.ts +65 -0
- package/src/Diff/index.ts +2 -0
- package/src/Events/EventBus.ts +160 -0
- package/src/Events/index.ts +2 -0
- package/src/Formatter/Formatter.ts +54 -0
- package/src/Formatter/index.ts +2 -0
- package/src/HTML/HTMLDocumentModel.ts +35 -0
- package/src/HTML/HTMLToGreenNode.ts +290 -0
- package/src/Incremental/ChangeTracker.ts +105 -0
- package/src/Incremental/IncrementalParser.ts +591 -0
- package/src/Incremental/__tests__/IncrementalParser.test.ts +164 -0
- package/src/Incremental/index.ts +4 -0
- package/src/Lexer/BBCodeLexer.ts +382 -0
- package/src/Lexer/Lexer.ts +181 -0
- package/src/Lexer/index.ts +10 -0
- package/src/Linter/Linter.ts +193 -0
- package/src/Linter/index.ts +2 -0
- package/src/Markdown/MarkdownAST.ts +112 -0
- package/src/Markdown/MarkdownDocumentModel.ts +55 -0
- package/src/Markdown/MarkdownLexer.ts +203 -0
- package/src/Markdown/MarkdownParser.ts +455 -0
- package/src/Markdown/MarkdownToGreenNode.ts +153 -0
- package/src/Model/DocumentModel.ts +694 -0
- package/src/Model/NodeFactory.ts +117 -0
- package/src/Model/TagRegistry.ts +495 -0
- package/src/Model/index.ts +5 -0
- package/src/Plugins/PluginAPI.ts +119 -0
- package/src/Plugins/PluginRegistry.ts +132 -0
- package/src/Plugins/index.ts +3 -0
- package/src/Queries/QueryEngine.ts +152 -0
- package/src/Queries/index.ts +1 -0
- package/src/RenderPipeline/RenderPipeline.ts +125 -0
- package/src/RenderPipeline/RenderTree.ts +134 -0
- package/src/RenderPipeline/index.ts +4 -0
- package/src/Semantic/SemanticAnalyzer.ts +506 -0
- package/src/Semantic/index.ts +2 -0
- package/src/Symbols/SymbolTable.ts +124 -0
- package/src/Symbols/index.ts +1 -0
- package/src/Syntax/GreenNode.ts +324 -0
- package/src/Syntax/GreenNodePool.ts +269 -0
- package/src/Syntax/NodeMatcher.ts +370 -0
- package/src/Syntax/RedNode.ts +569 -0
- package/src/Syntax/RedNodeStore.ts +184 -0
- package/src/Syntax/TreeBuilder.ts +214 -0
- package/src/Syntax/__tests__/GreenNode.test.ts +33 -0
- package/src/Syntax/__tests__/RedNode.test.ts +81 -0
- package/src/Syntax/__tests__/RedNodeStore.test.ts +104 -0
- package/src/Syntax/greenEdit.ts +110 -0
- package/src/Syntax/hash.ts +30 -0
- package/src/Syntax/index.ts +12 -0
- package/src/Syntax/partition.ts +161 -0
- package/src/Syntax/preserveNodeIds.ts +201 -0
- package/src/Tests/ASTOptimizerIdempotence.test.ts +77 -0
- package/src/Tests/BlockPatcher.test.ts +437 -0
- package/src/Tests/BlockPatcherWindowed.test.ts +364 -0
- package/src/Tests/BoxDrawer.test.ts +217 -0
- package/src/Tests/BoxRichTitle.test.ts +105 -0
- package/src/Tests/Chars500kBenchmark.test.ts +151 -0
- package/src/Tests/Chars500kEdits.test.ts +321 -0
- package/src/Tests/CollabPositions.test.ts +146 -0
- package/src/Tests/CompilerPathProfiling.test.ts +186 -0
- package/src/Tests/DOMMorpher.test.ts +142 -0
- package/src/Tests/DomPatchPerf.test.ts +60 -0
- package/src/Tests/EffectSegments.snapshot.json +616 -0
- package/src/Tests/EffectSegments.test.ts +68 -0
- package/src/Tests/FindNodeAtOffset.test.ts +65 -0
- package/src/Tests/Fuzzer.test.ts +166 -0
- package/src/Tests/GreenNodePool.test.ts +153 -0
- package/src/Tests/Lexer.test.ts +238 -0
- package/src/Tests/LyneMode.test.ts +187 -0
- package/src/Tests/ModelCoherence.test.ts +180 -0
- package/src/Tests/Partition.test.ts +238 -0
- package/src/Tests/PluginTags.test.ts +150 -0
- package/src/Tests/ProblematicSection.test.ts +46 -0
- package/src/Tests/ProblematicSectionHTML.test.ts +58 -0
- package/src/Tests/RedReuse.test.ts +134 -0
- package/src/Tests/ReproDelete20k.test.ts +62 -0
- package/src/Tests/SemanticValidators.test.ts +136 -0
- package/src/Tests/StableNodeIds.test.ts +210 -0
- package/src/Tests/StudioColorBloat.test.ts +25 -0
- package/src/Tests/StudioDebugText.test.ts +27 -0
- package/src/Tests/StudioTrailingChar.test.ts +25 -0
- package/src/Tests/StudioValidText.test.ts +25 -0
- package/src/Tests/UrlImgBug.test.ts +23 -0
- package/src/Tests/VisualBuilderFidelity.test.ts +105 -0
- package/src/Tests/referenceDocument.ts +119 -0
- package/src/Transactions/Transaction.ts +176 -0
- package/src/Transactions/UndoManager.ts +111 -0
- package/src/Transactions/index.ts +3 -0
- package/src/Transformers/ASTOptimizer.ts +315 -0
- package/src/Transformers/GradientTransformer.ts +143 -0
- package/src/Transformers/GrowTransformer.ts +115 -0
- package/src/Transformers/RainbowTransformer.ts +121 -0
- package/src/Transformers/SineWaveTransformer.ts +130 -0
- package/src/Transformers/Transformer.ts +22 -0
- package/src/Types/core.ts +270 -0
- package/src/Types/diagnostics.ts +156 -0
- package/src/Types/index.ts +23 -0
- package/src/Types/operations.ts +180 -0
- package/src/Types/queries.ts +121 -0
- package/src/Types/symbols.ts +69 -0
- package/src/Types/tokens.ts +186 -0
- package/src/Utils/BBCodeGenerator.ts +126 -0
- package/src/Utils/ColorMath.ts +276 -0
- package/src/Utils/color.ts +112 -0
- package/src/Utils/dom-to-svg.test.ts +86 -0
- package/src/Utils/dom-to-svg.ts +615 -0
- package/src/Utils/treeTransformers.ts +717 -0
- package/src/Visitors/BBBlocksExporter.ts +69 -0
- package/src/Visitors/BBCodeExporter.ts +318 -0
- package/src/Visitors/BlockPatcher.ts +963 -0
- package/src/Visitors/DOMMorpher.ts +134 -0
- package/src/Visitors/HTMLRenderer.ts +1077 -0
- package/src/Visitors/JSONExporter.ts +66 -0
- package/src/Visitors/MarkdownExporter.ts +99 -0
- package/src/Visitors/SVGRenderer.ts +35 -0
- package/src/Visitors/TiptapExporter.ts +145 -0
- package/src/Visitors/Visitor.ts +48 -0
- package/src/Visitors/index.ts +9 -0
- package/src/Visuals/BoxDrawer.ts +175 -0
- package/src/Visuals/index.ts +42 -0
- package/src/Visuals/lyne.css +1027 -0
- package/src/Visuals/osu.css +257 -0
- package/src/index.ts +197 -0
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DocumentEngine — DOMMorpher
|
|
3
|
+
*
|
|
4
|
+
* Reconciles and morphs an existing HTML DOM tree in-place to match a new HTML string.
|
|
5
|
+
* Operating on pure HTML string output from HTMLRenderer means ZERO changes to Quasar AST schemas.
|
|
6
|
+
*
|
|
7
|
+
* Features:
|
|
8
|
+
* - In-place attribute synchronization
|
|
9
|
+
* - In-place text node value updates
|
|
10
|
+
* - Preserves state of unchanged elements (spoilers, audio/video, selections)
|
|
11
|
+
* - Zero extra wrapper <div> elements
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
export function morphHTML(container: HTMLElement, newHTML: string): void {
|
|
15
|
+
if (container.childNodes.length === 0) {
|
|
16
|
+
container.innerHTML = newHTML
|
|
17
|
+
return
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const template = document.createElement('template')
|
|
21
|
+
template.innerHTML = newHTML
|
|
22
|
+
|
|
23
|
+
morphNodes(container, template.content)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Reconcile `parent`'s children against `newParent`'s.
|
|
28
|
+
*
|
|
29
|
+
* Children are paired positionally, which is why the identical prefix and
|
|
30
|
+
* suffix are trimmed first: without that, inserting a single node near the
|
|
31
|
+
* start shifts every following sibling by one, so each one compares against the
|
|
32
|
+
* wrong counterpart and gets rewritten — the exact cascade a morpher exists to
|
|
33
|
+
* avoid.
|
|
34
|
+
*
|
|
35
|
+
* Trimming uses `isEqualNode`, a native deep structural comparison. A subtree
|
|
36
|
+
* that compares equal is left completely untouched: no recursion, no attribute
|
|
37
|
+
* loops, and — because the DOM node is never replaced — any runtime state it
|
|
38
|
+
* holds (open spoilers, media playback, selection) survives for free.
|
|
39
|
+
*
|
|
40
|
+
* Note on keys: the obvious next step would be pairing by `data-node-id`, but
|
|
41
|
+
* those are regenerated on every parse. Measured on a one-character edit,
|
|
42
|
+
* **zero** ids survive a rebuild, so keying on them would make every node look
|
|
43
|
+
* new and reduce the morpher to a full replacement. That needs identity that is
|
|
44
|
+
* stable across re-parses first.
|
|
45
|
+
*/
|
|
46
|
+
function morphNodes(parent: Node, newParent: Node): void {
|
|
47
|
+
const oldNodes = parent.childNodes
|
|
48
|
+
const newNodes = newParent.childNodes
|
|
49
|
+
|
|
50
|
+
// ── Phase 1: trim the identical prefix and suffix ──────────────
|
|
51
|
+
// Nothing is mutated here, so reading the live NodeLists is safe.
|
|
52
|
+
const limit = Math.min(oldNodes.length, newNodes.length)
|
|
53
|
+
|
|
54
|
+
let lo = 0
|
|
55
|
+
while (lo < limit && oldNodes[lo].isEqualNode(newNodes[lo])) lo++
|
|
56
|
+
|
|
57
|
+
let oldHi = oldNodes.length - 1
|
|
58
|
+
let newHi = newNodes.length - 1
|
|
59
|
+
while (oldHi >= lo && newHi >= lo && oldNodes[oldHi].isEqualNode(newNodes[newHi])) {
|
|
60
|
+
oldHi--
|
|
61
|
+
newHi--
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Everything matched — this whole level is already correct.
|
|
65
|
+
if (lo > oldHi && lo > newHi) return
|
|
66
|
+
|
|
67
|
+
// ── Phase 2: reconcile only the window between them ────────────
|
|
68
|
+
// Snapshot before touching anything: the loop mutates `parent`, which would
|
|
69
|
+
// shift a live NodeList underneath us. Only the changed window is copied.
|
|
70
|
+
const oldChildren: Node[] = []
|
|
71
|
+
for (let i = lo; i <= oldHi; i++) oldChildren.push(oldNodes[i])
|
|
72
|
+
const newChildren: Node[] = []
|
|
73
|
+
for (let i = lo; i <= newHi; i++) newChildren.push(newNodes[i])
|
|
74
|
+
|
|
75
|
+
// Insertions must land before the preserved suffix, not at the end. Captured
|
|
76
|
+
// now, while indices still refer to the pre-mutation DOM.
|
|
77
|
+
const suffixAnchor: Node | null = oldNodes[oldHi + 1] ?? null
|
|
78
|
+
|
|
79
|
+
const maxLen = Math.max(oldChildren.length, newChildren.length)
|
|
80
|
+
|
|
81
|
+
for (let i = 0; i < maxLen; i++) {
|
|
82
|
+
const oldNode = oldChildren[i]
|
|
83
|
+
const newNode = newChildren[i]
|
|
84
|
+
|
|
85
|
+
if (!oldNode && newNode) {
|
|
86
|
+
parent.insertBefore(newNode.cloneNode(true), suffixAnchor)
|
|
87
|
+
} else if (oldNode && !newNode) {
|
|
88
|
+
parent.removeChild(oldNode)
|
|
89
|
+
} else if (oldNode && newNode) {
|
|
90
|
+
if (oldNode.nodeType === 3 && newNode.nodeType === 3) {
|
|
91
|
+
// Text node: update nodeValue in-place
|
|
92
|
+
if (oldNode.nodeValue !== newNode.nodeValue) {
|
|
93
|
+
oldNode.nodeValue = newNode.nodeValue
|
|
94
|
+
}
|
|
95
|
+
} else if (
|
|
96
|
+
oldNode.nodeType === 1 &&
|
|
97
|
+
newNode.nodeType === 1 &&
|
|
98
|
+
(oldNode as Element).tagName === (newNode as Element).tagName
|
|
99
|
+
) {
|
|
100
|
+
const oldEl = oldNode as Element
|
|
101
|
+
const newEl = newNode as Element
|
|
102
|
+
|
|
103
|
+
// Preserve interactive runtime states (such as <details open> for spoilerboxes and boxes)
|
|
104
|
+
if (oldEl.tagName === 'DETAILS' && oldEl.hasAttribute('open')) {
|
|
105
|
+
newEl.setAttribute('open', '')
|
|
106
|
+
}
|
|
107
|
+
if (oldEl.classList.contains('open')) {
|
|
108
|
+
newEl.classList.add('open')
|
|
109
|
+
}
|
|
110
|
+
if (oldEl.classList.contains('is-open')) {
|
|
111
|
+
newEl.classList.add('is-open')
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Sync attributes in-place
|
|
115
|
+
for (const attr of Array.from(newEl.attributes)) {
|
|
116
|
+
if (oldEl.getAttribute(attr.name) !== attr.value) {
|
|
117
|
+
oldEl.setAttribute(attr.name, attr.value)
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
for (const attr of Array.from(oldEl.attributes)) {
|
|
121
|
+
if (!newEl.hasAttribute(attr.name)) {
|
|
122
|
+
oldEl.removeAttribute(attr.name)
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Morph child nodes recursively
|
|
127
|
+
morphNodes(oldEl, newEl)
|
|
128
|
+
} else {
|
|
129
|
+
// Different tag or nodeType: replace node
|
|
130
|
+
oldNode.parentNode!.replaceChild(newNode.cloneNode(true), oldNode)
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|