@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,175 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DocumentEngine — BBCodeDocumentModel
|
|
3
|
+
*
|
|
4
|
+
* A DocumentModel subclass that uses the DocumentEngine's built-in
|
|
5
|
+
* BBCode Lexer + Parser to produce GreenNode/RedNode trees.
|
|
6
|
+
*
|
|
7
|
+
* This COMPLETELY replaces the old BBCode parser (MiliastryNovaFeatures/BBCode/Parser).
|
|
8
|
+
* The old parser is DEPRECATED.
|
|
9
|
+
*
|
|
10
|
+
* Architecture:
|
|
11
|
+
* BBCode text
|
|
12
|
+
* ↓ BBCodeLexer.scanBBCode()
|
|
13
|
+
* BBCodeToken[]
|
|
14
|
+
* ↓ Parser.parseTokensToGreen()
|
|
15
|
+
* GreenNode
|
|
16
|
+
* ↓ BBCodeToGreenNode.greenToRedNode()
|
|
17
|
+
* RedNode
|
|
18
|
+
* ↓ HTMLRenderer.render()
|
|
19
|
+
* HTML preview
|
|
20
|
+
*
|
|
21
|
+
* Usage:
|
|
22
|
+
* const model = new BBCodeDocumentModel({ source: '[b]Hello[/b]' })
|
|
23
|
+
* const html = new HTMLRenderer().render(model.redRoot!)
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
import { DocumentModel, type DocumentModelOptions } from '../Model/DocumentModel'
|
|
27
|
+
import type { ReparseParseOptions } from '../Incremental/IncrementalParser'
|
|
28
|
+
import { GreenNodePool, type InterningMode } from '../Syntax/GreenNodePool'
|
|
29
|
+
import { GreenNode, greenLeaf } from '../Syntax/GreenNode'
|
|
30
|
+
import { RedNode } from '../Syntax/RedNode'
|
|
31
|
+
import { greenToRedNode, greenToRedNodeReusing, type BBCodeDialect } from './BBCodeToGreenNode'
|
|
32
|
+
import { parseTokensToGreen } from './Parser'
|
|
33
|
+
import { scanBBCode } from '../Lexer/BBCodeLexer'
|
|
34
|
+
import { BBCodeExporter } from '../Visitors/BBCodeExporter'
|
|
35
|
+
import { HTMLRenderer } from '../Visitors/HTMLRenderer'
|
|
36
|
+
|
|
37
|
+
export interface BBCodeDocumentModelOptions extends DocumentModelOptions {
|
|
38
|
+
/** Source BBCode text to parse */
|
|
39
|
+
source?: string
|
|
40
|
+
/** Language identifier (default: 'bbcode') */
|
|
41
|
+
language?: string
|
|
42
|
+
/** Enforce strict tag nesting (disables osu! auto-close legacy behavior) */
|
|
43
|
+
strictMode?: boolean
|
|
44
|
+
/** BBCode dialect to parse against ('osu' | 'miliastry' | 'lyne'). Default: 'miliastry'. */
|
|
45
|
+
dialect?: BBCodeDialect
|
|
46
|
+
/** Alias for dialect ('osu' | 'miliastry' | 'lyne') */
|
|
47
|
+
mode?: BBCodeDialect
|
|
48
|
+
/**
|
|
49
|
+
* Deduplicate structurally identical green nodes across the document.
|
|
50
|
+
*
|
|
51
|
+
* Off by default. It is correct now — see the header of `GreenNodePool.ts`
|
|
52
|
+
* for why it was not — but it is a memory/latency trade, and this engine's
|
|
53
|
+
* declared budget is latency: on the 19.6 KB reference document `'leaves'`
|
|
54
|
+
* costs 16% more parse time to save 42% of the green tree's memory. Turn it
|
|
55
|
+
* on for workloads that hold many documents at once; leave it off to type
|
|
56
|
+
* into one.
|
|
57
|
+
*/
|
|
58
|
+
interning?: InterningMode
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// ─── BBCodeDocumentModel ────────────────────────────────────
|
|
62
|
+
|
|
63
|
+
export class BBCodeDocumentModel extends DocumentModel {
|
|
64
|
+
private _strictMode: boolean
|
|
65
|
+
private _dialect: BBCodeDialect
|
|
66
|
+
/** Per-document interner, or null when interning is off. */
|
|
67
|
+
private _interner: GreenNodePool | null
|
|
68
|
+
/** Memoized parser `extraTags`, rebuilt only when the registry changes. */
|
|
69
|
+
private _extraTags: ReadonlyMap<string, import('../Types/core').NodeKind> | null = null
|
|
70
|
+
private _extraTagsVersion: number = -1
|
|
71
|
+
|
|
72
|
+
constructor(options: BBCodeDocumentModelOptions = {}) {
|
|
73
|
+
// `source` is deliberately empty here: the base constructor would parse it
|
|
74
|
+
// with `parseToGreen`, which runs before this subclass has set
|
|
75
|
+
// `_strictMode`. The initial parse happens below instead.
|
|
76
|
+
//
|
|
77
|
+
// Everything else must be forwarded. It previously was not, so `autoAnalyze`
|
|
78
|
+
// and `maxUndo` were silently dropped and semantic analysis could not be
|
|
79
|
+
// turned off at all.
|
|
80
|
+
super({
|
|
81
|
+
source: '',
|
|
82
|
+
language: options.language ?? 'bbcode',
|
|
83
|
+
maxUndo: options.maxUndo,
|
|
84
|
+
autoAnalyze: options.autoAnalyze,
|
|
85
|
+
incremental: options.incremental,
|
|
86
|
+
reuseRed: options.reuseRed,
|
|
87
|
+
})
|
|
88
|
+
this._strictMode = options.strictMode ?? false
|
|
89
|
+
this._dialect = options.dialect ?? options.mode ?? 'miliastry'
|
|
90
|
+
this._interner = options.interning ? GreenNodePool.create(options.interning) : null
|
|
91
|
+
if (options.source) {
|
|
92
|
+
this.rebuild(options.source)
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
get dialect(): BBCodeDialect {
|
|
97
|
+
return this._dialect
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
get root(): RedNode | null {
|
|
101
|
+
return this.redRoot
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
toHTML(renderer?: HTMLRenderer): string {
|
|
105
|
+
if (!this.redRoot) return ''
|
|
106
|
+
const r = renderer ?? new HTMLRenderer({ dialect: this._dialect, theme: this._dialect === 'lyne' ? 'lyne' : 'osu' })
|
|
107
|
+
return r.render(this.redRoot)
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Parse BBCode text directly to a GreenNode tree using the
|
|
112
|
+
* DocumentEngine's built-in BBCode Lexer + Parser.
|
|
113
|
+
* No dependency on the deprecated old parser.
|
|
114
|
+
*/
|
|
115
|
+
protected parseToGreen(source: string, options?: ReparseParseOptions): GreenNode {
|
|
116
|
+
try {
|
|
117
|
+
// 1. Lex: BBCode text → tokens (with explicit newline tokens)
|
|
118
|
+
const tokens = scanBBCode(source)
|
|
119
|
+
|
|
120
|
+
// Plugin tags reach the parser here. Memoized against the registry's
|
|
121
|
+
// version: with no plugins (the common case) this is one integer
|
|
122
|
+
// compare and `extraTags` stays undefined — the parser's zero-cost path.
|
|
123
|
+
if (this._extraTagsVersion !== this.tagRegistry.version) {
|
|
124
|
+
this._extraTags = this.tagRegistry.customTags()
|
|
125
|
+
this._extraTagsVersion = this.tagRegistry.version
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// 2. Parse: tokens → GreenNode (with proper empty_line handling)
|
|
129
|
+
const green = parseTokensToGreen(tokens, source, {
|
|
130
|
+
strictMode: this._strictMode,
|
|
131
|
+
dialect: this._dialect,
|
|
132
|
+
normalizeParagraphs: options?.normalizeParagraphs ?? true,
|
|
133
|
+
interner: this._interner ?? undefined,
|
|
134
|
+
extraTags: this._extraTags ?? undefined,
|
|
135
|
+
})
|
|
136
|
+
|
|
137
|
+
return green
|
|
138
|
+
} catch (error) {
|
|
139
|
+
console.warn('[BBCodeDocumentModel] Parse error:', error)
|
|
140
|
+
// Fallback: preserve source as a text node
|
|
141
|
+
return greenLeaf('text', source)
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Build a RedNode from a GreenNode, extracting metadata
|
|
147
|
+
* from BBCode attributes in the process.
|
|
148
|
+
*/
|
|
149
|
+
protected buildRedFromGreen(green: GreenNode): RedNode {
|
|
150
|
+
return greenToRedNode(green)
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Reuse-aware red build for the incremental path: adopts old red subtrees
|
|
155
|
+
* wherever the splice shared their green by reference. See the contract on
|
|
156
|
+
* `greenToRedNodeReusing` — the old tree is consumed.
|
|
157
|
+
*/
|
|
158
|
+
protected buildRedFromGreenReusing(
|
|
159
|
+
green: GreenNode,
|
|
160
|
+
oldRed: RedNode,
|
|
161
|
+
stats?: { adopted: number },
|
|
162
|
+
): RedNode {
|
|
163
|
+
return greenToRedNodeReusing(green, oldRed, 0, stats)
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Serialize the red tree back to BBCode, so `transact`/`undo`/`redo` can
|
|
168
|
+
* rebuild from text. Target 'miliastry' keeps native tags (gradient, grow,
|
|
169
|
+
* …) as-is instead of expanding them, which is what round-tripping needs.
|
|
170
|
+
*/
|
|
171
|
+
protected exportSource(root: RedNode): string {
|
|
172
|
+
const exportTarget = this._dialect === 'lyne' ? 'lyne' : this._dialect === 'osu' ? 'osu' : 'miliastry'
|
|
173
|
+
return new BBCodeExporter(this.tagRegistry, exportTarget).export(root)
|
|
174
|
+
}
|
|
175
|
+
}
|