@miliastry/quasar 1.0.6 → 1.1.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/dist/Visuals/lyne.css +117 -6
- package/dist/Visuals/osu.css +36 -5
- package/dist/index.js +9664 -3282
- package/dist/index.mjs +9535 -3283
- package/dist/types/Analysis/Contracts/AnalysisReport.d.ts +22 -0
- package/dist/types/Analysis/Contracts/Contribution.d.ts +68 -0
- package/dist/types/Analysis/Contracts/Pass.d.ts +59 -0
- package/dist/types/Analysis/Contracts/PipelineContext.d.ts +34 -0
- package/dist/types/Analysis/Passes/Analysis/ColorUsageAnalyzer.d.ts +56 -0
- package/dist/types/Analysis/Passes/Analysis/GradientAnalyzer.d.ts +111 -0
- package/dist/types/Analysis/Passes/Analysis/MergeableColorAnalyzer.d.ts +26 -0
- package/dist/types/Analysis/Passes/Analysis/RainbowAnalyzer.d.ts +47 -0
- package/dist/types/Analysis/Passes/Analysis/SymbolAnalyzer.d.ts +89 -0
- package/dist/types/Analysis/Passes/Analysis/WaveAnalyzer.d.ts +44 -0
- package/dist/types/Analysis/Passes/Analysis/__tests__/GradientAnalyzer.test.d.ts +4 -0
- package/dist/types/Analysis/Passes/Analysis/__tests__/MergeableColorAnalyzer.test.d.ts +4 -0
- package/dist/types/Analysis/Passes/Analysis/__tests__/RainbowAnalyzer.test.d.ts +4 -0
- package/dist/types/Analysis/Passes/Analysis/__tests__/WaveAnalyzer.test.d.ts +4 -0
- package/dist/types/Analysis/Passes/Decision/DefaultDecision.d.ts +30 -0
- package/dist/types/Analysis/Passes/Decision/PaletteRemapDecision.d.ts +169 -0
- package/dist/types/Analysis/Passes/Decision/__tests__/DefaultDecision.test.d.ts +4 -0
- package/dist/types/Analysis/Passes/Transform/CollapseGradientTransform.d.ts +37 -0
- package/dist/types/Analysis/Passes/Transform/MergeColorsTransform.d.ts +28 -0
- package/dist/types/Analysis/Passes/Transform/RainbowCollapseTransform.d.ts +19 -0
- package/dist/types/Analysis/Passes/Transform/WaveCollapseTransform.d.ts +20 -0
- package/dist/types/Analysis/Passes/Utility/CharacterCountAnalyzer.d.ts +19 -0
- package/dist/types/Analysis/Pipeline/Pipeline.d.ts +69 -0
- package/dist/types/Analysis/Pipeline/PipelineBuilder.d.ts +31 -0
- package/dist/types/Analysis/Pipeline/PipelineStage.d.ts +17 -0
- package/dist/types/Analysis/Utils/color-utils.d.ts +60 -0
- package/dist/types/Analysis/__tests__/Integration.test.d.ts +8 -0
- package/dist/types/Analysis/__tests__/PaletteRemap.test.d.ts +14 -0
- package/dist/types/Analysis/__tests__/Pipeline.test.d.ts +10 -0
- package/dist/types/Analysis/__tests__/RoundTrip.test.d.ts +30 -0
- package/dist/types/Analysis/__tests__/SymbolAnalyzer.test.d.ts +11 -0
- package/dist/types/Analysis/index.d.ts +40 -0
- package/dist/types/BBCode/BBCodeDocumentModel.d.ts +92 -0
- package/dist/types/BBCode/BBCodeToGreenNode.d.ts +111 -0
- package/dist/types/BBCode/Parser.d.ts +78 -0
- package/dist/types/BBCode/index.d.ts +4 -0
- package/dist/types/Collab/positions.d.ts +55 -0
- package/dist/types/Commands/Command.d.ts +37 -0
- package/dist/types/Commands/CommandRegistry.d.ts +48 -0
- package/dist/types/Commands/DeleteNode.d.ts +7 -0
- package/dist/types/Commands/InsertText.d.ts +8 -0
- package/dist/types/Commands/SplitMerge.d.ts +9 -0
- package/dist/types/Commands/WrapInTag.d.ts +8 -0
- package/dist/types/Commands/index.d.ts +6 -0
- package/dist/types/Diff/TreeDiffer.d.ts +52 -0
- package/dist/types/Diff/__tests__/TreeDiffer.test.d.ts +1 -0
- package/dist/types/Diff/index.d.ts +2 -0
- package/dist/types/Edits/EditPlan.d.ts +144 -0
- package/dist/types/Edits/Optimizer.d.ts +78 -0
- package/dist/types/Edits/Rules/Rule.d.ts +91 -0
- package/dist/types/Edits/Rules/dropEmptyTags.d.ts +40 -0
- package/dist/types/Edits/Rules/dropRedundantNesting.d.ts +59 -0
- package/dist/types/Edits/Rules/index.d.ts +9 -0
- package/dist/types/Edits/Rules/mergeAdjacent.d.ts +93 -0
- package/dist/types/Edits/Rules/reorderWrappers.d.ts +42 -0
- package/dist/types/Edits/Rules/shortenHex.d.ts +30 -0
- package/dist/types/Edits/Rules/tagValue.d.ts +56 -0
- package/dist/types/Edits/Rules/unwrapInvisibleColor.d.ts +47 -0
- package/dist/types/Edits/applyEdits.d.ts +36 -0
- package/dist/types/Edits/index.d.ts +6 -0
- package/dist/types/Events/EventBus.d.ts +103 -0
- package/dist/types/Events/index.d.ts +2 -0
- package/dist/types/Formatter/Formatter.d.ts +32 -0
- package/dist/types/Formatter/index.d.ts +2 -0
- package/dist/types/HTML/HTMLDocumentModel.d.ts +13 -0
- package/dist/types/HTML/HTMLToGreenNode.d.ts +4 -0
- package/dist/types/Incremental/BracketIndex.d.ts +101 -0
- package/dist/types/Incremental/ChangeTracker.d.ts +69 -0
- package/dist/types/Incremental/IncrementalParser.d.ts +246 -0
- package/dist/types/Incremental/__tests__/BracketIndex.test.d.ts +1 -0
- package/dist/types/Incremental/__tests__/IncrementalParser.test.d.ts +1 -0
- package/dist/types/Incremental/index.d.ts +4 -0
- package/dist/types/Lexer/BBCodeLexer.d.ts +74 -0
- package/dist/types/Lexer/Lexer.d.ts +54 -0
- package/dist/types/Lexer/index.d.ts +4 -0
- package/dist/types/Linter/Linter.d.ts +58 -0
- package/dist/types/Linter/index.d.ts +2 -0
- package/dist/types/Markdown/MarkdownAST.d.ts +122 -0
- package/dist/types/Markdown/MarkdownDocumentModel.d.ts +15 -0
- package/dist/types/Markdown/MarkdownLexer.d.ts +155 -0
- package/dist/types/Markdown/MarkdownParser.d.ts +42 -0
- package/dist/types/Markdown/MarkdownToGreenNode.d.ts +6 -0
- package/dist/types/MilHibri/MilHibriDocumentModel.d.ts +21 -0
- package/dist/types/Model/DocumentModel.d.ts +318 -0
- package/dist/types/Model/NodeFactory.d.ts +29 -0
- package/dist/types/Model/TagRegistry.d.ts +165 -0
- package/dist/types/Model/index.d.ts +5 -0
- package/dist/types/Plugins/PluginAPI.d.ts +44 -0
- package/dist/types/Plugins/PluginRegistry.d.ts +81 -0
- package/dist/types/Plugins/index.d.ts +3 -0
- package/dist/types/Queries/QueryEngine.d.ts +32 -0
- package/dist/types/Queries/index.d.ts +1 -0
- package/dist/types/Reconciler/SurgicalReconciler.d.ts +23 -0
- package/dist/types/RenderPipeline/RenderPipeline.d.ts +46 -0
- package/dist/types/RenderPipeline/RenderTree.d.ts +55 -0
- package/dist/types/RenderPipeline/index.d.ts +4 -0
- package/dist/types/Repair/NestingRepair.d.ts +48 -0
- package/dist/types/Repair/index.d.ts +1 -0
- package/dist/types/Semantic/SemanticAnalyzer.d.ts +321 -0
- package/dist/types/Semantic/index.d.ts +2 -0
- package/dist/types/Symbols/SymbolTable.d.ts +47 -0
- package/dist/types/Symbols/index.d.ts +1 -0
- package/dist/types/Syntax/GreenNode.d.ts +154 -0
- package/dist/types/Syntax/GreenNodePool.d.ts +134 -0
- package/dist/types/Syntax/NodeMatcher.d.ts +75 -0
- package/dist/types/Syntax/RedNode.d.ts +280 -0
- package/dist/types/Syntax/RedNodeStore.d.ts +116 -0
- package/dist/types/Syntax/TreeBuilder.d.ts +54 -0
- package/dist/types/Syntax/__tests__/GreenNode.test.d.ts +1 -0
- package/dist/types/Syntax/__tests__/RedNode.test.d.ts +1 -0
- package/dist/types/Syntax/__tests__/RedNodeStore.test.d.ts +1 -0
- package/dist/types/Syntax/greenEdit.d.ts +64 -0
- package/dist/types/Syntax/hash.d.ts +17 -0
- package/dist/types/Syntax/index.d.ts +8 -0
- package/dist/types/Syntax/nodeAttr.d.ts +63 -0
- package/dist/types/Syntax/partition.d.ts +67 -0
- package/dist/types/Syntax/preserveNodeIds.d.ts +47 -0
- package/dist/types/Tokens/TokenResolver.d.ts +25 -0
- package/dist/types/Tokens/index.d.ts +1 -0
- package/dist/types/Transactions/Transaction.d.ts +36 -0
- package/dist/types/Transactions/UndoManager.d.ts +63 -0
- package/dist/types/Transactions/index.d.ts +3 -0
- package/dist/types/Transformers/ASTOptimizer.d.ts +34 -0
- package/dist/types/Transformers/GradientTransformer.d.ts +18 -0
- package/dist/types/Transformers/GrowTransformer.d.ts +16 -0
- package/dist/types/Transformers/RainbowTransformer.d.ts +17 -0
- package/dist/types/Transformers/SineWaveTransformer.d.ts +17 -0
- package/dist/types/Transformers/Transformer.d.ts +17 -0
- package/dist/types/Types/core.d.ts +104 -0
- package/dist/types/Types/diagnostics.d.ts +85 -0
- package/dist/types/Types/index.d.ts +11 -0
- package/dist/types/Types/operations.d.ts +109 -0
- package/dist/types/Types/queries.d.ts +67 -0
- package/dist/types/Types/symbols.d.ts +42 -0
- package/dist/types/Types/tokens.d.ts +75 -0
- package/dist/types/Utils/BBCodeGenerator.d.ts +21 -0
- package/dist/types/Utils/ColorMath.d.ts +92 -0
- package/dist/types/Utils/EffectMath.d.ts +643 -0
- package/dist/types/Utils/TagVocabulary.d.ts +104 -0
- package/dist/types/Utils/TagVocabulary.test.d.ts +1 -0
- package/dist/types/Utils/color.d.ts +29 -0
- package/dist/types/Utils/dom-to-svg.d.ts +28 -0
- package/dist/types/Utils/dom-to-svg.test.d.ts +1 -0
- package/dist/types/Utils/treeTransformers.d.ts +160 -0
- package/dist/types/Visitors/BBBlocksExporter.d.ts +27 -0
- package/dist/types/Visitors/BBCodeExporter.d.ts +90 -0
- package/dist/types/Visitors/BlockPatcher.d.ts +91 -0
- package/dist/types/Visitors/DOMMorpher.d.ts +13 -0
- package/dist/types/Visitors/HTMLRenderer.d.ts +380 -0
- package/dist/types/Visitors/JSONExporter.d.ts +42 -0
- package/dist/types/Visitors/MarkdownExporter.d.ts +28 -0
- package/dist/types/Visitors/SVGRenderer.d.ts +16 -0
- package/dist/types/Visitors/TiptapExporter.d.ts +40 -0
- package/dist/types/Visitors/Visitor.d.ts +35 -0
- package/dist/types/Visitors/index.d.ts +9 -0
- package/dist/types/Visuals/BoxDrawer.d.ts +49 -0
- package/dist/types/Visuals/index.d.ts +38 -0
- package/dist/types/index.d.ts +154 -0
- package/package.json +14 -10
- package/src/Analysis/Passes/Analysis/ColorUsageAnalyzer.ts +103 -0
- package/src/Analysis/Passes/Analysis/GradientAnalyzer.ts +294 -20
- package/src/Analysis/Passes/Analysis/SymbolAnalyzer.ts +257 -0
- package/src/Analysis/Passes/Decision/PaletteRemapDecision.ts +425 -0
- package/src/Analysis/Pipeline/Pipeline.ts +15 -2
- package/src/Analysis/index.ts +8 -2
- package/src/BBCode/BBCodeDocumentModel.ts +3 -0
- package/src/BBCode/BBCodeToGreenNode.ts +18 -12
- package/src/BBCode/Parser.ts +38 -1
- package/src/Edits/EditPlan.ts +290 -0
- package/src/Edits/Optimizer.ts +185 -0
- package/src/Edits/Rules/Rule.ts +145 -0
- package/src/Edits/Rules/dropEmptyTags.ts +110 -0
- package/src/Edits/Rules/dropRedundantNesting.ts +120 -0
- package/src/Edits/Rules/index.ts +28 -0
- package/src/Edits/Rules/mergeAdjacent.ts +224 -0
- package/src/Edits/Rules/reorderWrappers.ts +154 -0
- package/src/Edits/Rules/shortenHex.ts +79 -0
- package/src/Edits/Rules/tagValue.ts +105 -0
- package/src/Edits/Rules/unwrapInvisibleColor.ts +93 -0
- package/src/Edits/applyEdits.ts +54 -0
- package/src/Edits/index.ts +22 -0
- package/src/Events/EventBus.ts +18 -0
- package/src/HTML/HTMLToGreenNode.ts +185 -37
- package/src/Incremental/BracketIndex.ts +249 -0
- package/src/Incremental/IncrementalParser.ts +464 -41
- package/src/Lexer/BBCodeLexer.ts +25 -3
- package/src/Lexer/index.ts +1 -1
- package/src/Markdown/MarkdownAST.ts +65 -2
- package/src/Markdown/MarkdownLexer.ts +69 -14
- package/src/Markdown/MarkdownParser.ts +749 -62
- package/src/Markdown/MarkdownToGreenNode.ts +148 -27
- package/src/MilHibri/MilHibriDocumentModel.ts +56 -0
- package/src/Model/DocumentModel.ts +138 -5
- package/src/Model/TagRegistry.ts +129 -134
- package/src/Reconciler/SurgicalReconciler.ts +460 -0
- package/src/Repair/NestingRepair.ts +116 -0
- package/src/Repair/index.ts +1 -0
- package/src/Semantic/SemanticAnalyzer.ts +1802 -65
- package/src/Syntax/GreenNodePool.ts +12 -12
- package/src/Syntax/RedNode.ts +17 -3
- package/src/Syntax/RedNodeStore.ts +9 -1
- package/src/Syntax/nodeAttr.ts +172 -0
- package/src/Tokens/TokenResolver.ts +55 -0
- package/src/Tokens/index.ts +1 -0
- package/src/Types/core.ts +15 -0
- package/src/Utils/ColorMath.ts +276 -55
- package/src/Utils/EffectMath.ts +2462 -0
- package/src/Utils/TagVocabulary.ts +141 -0
- package/src/Utils/dom-to-svg.ts +28 -12
- package/src/Visitors/BBBlocksExporter.ts +15 -1
- package/src/Visitors/BBCodeExporter.ts +319 -32
- package/src/Visitors/BlockPatcher.ts +87 -11
- package/src/Visitors/DOMMorpher.ts +15 -5
- package/src/Visitors/HTMLRenderer.ts +374 -151
- package/src/Visitors/MarkdownExporter.ts +98 -41
- package/src/Visitors/TiptapExporter.ts +1 -0
- package/src/Visuals/index.ts +7 -4
- package/src/Visuals/lyne.css +117 -6
- package/src/Visuals/osu.css +36 -5
- package/src/index.ts +172 -5
- package/dist/index.d.mts +0 -4612
- package/dist/index.d.ts +0 -4612
- package/src/Analysis/Passes/Analysis/__tests__/GradientAnalyzer.test.ts +0 -135
- package/src/Analysis/Passes/Analysis/__tests__/MergeableColorAnalyzer.test.ts +0 -84
- package/src/Analysis/Passes/Analysis/__tests__/RainbowAnalyzer.test.ts +0 -99
- package/src/Analysis/Passes/Analysis/__tests__/WaveAnalyzer.test.ts +0 -119
- package/src/Analysis/Passes/Decision/__tests__/DefaultDecision.test.ts +0 -179
- package/src/Analysis/__tests__/Integration.test.ts +0 -162
- package/src/Analysis/__tests__/Pipeline.test.ts +0 -133
- package/src/Diff/__tests__/TreeDiffer.test.ts +0 -65
- package/src/Incremental/__tests__/IncrementalParser.test.ts +0 -164
- package/src/Syntax/__tests__/GreenNode.test.ts +0 -33
- package/src/Syntax/__tests__/RedNode.test.ts +0 -81
- package/src/Syntax/__tests__/RedNodeStore.test.ts +0 -104
- package/src/Tests/ASTOptimizerIdempotence.test.ts +0 -77
- package/src/Tests/BlockPatcher.test.ts +0 -437
- package/src/Tests/BlockPatcherWindowed.test.ts +0 -364
- package/src/Tests/BoxDrawer.test.ts +0 -217
- package/src/Tests/BoxRichTitle.test.ts +0 -105
- package/src/Tests/Chars500kBenchmark.test.ts +0 -151
- package/src/Tests/Chars500kEdits.test.ts +0 -321
- package/src/Tests/CollabPositions.test.ts +0 -146
- package/src/Tests/CompilerPathProfiling.test.ts +0 -186
- package/src/Tests/DOMMorpher.test.ts +0 -142
- package/src/Tests/DomPatchPerf.test.ts +0 -60
- package/src/Tests/EffectSegments.snapshot.json +0 -616
- package/src/Tests/EffectSegments.test.ts +0 -68
- package/src/Tests/FindNodeAtOffset.test.ts +0 -65
- package/src/Tests/Fuzzer.test.ts +0 -166
- package/src/Tests/GreenNodePool.test.ts +0 -153
- package/src/Tests/Lexer.test.ts +0 -238
- package/src/Tests/LyneMode.test.ts +0 -291
- package/src/Tests/ModelCoherence.test.ts +0 -180
- package/src/Tests/Partition.test.ts +0 -238
- package/src/Tests/PluginTags.test.ts +0 -150
- package/src/Tests/ProblematicSection.test.ts +0 -46
- package/src/Tests/ProblematicSectionHTML.test.ts +0 -58
- package/src/Tests/RedReuse.test.ts +0 -134
- package/src/Tests/ReproDelete20k.test.ts +0 -62
- package/src/Tests/SemanticValidators.test.ts +0 -136
- package/src/Tests/StableNodeIds.test.ts +0 -210
- package/src/Tests/StudioColorBloat.test.ts +0 -25
- package/src/Tests/StudioDebugText.test.ts +0 -27
- package/src/Tests/StudioTrailingChar.test.ts +0 -25
- package/src/Tests/StudioValidText.test.ts +0 -25
- package/src/Tests/UrlImgBug.test.ts +0 -23
- package/src/Tests/VisualBuilderFidelity.test.ts +0 -105
- package/src/Tests/referenceDocument.ts +0 -119
- package/src/Utils/dom-to-svg.test.ts +0 -86
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Quasar — Enumerated attribute vocabularies
|
|
3
|
+
*
|
|
4
|
+
* Some tags take an attribute that is not free text: `[effect=glow]`,
|
|
5
|
+
* `[anim=glitch]`, `[container=grid]`, `[separator=dots]`. The set of values
|
|
6
|
+
* each one accepts was, until now, knowable only by reading the `switch` in
|
|
7
|
+
* `HTMLRenderer` — so the editor could offer tag names but never values, and
|
|
8
|
+
* an author had to remember thirty-six magic words.
|
|
9
|
+
*
|
|
10
|
+
* ── Why this is a problem worth a module ──
|
|
11
|
+
*
|
|
12
|
+
* Every one of those switches ends in a `default:`, and none of the defaults
|
|
13
|
+
* is an error. A misspelling does not fail; it renders something else:
|
|
14
|
+
*
|
|
15
|
+
* [anim=glich] → `bb-pulse` (a different animation)
|
|
16
|
+
* [container=gird] → `bb-stack` (a different container)
|
|
17
|
+
* [effect=nen] → a bare span (no effect at all)
|
|
18
|
+
* [img=round,shadow]→ ignored (`parseImgAttr` is exclusive, not flags)
|
|
19
|
+
*
|
|
20
|
+
* The author sees a preview that works and never learns the value was wrong.
|
|
21
|
+
* Offering the vocabulary at the point of typing is the cheapest fix, and it
|
|
22
|
+
* needs the vocabulary to exist as data rather than as control flow.
|
|
23
|
+
*
|
|
24
|
+
* ── Why here and not in the editor ──
|
|
25
|
+
*
|
|
26
|
+
* This is the engine's knowledge: the renderer decides what `glow` means, so
|
|
27
|
+
* the renderer's package owns the list of what is spellable. A copy in the
|
|
28
|
+
* editor would be a fourth transcription of an engine fact, which is the
|
|
29
|
+
* exact mistake `TagSyntax` and `EffectMath` were both written to undo.
|
|
30
|
+
*
|
|
31
|
+
* `TagVocabulary.test.ts` pins every value below to the renderer: a value
|
|
32
|
+
* that stops being handled starts rendering as the fallback, and the test
|
|
33
|
+
* fails. The list cannot silently drift away from the behaviour.
|
|
34
|
+
*
|
|
35
|
+
* Human-readable descriptions are deliberately NOT here. Quasar has no
|
|
36
|
+
* locales; the editor names these values through its own i18n.
|
|
37
|
+
*/
|
|
38
|
+
|
|
39
|
+
/** How an attribute's value is written. */
|
|
40
|
+
export type VocabularySyntax =
|
|
41
|
+
/** Exactly one of `values`. */
|
|
42
|
+
| 'enum'
|
|
43
|
+
/** Any subset of `values`, comma- or space-separated. */
|
|
44
|
+
| 'flags'
|
|
45
|
+
|
|
46
|
+
export interface AttributeVocabulary {
|
|
47
|
+
/** The tag whose attribute this describes. */
|
|
48
|
+
tag: string
|
|
49
|
+
/** Every value the engine actually handles, in the renderer's own order. */
|
|
50
|
+
values: readonly string[]
|
|
51
|
+
syntax: VocabularySyntax
|
|
52
|
+
/**
|
|
53
|
+
* The value an unrecognised attribute behaves as, or `null` when an
|
|
54
|
+
* unrecognised attribute simply does nothing.
|
|
55
|
+
*
|
|
56
|
+
* This is the honest part: it is what the `default:` branch does, not what
|
|
57
|
+
* the documentation wishes it did.
|
|
58
|
+
*/
|
|
59
|
+
fallback: string | null
|
|
60
|
+
/**
|
|
61
|
+
* Whether a `:<param>` suffix is read after the value.
|
|
62
|
+
*
|
|
63
|
+
* What the suffix MEANS is per value, not per tag, which is why this is
|
|
64
|
+
* only a boolean: `[effect=glow:#2EE6E2]` and `[tables=striped:#hex]` take
|
|
65
|
+
* a colour, but `[container=grid:3]` takes a column count and
|
|
66
|
+
* `[container=flex:12]` a gap in pixels. Completion needs no more than
|
|
67
|
+
* "there is a suffix here, and it is not part of the vocabulary".
|
|
68
|
+
*/
|
|
69
|
+
suffixed: boolean
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/** `[effect=…]` — `HTMLRenderer.renderEffect`. */
|
|
73
|
+
export const EFFECT_TYPES = [
|
|
74
|
+
'glow', 'neon', 'outline', 'emboss', 'engrave',
|
|
75
|
+
'shimmer', 'ghost', 'rainbow', 'fire', 'ice',
|
|
76
|
+
] as const
|
|
77
|
+
|
|
78
|
+
/** `[anim=…]` — `HTMLRenderer.renderAnim`. */
|
|
79
|
+
export const ANIM_TYPES = [
|
|
80
|
+
'bounce', 'shake', 'pulse', 'fade-in', 'fade-out',
|
|
81
|
+
'typewriter', 'wave', 'sparkle', 'glitch', 'levitate',
|
|
82
|
+
] as const
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* `[container=…]` — `HTMLRenderer.renderContainer`.
|
|
86
|
+
*
|
|
87
|
+
* `neonbox` is the unhyphenated spelling of `neon-box` and renders
|
|
88
|
+
* identically; it stays in the list because a document may carry it, but the
|
|
89
|
+
* hyphenated form is the canonical one and comes first.
|
|
90
|
+
*/
|
|
91
|
+
export const CONTAINER_TYPES = [
|
|
92
|
+
'stack', 'flex', 'grid', 'middle', 'square', 'circle',
|
|
93
|
+
'card', 'glass', 'neon-box', 'neonbox',
|
|
94
|
+
] as const
|
|
95
|
+
|
|
96
|
+
/** `[separator=…]` — `HTMLRenderer.renderSeparator`. */
|
|
97
|
+
export const SEPARATOR_VARIANTS = ['line', 'dots', 'stars'] as const
|
|
98
|
+
|
|
99
|
+
/** `[tables=…]` — `HTMLRenderer.renderTables`. Combinable. */
|
|
100
|
+
export const TABLE_FLAGS = ['striped', 'borders'] as const
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* `[img=…]` — `parseImgAttr` in `Syntax/nodeAttr`.
|
|
104
|
+
*
|
|
105
|
+
* Exclusive despite reading like flags: the parser returns on the first
|
|
106
|
+
* match, so `[img=round,shadow]` yields neither. A dimension pair
|
|
107
|
+
* (`[img=200x100]`) is the other accepted form and is not enumerable.
|
|
108
|
+
*/
|
|
109
|
+
export const IMG_MODIFIERS = ['round', 'shadow', 'float'] as const
|
|
110
|
+
|
|
111
|
+
const VOCABULARIES: readonly AttributeVocabulary[] = [
|
|
112
|
+
// `effect` is suffixed, but only `glow`, `neon` and `outline` read the
|
|
113
|
+
// colour; the other seven ignore it. `container` is suffixed with a colour
|
|
114
|
+
// for the panels and with a number for `flex` and `grid`.
|
|
115
|
+
{ tag: 'effect', values: EFFECT_TYPES, syntax: 'enum', fallback: null, suffixed: true },
|
|
116
|
+
{ tag: 'anim', values: ANIM_TYPES, syntax: 'enum', fallback: 'pulse', suffixed: false },
|
|
117
|
+
{ tag: 'container', values: CONTAINER_TYPES, syntax: 'enum', fallback: 'stack', suffixed: true },
|
|
118
|
+
{ tag: 'separator', values: SEPARATOR_VARIANTS, syntax: 'enum', fallback: 'line', suffixed: false },
|
|
119
|
+
{ tag: 'tables', values: TABLE_FLAGS, syntax: 'flags', fallback: null, suffixed: true },
|
|
120
|
+
{ tag: 'img', values: IMG_MODIFIERS, syntax: 'enum', fallback: null, suffixed: false },
|
|
121
|
+
]
|
|
122
|
+
|
|
123
|
+
const BY_TAG = new Map(VOCABULARIES.map(v => [v.tag, v]))
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* The vocabulary for a tag's attribute, or `null` when its attribute is free
|
|
127
|
+
* text (`[box=Título]`, `[url=…]`, `[size=200]`).
|
|
128
|
+
*
|
|
129
|
+
* Case-insensitive, because the renderer lowercases before matching.
|
|
130
|
+
*
|
|
131
|
+
* Note this answers only "what can be spelled here"; whether the tag exists
|
|
132
|
+
* at all is a dialect question, and the caller already knows the dialect.
|
|
133
|
+
*/
|
|
134
|
+
export function attributeVocabularyFor(tag: string): AttributeVocabulary | null {
|
|
135
|
+
return BY_TAG.get(tag.toLowerCase()) ?? null
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/** Every vocabulary, for tests and for tooling that enumerates them. */
|
|
139
|
+
export function allAttributeVocabularies(): readonly AttributeVocabulary[] {
|
|
140
|
+
return VOCABULARIES
|
|
141
|
+
}
|
package/src/Utils/dom-to-svg.ts
CHANGED
|
@@ -17,6 +17,8 @@ export interface DomToSVGOptions {
|
|
|
17
17
|
includeBackground?: boolean
|
|
18
18
|
/** Scale factor applied to all coordinates (default 1) */
|
|
19
19
|
scale?: number
|
|
20
|
+
/** Maximum unscaled height in pixels to scan and render into the SVG (useful for thumbnails). Elements and lines below this cutoff are omitted. */
|
|
21
|
+
maxHeight?: number
|
|
20
22
|
}
|
|
21
23
|
|
|
22
24
|
export interface SVGLayerInfo {
|
|
@@ -51,7 +53,7 @@ export function domToSVGResult(
|
|
|
51
53
|
root: HTMLElement,
|
|
52
54
|
options: DomToSVGOptions = {},
|
|
53
55
|
): DomToSVGResult {
|
|
54
|
-
const { backgroundColor = "#0d0d0d", includeBackground = true, scale = 1 } = options
|
|
56
|
+
const { backgroundColor = "#0d0d0d", includeBackground = true, scale = 1, maxHeight } = options
|
|
55
57
|
|
|
56
58
|
// OPTIMIZATION & FIX: Remove visual interaction artifacts before measuring.
|
|
57
59
|
// We strip the cursor-highlight class synchronously so getComputedStyle reads the pure colors.
|
|
@@ -65,8 +67,9 @@ export function domToSVGResult(
|
|
|
65
67
|
closedDetails.forEach(el => el.setAttribute('open', ''))
|
|
66
68
|
|
|
67
69
|
const rootRect = root.getBoundingClientRect()
|
|
70
|
+
const unscaledH = maxHeight ? Math.min(rootRect.height, maxHeight) : rootRect.height
|
|
68
71
|
const W = Math.ceil(rootRect.width * scale)
|
|
69
|
-
const H = Math.ceil(
|
|
72
|
+
const H = Math.ceil(unscaledH * scale)
|
|
70
73
|
|
|
71
74
|
if (W < 4 || H < 4) {
|
|
72
75
|
// RESTORE on error
|
|
@@ -78,7 +81,7 @@ export function domToSVGResult(
|
|
|
78
81
|
}
|
|
79
82
|
|
|
80
83
|
try {
|
|
81
|
-
const state: WalkState = { rootRect, scale, parts: [], layerCount: 0, layersList: [] }
|
|
84
|
+
const state: WalkState = { rootRect, scale, parts: [], layerCount: 0, layersList: [], maxHeight }
|
|
82
85
|
|
|
83
86
|
const fontFamilies = collectFontFamilies(root)
|
|
84
87
|
|
|
@@ -141,6 +144,7 @@ interface WalkState {
|
|
|
141
144
|
parts: string[]
|
|
142
145
|
layerCount: number
|
|
143
146
|
layersList: SVGLayerInfo[]
|
|
147
|
+
maxHeight?: number
|
|
144
148
|
}
|
|
145
149
|
|
|
146
150
|
// ────────────────────────────────────────────────────────────
|
|
@@ -223,21 +227,24 @@ interface VisualLine {
|
|
|
223
227
|
* text string on the first line's rect, we emit only the characters that
|
|
224
228
|
* actually appear on each visual line.
|
|
225
229
|
*/
|
|
226
|
-
function getVisualLines(textNode: Text): VisualLine[] {
|
|
230
|
+
function getVisualLines(textNode: Text, maxHeight?: number, rootTop?: number): VisualLine[] {
|
|
227
231
|
const text = textNode.textContent ?? ""
|
|
228
232
|
if (!text.trim()) return [] // Skip purely empty/whitespace nodes
|
|
229
233
|
|
|
230
234
|
const range = document.createRange()
|
|
231
235
|
range.selectNode(textNode)
|
|
232
236
|
const fullRects = Array.from(range.getClientRects()).filter(r => r.width > 0 && r.height > 0)
|
|
233
|
-
|
|
237
|
+
if (fullRects.length === 0) return []
|
|
238
|
+
|
|
239
|
+
// If entire text node is below cutoff, skip immediately!
|
|
240
|
+
if (rootTop !== undefined && maxHeight !== undefined && fullRects[0].top - rootTop > maxHeight) {
|
|
241
|
+
return []
|
|
242
|
+
}
|
|
243
|
+
|
|
234
244
|
// OPTIMIZATION 1: If the entire text node fits on a single line, return immediately!
|
|
235
245
|
// This skips the expensive scan for 90% of text nodes (short inline elements).
|
|
236
246
|
if (fullRects.length <= 1) {
|
|
237
|
-
|
|
238
|
-
return [{ text, rect: fullRects[0] }]
|
|
239
|
-
}
|
|
240
|
-
return []
|
|
247
|
+
return [{ text, rect: fullRects[0] }]
|
|
241
248
|
}
|
|
242
249
|
|
|
243
250
|
// OPTIMIZATION 2: Word-by-word scan instead of char-by-char for multi-line text.
|
|
@@ -267,6 +274,10 @@ function getVisualLines(textNode: Text): VisualLine[] {
|
|
|
267
274
|
const tokenRect = rects[0]
|
|
268
275
|
if (tokenRect.width === 0 && tokenRect.height === 0) continue
|
|
269
276
|
|
|
277
|
+
if (rootTop !== undefined && maxHeight !== undefined && tokenRect.top - rootTop > maxHeight) {
|
|
278
|
+
break
|
|
279
|
+
}
|
|
280
|
+
|
|
270
281
|
if (!lineRect) {
|
|
271
282
|
lineRect = tokenRect
|
|
272
283
|
lineText = token
|
|
@@ -336,7 +347,12 @@ function walkElement(el: Element, state: WalkState, depth: number): void {
|
|
|
336
347
|
if (opacityVal === 0) return
|
|
337
348
|
|
|
338
349
|
const rect = el.getBoundingClientRect()
|
|
339
|
-
const { rootRect, scale } = state
|
|
350
|
+
const { rootRect, scale, maxHeight } = state
|
|
351
|
+
|
|
352
|
+
const unscaledTop = rect.top - rootRect.top
|
|
353
|
+
if (maxHeight !== undefined && unscaledTop > maxHeight) {
|
|
354
|
+
return
|
|
355
|
+
}
|
|
340
356
|
|
|
341
357
|
const x = (rect.left - rootRect.left) * scale
|
|
342
358
|
const y = (rect.top - rootRect.top) * scale
|
|
@@ -537,8 +553,8 @@ function walkTextNode(textNode: Text, state: WalkState, depth: number): void {
|
|
|
537
553
|
const cs = window.getComputedStyle(parent)
|
|
538
554
|
if (cs.display === "none" || cs.visibility === "hidden") return
|
|
539
555
|
|
|
540
|
-
// Get correctly-split visual lines via character-scan
|
|
541
|
-
const lines = getVisualLines(textNode)
|
|
556
|
+
// Get correctly-split visual lines via character-scan (capped at maxHeight)
|
|
557
|
+
const lines = getVisualLines(textNode, state.maxHeight, state.rootRect.top)
|
|
542
558
|
if (lines.length === 0) return
|
|
543
559
|
|
|
544
560
|
const { rootRect, scale } = state
|
|
@@ -10,12 +10,26 @@ export interface UIBBBlock {
|
|
|
10
10
|
content?: string
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
+
/** Distingue exportadores creados dentro del mismo milisegundo. */
|
|
14
|
+
let exporterSeq = 0
|
|
15
|
+
|
|
13
16
|
export class BBBlocksExporter extends Visitor<UIBBBlock[]> {
|
|
14
17
|
private idCounter = 0
|
|
15
18
|
|
|
19
|
+
/**
|
|
20
|
+
* Un identificador único dentro de ESTA exportación.
|
|
21
|
+
*
|
|
22
|
+
* Llevaba un `Date.now().toString(36)` por nodo. El reloj no aportaba nada
|
|
23
|
+
* —los identificadores solo tienen que distinguirse entre sí dentro del
|
|
24
|
+
* lote— y se leía, y se convertía a base 36, una vez por nodo del árbol.
|
|
25
|
+
* El prefijo se calcula una sola vez por exportador para que dos lotes
|
|
26
|
+
* consecutivos sigan sin colisionar.
|
|
27
|
+
*/
|
|
28
|
+
private readonly idPrefix = `block-${(exporterSeq++).toString(36)}-${Date.now().toString(36)}`
|
|
29
|
+
|
|
16
30
|
private generateId(): string {
|
|
17
31
|
this.idCounter++
|
|
18
|
-
return
|
|
32
|
+
return `${this.idPrefix}-${this.idCounter}`
|
|
19
33
|
}
|
|
20
34
|
|
|
21
35
|
visit(node: RedNode, context?: VisitorContext): UIBBBlock[] {
|