ranger-compiler 3.5.1 → 3.5.2
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/CHANGELOG.md +1064 -20
- package/LICENSE +3 -1
- package/README.md +123 -28
- package/dist/Lang.rgr +1188 -290
- package/dist/api.d.ts +2343 -879
- package/dist/api.js +79923 -56921
- package/dist/lib/JSON.rgr +102 -91
- package/dist/lib/Shell.rgr +4 -4
- package/dist/lib/apple/AppleToolchain.rgr +4 -4
- package/dist/lib/apple/README.md +5 -4
- package/dist/lib/apple/apple_test.rgr +1 -1
- package/dist/lib/core/README.md +1 -1
- package/dist/lib/evg/EVG.rgr +12 -0
- package/dist/lib/evg/EVGA11yFromTree.rgr +302 -0
- package/dist/lib/evg/EVGA11yTree.rgr +894 -0
- package/dist/lib/evg/EVGBox.rgr +267 -0
- package/dist/lib/evg/EVGBoxShorthandTest.rgr +220 -0
- package/dist/lib/evg/EVGCodepoint.rgr +316 -0
- package/dist/lib/evg/EVGColor.rgr +700 -0
- package/dist/lib/evg/EVGCommands.rgr +177 -0
- package/dist/lib/evg/EVGComponent.rgr +331 -0
- package/dist/lib/evg/EVGComponentTest.rgr +387 -0
- package/dist/lib/evg/EVGConnector.rgr +541 -0
- package/dist/lib/evg/EVGConnectorTest.rgr +306 -0
- package/dist/lib/evg/EVGDisplayList.rgr +4186 -0
- package/dist/lib/evg/EVGEasing.rgr +370 -0
- package/dist/lib/evg/EVGEffectTest.rgr +253 -0
- package/dist/lib/evg/EVGElement.rgr +4914 -0
- package/dist/lib/evg/EVGFixedTest.rgr +289 -0
- package/dist/lib/evg/EVGFlexRulesTest.rgr +317 -0
- package/dist/lib/evg/EVGFlexWrapTest.rgr +246 -0
- package/dist/lib/evg/EVGFling.rgr +244 -0
- package/dist/lib/evg/EVGFocus.rgr +400 -0
- package/dist/lib/evg/EVGFocusTest.rgr +399 -0
- package/dist/lib/evg/EVGGradient.rgr +322 -0
- package/dist/lib/evg/EVGGrapheme.rgr +190 -0
- package/dist/lib/evg/EVGGrid.rgr +975 -0
- package/dist/lib/evg/EVGHitTest.rgr +208 -0
- package/dist/lib/evg/EVGHoles.rgr +294 -0
- package/dist/lib/evg/EVGHostMeasurerTest.rgr +281 -0
- package/dist/lib/evg/EVGHostTextMeasurer.rgr +331 -0
- package/dist/lib/evg/EVGHostTree.rgr +834 -0
- package/dist/lib/evg/EVGHostTreeTest.rgr +447 -0
- package/dist/lib/evg/EVGImageDecode.rgr +117 -0
- package/dist/lib/evg/EVGImageMeasurer.rgr +86 -0
- package/dist/lib/evg/EVGInspect.rgr +883 -0
- package/dist/lib/evg/EVGInvalidateTest.rgr +432 -0
- package/dist/lib/evg/EVGJsonTest.rgr +535 -0
- package/dist/lib/evg/EVGLayout.rgr +4220 -0
- package/dist/lib/evg/EVGMeasure.rgr +1267 -0
- package/dist/lib/evg/EVGOverlayTest.rgr +626 -0
- package/dist/lib/evg/EVGPatch.rgr +1721 -0
- package/dist/lib/evg/EVGPatchTest.rgr +692 -0
- package/dist/lib/evg/EVGPopoverTest.rgr +395 -0
- package/dist/lib/evg/EVGReconcile.rgr +226 -0
- package/dist/lib/evg/EVGReconcileTest.rgr +421 -0
- package/dist/lib/evg/EVGReject.rgr +126 -0
- package/dist/lib/evg/EVGRelayoutTest.rgr +375 -0
- package/dist/lib/evg/EVGRtlLayoutTest.rgr +319 -0
- package/dist/lib/evg/EVGRuler.rgr +232 -0
- package/dist/lib/evg/EVGRulerTest.rgr +172 -0
- package/dist/lib/evg/EVGSelectChrome.rgr +178 -0
- package/dist/lib/evg/EVGStyleCacheTest.rgr +419 -0
- package/dist/lib/evg/EVGStyleSheet.rgr +2148 -0
- package/dist/lib/evg/EVGStyleStateTest.rgr +407 -0
- package/dist/lib/evg/EVGStyleVarTest.rgr +471 -0
- package/dist/lib/evg/EVGText.rgr +105 -0
- package/dist/lib/evg/EVGTextEngine.rgr +536 -0
- package/dist/lib/evg/EVGTextMeasurer.rgr +720 -0
- package/dist/lib/evg/EVGTimingTest.rgr +1417 -0
- package/dist/lib/evg/EVGToolbar.rgr +1369 -0
- package/dist/lib/evg/EVGTransition.rgr +728 -0
- package/dist/lib/evg/EVGTreeJson.rgr +721 -0
- package/dist/lib/evg/EVGUnit.rgr +554 -0
- package/dist/lib/evg/EVGViewportUnitTest.rgr +236 -0
- package/dist/lib/evg/EvgApp.rgr +189 -0
- package/dist/lib/evg/EvgBitmapTracer.rgr +4277 -0
- package/dist/lib/evg/EvgBitmapTracerTest.rgr +2119 -0
- package/dist/lib/evg/EvgHost.rgr +451 -0
- package/dist/lib/evg/EvgTest.rgr +91 -0
- package/dist/lib/evg/EvgTraceColor.rgr +236 -0
- package/dist/lib/evg/EvgTraceCurve.rgr +648 -0
- package/dist/lib/evg/EvgTraceFit.rgr +767 -0
- package/dist/lib/evg/EvgTracePath.rgr +435 -0
- package/dist/lib/evg/EvgTraceTypes.rgr +559 -0
- package/dist/lib/evg/EvgViewport.rgr +313 -0
- package/dist/lib/evg/FxDemoDoc.rgr +185 -0
- package/dist/lib/evg/HOSTS.md +227 -0
- package/dist/lib/evg/ISSUES.md +835 -0
- package/dist/lib/evg/PLAN_ACCESSIBILITY.md +650 -0
- package/dist/lib/evg/PLAN_CSS_LAYOUT_AND_FONTS.md +1124 -0
- package/dist/lib/evg/PLAN_EFFECTS.md +431 -0
- package/dist/lib/evg/PLAN_EVG.md +518 -0
- package/dist/lib/evg/PLAN_EVG_RENDERER.md +1674 -0
- package/dist/lib/evg/PLAN_INSPECTOR.md +788 -0
- package/dist/lib/evg/PLAN_LINKS_AND_FORMS.md +157 -0
- package/dist/lib/evg/PLAN_NATIVE_HOSTS.md +671 -0
- package/dist/lib/evg/PLAN_VECTOR_IR.md +664 -0
- package/dist/lib/evg/PLAN_VIEW_TRANSFORM.md +322 -0
- package/dist/lib/evg/PathBuilder.rgr +333 -0
- package/dist/lib/evg/README.md +1236 -0
- package/dist/lib/evg/SPEC.md +1252 -0
- package/dist/lib/evg/SVGPathParser.rgr +1199 -0
- package/dist/lib/evg/SvgParser.rgr +1736 -0
- package/dist/lib/evg/TODO_EVG_RENDERER.md +595 -0
- package/dist/lib/evg/VectorShapes.rgr +331 -0
- package/dist/lib/evg/VectorStroke.rgr +107 -0
- package/dist/lib/evg/VectorViewBox.rgr +380 -0
- package/dist/lib/evg/agent/README.md +290 -0
- package/dist/lib/evg/agent/evg_agent.rgr +899 -0
- package/dist/lib/evg/agent/fixtures/broken.evg.json +7 -0
- package/dist/lib/evg/agent/fixtures/card.evg.json +9 -0
- package/dist/lib/evg/agent/fixtures/connector.css +63 -0
- package/dist/lib/evg/agent/fixtures/connector.evg.json +14 -0
- package/dist/lib/evg/agent/fixtures/drawn.evg.json +129 -0
- package/dist/lib/evg/agent/fixtures/gradient.evg.json +4 -0
- package/dist/lib/evg/agent/fixtures/popover.css +99 -0
- package/dist/lib/evg/agent/fixtures/popover.evg.json +30 -0
- package/dist/lib/evg/agent/roundtrip.sh +74 -0
- package/dist/lib/evg/agent/smoke.sh +230 -0
- package/dist/lib/evg/android/README.md +97 -0
- package/dist/lib/evg/android/androidstubs/AndroidStubs.kt +175 -0
- package/dist/lib/evg/android/androidstubs/Annotation.kt +10 -0
- package/dist/lib/evg/android/androidstubs/App.kt +30 -0
- package/dist/lib/evg/android/androidstubs/Content.kt +41 -0
- package/dist/lib/evg/android/androidstubs/ContentRes.kt +12 -0
- package/dist/lib/evg/android/androidstubs/InputMethod.kt +46 -0
- package/dist/lib/evg/android/androidstubs/Net.kt +6 -0
- package/dist/lib/evg/android/androidstubs/Os.kt +30 -0
- package/dist/lib/evg/android/androidstubs/Util.kt +15 -0
- package/dist/lib/evg/android/androidstubs/View.kt +113 -0
- package/dist/lib/evg/android/androidstubs/Widget.kt +16 -0
- package/dist/lib/evg/android/src/android/kotlin/fi/ranger/evg/AndroidEvgSurface.kt +323 -0
- package/dist/lib/evg/android/src/android/kotlin/fi/ranger/evg/AndroidTextMeasurer.kt +56 -0
- package/dist/lib/evg/android/src/android/kotlin/fi/ranger/evg/RippleEffect.kt +262 -0
- package/dist/lib/evg/android/src/awt/kotlin/fi/ranger/evg/AwtEvgSurface.kt +238 -0
- package/dist/lib/evg/android/src/awt/kotlin/fi/ranger/evg/AwtTextMeasurer.kt +85 -0
- package/dist/lib/evg/android/src/main/kotlin/fi/ranger/evg/EvgEngineThread.kt +115 -0
- package/dist/lib/evg/android/src/main/kotlin/fi/ranger/evg/EvgPainter.kt +231 -0
- package/dist/lib/evg/android/src/main/kotlin/fi/ranger/evg/EvgSurface.kt +117 -0
- package/dist/lib/evg/android/src/main/kotlin/fi/ranger/evg/RecordingSurface.kt +94 -0
- package/dist/lib/evg/apple/README.md +128 -0
- package/dist/lib/evg/apple/Sources/CoreGraphicsEvgSurface.swift +329 -0
- package/dist/lib/evg/apple/Sources/CoreTextMeasurer.swift +70 -0
- package/dist/lib/evg/apple/Sources/EvgEngineQueue.swift +105 -0
- package/dist/lib/evg/apple/Sources/EvgPainter.swift +225 -0
- package/dist/lib/evg/apple/Sources/EvgSurface.swift +163 -0
- package/dist/lib/evg/apple/Sources/RecordingSurface.swift +110 -0
- package/dist/lib/evg/bench/EvgLayoutBench.rgr +34 -0
- package/dist/lib/evg/bench/README.md +64 -0
- package/dist/lib/evg/bench/layout-bench.mjs +316 -0
- package/dist/lib/evg/bench/layout-cases.mjs +510 -0
- package/dist/lib/evg/bench/layout-conformance.mjs +254 -0
- package/dist/lib/evg/bin/.gitignore +17 -0
- package/dist/lib/evg/evg_test.rgr +313 -0
- package/dist/lib/evg/gl/README.md +198 -0
- package/dist/lib/evg/gl/a11y-paint-check.mjs +73 -0
- package/dist/lib/evg/gl/blur-check.mjs +399 -0
- package/dist/lib/evg/gl/boxmodel.json +1 -0
- package/dist/lib/evg/gl/demo.html +46 -0
- package/dist/lib/evg/gl/effect-presets.css +285 -0
- package/dist/lib/evg/gl/effect-presets.js +63 -0
- package/dist/lib/evg/gl/effect-shots.mjs +135 -0
- package/dist/lib/evg/gl/evg-a11y.js +566 -0
- package/dist/lib/evg/gl/evg-binary.js +160 -0
- package/dist/lib/evg/gl/evg-engine.js +296 -0
- package/dist/lib/evg/gl/evg-fx.js +237 -0
- package/dist/lib/evg/gl/evg-gestures.js +209 -0
- package/dist/lib/evg/gl/evg-list.js +167 -0
- package/dist/lib/evg/gl/evg-measure.js +186 -0
- package/dist/lib/evg/gl/evg-textinput.js +303 -0
- package/dist/lib/evg/gl/evg-view.js +144 -0
- package/dist/lib/evg/gl/evg-webgl.js +3942 -0
- package/dist/lib/evg/gl/fx-check.mjs +998 -0
- package/dist/lib/evg/gl/fx-demo.html +166 -0
- package/dist/lib/evg/gl/fx-demo.js +2 -0
- package/dist/lib/evg/gl/fx-serve.mjs +47 -0
- package/dist/lib/evg/gl/gestures-check.mjs +189 -0
- package/dist/lib/evg/gl/list-binary-check.mjs +152 -0
- package/dist/lib/evg/gl/measure-check.mjs +135 -0
- package/dist/lib/evg/gl/rotation-check.mjs +207 -0
- package/dist/lib/evg/gl/shift-check.mjs +113 -0
- package/dist/lib/evg/gl/stroke-check.mjs +168 -0
- package/dist/lib/evg/gl/text-snap-check.mjs +139 -0
- package/dist/lib/evg/gl/view-check.mjs +343 -0
- package/dist/lib/evg/gl/view-policy-check.mjs +184 -0
- package/dist/lib/evg/html/evg-dom.js +318 -0
- package/dist/lib/evg/html/evg-html.js +600 -0
- package/dist/lib/evg/inspect/README.md +415 -0
- package/dist/lib/evg/inspect/browser-smoke.mjs +115 -0
- package/dist/lib/evg/inspect/evg-inspect.js +947 -0
- package/dist/lib/evg/inspect/shots/css.png +0 -0
- package/dist/lib/evg/inspect/shots/dashboard.png +0 -0
- package/dist/lib/evg/inspect/shots/pptx-slide.png +0 -0
- package/dist/lib/evg/inspect/shots/state.png +0 -0
- package/dist/lib/evg/inspect/shots.mjs +226 -0
- package/dist/lib/evg/oracle/css-blur.json +576 -0
- package/dist/lib/evg/oracle/css-box.json +157 -0
- package/dist/lib/evg/oracle/css-timing.json +709 -0
- package/dist/lib/evg/oracle/css_blur_oracle.mjs +529 -0
- package/dist/lib/evg/oracle/css_box_oracle.mjs +106 -0
- package/dist/lib/evg/oracle/css_timing_oracle.mjs +389 -0
- package/dist/lib/evg/original/EVGColor.clj +310 -0
- package/dist/lib/evg/original/EVGColorContext.rgr +178 -0
- package/dist/lib/evg/original/SVGPath.rgr +627 -0
- package/dist/lib/evg/original/Vec2.crgr +103 -0
- package/dist/lib/evg/ranger.json +9 -0
- package/dist/lib/evg/showcase/README.md +246 -0
- package/dist/lib/evg/showcase/assets/emblem.svg +30 -0
- package/dist/lib/evg/showcase/assets/rosette.svg +22 -0
- package/dist/lib/evg/showcase/build.mjs +651 -0
- package/dist/lib/evg/showcase/pages/album.tsx +30 -0
- package/dist/lib/evg/showcase/pages/boxmodel.tsx +37 -0
- package/dist/lib/evg/showcase/pages/cards.tsx +41 -0
- package/dist/lib/evg/showcase/pages/chart_api.tsx +170 -0
- package/dist/lib/evg/showcase/pages/charts.tsx +219 -0
- package/dist/lib/evg/showcase/pages/drawing.tsx +160 -0
- package/dist/lib/evg/showcase/pages/emoji.tsx +91 -0
- package/dist/lib/evg/showcase/pages/flex.tsx +46 -0
- package/dist/lib/evg/showcase/pages/more.tsx +332 -0
- package/dist/lib/evg/showcase/pages/plots.tsx +262 -0
- package/dist/lib/evg/showcase/pages/svg.tsx +63 -0
- package/dist/lib/evg/showcase/pages/tables.tsx +209 -0
- package/dist/lib/evg/showcase/pages/typography.tsx +43 -0
- package/dist/lib/evg/showcase/pages/units.tsx +35 -0
- package/dist/lib/evg/showcase/pages/variants.tsx +233 -0
- package/dist/lib/evg/showcase/pages/vector.tsx +75 -0
- package/dist/lib/evg/showcase/pages/views.tsx +223 -0
- package/dist/lib/evg/showcase/tests/chart_api_smoke.mjs +339 -0
- package/dist/lib/evg/showcase/tests/gl_smoke.mjs +125 -0
- package/dist/lib/evg/showcase/themes/chart_api-default.css +15 -0
- package/dist/lib/evg/showcase/themes/charts-default.css +29 -0
- package/dist/lib/evg/showcase/themes/drawing-default.css +35 -0
- package/dist/lib/evg/showcase/themes/more-default.css +128 -0
- package/dist/lib/evg/showcase/themes/plots-default.css +18 -0
- package/dist/lib/evg/showcase/themes/showcase.css +508 -0
- package/dist/lib/evg/showcase/themes/tables-default.css +123 -0
- package/dist/lib/evg/showcase/themes/variants-default.css +15 -0
- package/dist/lib/evg/showcase/themes/views-default.css +15 -0
- package/dist/lib/evg/tools/bench_vs_potrace.mjs +290 -0
- package/dist/lib/evg/tools/evg_image_tool.rgr +488 -0
- package/dist/lib/evg/tools/evg_trace_bench.rgr +114 -0
- package/dist/lib/evg/tools/evg_trace_cli.rgr +662 -0
- package/dist/lib/evg/tools/evg_trace_cpp_bench.rgr +83 -0
- package/dist/lib/evg/tools/run_trace_bench.sh +74 -0
- package/dist/lib/evg/tools/run_trace_cli_smoke.sh +128 -0
- package/dist/lib/evg/web/responsive/EvgResponsiveCheck.rgr +271 -0
- package/dist/lib/evg/web/responsive/EvgResponsiveDemo.rgr +531 -0
- package/dist/lib/evg/web/responsive/README.md +97 -0
- package/dist/lib/evg/web/responsive/build.mjs +90 -0
- package/dist/lib/evg/web/responsive/dom-check.mjs +169 -0
- package/dist/lib/evg/web/responsive/index.html +177 -0
- package/dist/lib/evg/web/responsive/smoke.mjs +221 -0
- package/dist/lib/evg/web/tools/assets-client.mjs +95 -0
- package/dist/lib/evg/web/tools/boot-bench.mjs +189 -0
- package/dist/lib/evg/web/tools/inline-assets.mjs +119 -0
- package/dist/lib/evg/web/tools/minify.mjs +60 -0
- package/dist/lib/evg/web/tracer/build.mjs +87 -0
- package/dist/lib/evg/web/tracer/index.html +2805 -0
- package/dist/lib/evg/web/tracer/sample.png +0 -0
- package/dist/lib/evg/web/tracer/smoke.mjs +1162 -0
- package/dist/lib/evgr/Cargo.lock +21 -0
- package/dist/lib/evgr/Cargo.toml +19 -0
- package/dist/lib/evgr/README.md +140 -0
- package/dist/lib/evgr/bench/NativeBench.rgr +246 -0
- package/dist/lib/evgr/bench/compare.mjs +252 -0
- package/dist/lib/evgr/bench/speed.mjs +277 -0
- package/dist/lib/evgr/bin/.gitignore +3 -0
- package/dist/lib/evgr/src/bin/bench.rs +106 -0
- package/dist/lib/evgr/src/bin/smoke.rs +13 -0
- package/dist/lib/evgr/src/grid.rs +730 -0
- package/dist/lib/evgr/src/lib.rs +1003 -0
- package/dist/lib/evgr/src/style.rs +468 -0
- package/dist/lib/evgr/src/text.rs +83 -0
- package/dist/lib/image/BitReader.rgr +171 -0
- package/dist/lib/image/Buffer.rgr +173 -0
- package/dist/lib/image/DCT.rgr +283 -0
- package/dist/lib/image/Deflate.rgr +339 -0
- package/dist/lib/image/HuffmanDecoder.rgr +181 -0
- package/dist/lib/image/ImageBuffer.rgr +706 -0
- package/dist/lib/image/JPEGDecoder.rgr +808 -0
- package/dist/lib/image/PNGDecoder.rgr +544 -0
- package/dist/lib/image/PNGEncoder.rgr +388 -0
- package/dist/lib/image/PPMImage.rgr +224 -0
- package/dist/lib/image/ProgressiveJPEGDecoder.rgr +1154 -0
- package/dist/lib/image/README.md +33 -0
- package/dist/lib/image/RasterBuffer.rgr +294 -0
- package/dist/lib/image/VP8BoolDecoder.rgr +163 -0
- package/dist/lib/image/WebPDecoder.rgr +433 -0
- package/dist/lib/image/WebPLossless.rgr +1035 -0
- package/dist/lib/image/WebPLossy.rgr +1929 -0
- package/dist/lib/image/ranger.json +9 -0
- package/dist/lib/image/testdata/webp/anim_2f_24x16.webp +0 -0
- package/dist/lib/image/testdata/webp/fixtures.txt +33 -0
- package/dist/lib/image/testdata/webp/gen_fixtures.py +261 -0
- package/dist/lib/image/testdata/webp/ll_1x1.webp +0 -0
- package/dist/lib/image/testdata/webp/ll_alpha_29x21.webp +0 -0
- package/dist/lib/image/testdata/webp/ll_gradient_64x64.webp +0 -0
- package/dist/lib/image/testdata/webp/ll_meta_32x32.webp +0 -0
- package/dist/lib/image/testdata/webp/ll_noise_17x9.webp +0 -0
- package/dist/lib/image/testdata/webp/ll_pal11_23x11.webp +0 -0
- package/dist/lib/image/testdata/webp/ll_pal2_19x7.webp +0 -0
- package/dist/lib/image/testdata/webp/ll_pal40_16x16.webp +0 -0
- package/dist/lib/image/testdata/webp/ll_pal4_13x5.webp +0 -0
- package/dist/lib/image/testdata/webp/ll_photo_40x30.webp +0 -0
- package/dist/lib/image/testdata/webp/ll_predictors_64x32.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_1x1.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_alph_raw_f0_21x13.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_alph_raw_f1_21x13.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_alph_raw_f2_21x13.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_alph_raw_f3_21x13.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_alph_vp8l_f0_21x13.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_alph_vp8l_f1_21x13.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_alph_vp8l_f2_21x13.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_alph_vp8l_f3_21x13.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_alpha_33x17.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_exif_15x11.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_i16_96x80.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_nofilter_24x20.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_odd_17x9.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_photo_48x40.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_q100_20x18.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_sharp_40x36.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_simple_filter_33x31.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_vpx_parts8_37x45.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_vpx_skip_96x80.webp +0 -0
- package/dist/lib/image/tests/WebPDecodeTool.rgr +81 -0
- package/dist/lib/image/tests/WebPDecoderTest.rgr +1162 -0
- package/dist/lib/image/tests/run_webp_tests.sh +39 -0
- package/dist/lib/rust/RsJson.rgr +468 -0
- package/dist/lib/rust/RsPrelude.rgr +1663 -0
- package/dist/lib/shell_test.rgr +7 -7
- package/dist/lib/stdlib.rgr +21 -5
- package/dist/lib/zip/ranger.json +6 -0
- package/dist/rgrc.js +87318 -67610
- package/package.json +1010 -1040
- package/dist/README.md +0 -117
- package/dist/package.json +0 -47
|
@@ -0,0 +1,883 @@
|
|
|
1
|
+
; SPDX-License-Identifier: MIT
|
|
2
|
+
|
|
3
|
+
; ==============================================================================
|
|
4
|
+
; EVGInspect — what the tree IS, for a panel that can ask
|
|
5
|
+
; ==============================================================================
|
|
6
|
+
;
|
|
7
|
+
; An EVG app in a browser is one <canvas>, and a browser's dev tools have
|
|
8
|
+
; nothing to say about it. Three descriptions already come out of the same
|
|
9
|
+
; laid-out tree — `EVGDisplayList` (what to draw), `EVGHitTest` (what is under
|
|
10
|
+
; the pointer) and `EVGA11yFromTree` (what it means). This is the fourth, and
|
|
11
|
+
; it obeys the same rule they do: it is DERIVED from the tree that was laid
|
|
12
|
+
; out, on the same pass, and it recomputes nothing.
|
|
13
|
+
;
|
|
14
|
+
; That rule is the whole design. Every rectangle reported here is the one
|
|
15
|
+
; `EVGLayout` computed and the display list drew, read off `calculatedX` and
|
|
16
|
+
; friends. Nothing here has a second opinion about geometry, so the panel
|
|
17
|
+
; cannot disagree with the picture.
|
|
18
|
+
;
|
|
19
|
+
; --- IDENTITY -----------------------------------------------------------------
|
|
20
|
+
;
|
|
21
|
+
; `EVGElement.id` is not an identity: it is optional, it is the app's own test
|
|
22
|
+
; id, and most elements have none. So the identity is a PATH, assigned here and
|
|
23
|
+
; nowhere else:
|
|
24
|
+
;
|
|
25
|
+
; "0" the root
|
|
26
|
+
; "0/3" its fourth child
|
|
27
|
+
; "0/3/k:share" a child with `key` set uses the key instead of the index
|
|
28
|
+
;
|
|
29
|
+
; The same trick `EVGComponentHost` plays with `enter`/`leave`: a name unique
|
|
30
|
+
; among siblings composes into a name unique in the tree, with no registry.
|
|
31
|
+
;
|
|
32
|
+
; It is STRUCTURAL, and the cost is honest — insert an unkeyed row above the
|
|
33
|
+
; selected one and the path names a different element. Keyed children are
|
|
34
|
+
; immune, which is the set a list rebuild actually reorders. A panel whose
|
|
35
|
+
; path stops resolving must drop the selection and say so, never re-point it
|
|
36
|
+
; at whatever is now at that index.
|
|
37
|
+
;
|
|
38
|
+
; --- WHY THE ELEMENT CARRIES A SLOT -------------------------------------------
|
|
39
|
+
;
|
|
40
|
+
; `build` stamps `el.inspectSlot`. Two things need to go from an element back
|
|
41
|
+
; to a node and Ranger has no identity comparison for objects: the hit test,
|
|
42
|
+
; which answers with an element, and the display list, which stamps the
|
|
43
|
+
; emitting element on each command. One int on the element buys both, and the
|
|
44
|
+
; alternative — a second walk that reimplements the paint order — is exactly
|
|
45
|
+
; the drift this file exists to avoid.
|
|
46
|
+
; ==============================================================================
|
|
47
|
+
|
|
48
|
+
Import "EVGElement.rgr"
|
|
49
|
+
Import "EVGBox.rgr"
|
|
50
|
+
Import "EVGColor.rgr"
|
|
51
|
+
Import "EVGHitTest.rgr"
|
|
52
|
+
Import "EVGStyleSheet.rgr"
|
|
53
|
+
Import "EVGDisplayList.rgr"
|
|
54
|
+
|
|
55
|
+
; ==============================================================================
|
|
56
|
+
; EVGInspectForce — states held on, by node path
|
|
57
|
+
; ==============================================================================
|
|
58
|
+
;
|
|
59
|
+
; A menu that closes when the pointer leaves it cannot be looked at, and a
|
|
60
|
+
; `:hover` rule cannot be edited while the only way to see it is to keep the
|
|
61
|
+
; mouse somewhere other than the panel. Chrome answers this with the `:hov`
|
|
62
|
+
; toggles and so does this: the four interaction bits are held ON for a node
|
|
63
|
+
; until they are let go.
|
|
64
|
+
;
|
|
65
|
+
; They are the four `EVGPseudo.holds` reads — `isHovered`, `isFocused`,
|
|
66
|
+
; `isPressed`, `a11yDisabled` — so nothing new has to be taught to the cascade.
|
|
67
|
+
; A held state is an ordinary state as far as every rule is concerned.
|
|
68
|
+
;
|
|
69
|
+
; KEYED BY PATH, NOT BY ELEMENT, and that is the whole reason this works at
|
|
70
|
+
; all. A page built from tree literals throws its elements away on every input,
|
|
71
|
+
; so a flag written onto an element would last one frame. A path is a fact
|
|
72
|
+
; about the tree's shape, so it names whatever element is in that position on
|
|
73
|
+
; the next pass too.
|
|
74
|
+
;
|
|
75
|
+
; A singleton because the table has to outlive the walk that reads it and every
|
|
76
|
+
; element in the tree, and because the alternative is a field on every app that
|
|
77
|
+
; wants the feature.
|
|
78
|
+
;
|
|
79
|
+
; ON only, like the browser's. Forcing a state OFF is a different thing — it
|
|
80
|
+
; would be arguing with the app about what is happening rather than holding
|
|
81
|
+
; still something that already is.
|
|
82
|
+
; ==============================================================================
|
|
83
|
+
|
|
84
|
+
class EVGInspectForce @singleton(true) {
|
|
85
|
+
def paths:[string]
|
|
86
|
+
def bits:[int]
|
|
87
|
+
|
|
88
|
+
Constructor () {
|
|
89
|
+
def a:[string]
|
|
90
|
+
paths = a
|
|
91
|
+
def b:[int]
|
|
92
|
+
bits = b
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
sfn HOVER:int () { return 1 }
|
|
96
|
+
sfn FOCUS:int () { return 2 }
|
|
97
|
+
sfn PRESSED:int () { return 4 }
|
|
98
|
+
sfn DISABLED:int () { return 8 }
|
|
99
|
+
|
|
100
|
+
fn indexOf:int (path:string) {
|
|
101
|
+
def i:int 0
|
|
102
|
+
while (i < (array_length paths)) {
|
|
103
|
+
if ((itemAt paths i) == path) {
|
|
104
|
+
return i
|
|
105
|
+
}
|
|
106
|
+
i = (i + 1)
|
|
107
|
+
}
|
|
108
|
+
return (0 - 1)
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
; `b` of 0 lets the node go rather than recording "nothing held", so an
|
|
112
|
+
; empty table is exactly "nothing is held" and the check that skips the
|
|
113
|
+
; whole feature is one array length.
|
|
114
|
+
fn set:void (path:string b:int) {
|
|
115
|
+
def at:int (this.indexOf(path))
|
|
116
|
+
if (b == 0) {
|
|
117
|
+
if (at >= 0) {
|
|
118
|
+
remove_index paths at
|
|
119
|
+
remove_index bits at
|
|
120
|
+
}
|
|
121
|
+
return
|
|
122
|
+
}
|
|
123
|
+
if (at < 0) {
|
|
124
|
+
push paths path
|
|
125
|
+
push bits b
|
|
126
|
+
return
|
|
127
|
+
}
|
|
128
|
+
set_at bits at b
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
fn get:int (path:string) {
|
|
132
|
+
def at:int (this.indexOf(path))
|
|
133
|
+
if (at < 0) {
|
|
134
|
+
return 0
|
|
135
|
+
}
|
|
136
|
+
return (itemAt bits at)
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
fn count:int () {
|
|
140
|
+
return (array_length paths)
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
fn clearAll:void () {
|
|
144
|
+
def a:[string]
|
|
145
|
+
paths = a
|
|
146
|
+
def b:[int]
|
|
147
|
+
bits = b
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
class EVGInspect {
|
|
152
|
+
; Parallel arrays, indexed by slot. A flat tree with a parent id is the
|
|
153
|
+
; shape `EVGA11yTree` already crosses this seam with, so a host learns one
|
|
154
|
+
; format and not two.
|
|
155
|
+
def paths:[string]
|
|
156
|
+
def parentPaths:[string]
|
|
157
|
+
def els:[EVGElement]
|
|
158
|
+
def index:[string:int]
|
|
159
|
+
def built:boolean false
|
|
160
|
+
|
|
161
|
+
Constructor () {
|
|
162
|
+
def a:[string]
|
|
163
|
+
paths = a
|
|
164
|
+
def b:[string]
|
|
165
|
+
parentPaths = b
|
|
166
|
+
def c:[EVGElement]
|
|
167
|
+
els = c
|
|
168
|
+
def d:[string:int]
|
|
169
|
+
index = d
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
; --- the walk -------------------------------------------------------------
|
|
173
|
+
|
|
174
|
+
fn build:void (root:EVGElement) {
|
|
175
|
+
def a:[string]
|
|
176
|
+
paths = a
|
|
177
|
+
def b:[string]
|
|
178
|
+
parentPaths = b
|
|
179
|
+
def c:[EVGElement]
|
|
180
|
+
els = c
|
|
181
|
+
def d:[string:int]
|
|
182
|
+
index = d
|
|
183
|
+
this.visit(root "0" "")
|
|
184
|
+
built = true
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
fn visit:void (el:EVGElement path:string parentPath:string) {
|
|
188
|
+
def slot:int (array_length paths)
|
|
189
|
+
push paths path
|
|
190
|
+
push parentPaths parentPath
|
|
191
|
+
push els el
|
|
192
|
+
set index path slot
|
|
193
|
+
el.inspectSlot = slot
|
|
194
|
+
def i:int 0
|
|
195
|
+
while (i < (array_length el.children)) {
|
|
196
|
+
def kid:EVGElement (itemAt el.children i)
|
|
197
|
+
def seg:string (to_string i)
|
|
198
|
+
if ((strlen kid.key) > 0) {
|
|
199
|
+
seg = ("k:" + kid.key)
|
|
200
|
+
}
|
|
201
|
+
def kidPath:string ((path + "/") + seg)
|
|
202
|
+
this.visit(kid kidPath path)
|
|
203
|
+
i = (i + 1)
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
fn count:int () {
|
|
208
|
+
return (array_length paths)
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
fn pathAt:string (slot:int) {
|
|
212
|
+
if (slot < 0) {
|
|
213
|
+
return ""
|
|
214
|
+
}
|
|
215
|
+
if (slot >= (array_length paths)) {
|
|
216
|
+
return ""
|
|
217
|
+
}
|
|
218
|
+
return (itemAt paths slot)
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
; The path of a node's parent. `visit` already recorded it, so this is a
|
|
222
|
+
; lookup and not a string operation — which matters because a keyed segment
|
|
223
|
+
; ("0/3/k:share") cannot be cut off by searching for the last "/".
|
|
224
|
+
fn parentOf:string (path:string) {
|
|
225
|
+
def slot:int (this.slotOf(path))
|
|
226
|
+
if (slot < 0) {
|
|
227
|
+
return ""
|
|
228
|
+
}
|
|
229
|
+
return (itemAt parentPaths slot)
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
fn slotOf:int (path:string) {
|
|
233
|
+
def at@(optional):int (get index path)
|
|
234
|
+
if (null? at) {
|
|
235
|
+
return (0 - 1)
|
|
236
|
+
}
|
|
237
|
+
return (unwrap at)
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
fn elementAt@(optional):EVGElement (path:string) {
|
|
241
|
+
def slot:int (this.slotOf(path))
|
|
242
|
+
if (slot < 0) {
|
|
243
|
+
def miss@(optional):EVGElement
|
|
244
|
+
return miss
|
|
245
|
+
}
|
|
246
|
+
def hit@(optional):EVGElement (itemAt els slot)
|
|
247
|
+
return hit
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
; A point to a node, through the REAL hit test — the same paint order the
|
|
251
|
+
; display list draws in, overlays deferred, topmost wins. Nothing about
|
|
252
|
+
; that order is restated here; the element that comes back is turned into
|
|
253
|
+
; a path by the slot it was stamped with.
|
|
254
|
+
fn hitPath:string (root:EVGElement px:double py:double) {
|
|
255
|
+
def hit (new EVGHitTest())
|
|
256
|
+
def order:[EVGElement] (hit.paintOrderAt(root px py))
|
|
257
|
+
def i:int ((array_length order) - 1)
|
|
258
|
+
while (i >= 0) {
|
|
259
|
+
def el:EVGElement (itemAt order i)
|
|
260
|
+
if (EVGHitTest.containsPoint(el px py)) {
|
|
261
|
+
return (this.pathAt(el.inspectSlot))
|
|
262
|
+
}
|
|
263
|
+
i = (i - 1)
|
|
264
|
+
}
|
|
265
|
+
return ""
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
; --- the tree -------------------------------------------------------------
|
|
269
|
+
|
|
270
|
+
fn treeJson:string (title:string gen:int w:double h:double) {
|
|
271
|
+
def out:string "{\"evginspect\":1,\"title\":"
|
|
272
|
+
out = (out + (EVGInspect.jsonString(title)))
|
|
273
|
+
out = (out + ",\"gen\":" + (to_string gen))
|
|
274
|
+
out = (out + ",\"w\":" + (EVGDisplayList.num(w)))
|
|
275
|
+
out = (out + ",\"h\":" + (EVGDisplayList.num(h)))
|
|
276
|
+
out = (out + ",\"root\":\"0\",\"nodes\":[")
|
|
277
|
+
def i:int 0
|
|
278
|
+
while (i < (array_length paths)) {
|
|
279
|
+
if (i > 0) {
|
|
280
|
+
out = (out + ",")
|
|
281
|
+
}
|
|
282
|
+
out = (out + (this.nodeBrief(i)))
|
|
283
|
+
i = (i + 1)
|
|
284
|
+
}
|
|
285
|
+
return (out + "]}")
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
fn nodeBrief:string (slot:int) {
|
|
289
|
+
def el:EVGElement (itemAt els slot)
|
|
290
|
+
def bx:EVGBox el.box
|
|
291
|
+
def out:string "{\"id\":"
|
|
292
|
+
out = (out + (EVGInspect.jsonString((itemAt paths slot))))
|
|
293
|
+
def pp:string (itemAt parentPaths slot)
|
|
294
|
+
if ((strlen pp) > 0) {
|
|
295
|
+
out = (out + ",\"p\":" + (EVGInspect.jsonString(pp)))
|
|
296
|
+
}
|
|
297
|
+
out = (out + ",\"slot\":" + (to_string slot))
|
|
298
|
+
out = (out + ",\"tag\":" + (EVGInspect.jsonString(el.tagName)))
|
|
299
|
+
if ((strlen el.id) > 0) {
|
|
300
|
+
out = (out + ",\"tid\":" + (EVGInspect.jsonString(el.id)))
|
|
301
|
+
}
|
|
302
|
+
if ((strlen el.className) > 0) {
|
|
303
|
+
out = (out + ",\"cls\":" + (EVGInspect.jsonString(el.className)))
|
|
304
|
+
}
|
|
305
|
+
if ((strlen el.role) > 0) {
|
|
306
|
+
out = (out + ",\"role\":" + (EVGInspect.jsonString(el.role)))
|
|
307
|
+
}
|
|
308
|
+
def txt:string (EVGInspect.clip(el.textContent 80))
|
|
309
|
+
if ((strlen txt) > 0) {
|
|
310
|
+
out = (out + ",\"text\":" + (EVGInspect.jsonString(txt)))
|
|
311
|
+
}
|
|
312
|
+
; The border box: what was painted, what the hit test tests.
|
|
313
|
+
out = (out + ",\"box\":[" + (EVGDisplayList.num(el.calculatedX)))
|
|
314
|
+
out = (out + "," + (EVGDisplayList.num(el.calculatedY)))
|
|
315
|
+
out = (out + "," + (EVGDisplayList.num(el.calculatedWidth)))
|
|
316
|
+
out = (out + "," + (EVGDisplayList.num(el.calculatedHeight)) + "]")
|
|
317
|
+
; The four rings, resolved to pixels by `EVGBox`. The authored units
|
|
318
|
+
; are in the detail, where the difference between `1em` and `12px` is
|
|
319
|
+
; the answer to a different question.
|
|
320
|
+
out = (out + ",\"m\":[" + (EVGDisplayList.num(bx.marginTopPx)))
|
|
321
|
+
out = (out + "," + (EVGDisplayList.num(bx.marginRightPx)))
|
|
322
|
+
out = (out + "," + (EVGDisplayList.num(bx.marginBottomPx)))
|
|
323
|
+
out = (out + "," + (EVGDisplayList.num(bx.marginLeftPx)) + "]")
|
|
324
|
+
out = (out + ",\"b\":" + (EVGDisplayList.num(bx.borderWidthPx)))
|
|
325
|
+
out = (out + ",\"pd\":[" + (EVGDisplayList.num(bx.paddingTopPx)))
|
|
326
|
+
out = (out + "," + (EVGDisplayList.num(bx.paddingRightPx)))
|
|
327
|
+
out = (out + "," + (EVGDisplayList.num(bx.paddingBottomPx)))
|
|
328
|
+
out = (out + "," + (EVGDisplayList.num(bx.paddingLeftPx)) + "]")
|
|
329
|
+
def flags:string (this.flagsOf(el))
|
|
330
|
+
if ((strlen flags) > 0) {
|
|
331
|
+
out = (out + ",\"flags\":[" + flags + "]")
|
|
332
|
+
}
|
|
333
|
+
out = (out + ",\"kids\":" + (to_string (array_length el.children)))
|
|
334
|
+
return (out + "}")
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
; The booleans that change how a node BEHAVES rather than how it looks.
|
|
338
|
+
; The state ones are here because a `:hover` rule that won is unreadable
|
|
339
|
+
; without knowing the element is hovered.
|
|
340
|
+
fn flagsOf:string (el:EVGElement) {
|
|
341
|
+
def out:string ""
|
|
342
|
+
if el.isAbsolute {
|
|
343
|
+
out = (EVGInspect.addFlag(out "abs"))
|
|
344
|
+
}
|
|
345
|
+
if (el.isSurface()) {
|
|
346
|
+
out = (EVGInspect.addFlag(out "overlay"))
|
|
347
|
+
}
|
|
348
|
+
if (el.clipsContent()) {
|
|
349
|
+
out = (EVGInspect.addFlag(out "clip"))
|
|
350
|
+
}
|
|
351
|
+
if el.isInline {
|
|
352
|
+
out = (EVGInspect.addFlag(out "inline"))
|
|
353
|
+
}
|
|
354
|
+
if el.isHovered {
|
|
355
|
+
out = (EVGInspect.addFlag(out "hover"))
|
|
356
|
+
}
|
|
357
|
+
if el.isFocused {
|
|
358
|
+
out = (EVGInspect.addFlag(out "focus"))
|
|
359
|
+
}
|
|
360
|
+
if el.isPressed {
|
|
361
|
+
out = (EVGInspect.addFlag(out "pressed"))
|
|
362
|
+
}
|
|
363
|
+
if el.a11yHidden {
|
|
364
|
+
out = (EVGInspect.addFlag(out "a11y-hidden"))
|
|
365
|
+
}
|
|
366
|
+
return out
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
sfn addFlag:string (soFar:string name:string) {
|
|
370
|
+
if ((strlen soFar) == 0) {
|
|
371
|
+
return ("\"" + name + "\"")
|
|
372
|
+
}
|
|
373
|
+
return (((soFar + ",\"") + name) + "\"")
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
; --- the detail -----------------------------------------------------------
|
|
377
|
+
;
|
|
378
|
+
; Fetched for one node at a time and never for the whole tree: a dashboard
|
|
379
|
+
; is twelve hundred elements and nobody is going to read every computed
|
|
380
|
+
; property of all of them.
|
|
381
|
+
;
|
|
382
|
+
; `inline` is not guessed. `EVGElement.inlineProps` is what the cascade
|
|
383
|
+
; itself consults to know what it must not overwrite, so it is the authoring
|
|
384
|
+
; layer's own record of what was set on the element, read rather than
|
|
385
|
+
; inferred.
|
|
386
|
+
|
|
387
|
+
fn nodeJson:string (path:string) {
|
|
388
|
+
def slot:int (this.slotOf(path))
|
|
389
|
+
if (slot < 0) {
|
|
390
|
+
return "{\"error\":\"no such node\"}"
|
|
391
|
+
}
|
|
392
|
+
def el:EVGElement (itemAt els slot)
|
|
393
|
+
def bx:EVGBox el.box
|
|
394
|
+
def out:string "{\"id\":"
|
|
395
|
+
out = (out + (EVGInspect.jsonString(path)))
|
|
396
|
+
out = (out + ",\"computed\":{")
|
|
397
|
+
def n:int 0
|
|
398
|
+
n = (this.prop(n "display" el.display))
|
|
399
|
+
; `position` is reported as the layout USED it, not as the field reads.
|
|
400
|
+
;
|
|
401
|
+
; The cascade has no `position` branch — `EVGElement.setAttribute` does
|
|
402
|
+
; not know the name — so a rule saying `position: absolute` never
|
|
403
|
+
; reaches the field, and `hasAbsolutePosition` decides out-of-flow from
|
|
404
|
+
; the offsets, the overlay flag and the tag instead. An element that a
|
|
405
|
+
; rule made absolute therefore still reads "relative", and a panel
|
|
406
|
+
; printing the field would be reporting a value nothing consulted.
|
|
407
|
+
;
|
|
408
|
+
; Two consequences worth knowing rather than hiding: `position:
|
|
409
|
+
; absolute` with no offsets is silently ignored by this engine, and the
|
|
410
|
+
; check in `inspect-check.mjs` is what would catch it, because the
|
|
411
|
+
; effective value would then disagree with the rule that asked for it.
|
|
412
|
+
def pos:string el.position
|
|
413
|
+
if el.isAbsolute {
|
|
414
|
+
pos = "absolute"
|
|
415
|
+
}
|
|
416
|
+
n = (this.prop(n "position" pos))
|
|
417
|
+
n = (this.prop(n "flex-direction" el.flexDirection))
|
|
418
|
+
n = (this.prop(n "justify-content" el.justifyContent))
|
|
419
|
+
n = (this.prop(n "align-items" el.alignItems))
|
|
420
|
+
n = (this.prop(n "align-content" el.alignContent))
|
|
421
|
+
n = (this.prop(n "flex-wrap" el.flexWrap))
|
|
422
|
+
n = (this.numProp(n "flex-grow" el.flex))
|
|
423
|
+
n = (this.numProp(n "flex-shrink" el.flexShrink))
|
|
424
|
+
n = (this.unitProp(n "flex-basis" el.flexBasis))
|
|
425
|
+
n = (this.prop(n "grid-template-columns" el.gridTemplateColumns))
|
|
426
|
+
n = (this.prop(n "grid-template-rows" el.gridTemplateRows))
|
|
427
|
+
n = (this.prop(n "grid-area" el.gridArea))
|
|
428
|
+
n = (this.unitProp(n "gap" el.gap))
|
|
429
|
+
n = (this.unitProp(n "width" el.width))
|
|
430
|
+
n = (this.unitProp(n "height" el.height))
|
|
431
|
+
n = (this.unitProp(n "min-width" el.minWidth))
|
|
432
|
+
n = (this.unitProp(n "min-height" el.minHeight))
|
|
433
|
+
n = (this.unitProp(n "max-width" el.maxWidth))
|
|
434
|
+
n = (this.unitProp(n "max-height" el.maxHeight))
|
|
435
|
+
n = (this.unitProp(n "left" el.left))
|
|
436
|
+
n = (this.unitProp(n "top" el.top))
|
|
437
|
+
n = (this.unitProp(n "right" el.right))
|
|
438
|
+
n = (this.unitProp(n "bottom" el.bottom))
|
|
439
|
+
n = (this.pxProp(n "margin-top" bx.marginTopPx))
|
|
440
|
+
n = (this.pxProp(n "margin-right" bx.marginRightPx))
|
|
441
|
+
n = (this.pxProp(n "margin-bottom" bx.marginBottomPx))
|
|
442
|
+
n = (this.pxProp(n "margin-left" bx.marginLeftPx))
|
|
443
|
+
n = (this.pxProp(n "padding-top" bx.paddingTopPx))
|
|
444
|
+
n = (this.pxProp(n "padding-right" bx.paddingRightPx))
|
|
445
|
+
n = (this.pxProp(n "padding-bottom" bx.paddingBottomPx))
|
|
446
|
+
n = (this.pxProp(n "padding-left" bx.paddingLeftPx))
|
|
447
|
+
n = (this.pxProp(n "border-width" bx.borderWidthPx))
|
|
448
|
+
n = (this.pxProp(n "border-radius" bx.borderRadiusPx))
|
|
449
|
+
n = (this.colorProp(n "border-color" bx.borderColor))
|
|
450
|
+
n = (this.colorProp(n "background-color" el.backgroundColor))
|
|
451
|
+
n = (this.colorProp(n "color" el.color))
|
|
452
|
+
n = (this.numProp(n "opacity" el.opacity))
|
|
453
|
+
n = (this.prop(n "background-gradient" el.backgroundGradient))
|
|
454
|
+
n = (this.prop(n "font-family" el.fontFamily))
|
|
455
|
+
n = (this.unitProp(n "font-size" el.fontSize))
|
|
456
|
+
n = (this.prop(n "font-weight" el.fontWeight))
|
|
457
|
+
n = (this.numProp(n "line-height" el.lineHeight))
|
|
458
|
+
n = (this.prop(n "text-align" el.textAlign))
|
|
459
|
+
n = (this.prop(n "overflow" el.overflow))
|
|
460
|
+
n = (this.prop(n "cursor" el.cursor))
|
|
461
|
+
n = (this.prop(n "transition" el.transitionSpec))
|
|
462
|
+
n = (this.prop(n "transform" el.transformSpec))
|
|
463
|
+
n = (this.numProp(n "rotate" el.rotate))
|
|
464
|
+
n = (this.numProp(n "scale" el.scale))
|
|
465
|
+
n = (this.prop(n "class" el.className))
|
|
466
|
+
n = (this.prop(n "theme" el.theme))
|
|
467
|
+
n = (this.prop(n "src" el.src))
|
|
468
|
+
n = (this.prop(n "object-fit" el.objectFit))
|
|
469
|
+
out = (out + acc)
|
|
470
|
+
out = (out + "}")
|
|
471
|
+
|
|
472
|
+
; The authoring layer's own record, not a guess. An entry here outranks
|
|
473
|
+
; every stylesheet rule and that is why the cascade keeps the list.
|
|
474
|
+
out = (out + ",\"inline\":[")
|
|
475
|
+
def k:int 0
|
|
476
|
+
while (k < (array_length el.inlineProps)) {
|
|
477
|
+
if (k > 0) {
|
|
478
|
+
out = (out + ",")
|
|
479
|
+
}
|
|
480
|
+
out = (out + (EVGInspect.jsonString((itemAt el.inlineProps k))))
|
|
481
|
+
k = (k + 1)
|
|
482
|
+
}
|
|
483
|
+
out = (out + "]")
|
|
484
|
+
|
|
485
|
+
; Geometry a panel draws the box diagram from, in one place so the
|
|
486
|
+
; diagram is not four subtractions done in a browser.
|
|
487
|
+
def cx:double ((el.calculatedX + bx.borderWidthPx) + bx.paddingLeftPx)
|
|
488
|
+
def cy:double ((el.calculatedY + bx.borderWidthPx) + bx.paddingTopPx)
|
|
489
|
+
def chW:double (bx.getPaddingHorizontal())
|
|
490
|
+
def chH:double (bx.getPaddingVertical())
|
|
491
|
+
def bw2:double (bx.borderWidthPx * 2.0)
|
|
492
|
+
def cw:double (((el.calculatedWidth - chW) - bw2))
|
|
493
|
+
def ch:double (((el.calculatedHeight - chH) - bw2))
|
|
494
|
+
out = (out + ",\"content\":[" + (EVGDisplayList.num(cx)))
|
|
495
|
+
out = (out + "," + (EVGDisplayList.num(cy)))
|
|
496
|
+
out = (out + "," + (EVGDisplayList.num(cw)))
|
|
497
|
+
out = (out + "," + (EVGDisplayList.num(ch)) + "]")
|
|
498
|
+
|
|
499
|
+
out = (out + (this.cascadeJson(el)))
|
|
500
|
+
out = (out + ",\"forced\":" + (to_string (EVGInspect.forcedState(path))))
|
|
501
|
+
out = (out + ",\"styleSlot\":" + (to_string el.styleSlot))
|
|
502
|
+
out = (out + ",\"styleClass\":" + (EVGInspect.jsonString(el.styleClass)))
|
|
503
|
+
out = (out + ",\"page\":" + (to_string el.calculatedPage))
|
|
504
|
+
def full:string (EVGInspect.clip(el.textContent 400))
|
|
505
|
+
out = (out + ",\"textFull\":" + (EVGInspect.jsonString(full)))
|
|
506
|
+
return (out + "}")
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
; --- what set this value --------------------------------------------------
|
|
510
|
+
;
|
|
511
|
+
; Which classes reach this element, and which rules under them wrote what.
|
|
512
|
+
;
|
|
513
|
+
; Read out of the PLAN, which is where `buildPlan` recorded the rule beside
|
|
514
|
+
; every declaration it flattened. Nothing is re-matched and no specificity
|
|
515
|
+
; is scored here: the plan's order is the cascade's order, so the LAST
|
|
516
|
+
; entry for a property is the winner and the ones before it are the ones it
|
|
517
|
+
; beat. That is why the panel cannot disagree with the engine about who
|
|
518
|
+
; won — it is not deciding, it is reading.
|
|
519
|
+
;
|
|
520
|
+
; Empty when no sheet was given, which is the honest answer for a host that
|
|
521
|
+
; has not offered one rather than a guess assembled from the element.
|
|
522
|
+
|
|
523
|
+
def sheet@(optional):EVGStyleSheet
|
|
524
|
+
def tally:[string]
|
|
525
|
+
def tallyCount:[int]
|
|
526
|
+
|
|
527
|
+
fn useSheet:void (s:EVGStyleSheet) {
|
|
528
|
+
sheet = s
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
; How many elements in this tree carry a class. The panel shows it before
|
|
532
|
+
; you edit a rule, because this cascade selects on classes alone: there is
|
|
533
|
+
; no way to reach one instance without giving it a class of its own, and
|
|
534
|
+
; ".db-card" is four cards whether or not that was the intention.
|
|
535
|
+
fn countClass:int (want:string) {
|
|
536
|
+
def n:int 0
|
|
537
|
+
def i:int 0
|
|
538
|
+
while (i < (array_length els)) {
|
|
539
|
+
def el:EVGElement (itemAt els i)
|
|
540
|
+
def classes:[string] (EVGInspect.splitWs(el.className))
|
|
541
|
+
def j:int 0
|
|
542
|
+
while (j < (array_length classes)) {
|
|
543
|
+
if ((itemAt classes j) == want) {
|
|
544
|
+
n = (n + 1)
|
|
545
|
+
j = (array_length classes)
|
|
546
|
+
} {
|
|
547
|
+
j = (j + 1)
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
i = (i + 1)
|
|
551
|
+
}
|
|
552
|
+
return n
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
fn cascadeJson:string (el:EVGElement) {
|
|
556
|
+
def out:string ",\"classes\":["
|
|
557
|
+
def classes:[string] (EVGInspect.splitWs(el.className))
|
|
558
|
+
def c:int 0
|
|
559
|
+
while (c < (array_length classes)) {
|
|
560
|
+
if (c > 0) {
|
|
561
|
+
out = (out + ",")
|
|
562
|
+
}
|
|
563
|
+
def nm:string (itemAt classes c)
|
|
564
|
+
out = (out + "{\"name\":" + (EVGInspect.jsonString(nm)))
|
|
565
|
+
out = (out + ",\"matches\":" + (to_string (this.countClass(nm))) + "}")
|
|
566
|
+
c = (c + 1)
|
|
567
|
+
}
|
|
568
|
+
out = (out + "]")
|
|
569
|
+
if (null? sheet) {
|
|
570
|
+
return (out + ",\"cascade\":[]")
|
|
571
|
+
}
|
|
572
|
+
def sh:EVGStyleSheet (unwrap sheet)
|
|
573
|
+
def slot:int el.styleSlot
|
|
574
|
+
def n:int (sh.planLength(slot))
|
|
575
|
+
if (n == 0) {
|
|
576
|
+
return (out + ",\"cascade\":[]")
|
|
577
|
+
}
|
|
578
|
+
; The winner of each property is the last entry that names it, so one
|
|
579
|
+
; backwards pass marks the winners and everything else lost.
|
|
580
|
+
def wonAt:[int]
|
|
581
|
+
def seen:[string]
|
|
582
|
+
def i:int (n - 1)
|
|
583
|
+
while (i >= 0) {
|
|
584
|
+
def nm2:string (sh.planNameAt(slot i))
|
|
585
|
+
def already:boolean false
|
|
586
|
+
def k:int 0
|
|
587
|
+
while (k < (array_length seen)) {
|
|
588
|
+
if ((itemAt seen k) == nm2) {
|
|
589
|
+
already = true
|
|
590
|
+
k = (array_length seen)
|
|
591
|
+
} {
|
|
592
|
+
k = (k + 1)
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
if already {
|
|
596
|
+
push wonAt 0
|
|
597
|
+
} {
|
|
598
|
+
push wonAt 1
|
|
599
|
+
push seen nm2
|
|
600
|
+
}
|
|
601
|
+
i = (i - 1)
|
|
602
|
+
}
|
|
603
|
+
; `wonAt` was filled backwards, so entry `i` is at `n - 1 - i`.
|
|
604
|
+
out = (out + ",\"cascade\":[")
|
|
605
|
+
def w:int 0
|
|
606
|
+
while (w < n) {
|
|
607
|
+
if (w > 0) {
|
|
608
|
+
out = (out + ",")
|
|
609
|
+
}
|
|
610
|
+
def ruleIdx:int (sh.planRuleAt(slot w))
|
|
611
|
+
out = (out + "{\"p\":" + (EVGInspect.jsonString((sh.planNameAt(slot w)))))
|
|
612
|
+
out = (out + ",\"v\":" + (EVGInspect.jsonString((sh.planValueAt(slot w)))))
|
|
613
|
+
out = (out + ",\"sel\":" + (EVGInspect.jsonString((sh.selectorOf(ruleIdx)))))
|
|
614
|
+
def med:string (sh.ruleMediaOf(ruleIdx))
|
|
615
|
+
if ((strlen med) > 0) {
|
|
616
|
+
out = (out + ",\"media\":" + (EVGInspect.jsonString(med)))
|
|
617
|
+
}
|
|
618
|
+
def cls:string (sh.ruleClassOf(ruleIdx))
|
|
619
|
+
if ((strlen cls) > 0) {
|
|
620
|
+
out = (out + ",\"cls\":" + (EVGInspect.jsonString(cls)))
|
|
621
|
+
}
|
|
622
|
+
def isWin:int (itemAt wonAt ((n - 1) - w))
|
|
623
|
+
if (isWin == 1) {
|
|
624
|
+
out = (out + ",\"win\":true")
|
|
625
|
+
}
|
|
626
|
+
; An inline attribute outranks every rule, so a declaration the
|
|
627
|
+
; element has set on itself never lands however the plan reads.
|
|
628
|
+
; Marked rather than dropped: "the app writes this one" is the
|
|
629
|
+
; answer to why editing the sheet did nothing.
|
|
630
|
+
def nm3:string (sh.planNameAt(slot w))
|
|
631
|
+
if (el.hasInline(nm3)) {
|
|
632
|
+
out = (out + ",\"beatenByInline\":true")
|
|
633
|
+
}
|
|
634
|
+
out = (out + "}")
|
|
635
|
+
w = (w + 1)
|
|
636
|
+
}
|
|
637
|
+
return (out + "]")
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
sfn splitWs:[string] (v:string) {
|
|
641
|
+
def out:[string]
|
|
642
|
+
def cur:string ""
|
|
643
|
+
def i:int 0
|
|
644
|
+
while (i < (strlen v)) {
|
|
645
|
+
def ch:int (charAt v i)
|
|
646
|
+
if ((((ch == 32) || (ch == 9)) || (ch == 10)) || (ch == 13)) {
|
|
647
|
+
if ((strlen cur) > 0) {
|
|
648
|
+
push out cur
|
|
649
|
+
cur = ""
|
|
650
|
+
}
|
|
651
|
+
} {
|
|
652
|
+
cur = (cur + (strfromcode ch))
|
|
653
|
+
}
|
|
654
|
+
i = (i + 1)
|
|
655
|
+
}
|
|
656
|
+
if ((strlen cur) > 0) {
|
|
657
|
+
push out cur
|
|
658
|
+
}
|
|
659
|
+
return out
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
; The property writer. An accumulator field rather than a returned string,
|
|
663
|
+
; because fifty `out = (out + this.prop(...))` lines would each be a
|
|
664
|
+
; concatenation of the whole buffer so far.
|
|
665
|
+
def acc:string ""
|
|
666
|
+
|
|
667
|
+
fn prop:int (n:int name:string value:string) {
|
|
668
|
+
if ((strlen value) == 0) {
|
|
669
|
+
return n
|
|
670
|
+
}
|
|
671
|
+
return (this.write(n name value))
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
fn pxProp:int (n:int name:string v:double) {
|
|
675
|
+
def s:string ((EVGDisplayList.num(v)) + "px")
|
|
676
|
+
return (this.write(n name s))
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
fn numProp:int (n:int name:string v:double) {
|
|
680
|
+
return (this.write(n name (EVGDisplayList.num(v))))
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
; The unit fields are optional on the element, so the null is a real
|
|
684
|
+
; answer here and not a defensive check: "this element never said anything
|
|
685
|
+
; about width" is different from "it said auto".
|
|
686
|
+
fn unitProp:int (n:int name:string u@(optional):EVGUnit) {
|
|
687
|
+
if (null? u) {
|
|
688
|
+
return n
|
|
689
|
+
}
|
|
690
|
+
def uu:EVGUnit (unwrap u)
|
|
691
|
+
if (uu.isSet == false) {
|
|
692
|
+
return n
|
|
693
|
+
}
|
|
694
|
+
def s:string (uu.toString())
|
|
695
|
+
def px:string (EVGDisplayList.num(uu.pixels))
|
|
696
|
+
def asPx:string (px + "px")
|
|
697
|
+
if (s != asPx) {
|
|
698
|
+
s = ((s + " -> ") + asPx)
|
|
699
|
+
}
|
|
700
|
+
return (this.write(n name s))
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
fn colorProp:int (n:int name:string c@(optional):EVGColor) {
|
|
704
|
+
if (null? c) {
|
|
705
|
+
return n
|
|
706
|
+
}
|
|
707
|
+
def cc:EVGColor (unwrap c)
|
|
708
|
+
if (cc.isSet == false) {
|
|
709
|
+
return n
|
|
710
|
+
}
|
|
711
|
+
def s:string (cc.toCSSString())
|
|
712
|
+
return (this.write(n name s))
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
fn write:int (n:int name:string value:string) {
|
|
716
|
+
if (n == 0) {
|
|
717
|
+
acc = ""
|
|
718
|
+
}
|
|
719
|
+
if (n > 0) {
|
|
720
|
+
acc = (acc + ",")
|
|
721
|
+
}
|
|
722
|
+
acc = (acc + (EVGInspect.jsonString(name)))
|
|
723
|
+
acc = (acc + ":")
|
|
724
|
+
acc = (acc + (EVGInspect.jsonString(value)))
|
|
725
|
+
return (n + 1)
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
; Hold what the panel asked to be held, on the tree as it is now.
|
|
729
|
+
;
|
|
730
|
+
; A host calls this between marking its OWN interaction states and running
|
|
731
|
+
; the cascade — the order matters and it is the only thing a host has to
|
|
732
|
+
; get right: after the app has said what is hovered, before the sheet is
|
|
733
|
+
; asked which rules that makes true.
|
|
734
|
+
;
|
|
735
|
+
; Costs one array length when nothing is held, which is the normal case and
|
|
736
|
+
; the whole shape of the guard.
|
|
737
|
+
sfn applyForced:void (root:EVGElement) {
|
|
738
|
+
def force:EVGInspectForce (EVGInspectForce.__singleton())
|
|
739
|
+
if ((force.count()) == 0) {
|
|
740
|
+
return
|
|
741
|
+
}
|
|
742
|
+
def ins (new EVGInspect())
|
|
743
|
+
ins.build(root)
|
|
744
|
+
def i:int 0
|
|
745
|
+
while (i < (array_length ins.paths)) {
|
|
746
|
+
def b:int (force.get((itemAt ins.paths i)))
|
|
747
|
+
if (b != 0) {
|
|
748
|
+
def el:EVGElement (itemAt ins.els i)
|
|
749
|
+
if ((b % 2) == 1) {
|
|
750
|
+
el.isHovered = true
|
|
751
|
+
}
|
|
752
|
+
def f:int (idiv b 2)
|
|
753
|
+
if ((f % 2) == 1) {
|
|
754
|
+
el.isFocused = true
|
|
755
|
+
}
|
|
756
|
+
def p:int (idiv b 4)
|
|
757
|
+
if ((p % 2) == 1) {
|
|
758
|
+
el.isPressed = true
|
|
759
|
+
}
|
|
760
|
+
def d:int (idiv b 8)
|
|
761
|
+
if ((d % 2) == 1) {
|
|
762
|
+
el.a11yDisabled = true
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
i = (i + 1)
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
sfn forceState:void (path:string bits:int) {
|
|
770
|
+
def force:EVGInspectForce (EVGInspectForce.__singleton())
|
|
771
|
+
force.set(path bits)
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
sfn forcedState:int (path:string) {
|
|
775
|
+
def force:EVGInspectForce (EVGInspectForce.__singleton())
|
|
776
|
+
return (force.get(path))
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
sfn forcedCount:int () {
|
|
780
|
+
def force:EVGInspectForce (EVGInspectForce.__singleton())
|
|
781
|
+
return (force.count())
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
sfn clearForced:void () {
|
|
785
|
+
def force:EVGInspectForce (EVGInspectForce.__singleton())
|
|
786
|
+
force.clearAll()
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
; --- the three calls a host actually makes ---------------------------------
|
|
790
|
+
;
|
|
791
|
+
; A fresh walk per call rather than a cached instance, and deliberately: a
|
|
792
|
+
; panel asks a handful of times per interaction, a walk over twelve hundred
|
|
793
|
+
; elements is microseconds, and an instance kept between calls would be a
|
|
794
|
+
; fourth thing that can go stale against a tree that was rebuilt. The paths
|
|
795
|
+
; are a pure function of the tree's shape, so two walks over the same tree
|
|
796
|
+
; agree by construction and `nodeOf` can be called without `treeOf` first.
|
|
797
|
+
|
|
798
|
+
sfn treeOf:string (root:EVGElement title:string gen:int w:double h:double) {
|
|
799
|
+
def ins (new EVGInspect())
|
|
800
|
+
ins.build(root)
|
|
801
|
+
return (ins.treeJson(title gen w h))
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
sfn nodeOf:string (root:EVGElement path:string) {
|
|
805
|
+
def ins (new EVGInspect())
|
|
806
|
+
ins.build(root)
|
|
807
|
+
return (ins.nodeJson(path))
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
; The same, with the cascade. A host that has its stylesheet in hand should
|
|
811
|
+
; call this one: without the sheet the detail can still say what the value IS,
|
|
812
|
+
; and only with it can it say what SET it.
|
|
813
|
+
sfn nodeOfIn:string (root:EVGElement path:string sheet:EVGStyleSheet) {
|
|
814
|
+
def ins (new EVGInspect())
|
|
815
|
+
ins.build(root)
|
|
816
|
+
ins.useSheet(sheet)
|
|
817
|
+
return (ins.nodeJson(path))
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
sfn hitOf:string (root:EVGElement px:double py:double) {
|
|
821
|
+
def ins (new EVGInspect())
|
|
822
|
+
ins.build(root)
|
|
823
|
+
return (ins.hitPath(root px py))
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
; The display list with every command carrying the element that emitted it.
|
|
827
|
+
; The walk runs FIRST because attribution reads `inspectSlot`, and a slot
|
|
828
|
+
; that has not been stamped this pass is -1 — which would attribute the
|
|
829
|
+
; whole frame to nothing at all.
|
|
830
|
+
sfn frameOf:string (root:EVGElement) {
|
|
831
|
+
def ins (new EVGInspect())
|
|
832
|
+
ins.build(root)
|
|
833
|
+
def dl (new EVGDisplayList())
|
|
834
|
+
dl.attribute = true
|
|
835
|
+
dl.build(root)
|
|
836
|
+
return (dl.toJson())
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
; --- helpers --------------------------------------------------------------
|
|
840
|
+
|
|
841
|
+
sfn clip:string (v:string limit:int) {
|
|
842
|
+
if ((strlen v) <= limit) {
|
|
843
|
+
return v
|
|
844
|
+
}
|
|
845
|
+
def cut:string (substring v 0 limit)
|
|
846
|
+
return (cut + "…")
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
sfn jsonString:string (v:string) {
|
|
850
|
+
def out:string "\""
|
|
851
|
+
def i:int 0
|
|
852
|
+
while (i < (strlen v)) {
|
|
853
|
+
def ch:int (charAt v i)
|
|
854
|
+
if (ch == 34) {
|
|
855
|
+
out = (out + "\\\"")
|
|
856
|
+
} {
|
|
857
|
+
if (ch == 92) {
|
|
858
|
+
out = (out + "\\\\")
|
|
859
|
+
} {
|
|
860
|
+
if (ch == 10) {
|
|
861
|
+
out = (out + "\\n")
|
|
862
|
+
} {
|
|
863
|
+
if (ch == 13) {
|
|
864
|
+
out = (out + "\\r")
|
|
865
|
+
} {
|
|
866
|
+
if (ch == 9) {
|
|
867
|
+
out = (out + "\\t")
|
|
868
|
+
} {
|
|
869
|
+
if (ch < 32) {
|
|
870
|
+
out = (out + " ")
|
|
871
|
+
} {
|
|
872
|
+
out = (out + (strfromcode ch))
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
}
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
}
|
|
879
|
+
i = (i + 1)
|
|
880
|
+
}
|
|
881
|
+
return (out + "\"")
|
|
882
|
+
}
|
|
883
|
+
}
|