omni-viewer-core 0.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/LICENSE +21 -0
- package/README.md +80 -0
- package/THIRD_PARTY_NOTICES.md +49 -0
- package/dist/assets/audio-engine/audio_engine.mjs +2 -0
- package/dist/assets/audio-engine/audio_engine.wasm +0 -0
- package/dist/assets/pdfjs/pdf.worker.min.mjs +21 -0
- package/dist/host/index.d.ts +133 -0
- package/dist/host/index.js +10 -0
- package/dist/i18n/catalog.en.d.ts +1 -0
- package/dist/i18n/catalog.en.js +411 -0
- package/dist/i18n/catalog.ko.d.ts +1 -0
- package/dist/i18n/catalog.ko.js +68 -0
- package/dist/i18n/index.d.ts +18 -0
- package/dist/i18n/index.js +41 -0
- package/dist/licenses/emscripten.txt +101 -0
- package/dist/licenses/kissfft.txt +28 -0
- package/dist/licenses/pdfjs-dist.txt +177 -0
- package/dist/parsers/a2l/index.d.ts +1 -0
- package/dist/parsers/a2l/index.js +1 -0
- package/dist/parsers/archive/index.d.ts +22 -0
- package/dist/parsers/archive/index.js +46 -0
- package/dist/parsers/archive/model.d.ts +29 -0
- package/dist/parsers/archive/model.js +1 -0
- package/dist/parsers/archive/worker.d.ts +21 -0
- package/dist/parsers/archive/worker.js +1 -0
- package/dist/parsers/arxml/index.d.ts +1 -0
- package/dist/parsers/arxml/index.js +1 -0
- package/dist/parsers/asc/index.d.ts +1 -0
- package/dist/parsers/asc/index.js +1 -0
- package/dist/parsers/audio/index.d.ts +9 -0
- package/dist/parsers/audio/index.js +46 -0
- package/dist/parsers/automotive/index.d.ts +33 -0
- package/dist/parsers/automotive/index.js +973 -0
- package/dist/parsers/blf/index.d.ts +1 -0
- package/dist/parsers/blf/index.js +1 -0
- package/dist/parsers/csv/delimiter.d.ts +31 -0
- package/dist/parsers/csv/delimiter.js +151 -0
- package/dist/parsers/csv/index.d.ts +30 -0
- package/dist/parsers/csv/index.js +108 -0
- package/dist/parsers/csv/parseText.d.ts +20 -0
- package/dist/parsers/csv/parseText.js +108 -0
- package/dist/parsers/csv/sort.d.ts +26 -0
- package/dist/parsers/csv/sort.js +224 -0
- package/dist/parsers/csv/statistics.d.ts +49 -0
- package/dist/parsers/csv/statistics.js +150 -0
- package/dist/parsers/dbc/index.d.ts +56 -0
- package/dist/parsers/dbc/index.js +94 -0
- package/dist/parsers/doc-binary/index.d.ts +35 -0
- package/dist/parsers/doc-binary/index.js +267 -0
- package/dist/parsers/doc-binary/vscode-parser.d.ts +142 -0
- package/dist/parsers/doc-binary/vscode-parser.js +3747 -0
- package/dist/parsers/excel/index.d.ts +17 -0
- package/dist/parsers/excel/index.js +406 -0
- package/dist/parsers/excel/model.d.ts +80 -0
- package/dist/parsers/excel/model.js +48 -0
- package/dist/parsers/excel/serialize.d.ts +3 -0
- package/dist/parsers/excel/serialize.js +78 -0
- package/dist/parsers/hdf5/index.d.ts +75 -0
- package/dist/parsers/hdf5/index.js +658 -0
- package/dist/parsers/hdf5/node.d.ts +21 -0
- package/dist/parsers/hdf5/node.js +95 -0
- package/dist/parsers/json/index.d.ts +15 -0
- package/dist/parsers/json/index.js +102 -0
- package/dist/parsers/json/model.d.ts +42 -0
- package/dist/parsers/json/model.js +140 -0
- package/dist/parsers/json/parse.d.ts +22 -0
- package/dist/parsers/json/parse.js +279 -0
- package/dist/parsers/json/tokenizer.d.ts +17 -0
- package/dist/parsers/json/tokenizer.js +175 -0
- package/dist/parsers/jsonl/index.d.ts +14 -0
- package/dist/parsers/jsonl/index.js +18 -0
- package/dist/parsers/jsonl/model.d.ts +23 -0
- package/dist/parsers/jsonl/model.js +1 -0
- package/dist/parsers/jsonl/parse.d.ts +7 -0
- package/dist/parsers/jsonl/parse.js +34 -0
- package/dist/parsers/markdown/index.d.ts +37 -0
- package/dist/parsers/markdown/index.js +59 -0
- package/dist/parsers/mat/index.d.ts +31 -0
- package/dist/parsers/mat/index.js +426 -0
- package/dist/parsers/mermaid/index.d.ts +5 -0
- package/dist/parsers/mermaid/index.js +3 -0
- package/dist/parsers/mf4/index.d.ts +1 -0
- package/dist/parsers/mf4/index.js +1 -0
- package/dist/parsers/parquet/index.d.ts +21 -0
- package/dist/parsers/parquet/index.js +68 -0
- package/dist/parsers/pcap/index.d.ts +1 -0
- package/dist/parsers/pcap/index.js +1 -0
- package/dist/parsers/pcapng/index.d.ts +1 -0
- package/dist/parsers/pcapng/index.js +1 -0
- package/dist/parsers/plantuml/index.d.ts +5 -0
- package/dist/parsers/plantuml/index.js +4 -0
- package/dist/parsers/ppt-binary/index.d.ts +5 -0
- package/dist/parsers/ppt-binary/index.js +62 -0
- package/dist/parsers/ppt-binary/pptBinaryBuildContext.d.ts +12 -0
- package/dist/parsers/ppt-binary/pptBinaryBuildContext.js +40 -0
- package/dist/parsers/ppt-binary/pptBinaryContainer.d.ts +4 -0
- package/dist/parsers/ppt-binary/pptBinaryContainer.js +174 -0
- package/dist/parsers/ppt-binary/pptBinaryTypes.d.ts +125 -0
- package/dist/parsers/ppt-binary/pptBinaryTypes.js +1 -0
- package/dist/parsers/ppt-binary/pptSlideLayouts.d.ts +9 -0
- package/dist/parsers/ppt-binary/pptSlideLayouts.js +510 -0
- package/dist/parsers/ppt-binary/vscode-parser.d.ts +116 -0
- package/dist/parsers/ppt-binary/vscode-parser.js +2853 -0
- package/dist/parsers/ppt-binary/vscode.d.ts +4 -0
- package/dist/parsers/ppt-binary/vscode.js +12 -0
- package/dist/parsers/pptx/index.d.ts +15 -0
- package/dist/parsers/pptx/index.js +88 -0
- package/dist/parsers/pptx/vscode-parser.d.ts +167 -0
- package/dist/parsers/pptx/vscode-parser.js +1503 -0
- package/dist/parsers/pptx/vscode.d.ts +4 -0
- package/dist/parsers/pptx/vscode.js +18 -0
- package/dist/parsers/pptx/zip-reader.d.ts +3 -0
- package/dist/parsers/pptx/zip-reader.js +20 -0
- package/dist/parsers/proto/index.d.ts +90 -0
- package/dist/parsers/proto/index.js +197 -0
- package/dist/parsers/psd/index.d.ts +16 -0
- package/dist/parsers/psd/index.js +10 -0
- package/dist/parsers/shapefile/dbf.d.ts +23 -0
- package/dist/parsers/shapefile/dbf.js +112 -0
- package/dist/parsers/shapefile/index.d.ts +44 -0
- package/dist/parsers/shapefile/index.js +119 -0
- package/dist/parsers/shapefile/reproject.d.ts +10 -0
- package/dist/parsers/shapefile/reproject.js +41 -0
- package/dist/parsers/slide-model.d.ts +106 -0
- package/dist/parsers/slide-model.js +1 -0
- package/dist/parsers/toml/index.d.ts +15 -0
- package/dist/parsers/toml/index.js +18 -0
- package/dist/parsers/toml/model.d.ts +15 -0
- package/dist/parsers/toml/model.js +1 -0
- package/dist/parsers/toml/parse.d.ts +16 -0
- package/dist/parsers/toml/parse.js +266 -0
- package/dist/parsers/types.d.ts +103 -0
- package/dist/parsers/types.js +106 -0
- package/dist/parsers/video/index.d.ts +6 -0
- package/dist/parsers/video/index.js +2 -0
- package/dist/parsers/yaml/index.d.ts +16 -0
- package/dist/parsers/yaml/index.js +58 -0
- package/dist/parsers/yaml/model.d.ts +22 -0
- package/dist/parsers/yaml/model.js +1 -0
- package/dist/parsers/yaml/self-loading.d.ts +3 -0
- package/dist/parsers/yaml/self-loading.js +19 -0
- package/dist/parsers/zip-scan.d.ts +8 -0
- package/dist/parsers/zip-scan.js +80 -0
- package/dist/registry/container.d.ts +17 -0
- package/dist/registry/container.js +49 -0
- package/dist/registry/index.d.ts +133 -0
- package/dist/registry/index.js +348 -0
- package/dist/registry/probe.d.ts +3 -0
- package/dist/registry/probe.js +177 -0
- package/dist/registry/sniff.d.ts +17 -0
- package/dist/registry/sniff.js +57 -0
- package/dist/styles/archive.css +10 -0
- package/dist/styles/audio.css +66 -0
- package/dist/styles/automotive.css +1 -0
- package/dist/styles/csv.css +262 -0
- package/dist/styles/excel.css +212 -0
- package/dist/styles/fallback.css +48 -0
- package/dist/styles/hdf5.css +3 -0
- package/dist/styles/hwp.css +12 -0
- package/dist/styles/image.css +115 -0
- package/dist/styles/json.css +342 -0
- package/dist/styles/jsonl.css +1 -0
- package/dist/styles/markdown.css +10 -0
- package/dist/styles/mat.css +2 -0
- package/dist/styles/mermaid.css +1 -0
- package/dist/styles/parquet.css +2 -0
- package/dist/styles/pdf.css +551 -0
- package/dist/styles/plantuml.css +1 -0
- package/dist/styles/ppt.css +1 -0
- package/dist/styles/proto.css +2 -0
- package/dist/styles/psd.css +1 -0
- package/dist/styles/shapefile.css +25 -0
- package/dist/styles/toml.css +1 -0
- package/dist/styles/video.css +74 -0
- package/dist/styles/word.css +685 -0
- package/dist/styles/yaml.css +1 -0
- package/dist/viewers/a2l/index.d.ts +15 -0
- package/dist/viewers/a2l/index.js +5 -0
- package/dist/viewers/archive/archive-preview-decoder.d.ts +4 -0
- package/dist/viewers/archive/archive-preview-decoder.js +223 -0
- package/dist/viewers/archive/controller.d.ts +24 -0
- package/dist/viewers/archive/controller.js +18 -0
- package/dist/viewers/archive/index.d.ts +25 -0
- package/dist/viewers/archive/index.js +230 -0
- package/dist/viewers/archive/preview.d.ts +2 -0
- package/dist/viewers/archive/preview.js +2 -0
- package/dist/viewers/archive/styles.d.ts +1 -0
- package/dist/viewers/archive/styles.js +11 -0
- package/dist/viewers/arxml/index.d.ts +15 -0
- package/dist/viewers/arxml/index.js +5 -0
- package/dist/viewers/asc/index.d.ts +15 -0
- package/dist/viewers/asc/index.js +5 -0
- package/dist/viewers/audio/controller.d.ts +33 -0
- package/dist/viewers/audio/controller.js +49 -0
- package/dist/viewers/audio/engine.d.ts +44 -0
- package/dist/viewers/audio/engine.js +108 -0
- package/dist/viewers/audio/index.d.ts +92 -0
- package/dist/viewers/audio/index.js +448 -0
- package/dist/viewers/audio/self-loading.d.ts +7 -0
- package/dist/viewers/audio/self-loading.js +42 -0
- package/dist/viewers/audio/styles.d.ts +1 -0
- package/dist/viewers/audio/styles.js +73 -0
- package/dist/viewers/automotive/index.d.ts +8 -0
- package/dist/viewers/automotive/index.js +152 -0
- package/dist/viewers/automotive/styles.d.ts +1 -0
- package/dist/viewers/automotive/styles.js +1 -0
- package/dist/viewers/avro/index.d.ts +15 -0
- package/dist/viewers/avro/index.js +5 -0
- package/dist/viewers/bag/index.d.ts +15 -0
- package/dist/viewers/bag/index.js +5 -0
- package/dist/viewers/blf/index.d.ts +15 -0
- package/dist/viewers/blf/index.js +5 -0
- package/dist/viewers/csv/controller.d.ts +126 -0
- package/dist/viewers/csv/controller.js +598 -0
- package/dist/viewers/csv/index.d.ts +48 -0
- package/dist/viewers/csv/index.js +846 -0
- package/dist/viewers/csv/styles.d.ts +1 -0
- package/dist/viewers/csv/styles.js +267 -0
- package/dist/viewers/db3/index.d.ts +15 -0
- package/dist/viewers/db3/index.js +5 -0
- package/dist/viewers/dbc/index.d.ts +15 -0
- package/dist/viewers/dbc/index.js +5 -0
- package/dist/viewers/diagram.d.ts +14 -0
- package/dist/viewers/diagram.js +95 -0
- package/dist/viewers/excel/controller.d.ts +108 -0
- package/dist/viewers/excel/controller.js +548 -0
- package/dist/viewers/excel/grid.d.ts +28 -0
- package/dist/viewers/excel/grid.js +99 -0
- package/dist/viewers/excel/index.d.ts +37 -0
- package/dist/viewers/excel/index.js +620 -0
- package/dist/viewers/excel/self-loading.d.ts +6 -0
- package/dist/viewers/excel/self-loading.js +13 -0
- package/dist/viewers/excel/styles.d.ts +1 -0
- package/dist/viewers/excel/styles.js +216 -0
- package/dist/viewers/fallback/index.d.ts +17 -0
- package/dist/viewers/fallback/index.js +130 -0
- package/dist/viewers/fallback/styles.d.ts +1 -0
- package/dist/viewers/fallback/styles.js +49 -0
- package/dist/viewers/hdf5/index.d.ts +19 -0
- package/dist/viewers/hdf5/index.js +170 -0
- package/dist/viewers/hdf5/styles.d.ts +1 -0
- package/dist/viewers/hdf5/styles.js +4 -0
- package/dist/viewers/hwp/controller.d.ts +19 -0
- package/dist/viewers/hwp/controller.js +22 -0
- package/dist/viewers/hwp/index.d.ts +39 -0
- package/dist/viewers/hwp/index.js +271 -0
- package/dist/viewers/hwp/self-loading.d.ts +2 -0
- package/dist/viewers/hwp/self-loading.js +6 -0
- package/dist/viewers/hwp/styles.d.ts +1 -0
- package/dist/viewers/hwp/styles.js +13 -0
- package/dist/viewers/image/controller.d.ts +210 -0
- package/dist/viewers/image/controller.js +336 -0
- package/dist/viewers/image/decode.d.ts +54 -0
- package/dist/viewers/image/decode.js +150 -0
- package/dist/viewers/image/index.d.ts +38 -0
- package/dist/viewers/image/index.js +749 -0
- package/dist/viewers/image/limits.d.ts +18 -0
- package/dist/viewers/image/limits.js +20 -0
- package/dist/viewers/image/styles.d.ts +1 -0
- package/dist/viewers/image/styles.js +119 -0
- package/dist/viewers/json/controller.d.ts +89 -0
- package/dist/viewers/json/controller.js +411 -0
- package/dist/viewers/json/index.d.ts +25 -0
- package/dist/viewers/json/index.js +503 -0
- package/dist/viewers/json/styles.d.ts +1 -0
- package/dist/viewers/json/styles.js +346 -0
- package/dist/viewers/json/transforms.d.ts +27 -0
- package/dist/viewers/json/transforms.js +253 -0
- package/dist/viewers/jsonl/controller.d.ts +48 -0
- package/dist/viewers/jsonl/controller.js +136 -0
- package/dist/viewers/jsonl/index.d.ts +22 -0
- package/dist/viewers/jsonl/index.js +184 -0
- package/dist/viewers/jsonl/styles.d.ts +1 -0
- package/dist/viewers/jsonl/styles.js +1 -0
- package/dist/viewers/markdown/controller.d.ts +50 -0
- package/dist/viewers/markdown/controller.js +62 -0
- package/dist/viewers/markdown/index.d.ts +64 -0
- package/dist/viewers/markdown/index.js +425 -0
- package/dist/viewers/markdown/math.d.ts +21 -0
- package/dist/viewers/markdown/math.js +100 -0
- package/dist/viewers/markdown/self-loading.d.ts +5 -0
- package/dist/viewers/markdown/self-loading.js +48 -0
- package/dist/viewers/markdown/styles.d.ts +1 -0
- package/dist/viewers/markdown/styles.js +11 -0
- package/dist/viewers/mat/index.d.ts +19 -0
- package/dist/viewers/mat/index.js +113 -0
- package/dist/viewers/mat/styles.d.ts +1 -0
- package/dist/viewers/mat/styles.js +3 -0
- package/dist/viewers/media.d.ts +9 -0
- package/dist/viewers/media.js +77 -0
- package/dist/viewers/mermaid/index.d.ts +17 -0
- package/dist/viewers/mermaid/index.js +6 -0
- package/dist/viewers/mermaid/self-loading.d.ts +2 -0
- package/dist/viewers/mermaid/self-loading.js +2 -0
- package/dist/viewers/mf4/index.d.ts +15 -0
- package/dist/viewers/mf4/index.js +5 -0
- package/dist/viewers/parquet/controller.d.ts +37 -0
- package/dist/viewers/parquet/controller.js +26 -0
- package/dist/viewers/parquet/index.d.ts +23 -0
- package/dist/viewers/parquet/index.js +134 -0
- package/dist/viewers/parquet/styles.d.ts +1 -0
- package/dist/viewers/parquet/styles.js +3 -0
- package/dist/viewers/pcap/index.d.ts +15 -0
- package/dist/viewers/pcap/index.js +5 -0
- package/dist/viewers/pcapng/index.d.ts +15 -0
- package/dist/viewers/pcapng/index.js +5 -0
- package/dist/viewers/pdf/controller.d.ts +120 -0
- package/dist/viewers/pdf/controller.js +191 -0
- package/dist/viewers/pdf/editing.d.ts +26 -0
- package/dist/viewers/pdf/editing.js +265 -0
- package/dist/viewers/pdf/index.d.ts +88 -0
- package/dist/viewers/pdf/index.js +1400 -0
- package/dist/viewers/pdf/self-loading.d.ts +6 -0
- package/dist/viewers/pdf/self-loading.js +14 -0
- package/dist/viewers/pdf/styles.d.ts +1 -0
- package/dist/viewers/pdf/styles.js +555 -0
- package/dist/viewers/plantuml/index.d.ts +17 -0
- package/dist/viewers/plantuml/index.js +6 -0
- package/dist/viewers/plantuml/self-loading.d.ts +2 -0
- package/dist/viewers/plantuml/self-loading.js +2 -0
- package/dist/viewers/ppt/chart.d.ts +8 -0
- package/dist/viewers/ppt/chart.js +83 -0
- package/dist/viewers/ppt/controller.d.ts +34 -0
- package/dist/viewers/ppt/controller.js +27 -0
- package/dist/viewers/ppt/index.d.ts +33 -0
- package/dist/viewers/ppt/index.js +101 -0
- package/dist/viewers/ppt/render.d.ts +5 -0
- package/dist/viewers/ppt/render.js +144 -0
- package/dist/viewers/ppt/self-loading.d.ts +9 -0
- package/dist/viewers/ppt/self-loading.js +4 -0
- package/dist/viewers/ppt/styles.d.ts +1 -0
- package/dist/viewers/ppt/styles.js +1 -0
- package/dist/viewers/proto/index.d.ts +17 -0
- package/dist/viewers/proto/index.js +170 -0
- package/dist/viewers/proto/styles.d.ts +1 -0
- package/dist/viewers/proto/styles.js +2 -0
- package/dist/viewers/psd/index.d.ts +27 -0
- package/dist/viewers/psd/index.js +39 -0
- package/dist/viewers/psd/self-loading.d.ts +10 -0
- package/dist/viewers/psd/self-loading.js +20 -0
- package/dist/viewers/psd/styles.d.ts +1 -0
- package/dist/viewers/psd/styles.js +1 -0
- package/dist/viewers/reqif/index.d.ts +15 -0
- package/dist/viewers/reqif/index.js +5 -0
- package/dist/viewers/shapefile/index.d.ts +35 -0
- package/dist/viewers/shapefile/index.js +336 -0
- package/dist/viewers/shapefile/self-loading.d.ts +7 -0
- package/dist/viewers/shapefile/self-loading.js +32 -0
- package/dist/viewers/shapefile/styles.d.ts +1 -0
- package/dist/viewers/shapefile/styles.js +28 -0
- package/dist/viewers/stp/index.d.ts +15 -0
- package/dist/viewers/stp/index.js +5 -0
- package/dist/viewers/structured-styles.d.ts +1 -0
- package/dist/viewers/structured-styles.js +1 -0
- package/dist/viewers/structured.d.ts +36 -0
- package/dist/viewers/structured.js +138 -0
- package/dist/viewers/toml/controller.d.ts +38 -0
- package/dist/viewers/toml/controller.js +61 -0
- package/dist/viewers/toml/index.d.ts +18 -0
- package/dist/viewers/toml/index.js +34 -0
- package/dist/viewers/types.d.ts +36 -0
- package/dist/viewers/types.js +9 -0
- package/dist/viewers/video/controller.d.ts +29 -0
- package/dist/viewers/video/controller.js +54 -0
- package/dist/viewers/video/index.d.ts +18 -0
- package/dist/viewers/video/index.js +305 -0
- package/dist/viewers/video/styles.d.ts +1 -0
- package/dist/viewers/video/styles.js +79 -0
- package/dist/viewers/word/controller.d.ts +19 -0
- package/dist/viewers/word/controller.js +22 -0
- package/dist/viewers/word/docx-preprocess.d.ts +63 -0
- package/dist/viewers/word/docx-preprocess.js +136 -0
- package/dist/viewers/word/index.d.ts +32 -0
- package/dist/viewers/word/index.js +187 -0
- package/dist/viewers/word/normalize-docx.d.ts +2 -0
- package/dist/viewers/word/normalize-docx.js +50 -0
- package/dist/viewers/word/paginate.d.ts +1 -0
- package/dist/viewers/word/paginate.js +1035 -0
- package/dist/viewers/word/self-loading.d.ts +2 -0
- package/dist/viewers/word/self-loading.js +7 -0
- package/dist/viewers/word/styles.d.ts +1 -0
- package/dist/viewers/word/styles.js +686 -0
- package/dist/viewers/yaml/controller.d.ts +42 -0
- package/dist/viewers/yaml/controller.js +41 -0
- package/dist/viewers/yaml/index.d.ts +21 -0
- package/dist/viewers/yaml/index.js +20 -0
- package/package.json +375 -0
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
const NAMES = { 0: 'Null', 1: 'Point', 3: 'PolyLine', 5: 'Polygon', 8: 'MultiPoint', 11: 'PointZ', 13: 'PolyLineZ', 15: 'PolygonZ', 18: 'MultiPointZ', 21: 'PointM', 23: 'PolyLineM', 25: 'PolygonM', 28: 'MultiPointM', 31: 'MultiPatch' };
|
|
2
|
+
export function parseShapefile(data, options = {}) {
|
|
3
|
+
const maxBytes = options.maxBytes ?? 128 * 1024 * 1024, maxFeatures = options.maxFeatures ?? 10_000, maxVertices = options.maxVertices ?? 200_000;
|
|
4
|
+
if (options.signal?.aborted)
|
|
5
|
+
throw new Error('aborted');
|
|
6
|
+
if (data.byteLength > maxBytes)
|
|
7
|
+
throw new Error(`Shapefile exceeds the ${maxBytes.toLocaleString()} byte limit.`);
|
|
8
|
+
if (data.byteLength < 100)
|
|
9
|
+
throw new Error('Shapefile header is truncated.');
|
|
10
|
+
const v = new DataView(data.buffer, data.byteOffset, data.byteLength);
|
|
11
|
+
if (v.getInt32(0, false) !== 9994)
|
|
12
|
+
throw new Error('Invalid Shapefile file code.');
|
|
13
|
+
if (v.getInt32(28, true) !== 1000)
|
|
14
|
+
throw new Error('Unsupported Shapefile version.');
|
|
15
|
+
const type = v.getInt32(32, true);
|
|
16
|
+
const declared = v.getInt32(24, false) * 2;
|
|
17
|
+
const bbox = readBBox(v, 36);
|
|
18
|
+
const features = [];
|
|
19
|
+
const warnings = [];
|
|
20
|
+
let offset = 100, vertices = 0, truncated = false;
|
|
21
|
+
while (offset + 8 <= data.length && features.length < maxFeatures && vertices < maxVertices) {
|
|
22
|
+
if (options.signal?.aborted)
|
|
23
|
+
throw new Error('aborted');
|
|
24
|
+
const id = v.getInt32(offset, false), length = v.getInt32(offset + 4, false) * 2, start = offset + 8, end = start + length;
|
|
25
|
+
if (length < 4 || end > data.length) {
|
|
26
|
+
truncated = true;
|
|
27
|
+
break;
|
|
28
|
+
}
|
|
29
|
+
try {
|
|
30
|
+
const parsed = parseRecord(v, start, end, maxVertices - vertices);
|
|
31
|
+
features.push({ id, geometry: parsed.geometry });
|
|
32
|
+
vertices += parsed.vertices;
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
warnings.push(`Record ${id} was skipped: ${error instanceof Error ? error.message : String(error)}`);
|
|
36
|
+
if (warnings.length >= 20) {
|
|
37
|
+
warnings.push('Additional record warnings were suppressed.');
|
|
38
|
+
break;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
offset = end;
|
|
42
|
+
}
|
|
43
|
+
if (declared !== data.byteLength)
|
|
44
|
+
warnings.push(`Header declares ${declared.toLocaleString()} bytes; input contains ${data.byteLength.toLocaleString()} bytes.`);
|
|
45
|
+
if (truncated)
|
|
46
|
+
warnings.push('Parsing stopped at a truncated record.');
|
|
47
|
+
if (offset < data.length && (features.length >= maxFeatures || vertices >= maxVertices))
|
|
48
|
+
warnings.push(`Preview is limited to ${maxFeatures.toLocaleString()} features and ${maxVertices.toLocaleString()} vertices.`);
|
|
49
|
+
return { shapeType: type, shapeTypeName: NAMES[type] ?? `Unknown (${type})`, fileLengthBytes: data.byteLength, bbox, features, vertexCount: vertices, warnings };
|
|
50
|
+
}
|
|
51
|
+
function parseRecord(v, start, end, remaining) { const type = v.getInt32(start, true); if (type === 0)
|
|
52
|
+
return { geometry: null, vertices: 0 }; if (type === 31)
|
|
53
|
+
throw new Error('unsupported MultiPatch geometry'); const base = type % 10; if (base === 1) {
|
|
54
|
+
bounds(start + 4, 16, end);
|
|
55
|
+
const point = readPoint(v, start + 4);
|
|
56
|
+
return { geometry: { type: 'Point', coordinates: point }, vertices: 1 };
|
|
57
|
+
} if (base !== 3 && base !== 5 && base !== 8)
|
|
58
|
+
throw new Error(`unsupported shape type ${type}`); bounds(start + 4, 36, end); let cursor = start + 36; if (base === 8) {
|
|
59
|
+
const count = v.getInt32(cursor, true);
|
|
60
|
+
cursor += 4;
|
|
61
|
+
checkCount(count, remaining);
|
|
62
|
+
bounds(cursor, count * 16, end);
|
|
63
|
+
const points = readPoints(v, cursor, count);
|
|
64
|
+
return { geometry: { type: 'MultiPoint', coordinates: points }, vertices: count };
|
|
65
|
+
} const partCount = v.getInt32(cursor, true), pointCount = v.getInt32(cursor + 4, true); cursor += 8; checkCount(partCount, 100_000); checkCount(pointCount, remaining); bounds(cursor, partCount * 4 + pointCount * 16, end); const parts = []; for (let i = 0; i < partCount; i++)
|
|
66
|
+
parts.push(v.getInt32(cursor + i * 4, true)); cursor += partCount * 4; const points = readPoints(v, cursor, pointCount); const groups = parts.map((at, i) => points.slice(at, parts[i + 1] ?? points.length)).filter(x => x.length > 0); if (base === 3)
|
|
67
|
+
return { geometry: groups.length === 1 ? { type: 'LineString', coordinates: groups[0] } : { type: 'MultiLineString', coordinates: groups }, vertices: pointCount }; return { geometry: buildPolygonGeometry(groups), vertices: pointCount }; }
|
|
68
|
+
function buildPolygonGeometry(rings) {
|
|
69
|
+
const outers = rings.filter(ring => signedRingArea(ring) < 0);
|
|
70
|
+
const holes = rings.filter(ring => signedRingArea(ring) >= 0);
|
|
71
|
+
const polygons = outers.map(outer => [outer]);
|
|
72
|
+
for (const hole of holes) {
|
|
73
|
+
const point = hole[0];
|
|
74
|
+
const owner = point === undefined ? undefined : outers
|
|
75
|
+
.map((outer, index) => ({ index, area: Math.abs(signedRingArea(outer)), contains: pointInRing(point, outer) }))
|
|
76
|
+
.filter(candidate => candidate.contains)
|
|
77
|
+
.sort((left, right) => left.area - right.area)[0]?.index;
|
|
78
|
+
if (owner !== undefined)
|
|
79
|
+
polygons[owner].push(hole);
|
|
80
|
+
else
|
|
81
|
+
polygons.push([signedRingArea(hole) > 0 ? [...hole].reverse() : hole]);
|
|
82
|
+
}
|
|
83
|
+
if (polygons.length === 1)
|
|
84
|
+
return { type: 'Polygon', coordinates: polygons[0] };
|
|
85
|
+
return { type: 'MultiPolygon', coordinates: polygons };
|
|
86
|
+
}
|
|
87
|
+
function signedRingArea(ring) {
|
|
88
|
+
let area = 0;
|
|
89
|
+
for (let index = 0; index < ring.length; index++) {
|
|
90
|
+
const current = ring[index];
|
|
91
|
+
const next = ring[(index + 1) % ring.length];
|
|
92
|
+
if (current && next)
|
|
93
|
+
area += current[0] * next[1] - next[0] * current[1];
|
|
94
|
+
}
|
|
95
|
+
return area / 2;
|
|
96
|
+
}
|
|
97
|
+
function pointInRing(point, ring) {
|
|
98
|
+
let inside = false;
|
|
99
|
+
for (let current = 0, previous = ring.length - 1; current < ring.length; previous = current++) {
|
|
100
|
+
const a = ring[current];
|
|
101
|
+
const b = ring[previous];
|
|
102
|
+
if (!a || !b)
|
|
103
|
+
continue;
|
|
104
|
+
const crosses = (a[1] > point[1]) !== (b[1] > point[1]) &&
|
|
105
|
+
point[0] < ((b[0] - a[0]) * (point[1] - a[1])) / (b[1] - a[1]) + a[0];
|
|
106
|
+
if (crosses)
|
|
107
|
+
inside = !inside;
|
|
108
|
+
}
|
|
109
|
+
return inside;
|
|
110
|
+
}
|
|
111
|
+
function readBBox(v, o) { const b = [v.getFloat64(o, true), v.getFloat64(o + 8, true), v.getFloat64(o + 16, true), v.getFloat64(o + 24, true)]; return b.every(Number.isFinite) ? b : null; }
|
|
112
|
+
function readPoint(v, o) { const p = [v.getFloat64(o, true), v.getFloat64(o + 8, true)]; if (!p.every(Number.isFinite))
|
|
113
|
+
throw new Error('non-finite coordinate'); return p; }
|
|
114
|
+
function readPoints(v, o, n) { const r = []; for (let i = 0; i < n; i++)
|
|
115
|
+
r.push(readPoint(v, o + i * 16)); return r; }
|
|
116
|
+
function bounds(o, n, end) { if (o < 0 || n < 0 || o + n > end)
|
|
117
|
+
throw new Error('truncated geometry'); }
|
|
118
|
+
function checkCount(n, max) { if (!Number.isInteger(n) || n < 0 || n > max)
|
|
119
|
+
throw new Error('geometry count exceeds the resource limit'); }
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ShapefileModel, ShpPosition } from './index.js';
|
|
2
|
+
export type CoordinateConverter = (position: ShpPosition) => ShpPosition;
|
|
3
|
+
/** WKT PROJCS/GEOGCS name, used for the projection label in the viewer. */
|
|
4
|
+
export declare function projectionName(wkt: string): string | null;
|
|
5
|
+
/** True for WKT that is already geographic (lon/lat) — no reprojection needed. */
|
|
6
|
+
export declare function isGeographicWkt(wkt: string): boolean;
|
|
7
|
+
/** Returns a new model with every coordinate converted; bbox is recomputed.
|
|
8
|
+
* Non-finite conversion results fail the whole reprojection (throw) so the
|
|
9
|
+
* caller can fall back to rendering native coordinates. */
|
|
10
|
+
export declare function reprojectModel(model: ShapefileModel, convert: CoordinateConverter): ShapefileModel;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// Coordinate reprojection over a parsed shapefile model. The converter is
|
|
2
|
+
// injected (proj4 is an optional peer loaded by the adapter or the viewer's
|
|
3
|
+
// self-loading entry); this module only walks the geometry.
|
|
4
|
+
/** WKT PROJCS/GEOGCS name, used for the projection label in the viewer. */
|
|
5
|
+
export function projectionName(wkt) {
|
|
6
|
+
return /^\s*(?:PROJCS|GEOGCS|GEOGCRS|PROJCRS)\s*\[\s*"([^"]+)"/i.exec(wkt)?.[1] ?? null;
|
|
7
|
+
}
|
|
8
|
+
/** True for WKT that is already geographic (lon/lat) — no reprojection needed. */
|
|
9
|
+
export function isGeographicWkt(wkt) {
|
|
10
|
+
return /^\s*(?:GEOGCS|GEOGCRS)\s*\[/i.test(wkt);
|
|
11
|
+
}
|
|
12
|
+
/** Returns a new model with every coordinate converted; bbox is recomputed.
|
|
13
|
+
* Non-finite conversion results fail the whole reprojection (throw) so the
|
|
14
|
+
* caller can fall back to rendering native coordinates. */
|
|
15
|
+
export function reprojectModel(model, convert) {
|
|
16
|
+
let bbox = null;
|
|
17
|
+
const convertChecked = (position) => {
|
|
18
|
+
const next = convert(position);
|
|
19
|
+
if (!Number.isFinite(next[0]) || !Number.isFinite(next[1]))
|
|
20
|
+
throw new Error('reprojection produced a non-finite coordinate');
|
|
21
|
+
bbox = bbox
|
|
22
|
+
? [Math.min(bbox[0], next[0]), Math.min(bbox[1], next[1]), Math.max(bbox[2], next[0]), Math.max(bbox[3], next[1])]
|
|
23
|
+
: [next[0], next[1], next[0], next[1]];
|
|
24
|
+
return next;
|
|
25
|
+
};
|
|
26
|
+
const features = model.features.map((feature) => ({
|
|
27
|
+
...feature,
|
|
28
|
+
geometry: feature.geometry ? convertGeometry(feature.geometry, convertChecked) : null
|
|
29
|
+
}));
|
|
30
|
+
return { ...model, features, bbox };
|
|
31
|
+
}
|
|
32
|
+
function convertGeometry(geometry, convert) {
|
|
33
|
+
switch (geometry.type) {
|
|
34
|
+
case 'Point': return { type: 'Point', coordinates: convert(geometry.coordinates) };
|
|
35
|
+
case 'MultiPoint': return { type: 'MultiPoint', coordinates: geometry.coordinates.map(convert) };
|
|
36
|
+
case 'LineString': return { type: 'LineString', coordinates: geometry.coordinates.map(convert) };
|
|
37
|
+
case 'MultiLineString': return { type: 'MultiLineString', coordinates: geometry.coordinates.map((line) => line.map(convert)) };
|
|
38
|
+
case 'Polygon': return { type: 'Polygon', coordinates: geometry.coordinates.map((ring) => ring.map(convert)) };
|
|
39
|
+
case 'MultiPolygon': return { type: 'MultiPolygon', coordinates: geometry.coordinates.map((polygon) => polygon.map((ring) => ring.map(convert))) };
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
export interface SlideTextRun {
|
|
2
|
+
text: string;
|
|
3
|
+
fontSizePx?: number;
|
|
4
|
+
bold?: boolean;
|
|
5
|
+
italic?: boolean;
|
|
6
|
+
color?: string;
|
|
7
|
+
}
|
|
8
|
+
export interface SlideParagraph {
|
|
9
|
+
text: string;
|
|
10
|
+
level: number;
|
|
11
|
+
bullet?: boolean;
|
|
12
|
+
align?: string;
|
|
13
|
+
fontSizePx?: number;
|
|
14
|
+
bold?: boolean;
|
|
15
|
+
italic?: boolean;
|
|
16
|
+
color?: string;
|
|
17
|
+
runs?: SlideTextRun[];
|
|
18
|
+
}
|
|
19
|
+
export interface SlideChartSeries {
|
|
20
|
+
name: string;
|
|
21
|
+
color: string;
|
|
22
|
+
values: number[];
|
|
23
|
+
valueFormat?: string;
|
|
24
|
+
dataLabel?: {
|
|
25
|
+
showValue?: boolean;
|
|
26
|
+
numFmt?: string;
|
|
27
|
+
fontSizePx?: number;
|
|
28
|
+
color?: string;
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
export interface SlideChartData {
|
|
32
|
+
kind: 'stackedColumn' | 'line';
|
|
33
|
+
categories: string[];
|
|
34
|
+
series: SlideChartSeries[];
|
|
35
|
+
gapWidth?: number;
|
|
36
|
+
overlap?: number;
|
|
37
|
+
legend?: {
|
|
38
|
+
position?: string;
|
|
39
|
+
fontSizePx?: number;
|
|
40
|
+
color?: string;
|
|
41
|
+
align?: string;
|
|
42
|
+
};
|
|
43
|
+
categoryAxis?: SlideChartAxis;
|
|
44
|
+
valueAxis?: SlideChartAxis & {
|
|
45
|
+
gridColor?: string;
|
|
46
|
+
majorUnit?: number;
|
|
47
|
+
min?: number;
|
|
48
|
+
max?: number;
|
|
49
|
+
crossesAt?: number;
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
export interface SlideChartAxis {
|
|
53
|
+
numFmt?: string;
|
|
54
|
+
fontSizePx?: number;
|
|
55
|
+
color?: string;
|
|
56
|
+
lineColor?: string;
|
|
57
|
+
}
|
|
58
|
+
export interface SlideElement {
|
|
59
|
+
type: 'text' | 'image' | 'table' | 'chart' | 'shape';
|
|
60
|
+
x: number;
|
|
61
|
+
y: number;
|
|
62
|
+
width: number;
|
|
63
|
+
height: number;
|
|
64
|
+
rotateDeg?: number;
|
|
65
|
+
zIndex: number;
|
|
66
|
+
placeholderKey?: string;
|
|
67
|
+
isTitle?: boolean;
|
|
68
|
+
paragraphs?: SlideParagraph[];
|
|
69
|
+
src?: string;
|
|
70
|
+
srcRect?: {
|
|
71
|
+
l: number;
|
|
72
|
+
t: number;
|
|
73
|
+
r: number;
|
|
74
|
+
b: number;
|
|
75
|
+
};
|
|
76
|
+
vectorFallback?: boolean;
|
|
77
|
+
tableRows?: string[][];
|
|
78
|
+
chartKind?: string;
|
|
79
|
+
chartTitle?: string;
|
|
80
|
+
chartData?: SlideChartData;
|
|
81
|
+
fillColor?: string;
|
|
82
|
+
borderColor?: string;
|
|
83
|
+
borderWidthPx?: number;
|
|
84
|
+
customSvgPath?: string;
|
|
85
|
+
presetGeom?: string;
|
|
86
|
+
headEnd?: string;
|
|
87
|
+
tailEnd?: string;
|
|
88
|
+
flipH?: boolean;
|
|
89
|
+
flipV?: boolean;
|
|
90
|
+
textStylePreset?: string;
|
|
91
|
+
}
|
|
92
|
+
export interface Slide {
|
|
93
|
+
slideNumber: number;
|
|
94
|
+
widthPx: number;
|
|
95
|
+
heightPx: number;
|
|
96
|
+
backgroundColor: string;
|
|
97
|
+
elements: SlideElement[];
|
|
98
|
+
}
|
|
99
|
+
export interface SlideDeck {
|
|
100
|
+
slides: Slide[];
|
|
101
|
+
totalSlides: number;
|
|
102
|
+
slideSize?: {
|
|
103
|
+
widthPx: number;
|
|
104
|
+
heightPx: number;
|
|
105
|
+
};
|
|
106
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { ParseOutcome } from '../types.js';
|
|
2
|
+
import type { TomlDocument } from './model.js';
|
|
3
|
+
export * from './model.js';
|
|
4
|
+
export { parseTomlText } from './parse.js';
|
|
5
|
+
export declare const TOML_INPUT_OWNERSHIP: "borrows";
|
|
6
|
+
export declare function parseToml(input: Uint8Array | string, options?: {
|
|
7
|
+
limits?: {
|
|
8
|
+
maxInputBytes?: number;
|
|
9
|
+
maxEntries?: number;
|
|
10
|
+
maxTables?: number;
|
|
11
|
+
maxArrayLength?: number;
|
|
12
|
+
};
|
|
13
|
+
signal?: AbortSignal;
|
|
14
|
+
maxDepth?: number;
|
|
15
|
+
}): ParseOutcome<TomlDocument>;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { decodeUtf8, utf8ByteLength } from '../types.js';
|
|
2
|
+
import { parseTomlText } from './parse.js';
|
|
3
|
+
export * from './model.js';
|
|
4
|
+
export { parseTomlText } from './parse.js';
|
|
5
|
+
export const TOML_INPUT_OWNERSHIP = 'borrows';
|
|
6
|
+
export function parseToml(input, options = {}) {
|
|
7
|
+
const started = Date.now();
|
|
8
|
+
const bytes = typeof input === 'string' ? utf8ByteLength(input) : input.byteLength;
|
|
9
|
+
const max = options.limits?.maxInputBytes ?? 10 * 1024 * 1024;
|
|
10
|
+
const finish = (result) => ({ result, execution: { workerUsed: false, hardLimitEnforced: false, elapsedMillis: Date.now() - started } });
|
|
11
|
+
if (bytes > max)
|
|
12
|
+
return finish({ status: 'failed', failure: { code: 'limit-exceeded', retryable: false, messageKey: 'diag.limit-exceeded.input', args: { maxBytes: max } }, diagnostics: [] });
|
|
13
|
+
if (options.signal?.aborted)
|
|
14
|
+
return finish({ status: 'failed', failure: { code: 'aborted', retryable: true, messageKey: 'diag.aborted' }, diagnostics: [] });
|
|
15
|
+
const treeLimits = { ...(options.maxDepth === undefined ? {} : { maxDepth: options.maxDepth }), ...(options.limits?.maxEntries === undefined ? {} : { maxNodes: options.limits.maxEntries }), ...(options.limits?.maxTables === undefined ? {} : { maxTables: options.limits.maxTables }), ...(options.limits?.maxArrayLength === undefined ? {} : { maxArrayLength: options.limits.maxArrayLength }), ...(options.signal ? { signal: options.signal } : {}) };
|
|
16
|
+
const tree = parseTomlText(typeof input === 'string' ? input : decodeUtf8(input), treeLimits);
|
|
17
|
+
return finish(tree.diagnostics.some(d => d.severity === 'error') ? { status: 'partial', document: tree.document, diagnostics: tree.diagnostics } : { status: 'ok', document: tree.document, diagnostics: tree.diagnostics });
|
|
18
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export type TomlValueKind = 'table' | 'array' | 'string' | 'integer' | 'float' | 'boolean' | 'datetime';
|
|
2
|
+
export interface TomlNode {
|
|
3
|
+
kind: TomlValueKind;
|
|
4
|
+
key: string;
|
|
5
|
+
path: string;
|
|
6
|
+
value?: string | boolean;
|
|
7
|
+
raw: string;
|
|
8
|
+
line: number;
|
|
9
|
+
children?: TomlNode[];
|
|
10
|
+
}
|
|
11
|
+
export interface TomlDocument {
|
|
12
|
+
text: string;
|
|
13
|
+
root: TomlNode;
|
|
14
|
+
}
|
|
15
|
+
export declare const tomlPath: (parent: string, key: string) => string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const tomlPath = (parent, key) => parent ? `${parent}.${key}` : key;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Diagnostic } from '../types.js';
|
|
2
|
+
import { type TomlDocument } from './model.js';
|
|
3
|
+
export interface TomlParseTree {
|
|
4
|
+
document: TomlDocument;
|
|
5
|
+
diagnostics: Diagnostic[];
|
|
6
|
+
}
|
|
7
|
+
/** A deliberately small, lossless TOML 1.0 reader. Values retain `raw` so
|
|
8
|
+
* datetime and unsafe integers never pass through JavaScript Number. */
|
|
9
|
+
export interface TomlTreeLimits {
|
|
10
|
+
maxDepth?: number;
|
|
11
|
+
maxNodes?: number;
|
|
12
|
+
maxTables?: number;
|
|
13
|
+
maxArrayLength?: number;
|
|
14
|
+
signal?: AbortSignal;
|
|
15
|
+
}
|
|
16
|
+
export declare function parseTomlText(text: string, limits?: TomlTreeLimits | number): TomlParseTree;
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
import { tomlPath } from './model.js';
|
|
2
|
+
export function parseTomlText(text, limits = {}) {
|
|
3
|
+
const settings = typeof limits === 'number' ? { maxDepth: limits } : limits;
|
|
4
|
+
const maxDepth = settings.maxDepth ?? 100, maxNodes = settings.maxNodes ?? 100_000, maxTables = settings.maxTables ?? 50_000, maxArrayLength = settings.maxArrayLength ?? 100_000;
|
|
5
|
+
const root = { kind: 'table', key: '$', path: '', raw: '', line: 1, children: [] };
|
|
6
|
+
const diagnostics = [];
|
|
7
|
+
let current = root, nodeCount = 1, tableCount = 1, stopped = false;
|
|
8
|
+
const tables = new Map([['', root]]);
|
|
9
|
+
const lines = logicalTomlLines(text.replace(/^\uFEFF/, ''));
|
|
10
|
+
const error = (code, line) => diagnostics.push({ severity: 'error', code, messageKey: `diag.${code}`, location: `line:${line}` });
|
|
11
|
+
const unquote = (value) => {
|
|
12
|
+
if (value.startsWith('"""') && value.endsWith('"""')) {
|
|
13
|
+
// TOML multiline basic strings allow literal newlines. Reuse the
|
|
14
|
+
// JSON escape decoder after making those newlines explicit.
|
|
15
|
+
const body = value.slice(3, -3).replace(/^\r?\n/, '');
|
|
16
|
+
try {
|
|
17
|
+
return JSON.parse(`"${body.replace(/\r?\n/g, '\\n')}"`);
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
return body;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
if (value.startsWith("'''") && value.endsWith("'''"))
|
|
24
|
+
return value.slice(3, -3).replace(/^\r?\n/, '');
|
|
25
|
+
if (value.startsWith('"') && value.endsWith('"')) {
|
|
26
|
+
try {
|
|
27
|
+
return JSON.parse(value);
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return value.slice(1, -1);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
if (value.startsWith("'") && value.endsWith("'"))
|
|
34
|
+
return value.slice(1, -1);
|
|
35
|
+
return value;
|
|
36
|
+
};
|
|
37
|
+
const split = (value) => {
|
|
38
|
+
const out = [];
|
|
39
|
+
let start = 0;
|
|
40
|
+
let quote = '';
|
|
41
|
+
let depth = 0;
|
|
42
|
+
for (let i = 0; i < value.length; i++) {
|
|
43
|
+
const c = value[i];
|
|
44
|
+
if (quote) {
|
|
45
|
+
if (c === quote && value[i - 1] !== '\\')
|
|
46
|
+
quote = '';
|
|
47
|
+
}
|
|
48
|
+
else if (c === '"' || c === "'")
|
|
49
|
+
quote = c;
|
|
50
|
+
else if (c === '[' || c === '{')
|
|
51
|
+
depth++;
|
|
52
|
+
else if (c === ']' || c === '}')
|
|
53
|
+
depth--;
|
|
54
|
+
else if (c === ',' && depth === 0) {
|
|
55
|
+
out.push(value.slice(start, i).trim());
|
|
56
|
+
start = i + 1;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
out.push(value.slice(start).trim());
|
|
60
|
+
return out.filter(Boolean);
|
|
61
|
+
};
|
|
62
|
+
const keyParts = (key) => splitKey(key).map(unquote);
|
|
63
|
+
const makeValue = (key, path, rawValue, line, depth) => {
|
|
64
|
+
const raw = rawValue.trim();
|
|
65
|
+
let kind = 'string';
|
|
66
|
+
let value = unquote(raw);
|
|
67
|
+
if (/^(true|false)$/.test(raw)) {
|
|
68
|
+
kind = 'boolean';
|
|
69
|
+
value = raw === 'true';
|
|
70
|
+
}
|
|
71
|
+
else if (/^[+-]?(?:0x[\da-fA-F_]+|0o[0-7_]+|0b[01_]+|\d[\d_]*)$/.test(raw))
|
|
72
|
+
kind = 'integer';
|
|
73
|
+
else if (/^[+-]?(?:\d[\d_]*\.\d[\d_]*|\d[\d_]*(?:\.\d[\d_]*)?[eE][+-]?\d[\d_]*|nan|inf)$/i.test(raw))
|
|
74
|
+
kind = 'float';
|
|
75
|
+
else if (/^\d{4}-\d\d-\d\d(?:[Tt ]\d\d:\d\d(?::\d\d(?:\.\d+)?)?(?:[Zz]|[+-]\d\d:\d\d)?)?$|^\d\d:\d\d(?::\d\d(?:\.\d+)?)?$/.test(raw))
|
|
76
|
+
kind = 'datetime';
|
|
77
|
+
else if (raw.startsWith('[') && raw.endsWith(']')) {
|
|
78
|
+
kind = 'array';
|
|
79
|
+
const values = split(raw.slice(1, -1));
|
|
80
|
+
if (values.length > maxArrayLength) {
|
|
81
|
+
error('toml.array-limit', line);
|
|
82
|
+
values.length = maxArrayLength;
|
|
83
|
+
}
|
|
84
|
+
const children = values.map((v, i) => makeValue(String(i), `${path}[${i}]`, v, line, depth + 1));
|
|
85
|
+
nodeCount += children.length;
|
|
86
|
+
return { kind, key, path, raw, line, children };
|
|
87
|
+
}
|
|
88
|
+
else if (raw.startsWith('{') && raw.endsWith('}')) {
|
|
89
|
+
kind = 'table';
|
|
90
|
+
const children = [];
|
|
91
|
+
for (const pair of split(raw.slice(1, -1))) {
|
|
92
|
+
const eq = indexOfEquals(pair);
|
|
93
|
+
if (eq < 0) {
|
|
94
|
+
error('toml.invalid-inline-table', line);
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
const childKey = unquote(pair.slice(0, eq).trim());
|
|
98
|
+
children.push(makeValue(childKey, tomlPath(path, childKey), pair.slice(eq + 1), line, depth + 1));
|
|
99
|
+
}
|
|
100
|
+
return { kind, key, path, raw, line, children };
|
|
101
|
+
}
|
|
102
|
+
if (depth > maxDepth)
|
|
103
|
+
error('toml.max-depth', line);
|
|
104
|
+
nodeCount++;
|
|
105
|
+
return { kind, key, path, value, raw, line };
|
|
106
|
+
};
|
|
107
|
+
for (const logical of lines) {
|
|
108
|
+
if (settings.signal?.aborted) {
|
|
109
|
+
error('aborted', logical.line);
|
|
110
|
+
stopped = true;
|
|
111
|
+
break;
|
|
112
|
+
}
|
|
113
|
+
if (nodeCount > maxNodes || tableCount > maxTables) {
|
|
114
|
+
error(nodeCount > maxNodes ? 'toml.node-limit' : 'toml.table-limit', logical.line);
|
|
115
|
+
stopped = true;
|
|
116
|
+
break;
|
|
117
|
+
}
|
|
118
|
+
const i = logical.line - 1;
|
|
119
|
+
const source = stripComment(logical.text).trim();
|
|
120
|
+
if (!source)
|
|
121
|
+
continue;
|
|
122
|
+
const arrayTable = source.match(/^\[\[(.+)\]\]$/);
|
|
123
|
+
const table = source.match(/^\[(.+)\]$/);
|
|
124
|
+
if (arrayTable || table) {
|
|
125
|
+
const matched = arrayTable ?? table;
|
|
126
|
+
const parts = keyParts((matched?.[1] ?? '').trim());
|
|
127
|
+
if (!parts.length) {
|
|
128
|
+
error('toml.invalid-table', i + 1);
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
const path = parts.join('.');
|
|
132
|
+
if (arrayTable) {
|
|
133
|
+
const parentPath = parts.slice(0, -1).join('.');
|
|
134
|
+
const parent = tables.get(parentPath) ?? root;
|
|
135
|
+
let collection = parent.children.find(node => node.key === parts.at(-1) && node.kind === 'array');
|
|
136
|
+
if (!collection) {
|
|
137
|
+
collection = { kind: 'array', key: parts.at(-1), path, raw: '', line: i + 1, children: [] };
|
|
138
|
+
parent.children.push(collection);
|
|
139
|
+
nodeCount++;
|
|
140
|
+
}
|
|
141
|
+
const index = collection.children.length;
|
|
142
|
+
const node = { kind: 'table', key: String(index), path: `${path}[${index}]`, raw: '', line: i + 1, children: [] };
|
|
143
|
+
collection.children.push(node);
|
|
144
|
+
tables.set(path, node);
|
|
145
|
+
current = node;
|
|
146
|
+
nodeCount++;
|
|
147
|
+
tableCount++;
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
let node = tables.get(path);
|
|
151
|
+
if (!node) {
|
|
152
|
+
node = { kind: 'table', key: parts.at(-1), path, raw: '', line: i + 1, children: [] };
|
|
153
|
+
(tables.get(parts.slice(0, -1).join('.')) ?? root).children.push(node);
|
|
154
|
+
tables.set(path, node);
|
|
155
|
+
nodeCount++;
|
|
156
|
+
tableCount++;
|
|
157
|
+
}
|
|
158
|
+
else if (node !== current && node.line !== i + 1 && node.children?.length)
|
|
159
|
+
error('toml.duplicate-table', i + 1);
|
|
160
|
+
current = node;
|
|
161
|
+
}
|
|
162
|
+
continue;
|
|
163
|
+
}
|
|
164
|
+
const eq = indexOfEquals(source);
|
|
165
|
+
if (eq < 0) {
|
|
166
|
+
error('toml.invalid-assignment', i + 1);
|
|
167
|
+
continue;
|
|
168
|
+
}
|
|
169
|
+
const parts = keyParts(source.slice(0, eq).trim());
|
|
170
|
+
if (!parts.length) {
|
|
171
|
+
error('toml.invalid-key', i + 1);
|
|
172
|
+
continue;
|
|
173
|
+
}
|
|
174
|
+
let parent = current;
|
|
175
|
+
for (const part of parts.slice(0, -1)) {
|
|
176
|
+
let nested = parent.children.find(n => n.key === part && n.kind === 'table');
|
|
177
|
+
if (!nested) {
|
|
178
|
+
nested = { kind: 'table', key: part, path: tomlPath(parent.path, part), raw: '', line: i + 1, children: [] };
|
|
179
|
+
parent.children.push(nested);
|
|
180
|
+
}
|
|
181
|
+
parent = nested;
|
|
182
|
+
}
|
|
183
|
+
const key = parts.at(-1);
|
|
184
|
+
if (parent.children.some(n => n.key === key))
|
|
185
|
+
error('toml.duplicate-key', i + 1);
|
|
186
|
+
else
|
|
187
|
+
parent.children.push(makeValue(key, tomlPath(parent.path, key), source.slice(eq + 1), i + 1, 0));
|
|
188
|
+
}
|
|
189
|
+
return { document: { text, root }, diagnostics };
|
|
190
|
+
}
|
|
191
|
+
/** Group physical lines while a multiline string or a composite array/table
|
|
192
|
+
* remains open. This preserves the declaration line for diagnostics. */
|
|
193
|
+
function logicalTomlLines(text) {
|
|
194
|
+
const physical = text.split(/\r\n|\n|\r/);
|
|
195
|
+
const out = [];
|
|
196
|
+
let buffer = '';
|
|
197
|
+
let start = 1;
|
|
198
|
+
let triple = '';
|
|
199
|
+
let depth = 0;
|
|
200
|
+
for (let i = 0; i < physical.length; i++) {
|
|
201
|
+
const line = physical[i] ?? '';
|
|
202
|
+
if (!buffer)
|
|
203
|
+
start = i + 1;
|
|
204
|
+
buffer += (buffer ? '\n' : '') + line;
|
|
205
|
+
for (let p = 0; p < line.length; p++) {
|
|
206
|
+
if (line.startsWith('"""', p) || line.startsWith("'''", p)) {
|
|
207
|
+
const token = line.slice(p, p + 3);
|
|
208
|
+
triple = triple === token ? '' : (triple || token);
|
|
209
|
+
p += 2;
|
|
210
|
+
continue;
|
|
211
|
+
}
|
|
212
|
+
if (triple)
|
|
213
|
+
continue;
|
|
214
|
+
const c = line[p];
|
|
215
|
+
if (c === '#')
|
|
216
|
+
break;
|
|
217
|
+
if (c === '[' || c === '{')
|
|
218
|
+
depth++;
|
|
219
|
+
else if (c === ']' || c === '}')
|
|
220
|
+
depth--;
|
|
221
|
+
}
|
|
222
|
+
if (!triple && depth <= 0) {
|
|
223
|
+
out.push({ line: start, text: buffer });
|
|
224
|
+
buffer = '';
|
|
225
|
+
depth = 0;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
if (buffer)
|
|
229
|
+
out.push({ line: start, text: buffer });
|
|
230
|
+
return out;
|
|
231
|
+
}
|
|
232
|
+
function stripComment(line) { let q = ''; for (let i = 0; i < line.length; i++) {
|
|
233
|
+
const c = line[i];
|
|
234
|
+
if (q) {
|
|
235
|
+
if (c === q && line[i - 1] !== '\\')
|
|
236
|
+
q = '';
|
|
237
|
+
}
|
|
238
|
+
else if (c === '"' || c === "'")
|
|
239
|
+
q = c;
|
|
240
|
+
else if (c === '#')
|
|
241
|
+
return line.slice(0, i);
|
|
242
|
+
} return line; }
|
|
243
|
+
function indexOfEquals(line) { let q = ''; for (let i = 0; i < line.length; i++) {
|
|
244
|
+
const c = line[i];
|
|
245
|
+
if (q) {
|
|
246
|
+
if (c === q && line[i - 1] !== '\\')
|
|
247
|
+
q = '';
|
|
248
|
+
}
|
|
249
|
+
else if (c === '"' || c === "'")
|
|
250
|
+
q = c;
|
|
251
|
+
else if (c === '=')
|
|
252
|
+
return i;
|
|
253
|
+
} return -1; }
|
|
254
|
+
function splitKey(value) { const out = []; let q = ''; let start = 0; for (let i = 0; i < value.length; i++) {
|
|
255
|
+
const c = value[i];
|
|
256
|
+
if (q) {
|
|
257
|
+
if (c === q && value[i - 1] !== '\\')
|
|
258
|
+
q = '';
|
|
259
|
+
}
|
|
260
|
+
else if (c === '"' || c === "'")
|
|
261
|
+
q = c;
|
|
262
|
+
else if (c === '.') {
|
|
263
|
+
out.push(value.slice(start, i).trim());
|
|
264
|
+
start = i + 1;
|
|
265
|
+
}
|
|
266
|
+
} out.push(value.slice(start).trim()); return out.filter(Boolean); }
|