@react-x11/components 0.8.0 → 0.10.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/README.md +105 -38
- package/dist/charts/node.d.ts +12 -2
- package/dist/charts/node.d.ts.map +1 -1
- package/dist/charts/node.js +50 -16
- package/dist/charts/node.js.map +1 -1
- package/dist/charts/render.d.ts +12 -3
- package/dist/charts/render.d.ts.map +1 -1
- package/dist/charts/render.js +94 -25
- package/dist/charts/render.js.map +1 -1
- package/dist/code/index.d.ts.map +1 -1
- package/dist/code/index.js +3 -1
- package/dist/code/index.js.map +1 -1
- package/dist/code-editor/completion.d.ts.map +1 -1
- package/dist/code-editor/completion.js +3 -2
- package/dist/code-editor/completion.js.map +1 -1
- package/dist/code-editor/index.d.ts.map +1 -1
- package/dist/code-editor/index.js +19 -0
- package/dist/code-editor/index.js.map +1 -1
- package/dist/code-editor/node.d.ts +177 -7
- package/dist/code-editor/node.d.ts.map +1 -1
- package/dist/code-editor/node.js +1329 -164
- package/dist/code-editor/node.js.map +1 -1
- package/dist/code-language/languages/glsl.d.ts.map +1 -1
- package/dist/code-language/languages/glsl.js +10 -2
- package/dist/code-language/languages/glsl.js.map +1 -1
- package/dist/code-language/languages/javascript.d.ts.map +1 -1
- package/dist/code-language/languages/javascript.js +18 -3
- package/dist/code-language/languages/javascript.js.map +1 -1
- package/dist/code-language/languages/json.d.ts.map +1 -1
- package/dist/code-language/languages/json.js +10 -2
- package/dist/code-language/languages/json.js.map +1 -1
- package/dist/code-language/languages/shell.d.ts.map +1 -1
- package/dist/code-language/languages/shell.js +10 -2
- package/dist/code-language/languages/shell.js.map +1 -1
- package/dist/code-language/languages/sql.d.ts.map +1 -1
- package/dist/code-language/languages/sql.js +20 -2
- package/dist/code-language/languages/sql.js.map +1 -1
- package/dist/code-language/stream.d.ts +22 -0
- package/dist/code-language/stream.d.ts.map +1 -1
- package/dist/code-language/stream.js +259 -9
- package/dist/code-language/stream.js.map +1 -1
- package/dist/code-language/types.d.ts +5 -4
- package/dist/code-language/types.d.ts.map +1 -1
- package/dist/codeblock/index.d.ts +13 -2
- package/dist/codeblock/index.d.ts.map +1 -1
- package/dist/codeblock/index.js +20 -3
- package/dist/codeblock/index.js.map +1 -1
- package/dist/embed/client.d.ts +48 -3
- package/dist/embed/client.d.ts.map +1 -1
- package/dist/embed/client.js +79 -5
- package/dist/embed/client.js.map +1 -1
- package/dist/embed/index.d.ts +1 -1
- package/dist/embed/index.d.ts.map +1 -1
- package/dist/embed/index.js +1 -1
- package/dist/embed/index.js.map +1 -1
- package/dist/flow/draw.d.ts +50 -0
- package/dist/flow/draw.d.ts.map +1 -1
- package/dist/flow/draw.js +132 -33
- package/dist/flow/draw.js.map +1 -1
- package/dist/flow/gl/color.d.ts +13 -0
- package/dist/flow/gl/color.d.ts.map +1 -0
- package/dist/flow/gl/color.js +82 -0
- package/dist/flow/gl/color.js.map +1 -0
- package/dist/flow/gl/index.d.ts +60 -0
- package/dist/flow/gl/index.d.ts.map +1 -0
- package/dist/flow/gl/index.js +283 -0
- package/dist/flow/gl/index.js.map +1 -0
- package/dist/flow/gl/pack.d.ts +133 -0
- package/dist/flow/gl/pack.d.ts.map +1 -0
- package/dist/flow/gl/pack.js +408 -0
- package/dist/flow/gl/pack.js.map +1 -0
- package/dist/flow/gl/renderer.d.ts +95 -0
- package/dist/flow/gl/renderer.d.ts.map +1 -0
- package/dist/flow/gl/renderer.js +459 -0
- package/dist/flow/gl/renderer.js.map +1 -0
- package/dist/flow/gl/shaders.d.ts +79 -0
- package/dist/flow/gl/shaders.d.ts.map +1 -0
- package/dist/flow/gl/shaders.js +346 -0
- package/dist/flow/gl/shaders.js.map +1 -0
- package/dist/flow/gl/text.d.ts +318 -0
- package/dist/flow/gl/text.d.ts.map +1 -0
- package/dist/flow/gl/text.js +1103 -0
- package/dist/flow/gl/text.js.map +1 -0
- package/dist/flow/index.d.ts +1 -1
- package/dist/flow/index.d.ts.map +1 -1
- package/dist/flow/index.js +619 -64
- package/dist/flow/index.js.map +1 -1
- package/dist/flow/node.d.ts +621 -72
- package/dist/flow/node.d.ts.map +1 -1
- package/dist/flow/node.js +2253 -1018
- package/dist/flow/node.js.map +1 -1
- package/dist/flow/paint.d.ts +35 -0
- package/dist/flow/paint.d.ts.map +1 -0
- package/dist/flow/paint.js +393 -0
- package/dist/flow/paint.js.map +1 -0
- package/dist/flow/paths.d.ts +14 -0
- package/dist/flow/paths.d.ts.map +1 -1
- package/dist/flow/paths.js +45 -19
- package/dist/flow/paths.js.map +1 -1
- package/dist/flow/scene.d.ts +584 -0
- package/dist/flow/scene.d.ts.map +1 -0
- package/dist/flow/scene.js +1453 -0
- package/dist/flow/scene.js.map +1 -0
- package/dist/flow/types.d.ts +111 -1
- package/dist/flow/types.d.ts.map +1 -1
- package/dist/html/controls.d.ts +28 -0
- package/dist/html/controls.d.ts.map +1 -1
- package/dist/html/controls.js +52 -2
- package/dist/html/controls.js.map +1 -1
- package/dist/html/css/calc.d.ts +14 -0
- package/dist/html/css/calc.d.ts.map +1 -0
- package/dist/html/css/calc.js +344 -0
- package/dist/html/css/calc.js.map +1 -0
- package/dist/html/css/cascade.d.ts +240 -6
- package/dist/html/css/cascade.d.ts.map +1 -1
- package/dist/html/css/cascade.js +1327 -66
- package/dist/html/css/cascade.js.map +1 -1
- package/dist/html/css/color.d.ts +23 -0
- package/dist/html/css/color.d.ts.map +1 -0
- package/dist/html/css/color.js +740 -0
- package/dist/html/css/color.js.map +1 -0
- package/dist/html/css/content.d.ts +92 -0
- package/dist/html/css/content.d.ts.map +1 -0
- package/dist/html/css/content.js +388 -0
- package/dist/html/css/content.js.map +1 -0
- package/dist/html/css/counter-styles.d.ts +76 -0
- package/dist/html/css/counter-styles.d.ts.map +1 -0
- package/dist/html/css/counter-styles.js +893 -0
- package/dist/html/css/counter-styles.js.map +1 -0
- package/dist/html/css/decode.d.ts +12 -0
- package/dist/html/css/decode.d.ts.map +1 -0
- package/dist/html/css/decode.js +116 -0
- package/dist/html/css/decode.js.map +1 -0
- package/dist/html/css/parse.d.ts +110 -10
- package/dist/html/css/parse.d.ts.map +1 -1
- package/dist/html/css/parse.js +1473 -180
- package/dist/html/css/parse.js.map +1 -1
- package/dist/html/css/style.d.ts +498 -15
- package/dist/html/css/style.d.ts.map +1 -1
- package/dist/html/css/style.js +3698 -206
- package/dist/html/css/style.js.map +1 -1
- package/dist/html/css/ua.d.ts.map +1 -1
- package/dist/html/css/ua.js +57 -11
- package/dist/html/css/ua.js.map +1 -1
- package/dist/html/css/values.d.ts +37 -3
- package/dist/html/css/values.d.ts.map +1 -1
- package/dist/html/css/values.js +122 -48
- package/dist/html/css/values.js.map +1 -1
- package/dist/html/css/vars.d.ts +52 -0
- package/dist/html/css/vars.d.ts.map +1 -0
- package/dist/html/css/vars.js +358 -0
- package/dist/html/css/vars.js.map +1 -0
- package/dist/html/dom.d.ts +30 -4
- package/dist/html/dom.d.ts.map +1 -1
- package/dist/html/dom.js +278 -17
- package/dist/html/dom.js.map +1 -1
- package/dist/html/fonts.d.ts +106 -0
- package/dist/html/fonts.d.ts.map +1 -0
- package/dist/html/fonts.js +565 -0
- package/dist/html/fonts.js.map +1 -0
- package/dist/html/gif.d.ts +15 -0
- package/dist/html/gif.d.ts.map +1 -0
- package/dist/html/gif.js +229 -0
- package/dist/html/gif.js.map +1 -0
- package/dist/html/index.d.ts +50 -11
- package/dist/html/index.d.ts.map +1 -1
- package/dist/html/index.js +115 -9
- package/dist/html/index.js.map +1 -1
- package/dist/html/layout/block.d.ts +226 -3
- package/dist/html/layout/block.d.ts.map +1 -1
- package/dist/html/layout/block.js +2937 -197
- package/dist/html/layout/block.js.map +1 -1
- package/dist/html/layout/boxes.d.ts +340 -17
- package/dist/html/layout/boxes.d.ts.map +1 -1
- package/dist/html/layout/boxes.js +1714 -182
- package/dist/html/layout/boxes.js.map +1 -1
- package/dist/html/layout/cache.d.ts +58 -0
- package/dist/html/layout/cache.d.ts.map +1 -0
- package/dist/html/layout/cache.js +224 -0
- package/dist/html/layout/cache.js.map +1 -0
- package/dist/html/layout/collapse.d.ts +45 -0
- package/dist/html/layout/collapse.d.ts.map +1 -0
- package/dist/html/layout/collapse.js +246 -0
- package/dist/html/layout/collapse.js.map +1 -0
- package/dist/html/layout/css-grid.d.ts +7 -0
- package/dist/html/layout/css-grid.d.ts.map +1 -0
- package/dist/html/layout/css-grid.js +900 -0
- package/dist/html/layout/css-grid.js.map +1 -0
- package/dist/html/layout/flex.d.ts.map +1 -1
- package/dist/html/layout/flex.js +1025 -89
- package/dist/html/layout/flex.js.map +1 -1
- package/dist/html/layout/floats.d.ts +45 -6
- package/dist/html/layout/floats.d.ts.map +1 -1
- package/dist/html/layout/floats.js +113 -14
- package/dist/html/layout/floats.js.map +1 -1
- package/dist/html/layout/grid-lines.d.ts +39 -0
- package/dist/html/layout/grid-lines.d.ts.map +1 -0
- package/dist/html/layout/grid-lines.js +119 -0
- package/dist/html/layout/grid-lines.js.map +1 -0
- package/dist/html/layout/grid.d.ts +53 -0
- package/dist/html/layout/grid.d.ts.map +1 -0
- package/dist/html/layout/grid.js +153 -0
- package/dist/html/layout/grid.js.map +1 -0
- package/dist/html/layout/inline.d.ts +151 -1
- package/dist/html/layout/inline.d.ts.map +1 -1
- package/dist/html/layout/inline.js +3375 -174
- package/dist/html/layout/inline.js.map +1 -1
- package/dist/html/layout/shaping.d.ts +6 -0
- package/dist/html/layout/shaping.d.ts.map +1 -0
- package/dist/html/layout/shaping.js +100 -0
- package/dist/html/layout/shaping.js.map +1 -0
- package/dist/html/layout/table.d.ts +3 -0
- package/dist/html/layout/table.d.ts.map +1 -1
- package/dist/html/layout/table.js +681 -175
- package/dist/html/layout/table.js.map +1 -1
- package/dist/html/layout/tracks.d.ts +44 -0
- package/dist/html/layout/tracks.d.ts.map +1 -0
- package/dist/html/layout/tracks.js +349 -0
- package/dist/html/layout/tracks.js.map +1 -0
- package/dist/html/node.d.ts +172 -5
- package/dist/html/node.d.ts.map +1 -1
- package/dist/html/node.js +1336 -103
- package/dist/html/node.js.map +1 -1
- package/dist/html/paint.d.ts +92 -3
- package/dist/html/paint.d.ts.map +1 -1
- package/dist/html/paint.js +3503 -141
- package/dist/html/paint.js.map +1 -1
- package/dist/html/resources.d.ts +60 -14
- package/dist/html/resources.d.ts.map +1 -1
- package/dist/html/resources.js +122 -36
- package/dist/html/resources.js.map +1 -1
- package/dist/html/surfaces.d.ts +23 -0
- package/dist/html/surfaces.d.ts.map +1 -0
- package/dist/html/surfaces.js +68 -0
- package/dist/html/surfaces.js.map +1 -0
- package/dist/html/svg.d.ts +80 -0
- package/dist/html/svg.d.ts.map +1 -0
- package/dist/html/svg.js +435 -0
- package/dist/html/svg.js.map +1 -0
- package/dist/html/url.d.ts +23 -0
- package/dist/html/url.d.ts.map +1 -0
- package/dist/html/url.js +80 -0
- package/dist/html/url.js.map +1 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/internal/collate.d.ts +3 -0
- package/dist/internal/collate.d.ts.map +1 -0
- package/dist/internal/collate.js +11 -0
- package/dist/internal/collate.js.map +1 -0
- package/dist/{markdown → internal/markdown}/ast.d.ts +23 -0
- package/dist/internal/markdown/ast.d.ts.map +1 -0
- package/dist/internal/markdown/ast.js +22 -0
- package/dist/internal/markdown/ast.js.map +1 -0
- package/dist/internal/markdown/parse.d.ts.map +1 -0
- package/dist/{markdown → internal/markdown}/parse.js +221 -30
- package/dist/internal/markdown/parse.js.map +1 -0
- package/dist/internal/markdown/stringify.d.ts +4 -0
- package/dist/internal/markdown/stringify.d.ts.map +1 -0
- package/dist/internal/markdown/stringify.js +684 -0
- package/dist/internal/markdown/stringify.js.map +1 -0
- package/dist/internal/markdown/tags.d.ts.map +1 -0
- package/dist/internal/markdown/tags.js.map +1 -0
- package/dist/internal/prewarm.d.ts +18 -0
- package/dist/internal/prewarm.d.ts.map +1 -0
- package/dist/internal/prewarm.js +42 -0
- package/dist/internal/prewarm.js.map +1 -0
- package/dist/internal/scroll.d.ts +3 -2
- package/dist/internal/scroll.d.ts.map +1 -1
- package/dist/internal/scroll.js +1 -0
- package/dist/internal/scroll.js.map +1 -1
- package/dist/internal/sdf.d.ts +20 -0
- package/dist/internal/sdf.d.ts.map +1 -0
- package/dist/internal/sdf.js +216 -0
- package/dist/internal/sdf.js.map +1 -0
- package/dist/internal/splice.d.ts +12 -0
- package/dist/internal/splice.d.ts.map +1 -0
- package/dist/internal/splice.js +23 -0
- package/dist/internal/splice.js.map +1 -0
- package/dist/internal/window.d.ts +12 -0
- package/dist/internal/window.d.ts.map +1 -1
- package/dist/internal/window.js +23 -6
- package/dist/internal/window.js.map +1 -1
- package/dist/maps/anchors.d.ts +103 -0
- package/dist/maps/anchors.d.ts.map +1 -0
- package/dist/maps/anchors.js +790 -0
- package/dist/maps/anchors.js.map +1 -0
- package/dist/maps/controller.d.ts +340 -0
- package/dist/maps/controller.d.ts.map +1 -0
- package/dist/maps/controller.js +822 -0
- package/dist/maps/controller.js.map +1 -0
- package/dist/maps/gl/buckets.d.ts +99 -0
- package/dist/maps/gl/buckets.d.ts.map +1 -0
- package/dist/maps/gl/buckets.js +365 -0
- package/dist/maps/gl/buckets.js.map +1 -0
- package/dist/maps/gl/build-worker.d.ts +15 -0
- package/dist/maps/gl/build-worker.d.ts.map +1 -0
- package/dist/maps/gl/build-worker.js +44 -0
- package/dist/maps/gl/build-worker.js.map +1 -0
- package/dist/maps/gl/color.d.ts +8 -0
- package/dist/maps/gl/color.d.ts.map +1 -0
- package/dist/maps/gl/color.js +57 -0
- package/dist/maps/gl/color.js.map +1 -0
- package/dist/maps/gl/cover.d.ts +70 -0
- package/dist/maps/gl/cover.d.ts.map +1 -0
- package/dist/maps/gl/cover.js +137 -0
- package/dist/maps/gl/cover.js.map +1 -0
- package/dist/maps/gl/index.d.ts +3 -0
- package/dist/maps/gl/index.d.ts.map +1 -0
- package/dist/maps/gl/index.js +20 -0
- package/dist/maps/gl/index.js.map +1 -0
- package/dist/maps/gl/markers.d.ts +28 -0
- package/dist/maps/gl/markers.d.ts.map +1 -0
- package/dist/maps/gl/markers.js +60 -0
- package/dist/maps/gl/markers.js.map +1 -0
- package/dist/maps/gl/overlays.d.ts +68 -0
- package/dist/maps/gl/overlays.d.ts.map +1 -0
- package/dist/maps/gl/overlays.js +300 -0
- package/dist/maps/gl/overlays.js.map +1 -0
- package/dist/maps/gl/pane.d.ts +12 -0
- package/dist/maps/gl/pane.d.ts.map +1 -0
- package/dist/maps/gl/pane.js +37 -0
- package/dist/maps/gl/pane.js.map +1 -0
- package/dist/maps/gl/placement.d.ts +124 -0
- package/dist/maps/gl/placement.d.ts.map +1 -0
- package/dist/maps/gl/placement.js +642 -0
- package/dist/maps/gl/placement.js.map +1 -0
- package/dist/maps/gl/renderer.d.ts +384 -0
- package/dist/maps/gl/renderer.d.ts.map +1 -0
- package/dist/maps/gl/renderer.js +1184 -0
- package/dist/maps/gl/renderer.js.map +1 -0
- package/dist/maps/gl/shaders.d.ts +121 -0
- package/dist/maps/gl/shaders.d.ts.map +1 -0
- package/dist/maps/gl/shaders.js +453 -0
- package/dist/maps/gl/shaders.js.map +1 -0
- package/dist/maps/gl/store.d.ts +125 -0
- package/dist/maps/gl/store.d.ts.map +1 -0
- package/dist/maps/gl/store.js +512 -0
- package/dist/maps/gl/store.js.map +1 -0
- package/dist/maps/gl/text.d.ts +283 -0
- package/dist/maps/gl/text.d.ts.map +1 -0
- package/dist/maps/gl/text.js +698 -0
- package/dist/maps/gl/text.js.map +1 -0
- package/dist/maps/gl/view.d.ts +345 -0
- package/dist/maps/gl/view.d.ts.map +1 -0
- package/dist/maps/gl/view.js +1209 -0
- package/dist/maps/gl/view.js.map +1 -0
- package/dist/maps/icons.d.ts +32 -0
- package/dist/maps/icons.d.ts.map +1 -0
- package/dist/maps/icons.js +151 -0
- package/dist/maps/icons.js.map +1 -0
- package/dist/maps/index.d.ts +3 -1
- package/dist/maps/index.d.ts.map +1 -1
- package/dist/maps/index.js +218 -52
- package/dist/maps/index.js.map +1 -1
- package/dist/maps/labels.d.ts +91 -18
- package/dist/maps/labels.d.ts.map +1 -1
- package/dist/maps/labels.js +376 -140
- package/dist/maps/labels.js.map +1 -1
- package/dist/maps/node.d.ts +179 -56
- package/dist/maps/node.d.ts.map +1 -1
- package/dist/maps/node.js +663 -537
- package/dist/maps/node.js.map +1 -1
- package/dist/maps/overlay.d.ts +72 -9
- package/dist/maps/overlay.d.ts.map +1 -1
- package/dist/maps/overlay.js +108 -28
- package/dist/maps/overlay.js.map +1 -1
- package/dist/maps/paint.d.ts +3 -0
- package/dist/maps/paint.d.ts.map +1 -1
- package/dist/maps/paint.js.map +1 -1
- package/dist/maps/proj.d.ts +62 -0
- package/dist/maps/proj.d.ts.map +1 -1
- package/dist/maps/proj.js +101 -0
- package/dist/maps/proj.js.map +1 -1
- package/dist/maps/renderer.d.ts +69 -0
- package/dist/maps/renderer.d.ts.map +1 -0
- package/dist/maps/renderer.js +66 -0
- package/dist/maps/renderer.js.map +1 -0
- package/dist/maps/sources.d.ts +30 -6
- package/dist/maps/sources.d.ts.map +1 -1
- package/dist/maps/sources.js +22 -3
- package/dist/maps/sources.js.map +1 -1
- package/dist/maps/style.d.ts +35 -0
- package/dist/maps/style.d.ts.map +1 -1
- package/dist/maps/style.js.map +1 -1
- package/dist/maps/styles.d.ts +12 -0
- package/dist/maps/styles.d.ts.map +1 -1
- package/dist/maps/styles.js +120 -6
- package/dist/maps/styles.js.map +1 -1
- package/dist/maps/theme.d.ts +19 -0
- package/dist/maps/theme.d.ts.map +1 -0
- package/dist/maps/theme.js +44 -0
- package/dist/maps/theme.js.map +1 -0
- package/dist/maps/tiles.d.ts +147 -27
- package/dist/maps/tiles.d.ts.map +1 -1
- package/dist/maps/tiles.js +221 -54
- package/dist/maps/tiles.js.map +1 -1
- package/dist/maps/types.d.ts +213 -21
- package/dist/maps/types.d.ts.map +1 -1
- package/dist/markdown/expressions.d.ts +1 -1
- package/dist/markdown/expressions.d.ts.map +1 -1
- package/dist/markdown/expressions.js.map +1 -1
- package/dist/markdown/index.d.ts +7 -6
- package/dist/markdown/index.d.ts.map +1 -1
- package/dist/markdown/index.js +121 -50
- package/dist/markdown/index.js.map +1 -1
- package/dist/markdown/spans.d.ts +1 -1
- package/dist/markdown/spans.d.ts.map +1 -1
- package/dist/markdown/spans.js +6 -0
- package/dist/markdown/spans.js.map +1 -1
- package/dist/media-player/index.d.ts +11 -3
- package/dist/media-player/index.d.ts.map +1 -1
- package/dist/media-player/index.js +13 -2
- package/dist/media-player/index.js.map +1 -1
- package/dist/qml/containers.d.ts.map +1 -1
- package/dist/qml/containers.js +6 -1
- package/dist/qml/containers.js.map +1 -1
- package/dist/qml/interaction.d.ts.map +1 -1
- package/dist/qml/interaction.js +38 -5
- package/dist/qml/interaction.js.map +1 -1
- package/dist/qml/layouts.d.ts.map +1 -1
- package/dist/qml/layouts.js +21 -6
- package/dist/qml/layouts.js.map +1 -1
- package/dist/qml/qtquick.d.ts.map +1 -1
- package/dist/qml/qtquick.js +9 -2
- package/dist/qml/qtquick.js.map +1 -1
- package/dist/qml/react.d.ts.map +1 -1
- package/dist/qml/react.js +9 -7
- package/dist/qml/react.js.map +1 -1
- package/dist/reorder/clock.d.ts +7 -0
- package/dist/reorder/clock.d.ts.map +1 -0
- package/dist/reorder/clock.js +26 -0
- package/dist/reorder/clock.js.map +1 -0
- package/dist/reorder/index.d.ts +25 -3
- package/dist/reorder/index.d.ts.map +1 -1
- package/dist/reorder/index.js +64 -19
- package/dist/reorder/index.js.map +1 -1
- package/dist/rich-text-editor/clipboard.d.ts +23 -0
- package/dist/rich-text-editor/clipboard.d.ts.map +1 -0
- package/dist/rich-text-editor/clipboard.js +307 -0
- package/dist/rich-text-editor/clipboard.js.map +1 -0
- package/dist/rich-text-editor/collab.d.ts +32 -0
- package/dist/rich-text-editor/collab.d.ts.map +1 -0
- package/dist/rich-text-editor/collab.js +55 -0
- package/dist/rich-text-editor/collab.js.map +1 -0
- package/dist/rich-text-editor/commands.d.ts +50 -0
- package/dist/rich-text-editor/commands.d.ts.map +1 -0
- package/dist/rich-text-editor/commands.js +376 -0
- package/dist/rich-text-editor/commands.js.map +1 -0
- package/dist/rich-text-editor/drag.d.ts +68 -0
- package/dist/rich-text-editor/drag.d.ts.map +1 -0
- package/dist/rich-text-editor/drag.js +148 -0
- package/dist/rich-text-editor/drag.js.map +1 -0
- package/dist/rich-text-editor/html.d.ts +145 -0
- package/dist/rich-text-editor/html.d.ts.map +1 -0
- package/dist/rich-text-editor/html.js +516 -0
- package/dist/rich-text-editor/html.js.map +1 -0
- package/dist/rich-text-editor/index.d.ts +252 -0
- package/dist/rich-text-editor/index.d.ts.map +1 -0
- package/dist/rich-text-editor/index.js +856 -0
- package/dist/rich-text-editor/index.js.map +1 -0
- package/dist/rich-text-editor/inline.d.ts +94 -0
- package/dist/rich-text-editor/inline.d.ts.map +1 -0
- package/dist/rich-text-editor/inline.js +252 -0
- package/dist/rich-text-editor/inline.js.map +1 -0
- package/dist/rich-text-editor/keymap.d.ts +71 -0
- package/dist/rich-text-editor/keymap.d.ts.map +1 -0
- package/dist/rich-text-editor/keymap.js +394 -0
- package/dist/rich-text-editor/keymap.js.map +1 -0
- package/dist/rich-text-editor/keys.d.ts +40 -0
- package/dist/rich-text-editor/keys.d.ts.map +1 -0
- package/dist/rich-text-editor/keys.js +202 -0
- package/dist/rich-text-editor/keys.js.map +1 -0
- package/dist/rich-text-editor/look.d.ts +71 -0
- package/dist/rich-text-editor/look.d.ts.map +1 -0
- package/dist/rich-text-editor/look.js +342 -0
- package/dist/rich-text-editor/look.js.map +1 -0
- package/dist/rich-text-editor/markdown.d.ts +18 -0
- package/dist/rich-text-editor/markdown.d.ts.map +1 -0
- package/dist/rich-text-editor/markdown.js +496 -0
- package/dist/rich-text-editor/markdown.js.map +1 -0
- package/dist/rich-text-editor/marks.d.ts +9 -0
- package/dist/rich-text-editor/marks.d.ts.map +1 -0
- package/dist/rich-text-editor/marks.js +83 -0
- package/dist/rich-text-editor/marks.js.map +1 -0
- package/dist/rich-text-editor/nodes.d.ts +135 -0
- package/dist/rich-text-editor/nodes.d.ts.map +1 -0
- package/dist/rich-text-editor/nodes.js +397 -0
- package/dist/rich-text-editor/nodes.js.map +1 -0
- package/dist/rich-text-editor/render.d.ts +68 -0
- package/dist/rich-text-editor/render.d.ts.map +1 -0
- package/dist/rich-text-editor/render.js +518 -0
- package/dist/rich-text-editor/render.js.map +1 -0
- package/dist/rich-text-editor/schema.d.ts +16 -0
- package/dist/rich-text-editor/schema.d.ts.map +1 -0
- package/dist/rich-text-editor/schema.js +386 -0
- package/dist/rich-text-editor/schema.js.map +1 -0
- package/dist/rich-text-editor/store.d.ts +11 -0
- package/dist/rich-text-editor/store.d.ts.map +1 -0
- package/dist/rich-text-editor/store.js +43 -0
- package/dist/rich-text-editor/store.js.map +1 -0
- package/dist/rich-text-editor/suggest.d.ts +127 -0
- package/dist/rich-text-editor/suggest.d.ts.map +1 -0
- package/dist/rich-text-editor/suggest.js +0 -0
- package/dist/rich-text-editor/suggest.js.map +1 -0
- package/dist/rich-text-editor/tables.d.ts +41 -0
- package/dist/rich-text-editor/tables.d.ts.map +1 -0
- package/dist/rich-text-editor/tables.js +204 -0
- package/dist/rich-text-editor/tables.js.map +1 -0
- package/dist/rich-text-editor/toolbar.d.ts +58 -0
- package/dist/rich-text-editor/toolbar.d.ts.map +1 -0
- package/dist/rich-text-editor/toolbar.js +548 -0
- package/dist/rich-text-editor/toolbar.js.map +1 -0
- package/dist/rich-text-editor/view.d.ts +368 -0
- package/dist/rich-text-editor/view.d.ts.map +1 -0
- package/dist/rich-text-editor/view.js +1968 -0
- package/dist/rich-text-editor/view.js.map +1 -0
- package/dist/rich-text-editor/virtual.d.ts +54 -0
- package/dist/rich-text-editor/virtual.d.ts.map +1 -0
- package/dist/rich-text-editor/virtual.js +279 -0
- package/dist/rich-text-editor/virtual.js.map +1 -0
- package/dist/richtext/node.d.ts +71 -4
- package/dist/richtext/node.d.ts.map +1 -1
- package/dist/richtext/node.js +233 -28
- package/dist/richtext/node.js.map +1 -1
- package/dist/richtext/runs.d.ts +13 -8
- package/dist/richtext/runs.d.ts.map +1 -1
- package/dist/richtext/runs.js +18 -8
- package/dist/richtext/runs.js.map +1 -1
- package/dist/table/index.d.ts.map +1 -1
- package/dist/table/index.js +23 -0
- package/dist/table/index.js.map +1 -1
- package/dist/table/rows.d.ts +3 -2
- package/dist/table/rows.d.ts.map +1 -1
- package/dist/table/rows.js +20 -6
- package/dist/table/rows.js.map +1 -1
- package/dist/terminal/backends.d.ts +4 -1
- package/dist/terminal/backends.d.ts.map +1 -1
- package/dist/terminal/backends.js.map +1 -1
- package/dist/terminal/index.d.ts +18 -7
- package/dist/terminal/index.d.ts.map +1 -1
- package/dist/terminal/index.js +32 -11
- package/dist/terminal/index.js.map +1 -1
- package/dist/terminal/vt/pty.d.ts +13 -2
- package/dist/terminal/vt/pty.d.ts.map +1 -1
- package/dist/terminal/vt/pty.js +18 -3
- package/dist/terminal/vt/pty.js.map +1 -1
- package/dist/terminal-output/index.d.ts.map +1 -1
- package/dist/terminal-output/index.js +6 -1
- package/dist/terminal-output/index.js.map +1 -1
- package/dist/three/canvas.d.ts.map +1 -1
- package/dist/three/canvas.js +85 -7
- package/dist/three/canvas.js.map +1 -1
- package/dist/three/events.d.ts +22 -4
- package/dist/three/events.d.ts.map +1 -1
- package/dist/three/events.js +34 -4
- package/dist/three/events.js.map +1 -1
- package/dist/tree/index.d.ts.map +1 -1
- package/dist/tree/index.js +17 -0
- package/dist/tree/index.js.map +1 -1
- package/package.json +59 -31
- package/src/charts/node.ts +68 -28
- package/src/charts/render.ts +120 -30
- package/src/code/index.ts +3 -1
- package/src/code-editor/completion.ts +3 -2
- package/src/code-editor/index.ts +19 -0
- package/src/code-editor/node.ts +1574 -184
- package/src/code-language/languages/glsl.ts +12 -2
- package/src/code-language/languages/javascript.ts +21 -4
- package/src/code-language/languages/json.ts +12 -2
- package/src/code-language/languages/shell.ts +12 -2
- package/src/code-language/languages/sql.ts +22 -2
- package/src/code-language/stream.ts +257 -17
- package/src/code-language/types.ts +5 -4
- package/src/codeblock/index.ts +20 -3
- package/src/embed/client.ts +102 -8
- package/src/embed/index.ts +2 -0
- package/src/flow/draw.ts +167 -41
- package/src/flow/gl/color.ts +85 -0
- package/src/flow/gl/index.ts +342 -0
- package/src/flow/gl/pack.ts +585 -0
- package/src/flow/gl/renderer.ts +679 -0
- package/src/flow/gl/shaders.ts +371 -0
- package/src/flow/gl/text.ts +1295 -0
- package/src/flow/index.ts +794 -67
- package/src/flow/node.ts +2496 -1256
- package/src/flow/paint.ts +511 -0
- package/src/flow/paths.ts +80 -15
- package/src/flow/scene.ts +2199 -0
- package/src/flow/types.ts +113 -1
- package/src/html/controls.ts +73 -2
- package/src/html/css/calc.ts +385 -0
- package/src/html/css/cascade.ts +1403 -62
- package/src/html/css/color.ts +755 -0
- package/src/html/css/content.ts +417 -0
- package/src/html/css/counter-styles.ts +973 -0
- package/src/html/css/decode.ts +130 -0
- package/src/html/css/parse.ts +1514 -160
- package/src/html/css/style.ts +4102 -222
- package/src/html/css/ua.ts +58 -12
- package/src/html/css/values.ts +150 -50
- package/src/html/css/vars.ts +348 -0
- package/src/html/dom.ts +284 -17
- package/src/html/fonts.ts +641 -0
- package/src/html/gif.ts +233 -0
- package/src/html/index.ts +180 -20
- package/src/html/layout/block.ts +3456 -230
- package/src/html/layout/boxes.ts +2100 -190
- package/src/html/layout/cache.ts +289 -0
- package/src/html/layout/collapse.ts +317 -0
- package/src/html/layout/css-grid.ts +1063 -0
- package/src/html/layout/flex.ts +1115 -106
- package/src/html/layout/floats.ts +128 -14
- package/src/html/layout/grid-lines.ts +141 -0
- package/src/html/layout/grid.ts +181 -0
- package/src/html/layout/inline.ts +3943 -192
- package/src/html/layout/shaping.ts +140 -0
- package/src/html/layout/table.ts +696 -186
- package/src/html/layout/tracks.ts +437 -0
- package/src/html/node.ts +1486 -121
- package/src/html/paint.ts +4293 -169
- package/src/html/resources.ts +161 -50
- package/src/html/surfaces.ts +81 -0
- package/src/html/svg.ts +493 -0
- package/src/html/url.ts +86 -0
- package/src/index.ts +4 -0
- package/src/internal/collate.ts +12 -0
- package/src/{markdown → internal/markdown}/ast.ts +35 -7
- package/src/{markdown → internal/markdown}/parse.ts +288 -35
- package/src/internal/markdown/stringify.ts +772 -0
- package/src/internal/prewarm.ts +45 -0
- package/src/internal/scroll.ts +5 -3
- package/src/internal/sdf.ts +227 -0
- package/src/internal/splice.ts +25 -0
- package/src/internal/window.ts +36 -5
- package/src/maps/anchors.ts +913 -0
- package/src/maps/controller.ts +1084 -0
- package/src/maps/gl/buckets.ts +461 -0
- package/src/maps/gl/build-worker.ts +66 -0
- package/src/maps/gl/color.ts +62 -0
- package/src/maps/gl/cover.ts +205 -0
- package/src/maps/gl/index.ts +23 -0
- package/src/maps/gl/markers.ts +83 -0
- package/src/maps/gl/overlays.ts +379 -0
- package/src/maps/gl/pane.ts +42 -0
- package/src/maps/gl/placement.ts +968 -0
- package/src/maps/gl/renderer.ts +1660 -0
- package/src/maps/gl/shaders.ts +489 -0
- package/src/maps/gl/store.ts +615 -0
- package/src/maps/gl/text.ts +868 -0
- package/src/maps/gl/view.ts +1489 -0
- package/src/maps/icons.ts +183 -0
- package/src/maps/index.ts +274 -81
- package/src/maps/labels.ts +457 -144
- package/src/maps/node.ts +832 -665
- package/src/maps/overlay.ts +148 -43
- package/src/maps/paint.ts +3 -0
- package/src/maps/proj.ts +118 -0
- package/src/maps/renderer.ts +155 -0
- package/src/maps/sources.ts +43 -6
- package/src/maps/style.ts +32 -0
- package/src/maps/styles.ts +215 -4
- package/src/maps/theme.ts +51 -0
- package/src/maps/tiles.ts +253 -62
- package/src/maps/types.ts +213 -21
- package/src/markdown/expressions.ts +5 -1
- package/src/markdown/index.ts +163 -78
- package/src/markdown/spans.ts +6 -1
- package/src/media-player/index.ts +18 -4
- package/src/qml/containers.tsx +6 -1
- package/src/qml/interaction.tsx +42 -5
- package/src/qml/layouts.tsx +21 -6
- package/src/qml/qtquick.tsx +9 -2
- package/src/qml/react.tsx +7 -5
- package/src/reorder/clock.ts +27 -0
- package/src/reorder/index.ts +100 -27
- package/src/rich-text-editor/clipboard.ts +439 -0
- package/src/rich-text-editor/collab.ts +91 -0
- package/src/rich-text-editor/commands.ts +448 -0
- package/src/rich-text-editor/dom-globals.d.ts +23 -0
- package/src/rich-text-editor/drag.ts +211 -0
- package/src/rich-text-editor/html.ts +619 -0
- package/src/rich-text-editor/index.ts +1364 -0
- package/src/rich-text-editor/inline.ts +345 -0
- package/src/rich-text-editor/keymap.ts +510 -0
- package/src/rich-text-editor/keys.ts +228 -0
- package/src/rich-text-editor/look.ts +427 -0
- package/src/rich-text-editor/markdown.ts +653 -0
- package/src/rich-text-editor/marks.ts +101 -0
- package/src/rich-text-editor/nodes.ts +497 -0
- package/src/rich-text-editor/render.ts +837 -0
- package/src/rich-text-editor/schema.ts +431 -0
- package/src/rich-text-editor/store.ts +39 -0
- package/src/rich-text-editor/suggest.ts +597 -0
- package/src/rich-text-editor/tables.ts +272 -0
- package/src/rich-text-editor/toolbar.ts +724 -0
- package/src/rich-text-editor/view.ts +2287 -0
- package/src/rich-text-editor/virtual.ts +372 -0
- package/src/richtext/node.ts +294 -44
- package/src/richtext/runs.ts +23 -12
- package/src/table/index.ts +29 -0
- package/src/table/rows.ts +18 -8
- package/src/terminal/backends.ts +4 -1
- package/src/terminal/index.ts +47 -15
- package/src/terminal/vt/pty.ts +16 -2
- package/src/terminal-output/index.ts +6 -1
- package/src/three/canvas.ts +102 -8
- package/src/three/events.ts +49 -9
- package/src/tree/index.ts +19 -0
- package/dist/markdown/ast.d.ts.map +0 -1
- package/dist/markdown/ast.js +0 -17
- package/dist/markdown/ast.js.map +0 -1
- package/dist/markdown/parse.d.ts.map +0 -1
- package/dist/markdown/parse.js.map +0 -1
- package/dist/markdown/tags.d.ts.map +0 -1
- package/dist/markdown/tags.js.map +0 -1
- /package/dist/{markdown → internal/markdown}/parse.d.ts +0 -0
- /package/dist/{markdown → internal/markdown}/tags.d.ts +0 -0
- /package/dist/{markdown → internal/markdown}/tags.js +0 -0
- /package/src/{markdown → internal/markdown}/tags.ts +0 -0
|
@@ -0,0 +1,772 @@
|
|
|
1
|
+
// AST → markdown: the other half of `./parse.ts`.
|
|
2
|
+
//
|
|
3
|
+
// The rich text editor keeps its document as ProseMirror nodes and saves it
|
|
4
|
+
// as markdown through this AST, so this is the serializer the package did not
|
|
5
|
+
// have — and it is written against the parser beside it rather than against
|
|
6
|
+
// CommonMark in the abstract, because that parser is the first reader every
|
|
7
|
+
// document written here meets. What comes out is *normalized* GFM, not the
|
|
8
|
+
// source a document was parsed from: ATX headings, `-` bullets, `1.`
|
|
9
|
+
// numbering, fenced code, `**`/`*`/`~~`, backslash hard breaks. What is
|
|
10
|
+
// promised is the round trip: `parse(stringify(ast), { partial: false })`
|
|
11
|
+
// gives back `ast` for every AST the parser can produce and every one the
|
|
12
|
+
// editor builds, which test/rich-text-editor-markdown.test.ts holds it to
|
|
13
|
+
// over a generated corpus as well as by example.
|
|
14
|
+
//
|
|
15
|
+
// Nearly all of the work is escaping, and nearly all of the escaping is
|
|
16
|
+
// context: `*` is always syntax, `_` only at the edge of a word, `~` only in
|
|
17
|
+
// pairs, and `#`, `>`, `-`, `1.` only at the start of a line — where a line
|
|
18
|
+
// starts after every hard break, not only at the top of a paragraph.
|
|
19
|
+
import type {
|
|
20
|
+
BlockNode,
|
|
21
|
+
CodeBlock,
|
|
22
|
+
Document,
|
|
23
|
+
InlineNode,
|
|
24
|
+
LinkInline,
|
|
25
|
+
ListBlock,
|
|
26
|
+
TableBlock,
|
|
27
|
+
} from './ast.js';
|
|
28
|
+
import { parseInline } from './parse.js';
|
|
29
|
+
|
|
30
|
+
/** Markdown for a document, or for a run of blocks. */
|
|
31
|
+
export function stringify(doc: Document | readonly BlockNode[]): string {
|
|
32
|
+
const blocks = 'blocks' in doc ? doc.blocks : doc;
|
|
33
|
+
return blockSequence(blocks, false).join('\n');
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// --- blocks ------------------------------------------------------------------
|
|
37
|
+
|
|
38
|
+
interface ListMarker {
|
|
39
|
+
ordered: boolean;
|
|
40
|
+
marker: string;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** A list line with a marker and nothing after it. */
|
|
44
|
+
const EMPTY_ITEM = /^(?:\d{1,9}[.)]|[-+*])(?: \[[ x]\])? *$/;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* The lines for a run of sibling blocks, with a blank line between each two.
|
|
48
|
+
* The exception is a nested list straight after the paragraph of a tight
|
|
49
|
+
* item — "- a\n - b" — which is how a tight list stays tight.
|
|
50
|
+
*/
|
|
51
|
+
function blockSequence(
|
|
52
|
+
blocks: readonly BlockNode[],
|
|
53
|
+
tightItem: boolean,
|
|
54
|
+
): string[] {
|
|
55
|
+
const out: string[] = [];
|
|
56
|
+
let prevList: ListMarker | null = null;
|
|
57
|
+
for (const block of blocks) {
|
|
58
|
+
let lines: string[];
|
|
59
|
+
let list: ListMarker | null = null;
|
|
60
|
+
if (block.type === 'list') {
|
|
61
|
+
// Two lists in a row with the same marker are one list to a reader —
|
|
62
|
+
// a blank line between them only makes it loose — so the second takes
|
|
63
|
+
// its kind's other marker, which is the break CommonMark recognises.
|
|
64
|
+
const base = block.ordered ? '.' : '-';
|
|
65
|
+
const other = block.ordered ? ')' : '*';
|
|
66
|
+
const marker: string =
|
|
67
|
+
prevList &&
|
|
68
|
+
prevList.ordered === block.ordered &&
|
|
69
|
+
prevList.marker === base
|
|
70
|
+
? other
|
|
71
|
+
: base;
|
|
72
|
+
list = { ordered: block.ordered, marker };
|
|
73
|
+
lines = listLines(block, marker);
|
|
74
|
+
} else {
|
|
75
|
+
lines = blockLines(block);
|
|
76
|
+
}
|
|
77
|
+
// an empty paragraph has no markdown; dropping it is the only honest
|
|
78
|
+
// spelling of "nothing", and it keeps adjacent lists adjacent
|
|
79
|
+
if (lines.length === 0) continue;
|
|
80
|
+
// …and an empty item cannot interrupt a paragraph ("a\n3." is one
|
|
81
|
+
// paragraph), so a list that opens with one keeps its blank line
|
|
82
|
+
const interrupts =
|
|
83
|
+
tightItem && block.type === 'list' && !EMPTY_ITEM.test(lines[0]);
|
|
84
|
+
if (out.length > 0 && !interrupts) out.push('');
|
|
85
|
+
out.push(...lines);
|
|
86
|
+
prevList = list;
|
|
87
|
+
}
|
|
88
|
+
return out;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function blockLines(block: BlockNode): string[] {
|
|
92
|
+
switch (block.type) {
|
|
93
|
+
case 'paragraph': {
|
|
94
|
+
const text = inline(block.children, 'block');
|
|
95
|
+
return text === '' ? [] : text.split('\n');
|
|
96
|
+
}
|
|
97
|
+
case 'heading':
|
|
98
|
+
return [headingLine(block.depth, block.children)];
|
|
99
|
+
case 'code':
|
|
100
|
+
return fenceLines(block);
|
|
101
|
+
case 'quote':
|
|
102
|
+
return blockSequence(block.children, false).map((line) =>
|
|
103
|
+
line === '' ? '>' : `> ${line}`,
|
|
104
|
+
);
|
|
105
|
+
case 'list':
|
|
106
|
+
return listLines(block, block.ordered ? '.' : '-');
|
|
107
|
+
case 'table':
|
|
108
|
+
return tableLines(block);
|
|
109
|
+
case 'rule':
|
|
110
|
+
return ['---'];
|
|
111
|
+
case 'component':
|
|
112
|
+
// The editor never builds one; an AST that has one keeps its content.
|
|
113
|
+
return blockSequence(block.children, false);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function headingLine(depth: number, children: readonly InlineNode[]): string {
|
|
118
|
+
let text = inline(children, 'heading');
|
|
119
|
+
// `# Title #` loses its closing run to the ATX rule — so a heading that
|
|
120
|
+
// really ends in a `#` escapes the last one
|
|
121
|
+
if (/(^|[ \t])#+$/.test(text)) text = `${text.slice(0, -1)}\\#`;
|
|
122
|
+
const level = Math.max(1, Math.min(6, Math.round(depth)));
|
|
123
|
+
return '#'.repeat(level) + (text ? ` ${text}` : '');
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function fenceLines(block: CodeBlock): string[] {
|
|
127
|
+
const info = (block.info ?? block.lang).trim();
|
|
128
|
+
// a backtick fence cannot carry a backtick in its info string
|
|
129
|
+
const char = info.includes('`') ? '~' : '`';
|
|
130
|
+
let longest = 0;
|
|
131
|
+
for (const m of block.text.matchAll(char === '`' ? /`+/g : /~+/g)) {
|
|
132
|
+
longest = Math.max(longest, m[0].length);
|
|
133
|
+
}
|
|
134
|
+
const fence = char.repeat(Math.max(3, longest + 1));
|
|
135
|
+
const body = block.text === '' ? [] : block.text.split('\n');
|
|
136
|
+
return [fence + info, ...body, fence];
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function listLines(list: ListBlock, marker: string): string[] {
|
|
140
|
+
const out: string[] = [];
|
|
141
|
+
list.items.forEach((item, index) => {
|
|
142
|
+
const bullet = list.ordered ? `${list.start + index}${marker}` : marker;
|
|
143
|
+
const pad = ' '.repeat(bullet.length + 1);
|
|
144
|
+
const task = item.checked === null ? '' : item.checked ? '[x] ' : '[ ] ';
|
|
145
|
+
const body = blockSequence(item.children, list.tight);
|
|
146
|
+
if (index > 0 && !list.tight) out.push('');
|
|
147
|
+
if (body.length === 0) {
|
|
148
|
+
// "- [ ] " keeps the space: a task marker needs one after it
|
|
149
|
+
out.push(task ? `${bullet} ${task}` : bullet);
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
out.push(`${bullet} ${task}${body[0]}`);
|
|
153
|
+
for (let i = 1; i < body.length; i++) {
|
|
154
|
+
out.push(body[i] === '' ? '' : pad + body[i]);
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
return out;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function tableLines(table: TableBlock): string[] {
|
|
161
|
+
const row = (cells: string[]): string =>
|
|
162
|
+
`| ${cells.map((c) => c || ' ').join(' | ')} |`;
|
|
163
|
+
const cell = (nodes: readonly InlineNode[]): string => inline(nodes, 'cell');
|
|
164
|
+
const delimiter = table.align.map((a) =>
|
|
165
|
+
a === 'left'
|
|
166
|
+
? ':---'
|
|
167
|
+
: a === 'center'
|
|
168
|
+
? ':---:'
|
|
169
|
+
: a === 'right'
|
|
170
|
+
? '---:'
|
|
171
|
+
: '---',
|
|
172
|
+
);
|
|
173
|
+
return [
|
|
174
|
+
row(table.header.map(cell)),
|
|
175
|
+
row(delimiter),
|
|
176
|
+
...table.rows.map((r) => row(r.map(cell))),
|
|
177
|
+
];
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// --- inline ------------------------------------------------------------------
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Where inline text is going. A paragraph's lines are `'block'`: each starts
|
|
184
|
+
* a line, so the characters that open a block there are escaped. A heading
|
|
185
|
+
* and a table cell sit on a line that has already started, so they are not —
|
|
186
|
+
* but neither can hold a line break, and a cell cannot hold a bare `|`.
|
|
187
|
+
*/
|
|
188
|
+
type InlineMode = 'block' | 'heading' | 'cell';
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Inline content as markdown — checked. The rules above cover what prose
|
|
192
|
+
* does, but the flanking rules have corners no delimiter placement escapes
|
|
193
|
+
* (bold that ends in punctuation, glued to the word after it, next to
|
|
194
|
+
* italic that does the same), and a corner is where a document loses text
|
|
195
|
+
* to literal asterisks. So the output is read back with the parser and
|
|
196
|
+
* compared, as flat runs of marked text, with what was meant; if they
|
|
197
|
+
* differ, the same content is written without its emphasis, and failing
|
|
198
|
+
* that as plain text. Links, code and every character survive either way.
|
|
199
|
+
*/
|
|
200
|
+
function inline(nodes: readonly InlineNode[], mode: InlineMode): string {
|
|
201
|
+
const meant = expel(nodes);
|
|
202
|
+
const first = write(meant, mode);
|
|
203
|
+
if (!checkable(meant) || readsAs(first, meant, mode)) return first;
|
|
204
|
+
const plainer = expel(stripEmphasis(meant));
|
|
205
|
+
const second = write(plainer, mode);
|
|
206
|
+
if (readsAs(second, plainer, mode)) return second;
|
|
207
|
+
return write(expel(textOnly(meant)), mode);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
function write(nodes: readonly InlineNode[], mode: InlineMode): string {
|
|
211
|
+
const w = new InlineWriter(mode);
|
|
212
|
+
w.nodes(nodes);
|
|
213
|
+
return w.finish();
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/** Only content the parser can say back — no MDX nodes — is checked. */
|
|
217
|
+
function checkable(nodes: readonly InlineNode[]): boolean {
|
|
218
|
+
return nodes.every(
|
|
219
|
+
(n) =>
|
|
220
|
+
n.type !== 'expression' &&
|
|
221
|
+
n.type !== 'component' &&
|
|
222
|
+
(!('children' in n) || checkable(n.children)),
|
|
223
|
+
);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/** Whether `text`, read back where it will be read, is `meant`. */
|
|
227
|
+
function readsAs(
|
|
228
|
+
text: string,
|
|
229
|
+
meant: readonly InlineNode[],
|
|
230
|
+
mode: InlineMode,
|
|
231
|
+
): boolean {
|
|
232
|
+
// a row is split on bare pipes before its cells are read, and a cell is
|
|
233
|
+
// trimmed; the other two modes read their text as it is
|
|
234
|
+
const source = mode === 'cell' ? text.replace(/\\\|/g, '|').trim() : text;
|
|
235
|
+
const back = parseInline(source, false);
|
|
236
|
+
return flatKey(back, mode) === flatKey(meant, mode);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Inline content as flat runs of marked text — what a ProseMirror document
|
|
241
|
+
* holds, and so what has to survive. Nesting order is not in it (`***x***`
|
|
242
|
+
* is bold and italic either way round), and neither are the breaks that
|
|
243
|
+
* trail a paragraph, which markdown cannot hold.
|
|
244
|
+
*/
|
|
245
|
+
function flatKey(nodes: readonly InlineNode[], mode: InlineMode): string {
|
|
246
|
+
const runs: [string, string][] = [];
|
|
247
|
+
const push = (marks: string, text: string): void => {
|
|
248
|
+
const last = runs[runs.length - 1];
|
|
249
|
+
if (last && last[0] === marks) last[1] += text;
|
|
250
|
+
else runs.push([marks, text]);
|
|
251
|
+
};
|
|
252
|
+
const walk = (list: readonly InlineNode[], marks: string): void => {
|
|
253
|
+
for (const node of list) {
|
|
254
|
+
switch (node.type) {
|
|
255
|
+
case 'text':
|
|
256
|
+
for (const part of node.text.split(/(\n)/)) {
|
|
257
|
+
if (part === '\n') push('\n', mode === 'block' ? '\n' : ' ');
|
|
258
|
+
else if (part) push(marks, part);
|
|
259
|
+
}
|
|
260
|
+
break;
|
|
261
|
+
case 'code':
|
|
262
|
+
push(`${marks}|code`, node.text.replace(/\n/g, ' '));
|
|
263
|
+
break;
|
|
264
|
+
case 'break':
|
|
265
|
+
if (mode === 'block') push('\n', '\n');
|
|
266
|
+
else push(marks, ' ');
|
|
267
|
+
break;
|
|
268
|
+
case 'link':
|
|
269
|
+
if (node.image)
|
|
270
|
+
push(
|
|
271
|
+
`${marks}|img:${node.href}:${node.title ?? ''}`,
|
|
272
|
+
plain(node.children) || '',
|
|
273
|
+
);
|
|
274
|
+
else if (node.href === null) walk(node.children, marks);
|
|
275
|
+
else
|
|
276
|
+
walk(node.children, `${marks}|a:${node.href}:${node.title ?? ''}`);
|
|
277
|
+
break;
|
|
278
|
+
case 'strong':
|
|
279
|
+
case 'em':
|
|
280
|
+
case 'del':
|
|
281
|
+
walk(
|
|
282
|
+
node.children,
|
|
283
|
+
[...marks.split('|').filter(Boolean), node.type].sort().join('|'),
|
|
284
|
+
);
|
|
285
|
+
break;
|
|
286
|
+
default:
|
|
287
|
+
break;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
};
|
|
291
|
+
walk(nodes, '');
|
|
292
|
+
while (runs.length && runs[runs.length - 1][0] === '\n') runs.pop();
|
|
293
|
+
return JSON.stringify(runs);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
function plain(nodes: readonly InlineNode[]): string {
|
|
297
|
+
let out = '';
|
|
298
|
+
for (const node of nodes) {
|
|
299
|
+
if (node.type === 'text' || node.type === 'code') out += node.text;
|
|
300
|
+
else if ('children' in node) out += plain(node.children);
|
|
301
|
+
}
|
|
302
|
+
return out;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
function stripEmphasis(nodes: readonly InlineNode[]): InlineNode[] {
|
|
306
|
+
const out: InlineNode[] = [];
|
|
307
|
+
for (const node of nodes) {
|
|
308
|
+
if (node.type === 'strong' || node.type === 'em' || node.type === 'del') {
|
|
309
|
+
out.push(...stripEmphasis(node.children));
|
|
310
|
+
} else if (node.type === 'link') {
|
|
311
|
+
out.push({ ...node, children: stripEmphasis(node.children) });
|
|
312
|
+
} else out.push(node);
|
|
313
|
+
}
|
|
314
|
+
return out;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
function textOnly(nodes: readonly InlineNode[]): InlineNode[] {
|
|
318
|
+
const out: InlineNode[] = [];
|
|
319
|
+
for (const node of nodes) {
|
|
320
|
+
if (node.type === 'text' || node.type === 'break') out.push(node);
|
|
321
|
+
else if (node.type === 'code') out.push({ type: 'text', text: node.text });
|
|
322
|
+
else if ('children' in node) out.push(...textOnly(node.children));
|
|
323
|
+
}
|
|
324
|
+
return out;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
const WS = /\s/u;
|
|
328
|
+
const WORD = /[\p{L}\p{N}]/u;
|
|
329
|
+
const ENTITY_LIKE =
|
|
330
|
+
/^&(?:#\d{1,7}|#[xX][0-9a-fA-F]{1,6}|[a-zA-Z][a-zA-Z0-9]{1,31});/;
|
|
331
|
+
|
|
332
|
+
class InlineWriter {
|
|
333
|
+
private out = '';
|
|
334
|
+
/** The next character starts a line — the top of the text, or just after
|
|
335
|
+
* a hard break — which is where block syntax lives. */
|
|
336
|
+
private lineStart = true;
|
|
337
|
+
|
|
338
|
+
constructor(private readonly mode: InlineMode) {}
|
|
339
|
+
|
|
340
|
+
finish(): string {
|
|
341
|
+
let text = this.out;
|
|
342
|
+
if (this.mode === 'block') {
|
|
343
|
+
// A hard break has to be followed by something: at the very end of a
|
|
344
|
+
// paragraph it would read back as a literal backslash, so it goes.
|
|
345
|
+
text = text.replace(/(\\\n)+$/, '');
|
|
346
|
+
} else if (/\s$/u.test(text)) {
|
|
347
|
+
// The ATX rule and a cell's trim both eat trailing whitespace; the last
|
|
348
|
+
// character of it is spelled as a reference so the text keeps it.
|
|
349
|
+
const last = text[text.length - 1];
|
|
350
|
+
text = text.slice(0, -1) + (last === '\t' ? '	' : ' ');
|
|
351
|
+
}
|
|
352
|
+
return text;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
/** `after` is the character the output continues with once these nodes
|
|
356
|
+
* are written — a closing delimiter, a `]`, or nothing at all. */
|
|
357
|
+
nodes(nodes: readonly InlineNode[], after?: string): void {
|
|
358
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
359
|
+
const node = nodes[i];
|
|
360
|
+
const next = i + 1 < nodes.length ? leadOf(nodes[i + 1]) : after;
|
|
361
|
+
switch (node.type) {
|
|
362
|
+
case 'text':
|
|
363
|
+
this.text(node.text, next);
|
|
364
|
+
break;
|
|
365
|
+
case 'code':
|
|
366
|
+
this.code(node.text);
|
|
367
|
+
break;
|
|
368
|
+
case 'strong':
|
|
369
|
+
this.wrap('**', node.children, next);
|
|
370
|
+
break;
|
|
371
|
+
case 'em': {
|
|
372
|
+
// Beside another `*` run — italic at the start of bold, at its
|
|
373
|
+
// end, or right before it — the two delimiters would merge into
|
|
374
|
+
// one run and be read differently (`***x***` is bold inside
|
|
375
|
+
// italic), so this one is `_`, where `_` can stand: not against a
|
|
376
|
+
// word on either side.
|
|
377
|
+
const besideStar = this.out.endsWith('*') || next === '*';
|
|
378
|
+
const underscore =
|
|
379
|
+
besideStar &&
|
|
380
|
+
!WORD.test(lastChar(this.out) ?? '') &&
|
|
381
|
+
!WORD.test(next ?? '');
|
|
382
|
+
this.wrap(underscore ? '_' : '*', node.children, next);
|
|
383
|
+
break;
|
|
384
|
+
}
|
|
385
|
+
case 'del':
|
|
386
|
+
this.wrap('~~', node.children, next);
|
|
387
|
+
break;
|
|
388
|
+
case 'link':
|
|
389
|
+
this.link(node);
|
|
390
|
+
break;
|
|
391
|
+
case 'break':
|
|
392
|
+
this.hardBreak();
|
|
393
|
+
break;
|
|
394
|
+
case 'expression':
|
|
395
|
+
this.raw(`{${node.src}}`);
|
|
396
|
+
break;
|
|
397
|
+
case 'component':
|
|
398
|
+
this.nodes(node.children);
|
|
399
|
+
break;
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
private raw(text: string): void {
|
|
405
|
+
this.out += text;
|
|
406
|
+
if (text) this.lineStart = false;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
private hardBreak(): void {
|
|
410
|
+
if (this.mode !== 'block') {
|
|
411
|
+
// a heading or a cell is one line: the break is a space, spelled the
|
|
412
|
+
// way any other space at its edge is
|
|
413
|
+
this.text(' ', undefined);
|
|
414
|
+
return;
|
|
415
|
+
}
|
|
416
|
+
this.out += '\\\n';
|
|
417
|
+
this.lineStart = true;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
/**
|
|
421
|
+
* A delimited run. Whether a delimiter opens or closes depends on the
|
|
422
|
+
* characters either side of it — CommonMark's flanking rules — so the
|
|
423
|
+
* content is written first and the placement checked against what
|
|
424
|
+
* actually surrounds it. Some placements have no spelling at all: `**`
|
|
425
|
+
* cannot close after punctuation when a letter follows (`**"a"**s`). Then
|
|
426
|
+
* the text is kept and the emphasis is not, because a word that stops
|
|
427
|
+
* being bold is a smaller loss than a document that grows literal
|
|
428
|
+
* asterisks every time it is saved.
|
|
429
|
+
*
|
|
430
|
+
* A dropped run is written again rather than unwrapped: what is inside it
|
|
431
|
+
* was judged against this run's delimiters, which are no longer there, so
|
|
432
|
+
* an inner run that stood beside them may not stand beside what replaced
|
|
433
|
+
* them — and a line start it sat after is a line start again.
|
|
434
|
+
*/
|
|
435
|
+
private wrap(
|
|
436
|
+
delimiter: string,
|
|
437
|
+
children: readonly InlineNode[],
|
|
438
|
+
after: string | undefined,
|
|
439
|
+
): void {
|
|
440
|
+
const start = this.out.length;
|
|
441
|
+
const wasLineStart = this.lineStart;
|
|
442
|
+
const before = lastChar(this.out);
|
|
443
|
+
this.raw(delimiter);
|
|
444
|
+
const innerStart = this.out.length;
|
|
445
|
+
this.nodes(children, delimiter[0]);
|
|
446
|
+
const inner = this.out.slice(innerStart);
|
|
447
|
+
const ch = delimiter[0];
|
|
448
|
+
if (
|
|
449
|
+
inner !== '' &&
|
|
450
|
+
canOpen(ch, before, firstChar(inner)) &&
|
|
451
|
+
canClose(ch, lastChar(inner), after)
|
|
452
|
+
) {
|
|
453
|
+
this.raw(delimiter);
|
|
454
|
+
return;
|
|
455
|
+
}
|
|
456
|
+
this.out = this.out.slice(0, start);
|
|
457
|
+
this.lineStart = wasLineStart;
|
|
458
|
+
this.nodes(children, after);
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
private code(text: string): void {
|
|
462
|
+
const flat = text.replace(/\n/g, ' ');
|
|
463
|
+
let longest = 0;
|
|
464
|
+
for (const m of flat.matchAll(/`+/g))
|
|
465
|
+
longest = Math.max(longest, m[0].length);
|
|
466
|
+
const fence = '`'.repeat(longest + 1);
|
|
467
|
+
// CommonMark shaves one space off each end when both have one, and a
|
|
468
|
+
// span that starts or ends in a backtick would merge with its fence
|
|
469
|
+
const pad =
|
|
470
|
+
flat.startsWith('`') ||
|
|
471
|
+
flat.endsWith('`') ||
|
|
472
|
+
(flat.startsWith(' ') && flat.endsWith(' ') && flat.trim() !== '')
|
|
473
|
+
? ' '
|
|
474
|
+
: '';
|
|
475
|
+
this.raw(this.cellSafe(fence + pad + flat + pad + fence));
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
/**
|
|
479
|
+
* In a table cell a bare `|` ends the cell — inside a code span or a link
|
|
480
|
+
* destination too, because a table row is split before its cells' inline
|
|
481
|
+
* syntax is read, and `\|` is turned back into `|` as it is split.
|
|
482
|
+
*/
|
|
483
|
+
private cellSafe(raw: string): string {
|
|
484
|
+
return this.mode === 'cell' ? raw.replace(/\|/g, '\\|') : raw;
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
private link(node: LinkInline): void {
|
|
488
|
+
if (node.href === null) {
|
|
489
|
+
this.nodes(node.children); // a link still streaming in has nowhere to go
|
|
490
|
+
return;
|
|
491
|
+
}
|
|
492
|
+
const tail = this.cellSafe(
|
|
493
|
+
`](${destination(node.href)}${titlePart(node.title)})`,
|
|
494
|
+
);
|
|
495
|
+
if (node.image) {
|
|
496
|
+
this.raw('![');
|
|
497
|
+
this.nodes(node.children, ']');
|
|
498
|
+
this.raw(tail);
|
|
499
|
+
return;
|
|
500
|
+
}
|
|
501
|
+
const auto = autolink(node);
|
|
502
|
+
if (auto !== null) {
|
|
503
|
+
this.raw(this.cellSafe(auto));
|
|
504
|
+
return;
|
|
505
|
+
}
|
|
506
|
+
this.raw('[');
|
|
507
|
+
this.nodes(node.children, ']');
|
|
508
|
+
this.raw(tail);
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
/** `after` is the character the output continues with past this text, so
|
|
512
|
+
* a character at the text's edge is judged by its real neighbour and not
|
|
513
|
+
* by where one node happened to end. */
|
|
514
|
+
private text(text: string, after: string | undefined): void {
|
|
515
|
+
for (let i = 0; i < text.length; i++) {
|
|
516
|
+
const ch = text[i];
|
|
517
|
+
if (ch === '\n') {
|
|
518
|
+
this.hardBreak(); // a text node the editor built may carry one
|
|
519
|
+
continue;
|
|
520
|
+
}
|
|
521
|
+
if (this.lineStart) {
|
|
522
|
+
this.lineStart = false;
|
|
523
|
+
const lead = this.lineLead(text, i);
|
|
524
|
+
if (lead !== null) {
|
|
525
|
+
this.out += lead.text;
|
|
526
|
+
i += lead.consumed - 1;
|
|
527
|
+
continue;
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
this.out += this.escape(text, i, after);
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
/**
|
|
535
|
+
* The first character of a line, when it would open a block: `# ` a
|
|
536
|
+
* heading, `>` a quote, `-`/`+`/`=`/`:`/`|`/`~` a list, a setext underline,
|
|
537
|
+
* a table's delimiter row or a fence, `12.` an ordered list, and leading
|
|
538
|
+
* whitespace an indented code block (or nothing, after a trim). The last is
|
|
539
|
+
* spelled as a character reference, which no block rule looks at.
|
|
540
|
+
*/
|
|
541
|
+
private lineLead(
|
|
542
|
+
text: string,
|
|
543
|
+
i: number,
|
|
544
|
+
): { text: string; consumed: number } | null {
|
|
545
|
+
const ch = text[i];
|
|
546
|
+
if (ch === ' ') return { text: ' ', consumed: 1 };
|
|
547
|
+
if (ch === '\t') return { text: '	', consumed: 1 };
|
|
548
|
+
if (this.mode !== 'block') return null;
|
|
549
|
+
if ('#>-+=:|~'.includes(ch)) return { text: `\\${ch}`, consumed: 1 };
|
|
550
|
+
const ordered = /^(\d{1,9})([.)])/.exec(text.slice(i));
|
|
551
|
+
if (ordered) {
|
|
552
|
+
const after = text[i + ordered[0].length];
|
|
553
|
+
if (after === undefined || WS.test(after)) {
|
|
554
|
+
return {
|
|
555
|
+
text: `${ordered[1]}\\${ordered[2]}`,
|
|
556
|
+
consumed: ordered[0].length,
|
|
557
|
+
};
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
return null;
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
private escape(text: string, i: number, after: string | undefined): string {
|
|
564
|
+
const ch = text[i];
|
|
565
|
+
const prev = i > 0 ? text[i - 1] : lastChar(this.out);
|
|
566
|
+
const next = i + 1 < text.length ? text[i + 1] : after;
|
|
567
|
+
switch (ch) {
|
|
568
|
+
case '\\':
|
|
569
|
+
case '`':
|
|
570
|
+
case '*':
|
|
571
|
+
case '[':
|
|
572
|
+
case ']':
|
|
573
|
+
return `\\${ch}`;
|
|
574
|
+
case '_':
|
|
575
|
+
// intraword `_` is never emphasis — snake_case needs nothing
|
|
576
|
+
return WORD.test(prev ?? '') && WORD.test(next ?? '') ? ch : `\\${ch}`;
|
|
577
|
+
case '~':
|
|
578
|
+
// strikethrough is `~~` only, so a lone tilde is text — but one
|
|
579
|
+
// beside another, or beside a strikethrough's own delimiter, is not
|
|
580
|
+
return prev === '~' || next === '~' ? `\\${ch}` : ch;
|
|
581
|
+
case '<':
|
|
582
|
+
return /[A-Za-z/!?]/.test(text[i + 1] ?? '') ? `\\${ch}` : ch;
|
|
583
|
+
case '&':
|
|
584
|
+
return ENTITY_LIKE.test(text.slice(i)) ? `\\${ch}` : ch;
|
|
585
|
+
case '!':
|
|
586
|
+
// `!` then a link is an image
|
|
587
|
+
return next === '[' ? `\\${ch}` : ch;
|
|
588
|
+
case '|':
|
|
589
|
+
return this.mode === 'cell' ? `\\${ch}` : ch;
|
|
590
|
+
default:
|
|
591
|
+
return ch;
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
// --- flanking -----------------------------------------------------------------
|
|
597
|
+
//
|
|
598
|
+
// The parser's own rules (`./parse.ts`, the emphasis scan), asked in advance.
|
|
599
|
+
|
|
600
|
+
const PUNCT = /[\p{P}\p{S}]/u;
|
|
601
|
+
|
|
602
|
+
function kind(ch: string | undefined): 'ws' | 'punct' | 'other' {
|
|
603
|
+
if (ch === undefined || ch === '' || WS.test(ch)) return 'ws';
|
|
604
|
+
return PUNCT.test(ch) ? 'punct' : 'other';
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
function flanks(before: string | undefined, after: string | undefined) {
|
|
608
|
+
const b = kind(before);
|
|
609
|
+
const a = kind(after);
|
|
610
|
+
return {
|
|
611
|
+
b,
|
|
612
|
+
a,
|
|
613
|
+
left: a !== 'ws' && (a !== 'punct' || b !== 'other'),
|
|
614
|
+
right: b !== 'ws' && (b !== 'punct' || a !== 'other'),
|
|
615
|
+
};
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
function canOpen(
|
|
619
|
+
ch: string,
|
|
620
|
+
before: string | undefined,
|
|
621
|
+
first: string | undefined,
|
|
622
|
+
): boolean {
|
|
623
|
+
const f = flanks(before, first);
|
|
624
|
+
return ch === '_' ? f.left && (!f.right || f.b === 'punct') : f.left;
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
function canClose(
|
|
628
|
+
ch: string,
|
|
629
|
+
last: string | undefined,
|
|
630
|
+
after: string | undefined,
|
|
631
|
+
): boolean {
|
|
632
|
+
const f = flanks(last, after);
|
|
633
|
+
return ch === '_' ? f.right && (!f.left || f.a === 'punct') : f.right;
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
/** The whole last character of `text` — both halves of a surrogate pair. */
|
|
637
|
+
function lastChar(text: string): string | undefined {
|
|
638
|
+
if (text === '') return undefined;
|
|
639
|
+
const unit = text.charCodeAt(text.length - 1);
|
|
640
|
+
return unit >= 0xdc00 && unit <= 0xdfff && text.length >= 2
|
|
641
|
+
? text.slice(-2)
|
|
642
|
+
: text[text.length - 1];
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
function firstChar(text: string): string | undefined {
|
|
646
|
+
const cp = text.codePointAt(0);
|
|
647
|
+
return cp === undefined ? undefined : String.fromCodePoint(cp);
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
/** The first character a node writes — all its neighbour's flanking can
|
|
651
|
+
* see. Every delimiter and bracket is punctuation, whichever it turns out
|
|
652
|
+
* to be. */
|
|
653
|
+
function leadOf(node: InlineNode): string | undefined {
|
|
654
|
+
switch (node.type) {
|
|
655
|
+
case 'text':
|
|
656
|
+
return firstChar(node.text);
|
|
657
|
+
case 'code':
|
|
658
|
+
return '`';
|
|
659
|
+
case 'strong':
|
|
660
|
+
case 'em':
|
|
661
|
+
return '*';
|
|
662
|
+
case 'del':
|
|
663
|
+
return '~';
|
|
664
|
+
case 'link':
|
|
665
|
+
return node.image ? '!' : '[';
|
|
666
|
+
case 'break':
|
|
667
|
+
return '\\';
|
|
668
|
+
case 'expression':
|
|
669
|
+
return '{';
|
|
670
|
+
case 'component':
|
|
671
|
+
return node.children.length ? leadOf(node.children[0]) : undefined;
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
/** `<https://…>` for a link whose text is its own target. */
|
|
676
|
+
function autolink(node: LinkInline): string | null {
|
|
677
|
+
if (node.title || !node.href || node.children.length !== 1) return null;
|
|
678
|
+
const only = node.children[0];
|
|
679
|
+
if (only.type !== 'text') return null;
|
|
680
|
+
const text = only.text;
|
|
681
|
+
if (
|
|
682
|
+
text === node.href &&
|
|
683
|
+
/^[a-zA-Z][a-zA-Z0-9+.-]{1,31}:[^<>\s]*$/.test(text)
|
|
684
|
+
) {
|
|
685
|
+
return `<${text}>`;
|
|
686
|
+
}
|
|
687
|
+
if (
|
|
688
|
+
node.href === `mailto:${text}` &&
|
|
689
|
+
/^[^<>\s@]+@[^<>\s@]+\.[^<>\s@]+$/.test(text)
|
|
690
|
+
) {
|
|
691
|
+
return `<${text}>`;
|
|
692
|
+
}
|
|
693
|
+
return null;
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
/** A link destination: bare with its parentheses escaped, or in `<…>` when
|
|
697
|
+
* it has whitespace in it — the one form a space survives in. */
|
|
698
|
+
function destination(href: string): string {
|
|
699
|
+
if (href === '') return '<>';
|
|
700
|
+
if (/[\s<>]/.test(href)) {
|
|
701
|
+
return `<${href.replace(/[\n\r]/g, '').replace(/[<>]/g, (c) => encodeURIComponent(c))}>`;
|
|
702
|
+
}
|
|
703
|
+
return href.replace(/[\\()]/g, (c) => `\\${c}`);
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
/** ` "title"`, in whichever of the three quote styles the title does not
|
|
707
|
+
* contain — the parser's title scan has no escapes. */
|
|
708
|
+
function titlePart(title: string | undefined): string {
|
|
709
|
+
if (!title) return '';
|
|
710
|
+
if (!title.includes('"')) return ` "${title}"`;
|
|
711
|
+
if (!title.includes("'")) return ` '${title}'`;
|
|
712
|
+
if (!title.includes(')')) return ` (${title})`;
|
|
713
|
+
return ` "${title.replace(/"/g, '"')}"`;
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
/**
|
|
717
|
+
* Emphasis can open only before non-space and close only after it (the
|
|
718
|
+
* flanking rules), so `**bold **` is not bold. Whitespace at the edge of a
|
|
719
|
+
* strong/em/del node moves outside it, and a node that was all whitespace
|
|
720
|
+
* becomes that whitespace.
|
|
721
|
+
*/
|
|
722
|
+
function expel(nodes: readonly InlineNode[]): InlineNode[] {
|
|
723
|
+
const out: InlineNode[] = [];
|
|
724
|
+
for (const node of nodes) {
|
|
725
|
+
if (node.type === 'strong' || node.type === 'em' || node.type === 'del') {
|
|
726
|
+
const children = expel(node.children);
|
|
727
|
+
const lead = takeEdge(children, 'start');
|
|
728
|
+
const trail = takeEdge(children, 'end');
|
|
729
|
+
if (lead) out.push({ type: 'text', text: lead });
|
|
730
|
+
if (children.length > 0) out.push({ type: node.type, children });
|
|
731
|
+
if (trail) out.push({ type: 'text', text: trail });
|
|
732
|
+
} else if (node.type === 'link' || node.type === 'component') {
|
|
733
|
+
out.push({ ...node, children: expel(node.children) });
|
|
734
|
+
} else {
|
|
735
|
+
out.push(node);
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
return mergeTexts(out);
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
/** Remove, and return, the whitespace at one end of `nodes` (in place). */
|
|
742
|
+
function takeEdge(nodes: InlineNode[], side: 'start' | 'end'): string {
|
|
743
|
+
const at = side === 'start' ? 0 : nodes.length - 1;
|
|
744
|
+
const node = nodes[at];
|
|
745
|
+
if (!node || node.type !== 'text') return '';
|
|
746
|
+
const m =
|
|
747
|
+
side === 'start' ? /^\s+/u.exec(node.text) : /\s+$/u.exec(node.text);
|
|
748
|
+
if (!m) return '';
|
|
749
|
+
const rest =
|
|
750
|
+
side === 'start'
|
|
751
|
+
? node.text.slice(m[0].length)
|
|
752
|
+
: node.text.slice(0, node.text.length - m[0].length);
|
|
753
|
+
if (rest === '') nodes.splice(at, 1);
|
|
754
|
+
else nodes[at] = { type: 'text', text: rest };
|
|
755
|
+
return m[0];
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
function mergeTexts(nodes: InlineNode[]): InlineNode[] {
|
|
759
|
+
const out: InlineNode[] = [];
|
|
760
|
+
for (const node of nodes) {
|
|
761
|
+
const prev = out[out.length - 1];
|
|
762
|
+
if (node.type === 'text') {
|
|
763
|
+
if (node.text === '') continue;
|
|
764
|
+
if (prev?.type === 'text') {
|
|
765
|
+
out[out.length - 1] = { type: 'text', text: prev.text + node.text };
|
|
766
|
+
continue;
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
out.push(node);
|
|
770
|
+
}
|
|
771
|
+
return out;
|
|
772
|
+
}
|