@nac3/forge-cli 0.2.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +45 -0
- package/README.md +371 -0
- package/dist/bin/yf.d.ts +5 -0
- package/dist/bin/yf.d.ts.map +1 -0
- package/dist/bin/yf.js +86 -0
- package/dist/bin/yf.js.map +1 -0
- package/dist/chat/claude.d.ts +100 -0
- package/dist/chat/claude.d.ts.map +1 -0
- package/dist/chat/claude.js +228 -0
- package/dist/chat/claude.js.map +1 -0
- package/dist/chat/ingest_session.d.ts +97 -0
- package/dist/chat/ingest_session.d.ts.map +1 -0
- package/dist/chat/ingest_session.js +99 -0
- package/dist/chat/ingest_session.js.map +1 -0
- package/dist/chat/panel.d.ts +15 -0
- package/dist/chat/panel.d.ts.map +1 -0
- package/dist/chat/panel.js +1526 -0
- package/dist/chat/panel.js.map +1 -0
- package/dist/chat/persistence.d.ts +37 -0
- package/dist/chat/persistence.d.ts.map +1 -0
- package/dist/chat/persistence.js +91 -0
- package/dist/chat/persistence.js.map +1 -0
- package/dist/chat/server.d.ts +34 -0
- package/dist/chat/server.d.ts.map +1 -0
- package/dist/chat/server.js +1540 -0
- package/dist/chat/server.js.map +1 -0
- package/dist/chat/spec_extract.d.ts +35 -0
- package/dist/chat/spec_extract.d.ts.map +1 -0
- package/dist/chat/spec_extract.js +152 -0
- package/dist/chat/spec_extract.js.map +1 -0
- package/dist/chat/spec_plan.d.ts +65 -0
- package/dist/chat/spec_plan.d.ts.map +1 -0
- package/dist/chat/spec_plan.js +160 -0
- package/dist/chat/spec_plan.js.map +1 -0
- package/dist/chat/spec_scaffold.d.ts +95 -0
- package/dist/chat/spec_scaffold.d.ts.map +1 -0
- package/dist/chat/spec_scaffold.js +220 -0
- package/dist/chat/spec_scaffold.js.map +1 -0
- package/dist/chat/tools/git.d.ts +59 -0
- package/dist/chat/tools/git.d.ts.map +1 -0
- package/dist/chat/tools/git.js +313 -0
- package/dist/chat/tools/git.js.map +1 -0
- package/dist/chat/tools/github.d.ts +59 -0
- package/dist/chat/tools/github.d.ts.map +1 -0
- package/dist/chat/tools/github.js +310 -0
- package/dist/chat/tools/github.js.map +1 -0
- package/dist/chat/tools/lifecycle.d.ts +82 -0
- package/dist/chat/tools/lifecycle.d.ts.map +1 -0
- package/dist/chat/tools/lifecycle.js +295 -0
- package/dist/chat/tools/lifecycle.js.map +1 -0
- package/dist/chat/tools/manual.d.ts +26 -0
- package/dist/chat/tools/manual.d.ts.map +1 -0
- package/dist/chat/tools/manual.js +164 -0
- package/dist/chat/tools/manual.js.map +1 -0
- package/dist/chat/tools/reader.d.ts +80 -0
- package/dist/chat/tools/reader.d.ts.map +1 -0
- package/dist/chat/tools/reader.js +471 -0
- package/dist/chat/tools/reader.js.map +1 -0
- package/dist/chat/tools.d.ts +106 -0
- package/dist/chat/tools.d.ts.map +1 -0
- package/dist/chat/tools.js +587 -0
- package/dist/chat/tools.js.map +1 -0
- package/dist/codegen/e2e.d.ts +106 -0
- package/dist/codegen/e2e.d.ts.map +1 -0
- package/dist/codegen/e2e.js +931 -0
- package/dist/codegen/e2e.js.map +1 -0
- package/dist/codegen/v3_flow_emit.d.ts +70 -0
- package/dist/codegen/v3_flow_emit.d.ts.map +1 -0
- package/dist/codegen/v3_flow_emit.js +225 -0
- package/dist/codegen/v3_flow_emit.js.map +1 -0
- package/dist/commands/_stub.d.ts +2 -0
- package/dist/commands/_stub.d.ts.map +1 -0
- package/dist/commands/_stub.js +21 -0
- package/dist/commands/_stub.js.map +1 -0
- package/dist/commands/app.d.ts +31 -0
- package/dist/commands/app.d.ts.map +1 -0
- package/dist/commands/app.js +331 -0
- package/dist/commands/app.js.map +1 -0
- package/dist/commands/chat.d.ts +18 -0
- package/dist/commands/chat.d.ts.map +1 -0
- package/dist/commands/chat.js +76 -0
- package/dist/commands/chat.js.map +1 -0
- package/dist/commands/deploy.d.ts +21 -0
- package/dist/commands/deploy.d.ts.map +1 -0
- package/dist/commands/deploy.js +121 -0
- package/dist/commands/deploy.js.map +1 -0
- package/dist/commands/doctor.d.ts +14 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +280 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/figma.d.ts +32 -0
- package/dist/commands/figma.d.ts.map +1 -0
- package/dist/commands/figma.js +141 -0
- package/dist/commands/figma.js.map +1 -0
- package/dist/commands/gen-flow-tests.d.ts +8 -0
- package/dist/commands/gen-flow-tests.d.ts.map +1 -0
- package/dist/commands/gen-flow-tests.js +78 -0
- package/dist/commands/gen-flow-tests.js.map +1 -0
- package/dist/commands/gen-tests.d.ts +9 -0
- package/dist/commands/gen-tests.d.ts.map +1 -0
- package/dist/commands/gen-tests.js +118 -0
- package/dist/commands/gen-tests.js.map +1 -0
- package/dist/commands/license.d.ts +14 -0
- package/dist/commands/license.d.ts.map +1 -0
- package/dist/commands/license.js +182 -0
- package/dist/commands/license.js.map +1 -0
- package/dist/commands/log.d.ts +19 -0
- package/dist/commands/log.d.ts.map +1 -0
- package/dist/commands/log.js +101 -0
- package/dist/commands/log.js.map +1 -0
- package/dist/commands/migrate.d.ts +118 -0
- package/dist/commands/migrate.d.ts.map +1 -0
- package/dist/commands/migrate.js +1410 -0
- package/dist/commands/migrate.js.map +1 -0
- package/dist/commands/mobile.d.ts +27 -0
- package/dist/commands/mobile.d.ts.map +1 -0
- package/dist/commands/mobile.js +90 -0
- package/dist/commands/mobile.js.map +1 -0
- package/dist/commands/new.d.ts +32 -0
- package/dist/commands/new.d.ts.map +1 -0
- package/dist/commands/new.js +107 -0
- package/dist/commands/new.js.map +1 -0
- package/dist/commands/pilot.d.ts +8 -0
- package/dist/commands/pilot.d.ts.map +1 -0
- package/dist/commands/pilot.js +104 -0
- package/dist/commands/pilot.js.map +1 -0
- package/dist/commands/projects.d.ts +21 -0
- package/dist/commands/projects.d.ts.map +1 -0
- package/dist/commands/projects.js +238 -0
- package/dist/commands/projects.js.map +1 -0
- package/dist/commands/publish.d.ts +35 -0
- package/dist/commands/publish.d.ts.map +1 -0
- package/dist/commands/publish.js +194 -0
- package/dist/commands/publish.js.map +1 -0
- package/dist/commands/repo.d.ts +59 -0
- package/dist/commands/repo.d.ts.map +1 -0
- package/dist/commands/repo.js +178 -0
- package/dist/commands/repo.js.map +1 -0
- package/dist/commands/review-screens.d.ts +28 -0
- package/dist/commands/review-screens.d.ts.map +1 -0
- package/dist/commands/review-screens.js +345 -0
- package/dist/commands/review-screens.js.map +1 -0
- package/dist/commands/scenarios.d.ts +23 -0
- package/dist/commands/scenarios.d.ts.map +1 -0
- package/dist/commands/scenarios.js +304 -0
- package/dist/commands/scenarios.js.map +1 -0
- package/dist/commands/ship.d.ts +18 -0
- package/dist/commands/ship.d.ts.map +1 -0
- package/dist/commands/ship.js +41 -0
- package/dist/commands/ship.js.map +1 -0
- package/dist/commands/test.d.ts +29 -0
- package/dist/commands/test.d.ts.map +1 -0
- package/dist/commands/test.js +62 -0
- package/dist/commands/test.js.map +1 -0
- package/dist/commands/tunnel.d.ts +22 -0
- package/dist/commands/tunnel.d.ts.map +1 -0
- package/dist/commands/tunnel.js +77 -0
- package/dist/commands/tunnel.js.map +1 -0
- package/dist/commands/validate.d.ts +14 -0
- package/dist/commands/validate.d.ts.map +1 -0
- package/dist/commands/validate.js +51 -0
- package/dist/commands/validate.js.map +1 -0
- package/dist/commands/vault.d.ts +32 -0
- package/dist/commands/vault.d.ts.map +1 -0
- package/dist/commands/vault.js +489 -0
- package/dist/commands/vault.js.map +1 -0
- package/dist/commands/voice.d.ts +16 -0
- package/dist/commands/voice.d.ts.map +1 -0
- package/dist/commands/voice.js +69 -0
- package/dist/commands/voice.js.map +1 -0
- package/dist/core/cascade_router.d.ts +90 -0
- package/dist/core/cascade_router.d.ts.map +1 -0
- package/dist/core/cascade_router.js +131 -0
- package/dist/core/cascade_router.js.map +1 -0
- package/dist/core/cf_tunnel.d.ts +52 -0
- package/dist/core/cf_tunnel.d.ts.map +1 -0
- package/dist/core/cf_tunnel.js +134 -0
- package/dist/core/cf_tunnel.js.map +1 -0
- package/dist/core/gha_dispatcher.d.ts +48 -0
- package/dist/core/gha_dispatcher.d.ts.map +1 -0
- package/dist/core/gha_dispatcher.js +198 -0
- package/dist/core/gha_dispatcher.js.map +1 -0
- package/dist/core/logger.d.ts +89 -0
- package/dist/core/logger.d.ts.map +1 -0
- package/dist/core/logger.js +245 -0
- package/dist/core/logger.js.map +1 -0
- package/dist/core/mode.d.ts +26 -0
- package/dist/core/mode.d.ts.map +1 -0
- package/dist/core/mode.js +122 -0
- package/dist/core/mode.js.map +1 -0
- package/dist/core/pairing.d.ts +40 -0
- package/dist/core/pairing.d.ts.map +1 -0
- package/dist/core/pairing.js +145 -0
- package/dist/core/pairing.js.map +1 -0
- package/dist/core/pilot_setup.d.ts +29 -0
- package/dist/core/pilot_setup.d.ts.map +1 -0
- package/dist/core/pilot_setup.js +119 -0
- package/dist/core/pilot_setup.js.map +1 -0
- package/dist/core/polar.d.ts +81 -0
- package/dist/core/polar.d.ts.map +1 -0
- package/dist/core/polar.js +175 -0
- package/dist/core/polar.js.map +1 -0
- package/dist/core/project_picker.d.ts +56 -0
- package/dist/core/project_picker.d.ts.map +1 -0
- package/dist/core/project_picker.js +86 -0
- package/dist/core/project_picker.js.map +1 -0
- package/dist/core/projects.d.ts +58 -0
- package/dist/core/projects.d.ts.map +1 -0
- package/dist/core/projects.js +146 -0
- package/dist/core/projects.js.map +1 -0
- package/dist/core/projects_sync.d.ts +80 -0
- package/dist/core/projects_sync.d.ts.map +1 -0
- package/dist/core/projects_sync.js +278 -0
- package/dist/core/projects_sync.js.map +1 -0
- package/dist/core/remote_runner.d.ts +70 -0
- package/dist/core/remote_runner.d.ts.map +1 -0
- package/dist/core/remote_runner.js +133 -0
- package/dist/core/remote_runner.js.map +1 -0
- package/dist/core/repo_state.d.ts +24 -0
- package/dist/core/repo_state.d.ts.map +1 -0
- package/dist/core/repo_state.js +109 -0
- package/dist/core/repo_state.js.map +1 -0
- package/dist/core/target.d.ts +31 -0
- package/dist/core/target.d.ts.map +1 -0
- package/dist/core/target.js +121 -0
- package/dist/core/target.js.map +1 -0
- package/dist/deploy/aws.d.ts +43 -0
- package/dist/deploy/aws.d.ts.map +1 -0
- package/dist/deploy/aws.js +173 -0
- package/dist/deploy/aws.js.map +1 -0
- package/dist/figma/api.d.ts +35 -0
- package/dist/figma/api.d.ts.map +1 -0
- package/dist/figma/api.js +40 -0
- package/dist/figma/api.js.map +1 -0
- package/dist/figma/decorator.d.ts +74 -0
- package/dist/figma/decorator.d.ts.map +1 -0
- package/dist/figma/decorator.js +210 -0
- package/dist/figma/decorator.js.map +1 -0
- package/dist/figma/heuristics.d.ts +29 -0
- package/dist/figma/heuristics.d.ts.map +1 -0
- package/dist/figma/heuristics.js +110 -0
- package/dist/figma/heuristics.js.map +1 -0
- package/dist/figma/normalize.d.ts +33 -0
- package/dist/figma/normalize.d.ts.map +1 -0
- package/dist/figma/normalize.js +101 -0
- package/dist/figma/normalize.js.map +1 -0
- package/dist/figma/tokens.d.ts +23 -0
- package/dist/figma/tokens.d.ts.map +1 -0
- package/dist/figma/tokens.js +111 -0
- package/dist/figma/tokens.js.map +1 -0
- package/dist/figma/types.d.ts +118 -0
- package/dist/figma/types.d.ts.map +1 -0
- package/dist/figma/types.js +12 -0
- package/dist/figma/types.js.map +1 -0
- package/dist/i18n/index.d.ts +48 -0
- package/dist/i18n/index.d.ts.map +1 -0
- package/dist/i18n/index.js +135 -0
- package/dist/i18n/index.js.map +1 -0
- package/dist/i18n/types.d.ts +52 -0
- package/dist/i18n/types.d.ts.map +1 -0
- package/dist/i18n/types.js +85 -0
- package/dist/i18n/types.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -0
- package/dist/lan/mdns_packet.d.ts +74 -0
- package/dist/lan/mdns_packet.d.ts.map +1 -0
- package/dist/lan/mdns_packet.js +247 -0
- package/dist/lan/mdns_packet.js.map +1 -0
- package/dist/lan/mdns_service.d.ts +102 -0
- package/dist/lan/mdns_service.d.ts.map +1 -0
- package/dist/lan/mdns_service.js +206 -0
- package/dist/lan/mdns_service.js.map +1 -0
- package/dist/license/activate.d.ts +33 -0
- package/dist/license/activate.d.ts.map +1 -0
- package/dist/license/activate.js +135 -0
- package/dist/license/activate.js.map +1 -0
- package/dist/license/fingerprint.d.ts +2 -0
- package/dist/license/fingerprint.d.ts.map +1 -0
- package/dist/license/fingerprint.js +29 -0
- package/dist/license/fingerprint.js.map +1 -0
- package/dist/license/hito4_client.d.ts +24 -0
- package/dist/license/hito4_client.d.ts.map +1 -0
- package/dist/license/hito4_client.js +103 -0
- package/dist/license/hito4_client.js.map +1 -0
- package/dist/license/index.d.ts +22 -0
- package/dist/license/index.d.ts.map +1 -0
- package/dist/license/index.js +125 -0
- package/dist/license/index.js.map +1 -0
- package/dist/license/types.d.ts +38 -0
- package/dist/license/types.d.ts.map +1 -0
- package/dist/license/types.js +9 -0
- package/dist/license/types.js.map +1 -0
- package/dist/migrate/ai-apply.d.ts +198 -0
- package/dist/migrate/ai-apply.d.ts.map +1 -0
- package/dist/migrate/ai-apply.js +833 -0
- package/dist/migrate/ai-apply.js.map +1 -0
- package/dist/migrate/ai-decorator.d.ts +87 -0
- package/dist/migrate/ai-decorator.d.ts.map +1 -0
- package/dist/migrate/ai-decorator.js +203 -0
- package/dist/migrate/ai-decorator.js.map +1 -0
- package/dist/migrate/apply.d.ts +28 -0
- package/dist/migrate/apply.d.ts.map +1 -0
- package/dist/migrate/apply.js +119 -0
- package/dist/migrate/apply.js.map +1 -0
- package/dist/migrate/audit.d.ts +9 -0
- package/dist/migrate/audit.d.ts.map +1 -0
- package/dist/migrate/audit.js +197 -0
- package/dist/migrate/audit.js.map +1 -0
- package/dist/migrate/diff.d.ts +28 -0
- package/dist/migrate/diff.d.ts.map +1 -0
- package/dist/migrate/diff.js +154 -0
- package/dist/migrate/diff.js.map +1 -0
- package/dist/migrate/html-orchestrator.d.ts +81 -0
- package/dist/migrate/html-orchestrator.d.ts.map +1 -0
- package/dist/migrate/html-orchestrator.js +233 -0
- package/dist/migrate/html-orchestrator.js.map +1 -0
- package/dist/migrate/html-walker.d.ts +93 -0
- package/dist/migrate/html-walker.d.ts.map +1 -0
- package/dist/migrate/html-walker.js +288 -0
- package/dist/migrate/html-walker.js.map +1 -0
- package/dist/migrate/js-template-walker.d.ts +118 -0
- package/dist/migrate/js-template-walker.d.ts.map +1 -0
- package/dist/migrate/js-template-walker.js +644 -0
- package/dist/migrate/js-template-walker.js.map +1 -0
- package/dist/migrate/manifest-validator.d.ts +30 -0
- package/dist/migrate/manifest-validator.d.ts.map +1 -0
- package/dist/migrate/manifest-validator.js +261 -0
- package/dist/migrate/manifest-validator.js.map +1 -0
- package/dist/migrate/overrides.d.ts +58 -0
- package/dist/migrate/overrides.d.ts.map +1 -0
- package/dist/migrate/overrides.js +193 -0
- package/dist/migrate/overrides.js.map +1 -0
- package/dist/migrate/plugin-scope.d.ts +42 -0
- package/dist/migrate/plugin-scope.d.ts.map +1 -0
- package/dist/migrate/plugin-scope.js +94 -0
- package/dist/migrate/plugin-scope.js.map +1 -0
- package/dist/migrate/types.d.ts +45 -0
- package/dist/migrate/types.d.ts.map +1 -0
- package/dist/migrate/types.js +9 -0
- package/dist/migrate/types.js.map +1 -0
- package/dist/migrate/verb-inference.d.ts +37 -0
- package/dist/migrate/verb-inference.d.ts.map +1 -0
- package/dist/migrate/verb-inference.js +274 -0
- package/dist/migrate/verb-inference.js.map +1 -0
- package/dist/nac3/attrs.d.ts +87 -0
- package/dist/nac3/attrs.d.ts.map +1 -0
- package/dist/nac3/attrs.js +134 -0
- package/dist/nac3/attrs.js.map +1 -0
- package/dist/nac3/scenario_dsl.d.ts +71 -0
- package/dist/nac3/scenario_dsl.d.ts.map +1 -0
- package/dist/nac3/scenario_dsl.js +191 -0
- package/dist/nac3/scenario_dsl.js.map +1 -0
- package/dist/nac3/tokens.d.ts +126 -0
- package/dist/nac3/tokens.d.ts.map +1 -0
- package/dist/nac3/tokens.js +138 -0
- package/dist/nac3/tokens.js.map +1 -0
- package/dist/reader/parsers/csv.d.ts +42 -0
- package/dist/reader/parsers/csv.d.ts.map +1 -0
- package/dist/reader/parsers/csv.js +221 -0
- package/dist/reader/parsers/csv.js.map +1 -0
- package/dist/reader/parsers/docx.d.ts +31 -0
- package/dist/reader/parsers/docx.d.ts.map +1 -0
- package/dist/reader/parsers/docx.js +51 -0
- package/dist/reader/parsers/docx.js.map +1 -0
- package/dist/reader/parsers/epub.d.ts +39 -0
- package/dist/reader/parsers/epub.d.ts.map +1 -0
- package/dist/reader/parsers/epub.js +265 -0
- package/dist/reader/parsers/epub.js.map +1 -0
- package/dist/reader/parsers/html.d.ts +40 -0
- package/dist/reader/parsers/html.d.ts.map +1 -0
- package/dist/reader/parsers/html.js +386 -0
- package/dist/reader/parsers/html.js.map +1 -0
- package/dist/reader/parsers/md.d.ts +30 -0
- package/dist/reader/parsers/md.d.ts.map +1 -0
- package/dist/reader/parsers/md.js +199 -0
- package/dist/reader/parsers/md.js.map +1 -0
- package/dist/reader/parsers/pdf.d.ts +39 -0
- package/dist/reader/parsers/pdf.d.ts.map +1 -0
- package/dist/reader/parsers/pdf.js +220 -0
- package/dist/reader/parsers/pdf.js.map +1 -0
- package/dist/reader/parsers/rtf.d.ts +37 -0
- package/dist/reader/parsers/rtf.d.ts.map +1 -0
- package/dist/reader/parsers/rtf.js +347 -0
- package/dist/reader/parsers/rtf.js.map +1 -0
- package/dist/reader/parsers/source.d.ts +32 -0
- package/dist/reader/parsers/source.d.ts.map +1 -0
- package/dist/reader/parsers/source.js +122 -0
- package/dist/reader/parsers/source.js.map +1 -0
- package/dist/reader/parsers/txt.d.ts +25 -0
- package/dist/reader/parsers/txt.d.ts.map +1 -0
- package/dist/reader/parsers/txt.js +56 -0
- package/dist/reader/parsers/txt.js.map +1 -0
- package/dist/reader/parsers/xlsx.d.ts +33 -0
- package/dist/reader/parsers/xlsx.d.ts.map +1 -0
- package/dist/reader/parsers/xlsx.js +143 -0
- package/dist/reader/parsers/xlsx.js.map +1 -0
- package/dist/reader/registry.d.ts +39 -0
- package/dist/reader/registry.d.ts.map +1 -0
- package/dist/reader/registry.js +172 -0
- package/dist/reader/registry.js.map +1 -0
- package/dist/reader/search.d.ts +27 -0
- package/dist/reader/search.d.ts.map +1 -0
- package/dist/reader/search.js +77 -0
- package/dist/reader/search.js.map +1 -0
- package/dist/reader/state.d.ts +56 -0
- package/dist/reader/state.d.ts.map +1 -0
- package/dist/reader/state.js +179 -0
- package/dist/reader/state.js.map +1 -0
- package/dist/reader/types.d.ts +119 -0
- package/dist/reader/types.d.ts.map +1 -0
- package/dist/reader/types.js +23 -0
- package/dist/reader/types.js.map +1 -0
- package/dist/ship/run.d.ts +26 -0
- package/dist/ship/run.d.ts.map +1 -0
- package/dist/ship/run.js +123 -0
- package/dist/ship/run.js.map +1 -0
- package/dist/template/index.d.ts +50 -0
- package/dist/template/index.d.ts.map +1 -0
- package/dist/template/index.js +140 -0
- package/dist/template/index.js.map +1 -0
- package/dist/ui/colors.d.ts +13 -0
- package/dist/ui/colors.d.ts.map +1 -0
- package/dist/ui/colors.js +26 -0
- package/dist/ui/colors.js.map +1 -0
- package/dist/validate/index.d.ts +19 -0
- package/dist/validate/index.d.ts.map +1 -0
- package/dist/validate/index.js +181 -0
- package/dist/validate/index.js.map +1 -0
- package/dist/vault/catalog.d.ts +55 -0
- package/dist/vault/catalog.d.ts.map +1 -0
- package/dist/vault/catalog.js +424 -0
- package/dist/vault/catalog.js.map +1 -0
- package/dist/vault/crypto.d.ts +82 -0
- package/dist/vault/crypto.d.ts.map +1 -0
- package/dist/vault/crypto.js +173 -0
- package/dist/vault/crypto.js.map +1 -0
- package/dist/vault/git_askpass.d.ts +26 -0
- package/dist/vault/git_askpass.d.ts.map +1 -0
- package/dist/vault/git_askpass.js +104 -0
- package/dist/vault/git_askpass.js.map +1 -0
- package/dist/vault/migrator.d.ts +57 -0
- package/dist/vault/migrator.d.ts.map +1 -0
- package/dist/vault/migrator.js +204 -0
- package/dist/vault/migrator.js.map +1 -0
- package/dist/vault/redactor.d.ts +73 -0
- package/dist/vault/redactor.d.ts.map +1 -0
- package/dist/vault/redactor.js +182 -0
- package/dist/vault/redactor.js.map +1 -0
- package/dist/vault/store.d.ts +132 -0
- package/dist/vault/store.d.ts.map +1 -0
- package/dist/vault/store.js +335 -0
- package/dist/vault/store.js.map +1 -0
- package/dist/version.d.ts +8 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +8 -0
- package/dist/version.js.map +1 -0
- package/dist/voice/chunker.d.ts +43 -0
- package/dist/voice/chunker.d.ts.map +1 -0
- package/dist/voice/chunker.js +133 -0
- package/dist/voice/chunker.js.map +1 -0
- package/dist/voice/config.d.ts +14 -0
- package/dist/voice/config.d.ts.map +1 -0
- package/dist/voice/config.js +51 -0
- package/dist/voice/config.js.map +1 -0
- package/dist/voice/intents.d.ts +71 -0
- package/dist/voice/intents.d.ts.map +1 -0
- package/dist/voice/intents.js +0 -0
- package/dist/voice/intents.js.map +1 -0
- package/dist/voice/providers/elevenlabs.d.ts +53 -0
- package/dist/voice/providers/elevenlabs.d.ts.map +1 -0
- package/dist/voice/providers/elevenlabs.js +159 -0
- package/dist/voice/providers/elevenlabs.js.map +1 -0
- package/dist/voice/providers/google.d.ts +56 -0
- package/dist/voice/providers/google.d.ts.map +1 -0
- package/dist/voice/providers/google.js +253 -0
- package/dist/voice/providers/google.js.map +1 -0
- package/dist/voice/providers/whisper.d.ts +44 -0
- package/dist/voice/providers/whisper.d.ts.map +1 -0
- package/dist/voice/providers/whisper.js +179 -0
- package/dist/voice/providers/whisper.js.map +1 -0
- package/dist/voice/registry.d.ts +35 -0
- package/dist/voice/registry.d.ts.map +1 -0
- package/dist/voice/registry.js +48 -0
- package/dist/voice/registry.js.map +1 -0
- package/dist/voice/router.d.ts +62 -0
- package/dist/voice/router.d.ts.map +1 -0
- package/dist/voice/router.js +175 -0
- package/dist/voice/router.js.map +1 -0
- package/dist/voice/types.d.ts +116 -0
- package/dist/voice/types.d.ts.map +1 -0
- package/dist/voice/types.js +22 -0
- package/dist/voice/types.js.map +1 -0
- package/dist/voice/voiceprint/enrollment.d.ts +36 -0
- package/dist/voice/voiceprint/enrollment.d.ts.map +1 -0
- package/dist/voice/voiceprint/enrollment.js +71 -0
- package/dist/voice/voiceprint/enrollment.js.map +1 -0
- package/dist/voice/voiceprint/identify.d.ts +16 -0
- package/dist/voice/voiceprint/identify.d.ts.map +1 -0
- package/dist/voice/voiceprint/identify.js +20 -0
- package/dist/voice/voiceprint/identify.js.map +1 -0
- package/dist/voice/voiceprint/liveness.d.ts +90 -0
- package/dist/voice/voiceprint/liveness.d.ts.map +1 -0
- package/dist/voice/voiceprint/liveness.js +251 -0
- package/dist/voice/voiceprint/liveness.js.map +1 -0
- package/dist/voice/voiceprint/match.d.ts +54 -0
- package/dist/voice/voiceprint/match.d.ts.map +1 -0
- package/dist/voice/voiceprint/match.js +88 -0
- package/dist/voice/voiceprint/match.js.map +1 -0
- package/dist/voice/voiceprint/providers/local-mfcc-stub.d.ts +44 -0
- package/dist/voice/voiceprint/providers/local-mfcc-stub.d.ts.map +1 -0
- package/dist/voice/voiceprint/providers/local-mfcc-stub.js +92 -0
- package/dist/voice/voiceprint/providers/local-mfcc-stub.js.map +1 -0
- package/dist/voice/voiceprint/store.d.ts +60 -0
- package/dist/voice/voiceprint/store.d.ts.map +1 -0
- package/dist/voice/voiceprint/store.js +155 -0
- package/dist/voice/voiceprint/store.js.map +1 -0
- package/dist/voice/voiceprint/trust.d.ts +90 -0
- package/dist/voice/voiceprint/trust.d.ts.map +1 -0
- package/dist/voice/voiceprint/trust.js +150 -0
- package/dist/voice/voiceprint/trust.js.map +1 -0
- package/dist/voice/voiceprint/types.d.ts +100 -0
- package/dist/voice/voiceprint/types.d.ts.map +1 -0
- package/dist/voice/voiceprint/types.js +23 -0
- package/dist/voice/voiceprint/types.js.map +1 -0
- package/dist/voice/wake.d.ts +64 -0
- package/dist/voice/wake.d.ts.map +1 -0
- package/dist/voice/wake.js +143 -0
- package/dist/voice/wake.js.map +1 -0
- package/docs/manuals/manual.ar.html +91 -0
- package/docs/manuals/manual.de.html +100 -0
- package/docs/manuals/manual.en.html +118 -0
- package/docs/manuals/manual.es.html +120 -0
- package/docs/manuals/manual.fr.html +102 -0
- package/docs/manuals/manual.hi.html +93 -0
- package/docs/manuals/manual.it.html +93 -0
- package/docs/manuals/manual.ja.html +97 -0
- package/docs/manuals/manual.pt.html +103 -0
- package/docs/manuals/manual.zh.html +89 -0
- package/package.json +94 -0
- package/src/i18n/catalogs/ar.json +86 -0
- package/src/i18n/catalogs/de.json +86 -0
- package/src/i18n/catalogs/en.json +86 -0
- package/src/i18n/catalogs/es.json +86 -0
- package/src/i18n/catalogs/fr.json +86 -0
- package/src/i18n/catalogs/hi.json +86 -0
- package/src/i18n/catalogs/it.json +86 -0
- package/src/i18n/catalogs/ja.json +86 -0
- package/src/i18n/catalogs/pt.json +86 -0
- package/src/i18n/catalogs/zh.json +86 -0
- package/templates/react-app/README.md +43 -0
- package/templates/react-app/index.html +12 -0
- package/templates/react-app/package.json +35 -0
- package/templates/react-app/src/App.tsx +106 -0
- package/templates/react-app/src/main.tsx +21 -0
- package/templates/react-app/src/nac/manifest.ts +46 -0
- package/templates/react-app/src/styles.css +68 -0
- package/templates/react-app/tsconfig.json +19 -0
- package/templates/react-app/vite.config.ts +12 -0
- package/templates/react-app/yujin.forge.json +15 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PDF parser for the document reader (V1.16 of HITO 1).
|
|
3
|
+
*
|
|
4
|
+
* Uses pdfjs-dist (Mozilla's pdf.js). PDF is dense + complex
|
|
5
|
+
* to hand-roll, and ADIP specs really need it -- accepting
|
|
6
|
+
* the ~3MB dependency was Pablo-approved.
|
|
7
|
+
*
|
|
8
|
+
* Pipeline:
|
|
9
|
+
* 1. pdfjs.getDocument(buffer).promise -> PDFDocumentProxy
|
|
10
|
+
* 2. for each page in document order:
|
|
11
|
+
* page.getTextContent() -> text items grouped by y
|
|
12
|
+
* coordinate -> reconstruct lines -> reconstruct
|
|
13
|
+
* paragraphs by blank-line breaks.
|
|
14
|
+
* 3. paragraph blocks; one section per page (with heading
|
|
15
|
+
* "Pagina N"). The first non-empty line of page 1 becomes
|
|
16
|
+
* the document title.
|
|
17
|
+
*
|
|
18
|
+
* Voice-readback choices:
|
|
19
|
+
* - One section per page so users can navigate "leeme la
|
|
20
|
+
* pagina 3".
|
|
21
|
+
* - "Pagina N" heading is concise enough not to clutter TTS.
|
|
22
|
+
* - Text items with very small font sizes (e.g. footnotes)
|
|
23
|
+
* fold into the surrounding paragraph -- the voice reader
|
|
24
|
+
* does not need typographic structure.
|
|
25
|
+
*
|
|
26
|
+
* Pathological inputs (encrypted PDFs, malformed XObjects)
|
|
27
|
+
* surface the pdfjs error message in a wrapper -- the voice
|
|
28
|
+
* reader stays alive.
|
|
29
|
+
*
|
|
30
|
+
* ASCII-only.
|
|
31
|
+
*/
|
|
32
|
+
import type { NormalisedDocument } from '../types.js';
|
|
33
|
+
export interface ParsePdfOptions {
|
|
34
|
+
buffer: Buffer;
|
|
35
|
+
filename: string;
|
|
36
|
+
language?: string;
|
|
37
|
+
}
|
|
38
|
+
export declare function parsePdf(opts: ParsePdfOptions): Promise<NormalisedDocument>;
|
|
39
|
+
//# sourceMappingURL=pdf.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pdf.d.ts","sourceRoot":"","sources":["../../../src/reader/parsers/pdf.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAkB,MAAM,aAAa,CAAC;AAEtE,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AA+HD,wBAAsB,QAAQ,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAmFjF"}
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PDF parser for the document reader (V1.16 of HITO 1).
|
|
3
|
+
*
|
|
4
|
+
* Uses pdfjs-dist (Mozilla's pdf.js). PDF is dense + complex
|
|
5
|
+
* to hand-roll, and ADIP specs really need it -- accepting
|
|
6
|
+
* the ~3MB dependency was Pablo-approved.
|
|
7
|
+
*
|
|
8
|
+
* Pipeline:
|
|
9
|
+
* 1. pdfjs.getDocument(buffer).promise -> PDFDocumentProxy
|
|
10
|
+
* 2. for each page in document order:
|
|
11
|
+
* page.getTextContent() -> text items grouped by y
|
|
12
|
+
* coordinate -> reconstruct lines -> reconstruct
|
|
13
|
+
* paragraphs by blank-line breaks.
|
|
14
|
+
* 3. paragraph blocks; one section per page (with heading
|
|
15
|
+
* "Pagina N"). The first non-empty line of page 1 becomes
|
|
16
|
+
* the document title.
|
|
17
|
+
*
|
|
18
|
+
* Voice-readback choices:
|
|
19
|
+
* - One section per page so users can navigate "leeme la
|
|
20
|
+
* pagina 3".
|
|
21
|
+
* - "Pagina N" heading is concise enough not to clutter TTS.
|
|
22
|
+
* - Text items with very small font sizes (e.g. footnotes)
|
|
23
|
+
* fold into the surrounding paragraph -- the voice reader
|
|
24
|
+
* does not need typographic structure.
|
|
25
|
+
*
|
|
26
|
+
* Pathological inputs (encrypted PDFs, malformed XObjects)
|
|
27
|
+
* surface the pdfjs error message in a wrapper -- the voice
|
|
28
|
+
* reader stays alive.
|
|
29
|
+
*
|
|
30
|
+
* ASCII-only.
|
|
31
|
+
*/
|
|
32
|
+
/** Reconstruct lines + paragraphs from a page's text items.
|
|
33
|
+
*
|
|
34
|
+
* pdf.js gives items in approximate reading order but with no
|
|
35
|
+
* paragraph structure. We:
|
|
36
|
+
* 1. Group items by y-coordinate (within 2 PDF units).
|
|
37
|
+
* 2. Sort each group by x-coordinate so left-to-right order
|
|
38
|
+
* is preserved.
|
|
39
|
+
* 3. Sort groups top-to-bottom (y descending; PDF coords
|
|
40
|
+
* grow upward).
|
|
41
|
+
* 4. Detect paragraph breaks when consecutive lines have
|
|
42
|
+
* large y-gaps (>= 1.5 * median line height) OR when a
|
|
43
|
+
* line ends with sentence punctuation followed by an
|
|
44
|
+
* indented next line.
|
|
45
|
+
*/
|
|
46
|
+
function reconstructParagraphs(items) {
|
|
47
|
+
if (items.length === 0)
|
|
48
|
+
return [];
|
|
49
|
+
/* Group by quantised y (round to 2 PDF units). */
|
|
50
|
+
const buckets = new Map();
|
|
51
|
+
for (const it of items) {
|
|
52
|
+
if (!it.str || !it.transform || it.transform.length < 6)
|
|
53
|
+
continue;
|
|
54
|
+
const y = Math.round((it.transform[5] ?? 0) / 2) * 2;
|
|
55
|
+
if (!buckets.has(y))
|
|
56
|
+
buckets.set(y, []);
|
|
57
|
+
buckets.get(y).push(it);
|
|
58
|
+
}
|
|
59
|
+
/* Build lines top to bottom (y descending). */
|
|
60
|
+
const ys = Array.from(buckets.keys()).sort((a, b) => b - a);
|
|
61
|
+
const lines = [];
|
|
62
|
+
for (const y of ys) {
|
|
63
|
+
const bucket = buckets.get(y);
|
|
64
|
+
bucket.sort((a, b) => (a.transform[4] ?? 0) - (b.transform[4] ?? 0));
|
|
65
|
+
const text = bucket.map((it) => it.str).join('').replace(/\s+/g, ' ').trim();
|
|
66
|
+
if (text)
|
|
67
|
+
lines.push({ y, text });
|
|
68
|
+
}
|
|
69
|
+
if (lines.length === 0)
|
|
70
|
+
return [];
|
|
71
|
+
/* Median gap between consecutive lines. */
|
|
72
|
+
const gaps = [];
|
|
73
|
+
for (let i = 1; i < lines.length; i += 1) {
|
|
74
|
+
gaps.push((lines[i - 1].y) - (lines[i].y));
|
|
75
|
+
}
|
|
76
|
+
gaps.sort((a, b) => a - b);
|
|
77
|
+
const median = gaps[Math.floor(gaps.length / 2)] ?? 12;
|
|
78
|
+
const paragraphBreakAt = median * 1.6;
|
|
79
|
+
/* Build paragraphs. */
|
|
80
|
+
const paras = [];
|
|
81
|
+
let buf = lines[0].text;
|
|
82
|
+
for (let i = 1; i < lines.length; i += 1) {
|
|
83
|
+
const gap = (lines[i - 1].y) - (lines[i].y);
|
|
84
|
+
if (gap >= paragraphBreakAt) {
|
|
85
|
+
if (buf.trim())
|
|
86
|
+
paras.push(buf.trim());
|
|
87
|
+
buf = lines[i].text;
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
/* Same paragraph -- hyphenated line break joins without
|
|
91
|
+
a space. */
|
|
92
|
+
if (buf.endsWith('-') && /^[a-zA-Z]/.test(lines[i].text)) {
|
|
93
|
+
buf = buf.slice(0, -1) + lines[i].text;
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
buf += ' ' + lines[i].text;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
if (buf.trim())
|
|
101
|
+
paras.push(buf.trim());
|
|
102
|
+
return paras;
|
|
103
|
+
}
|
|
104
|
+
/* Dynamic import wrapper -- pdfjs-dist is ESM only. */
|
|
105
|
+
async function loadPdfjs() {
|
|
106
|
+
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
|
|
107
|
+
return await import('pdfjs-dist/legacy/build/pdf.mjs');
|
|
108
|
+
}
|
|
109
|
+
/** Resolve the path to pdf.worker.mjs inside the installed
|
|
110
|
+
* pdfjs-dist. pdfjs v4 requires workerSrc to be set even
|
|
111
|
+
* when disableWorker is true (the "fake worker" still loads
|
|
112
|
+
* the module). */
|
|
113
|
+
async function resolveWorkerSrc() {
|
|
114
|
+
/* createRequire is the most reliable cross-platform way to
|
|
115
|
+
find an installed module's actual file path under both
|
|
116
|
+
ESM and CJS. The ESM import shape varies across TS lib
|
|
117
|
+
versions; cast through unknown to get a stable handle. */
|
|
118
|
+
const mod = await import('node:module');
|
|
119
|
+
const createRequire = mod.createRequire
|
|
120
|
+
?? mod.default.createRequire;
|
|
121
|
+
const require = createRequire(import.meta.url);
|
|
122
|
+
return require.resolve('pdfjs-dist/legacy/build/pdf.worker.mjs');
|
|
123
|
+
}
|
|
124
|
+
async function getDocument(buffer) {
|
|
125
|
+
const pdfjs = await loadPdfjs();
|
|
126
|
+
if (pdfjs.GlobalWorkerOptions && !pdfjs.GlobalWorkerOptions.workerSrc) {
|
|
127
|
+
pdfjs.GlobalWorkerOptions.workerSrc = await resolveWorkerSrc();
|
|
128
|
+
}
|
|
129
|
+
const loadingTask = pdfjs.getDocument({
|
|
130
|
+
data: new Uint8Array(buffer),
|
|
131
|
+
isEvalSupported: false,
|
|
132
|
+
useSystemFonts: true,
|
|
133
|
+
});
|
|
134
|
+
return await loadingTask.promise;
|
|
135
|
+
}
|
|
136
|
+
/* ----- document assembly ----- */
|
|
137
|
+
export async function parsePdf(opts) {
|
|
138
|
+
let doc;
|
|
139
|
+
try {
|
|
140
|
+
doc = await getDocument(opts.buffer);
|
|
141
|
+
}
|
|
142
|
+
catch (err) {
|
|
143
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
144
|
+
throw new Error('pdf: pdfjs could not open the document: ' + msg);
|
|
145
|
+
}
|
|
146
|
+
const sections = [];
|
|
147
|
+
let blockCounter = 0;
|
|
148
|
+
function nextId(prefix) {
|
|
149
|
+
blockCounter += 1;
|
|
150
|
+
return 's-' + prefix + '-' + blockCounter;
|
|
151
|
+
}
|
|
152
|
+
let title = '';
|
|
153
|
+
for (let pageNum = 1; pageNum <= doc.numPages; pageNum += 1) {
|
|
154
|
+
let page;
|
|
155
|
+
let content;
|
|
156
|
+
try {
|
|
157
|
+
page = await doc.getPage(pageNum);
|
|
158
|
+
content = await page.getTextContent();
|
|
159
|
+
}
|
|
160
|
+
catch (err) {
|
|
161
|
+
/* Skip the page rather than aborting -- voice reader
|
|
162
|
+
degrades to "pagina N: contenido ilegible". */
|
|
163
|
+
sections.push({
|
|
164
|
+
id: 's-' + pageNum,
|
|
165
|
+
heading: 'Pagina ' + pageNum,
|
|
166
|
+
level: 1,
|
|
167
|
+
blocks: [
|
|
168
|
+
{ kind: 'heading', level: 1, text: 'Pagina ' + pageNum, id: nextId('h') },
|
|
169
|
+
{ kind: 'paragraph', level: 0, text: 'Contenido ilegible.', id: nextId('p') },
|
|
170
|
+
],
|
|
171
|
+
});
|
|
172
|
+
continue;
|
|
173
|
+
}
|
|
174
|
+
const paras = reconstructParagraphs(content.items);
|
|
175
|
+
if (pageNum === 1 && paras.length > 0 && !title) {
|
|
176
|
+
/* First non-empty line of page 1 becomes the title. */
|
|
177
|
+
const firstLine = paras[0].split(/[\n.;]/)[0].trim();
|
|
178
|
+
if (firstLine && firstLine.length < 120)
|
|
179
|
+
title = firstLine;
|
|
180
|
+
}
|
|
181
|
+
const heading = 'Pagina ' + pageNum;
|
|
182
|
+
const blocks = [
|
|
183
|
+
{ kind: 'heading', level: 1, text: heading, id: nextId('h') },
|
|
184
|
+
];
|
|
185
|
+
for (const p of paras) {
|
|
186
|
+
blocks.push({
|
|
187
|
+
kind: 'paragraph',
|
|
188
|
+
level: 0,
|
|
189
|
+
text: p,
|
|
190
|
+
id: nextId('p'),
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
sections.push({
|
|
194
|
+
id: 's-' + pageNum,
|
|
195
|
+
heading,
|
|
196
|
+
level: 1,
|
|
197
|
+
blocks,
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
if (sections.length === 0) {
|
|
201
|
+
sections.push({ id: 's-0', heading: '', level: 0, blocks: [] });
|
|
202
|
+
}
|
|
203
|
+
const docId = (opts.filename.split(/[\\/]/).pop() || 'doc')
|
|
204
|
+
.replace(/\.[^.]+$/, '')
|
|
205
|
+
.toLowerCase()
|
|
206
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
207
|
+
.replace(/^-+|-+$/g, '') || 'doc';
|
|
208
|
+
const out = {
|
|
209
|
+
id: docId,
|
|
210
|
+
filename: opts.filename,
|
|
211
|
+
format: 'pdf',
|
|
212
|
+
bytes: opts.buffer.length,
|
|
213
|
+
title: title || ('PDF (' + doc.numPages + ' pages)'),
|
|
214
|
+
sections,
|
|
215
|
+
};
|
|
216
|
+
if (opts.language !== undefined)
|
|
217
|
+
out.language = opts.language;
|
|
218
|
+
return out;
|
|
219
|
+
}
|
|
220
|
+
//# sourceMappingURL=pdf.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pdf.js","sourceRoot":"","sources":["../../../src/reader/parsers/pdf.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RTF parser for the document reader (V1.20 of HITO 1).
|
|
3
|
+
*
|
|
4
|
+
* Tiny hand-rolled parser. No npm dep. RTF (Rich Text Format)
|
|
5
|
+
* is plain text with control words ({\rtf1 ... \par ... }),
|
|
6
|
+
* groups in {curly braces}, hex escapes (\'XX), and unicode
|
|
7
|
+
* escapes (\uNNNN). The parser walks the byte stream as a
|
|
8
|
+
* tiny state machine, dropping anything inside groups whose
|
|
9
|
+
* destination is metadata (fonttbl, colortbl, stylesheet,
|
|
10
|
+
* info, header, footer, pict, object, ...), and keeps the
|
|
11
|
+
* plain-text contents of the body.
|
|
12
|
+
*
|
|
13
|
+
* Paragraph breaks come from \par. Headings are detected
|
|
14
|
+
* heuristically (a line whose paragraph is fully bold and
|
|
15
|
+
* short, or a line tagged with \outlinelevelN, opens a new
|
|
16
|
+
* section). Plain paragraphs read as paragraph blocks.
|
|
17
|
+
*
|
|
18
|
+
* Bold/italic spans inside a paragraph are NOT preserved as
|
|
19
|
+
* structure -- they just contribute their text content. The
|
|
20
|
+
* reader spec doesn't need inline emphasis for voice readback;
|
|
21
|
+
* TTS prosody is handled elsewhere.
|
|
22
|
+
*
|
|
23
|
+
* Pathological inputs (mismatched braces, half-finished
|
|
24
|
+
* control words) degrade to "stop emitting and keep what we
|
|
25
|
+
* have so far" so the reader never crashes on a malformed
|
|
26
|
+
* file.
|
|
27
|
+
*
|
|
28
|
+
* ASCII-only.
|
|
29
|
+
*/
|
|
30
|
+
import type { NormalisedDocument } from '../types.js';
|
|
31
|
+
export interface ParseRtfOptions {
|
|
32
|
+
buffer: Buffer;
|
|
33
|
+
filename: string;
|
|
34
|
+
language?: string;
|
|
35
|
+
}
|
|
36
|
+
export declare function parseRtf(opts: ParseRtfOptions): NormalisedDocument;
|
|
37
|
+
//# sourceMappingURL=rtf.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rtf.d.ts","sourceRoot":"","sources":["../../../src/reader/parsers/rtf.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAkB,MAAM,aAAa,CAAC;AAEtE,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAkSD,wBAAgB,QAAQ,CAAC,IAAI,EAAE,eAAe,GAAG,kBAAkB,CA4ElE"}
|
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RTF parser for the document reader (V1.20 of HITO 1).
|
|
3
|
+
*
|
|
4
|
+
* Tiny hand-rolled parser. No npm dep. RTF (Rich Text Format)
|
|
5
|
+
* is plain text with control words ({\rtf1 ... \par ... }),
|
|
6
|
+
* groups in {curly braces}, hex escapes (\'XX), and unicode
|
|
7
|
+
* escapes (\uNNNN). The parser walks the byte stream as a
|
|
8
|
+
* tiny state machine, dropping anything inside groups whose
|
|
9
|
+
* destination is metadata (fonttbl, colortbl, stylesheet,
|
|
10
|
+
* info, header, footer, pict, object, ...), and keeps the
|
|
11
|
+
* plain-text contents of the body.
|
|
12
|
+
*
|
|
13
|
+
* Paragraph breaks come from \par. Headings are detected
|
|
14
|
+
* heuristically (a line whose paragraph is fully bold and
|
|
15
|
+
* short, or a line tagged with \outlinelevelN, opens a new
|
|
16
|
+
* section). Plain paragraphs read as paragraph blocks.
|
|
17
|
+
*
|
|
18
|
+
* Bold/italic spans inside a paragraph are NOT preserved as
|
|
19
|
+
* structure -- they just contribute their text content. The
|
|
20
|
+
* reader spec doesn't need inline emphasis for voice readback;
|
|
21
|
+
* TTS prosody is handled elsewhere.
|
|
22
|
+
*
|
|
23
|
+
* Pathological inputs (mismatched braces, half-finished
|
|
24
|
+
* control words) degrade to "stop emitting and keep what we
|
|
25
|
+
* have so far" so the reader never crashes on a malformed
|
|
26
|
+
* file.
|
|
27
|
+
*
|
|
28
|
+
* ASCII-only.
|
|
29
|
+
*/
|
|
30
|
+
/** Destinations whose content is metadata and should NOT
|
|
31
|
+
* appear in spoken text. When we enter a group whose first
|
|
32
|
+
* control word is one of these, we drop everything until the
|
|
33
|
+
* group closes. */
|
|
34
|
+
const DROP_DESTINATIONS = new Set([
|
|
35
|
+
'fonttbl', 'colortbl', 'stylesheet', 'info', 'header',
|
|
36
|
+
'footer', 'pict', 'object', 'shp', 'shppict', 'nonshppict',
|
|
37
|
+
'datafield', 'panose', 'listtable', 'listoverridetable',
|
|
38
|
+
'rsidtbl', 'mmathPr', 'themedata', 'colorschememapping',
|
|
39
|
+
'latentstyles', 'datastore', 'wgrffmtfilter', 'xmlnstbl',
|
|
40
|
+
'fldinst',
|
|
41
|
+
/* Document protection / revision tracking -- not useful
|
|
42
|
+
for voice readback. */
|
|
43
|
+
'protect',
|
|
44
|
+
]);
|
|
45
|
+
function emptyPara() {
|
|
46
|
+
return { spans: [], outline: -1, hadPlain: false, hadBold: false };
|
|
47
|
+
}
|
|
48
|
+
function paraText(p) {
|
|
49
|
+
return p.spans.map((s) => s.text).join('').replace(/\s+/g, ' ').trim();
|
|
50
|
+
}
|
|
51
|
+
function emit(state) {
|
|
52
|
+
const text = paraText(state.para);
|
|
53
|
+
if (text) {
|
|
54
|
+
state.out.push({
|
|
55
|
+
text,
|
|
56
|
+
outline: state.para.outline,
|
|
57
|
+
bold: state.para.hadBold && !state.para.hadPlain,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
state.para = emptyPara();
|
|
61
|
+
}
|
|
62
|
+
function appendText(state, text) {
|
|
63
|
+
if (state.dropDepth >= 0)
|
|
64
|
+
return;
|
|
65
|
+
if (!text)
|
|
66
|
+
return;
|
|
67
|
+
/* Decide whether this run is bold for the "fully bold para
|
|
68
|
+
= heading" heuristic. */
|
|
69
|
+
state.para.spans.push({ text, bold: state.bold, outline: state.outline });
|
|
70
|
+
if (state.bold)
|
|
71
|
+
state.para.hadBold = true;
|
|
72
|
+
else
|
|
73
|
+
state.para.hadPlain = true;
|
|
74
|
+
}
|
|
75
|
+
/** Handle one control word (and its optional numeric arg). */
|
|
76
|
+
function handleControlWord(state, word, arg) {
|
|
77
|
+
/* Destination-introducing keywords. The RTF spec marks
|
|
78
|
+
destinations with a leading '*\\' but in practice we
|
|
79
|
+
can recognise them by name. */
|
|
80
|
+
if (DROP_DESTINATIONS.has(word)) {
|
|
81
|
+
state.dropDepth = state.depth;
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
/* Skip the destination switch if we're already dropping. */
|
|
85
|
+
if (state.dropDepth >= 0)
|
|
86
|
+
return;
|
|
87
|
+
switch (word) {
|
|
88
|
+
case 'par':
|
|
89
|
+
case 'sect':
|
|
90
|
+
case 'page':
|
|
91
|
+
case 'line':
|
|
92
|
+
emit(state);
|
|
93
|
+
return;
|
|
94
|
+
case 'tab':
|
|
95
|
+
appendText(state, '\t');
|
|
96
|
+
return;
|
|
97
|
+
case 'b':
|
|
98
|
+
state.bold = arg === 0 ? false : true;
|
|
99
|
+
return;
|
|
100
|
+
case 'plain':
|
|
101
|
+
state.bold = false;
|
|
102
|
+
return;
|
|
103
|
+
case 'outlinelevel':
|
|
104
|
+
if (arg !== null && arg >= 0 && arg <= 5) {
|
|
105
|
+
state.outline = arg;
|
|
106
|
+
if (state.para.outline < 0 || arg < state.para.outline) {
|
|
107
|
+
state.para.outline = arg;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return;
|
|
111
|
+
default:
|
|
112
|
+
/* Unknown control word -> ignore. */
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
/** Handle \'XX hex escape. Interprets as a single byte in
|
|
117
|
+
* CP1252 (the most common default RTF code page). For
|
|
118
|
+
* bytes < 0x80, this matches ASCII. */
|
|
119
|
+
function handleHexEscape(state, hex) {
|
|
120
|
+
const code = parseInt(hex, 16);
|
|
121
|
+
if (!isFinite(code))
|
|
122
|
+
return;
|
|
123
|
+
let ch;
|
|
124
|
+
if (code < 0x80) {
|
|
125
|
+
ch = String.fromCharCode(code);
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
/* Map a few common CP1252 codepoints. Most RTF docs in
|
|
129
|
+
the wild use ASCII + utf-8 escapes; this fallback is
|
|
130
|
+
sufficient for voice readback. */
|
|
131
|
+
const CP1252 = {
|
|
132
|
+
0x91: "'", 0x92: "'", 0x93: '"', 0x94: '"',
|
|
133
|
+
0x95: '*', 0x96: '-', 0x97: '--', 0x85: '...',
|
|
134
|
+
0x99: '(tm)', 0xa9: '(c)', 0xae: '(R)',
|
|
135
|
+
0xa0: ' ',
|
|
136
|
+
};
|
|
137
|
+
ch = CP1252[code] || '?';
|
|
138
|
+
}
|
|
139
|
+
appendText(state, ch);
|
|
140
|
+
}
|
|
141
|
+
/** Handle \uNNNN unicode escape. RTF emits the code point as
|
|
142
|
+
* a signed 16-bit integer, optionally followed by a fallback
|
|
143
|
+
* ASCII character we must skip. */
|
|
144
|
+
function handleUnicodeEscape(state, value) {
|
|
145
|
+
/* Cast signed 16-bit to actual code point. */
|
|
146
|
+
let code = value;
|
|
147
|
+
if (code < 0)
|
|
148
|
+
code = code + 0x10000;
|
|
149
|
+
if (code >= 0 && code <= 0x10ffff) {
|
|
150
|
+
try {
|
|
151
|
+
appendText(state, String.fromCodePoint(code));
|
|
152
|
+
}
|
|
153
|
+
catch {
|
|
154
|
+
appendText(state, '?');
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
/* The fallback char count is \ucN; we don't track that
|
|
158
|
+
dynamically here -- assume default uc=1. */
|
|
159
|
+
return { skipChars: 1 };
|
|
160
|
+
}
|
|
161
|
+
function parseRtfBody(src) {
|
|
162
|
+
const state = {
|
|
163
|
+
src,
|
|
164
|
+
i: 0,
|
|
165
|
+
depth: 0,
|
|
166
|
+
dropDepth: -1,
|
|
167
|
+
bold: false,
|
|
168
|
+
outline: -1,
|
|
169
|
+
para: emptyPara(),
|
|
170
|
+
out: [],
|
|
171
|
+
};
|
|
172
|
+
while (state.i < state.src.length) {
|
|
173
|
+
const ch = state.src.charAt(state.i);
|
|
174
|
+
if (ch === '{') {
|
|
175
|
+
state.depth += 1;
|
|
176
|
+
state.i += 1;
|
|
177
|
+
continue;
|
|
178
|
+
}
|
|
179
|
+
if (ch === '}') {
|
|
180
|
+
state.depth -= 1;
|
|
181
|
+
/* Closing the group that started a drop ends the drop. */
|
|
182
|
+
if (state.dropDepth >= 0 && state.depth < state.dropDepth) {
|
|
183
|
+
state.dropDepth = -1;
|
|
184
|
+
}
|
|
185
|
+
state.i += 1;
|
|
186
|
+
continue;
|
|
187
|
+
}
|
|
188
|
+
if (ch === '\\') {
|
|
189
|
+
const next = state.src.charAt(state.i + 1);
|
|
190
|
+
/* Special single-char escapes. */
|
|
191
|
+
if (next === '\\' || next === '{' || next === '}') {
|
|
192
|
+
appendText(state, next);
|
|
193
|
+
state.i += 2;
|
|
194
|
+
continue;
|
|
195
|
+
}
|
|
196
|
+
if (next === '\n' || next === '\r') {
|
|
197
|
+
/* Backslash followed by newline = literal newline
|
|
198
|
+
paragraph break in some flavours. Treat as space. */
|
|
199
|
+
state.i += 2;
|
|
200
|
+
continue;
|
|
201
|
+
}
|
|
202
|
+
if (next === '*') {
|
|
203
|
+
/* Optional-destination prefix. The next control word
|
|
204
|
+
(if a destination) MUST be dropped; we just skip the
|
|
205
|
+
'*' and let the next token classify itself. */
|
|
206
|
+
state.i += 2;
|
|
207
|
+
continue;
|
|
208
|
+
}
|
|
209
|
+
if (next === "'") {
|
|
210
|
+
/* \'XX hex escape. */
|
|
211
|
+
const hex = state.src.substr(state.i + 2, 2);
|
|
212
|
+
handleHexEscape(state, hex);
|
|
213
|
+
state.i += 4;
|
|
214
|
+
continue;
|
|
215
|
+
}
|
|
216
|
+
if (next === 'u' && /[0-9-]/.test(state.src.charAt(state.i + 2) || '')) {
|
|
217
|
+
/* \uNNNN unicode escape. */
|
|
218
|
+
const m = state.src.slice(state.i + 1).match(/^u(-?\d+)/);
|
|
219
|
+
if (m) {
|
|
220
|
+
const result = handleUnicodeEscape(state, parseInt(m[1], 10));
|
|
221
|
+
state.i += 1 + m[0].length;
|
|
222
|
+
/* Skip the configured number of fallback chars. */
|
|
223
|
+
let skip = result.skipChars;
|
|
224
|
+
while (skip > 0 && state.i < state.src.length) {
|
|
225
|
+
const fc = state.src.charAt(state.i);
|
|
226
|
+
if (fc === ' ') {
|
|
227
|
+
state.i += 1;
|
|
228
|
+
skip -= 1;
|
|
229
|
+
continue;
|
|
230
|
+
}
|
|
231
|
+
if (fc === '\\') {
|
|
232
|
+
/* A fallback that itself is an escape -- bail. */
|
|
233
|
+
break;
|
|
234
|
+
}
|
|
235
|
+
state.i += 1;
|
|
236
|
+
skip -= 1;
|
|
237
|
+
}
|
|
238
|
+
continue;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
/* Generic control word: \wordN where N is optional
|
|
242
|
+
signed numeric argument, optionally terminated by a
|
|
243
|
+
space. */
|
|
244
|
+
const m = state.src.slice(state.i + 1).match(/^([a-zA-Z]+)(-?\d+)?/);
|
|
245
|
+
if (!m) {
|
|
246
|
+
/* Stray backslash -- skip. */
|
|
247
|
+
state.i += 1;
|
|
248
|
+
continue;
|
|
249
|
+
}
|
|
250
|
+
const word = m[1].toLowerCase();
|
|
251
|
+
const arg = m[2] !== undefined ? parseInt(m[2], 10) : null;
|
|
252
|
+
state.i += 1 + m[0].length;
|
|
253
|
+
/* The control word may be terminated by a single space
|
|
254
|
+
that does NOT contribute to output. */
|
|
255
|
+
if (state.src.charAt(state.i) === ' ')
|
|
256
|
+
state.i += 1;
|
|
257
|
+
handleControlWord(state, word, arg);
|
|
258
|
+
continue;
|
|
259
|
+
}
|
|
260
|
+
/* Plain character. Drop CR/LF (RTF uses them as readability
|
|
261
|
+
breaks, not content). */
|
|
262
|
+
if (ch === '\r' || ch === '\n') {
|
|
263
|
+
state.i += 1;
|
|
264
|
+
continue;
|
|
265
|
+
}
|
|
266
|
+
appendText(state, ch);
|
|
267
|
+
state.i += 1;
|
|
268
|
+
}
|
|
269
|
+
/* Flush the final paragraph. */
|
|
270
|
+
emit(state);
|
|
271
|
+
return state.out;
|
|
272
|
+
}
|
|
273
|
+
/* ----- document assembly ----- */
|
|
274
|
+
export function parseRtf(opts) {
|
|
275
|
+
const text = opts.buffer.toString('utf-8');
|
|
276
|
+
const paras = parseRtfBody(text);
|
|
277
|
+
const sections = [];
|
|
278
|
+
let current = { id: 's-0', heading: '', level: 0, blocks: [] };
|
|
279
|
+
let sectionCounter = 0;
|
|
280
|
+
let blockCounter = 0;
|
|
281
|
+
let firstHeading = '';
|
|
282
|
+
function flush() {
|
|
283
|
+
if (current.blocks.length > 0 || current.heading)
|
|
284
|
+
sections.push(current);
|
|
285
|
+
}
|
|
286
|
+
function nextId(prefix) {
|
|
287
|
+
blockCounter += 1;
|
|
288
|
+
return 's-' + prefix + '-' + blockCounter;
|
|
289
|
+
}
|
|
290
|
+
function openSection(heading, level) {
|
|
291
|
+
flush();
|
|
292
|
+
sectionCounter += 1;
|
|
293
|
+
current = {
|
|
294
|
+
id: 's-' + sectionCounter,
|
|
295
|
+
heading,
|
|
296
|
+
level,
|
|
297
|
+
blocks: [{ kind: 'heading', level, text: heading, id: nextId('h') }],
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
for (const p of paras) {
|
|
301
|
+
/* Heading heuristics:
|
|
302
|
+
1. explicit \outlinelevelN -> level = N+1.
|
|
303
|
+
2. fully-bold short paragraph with no sentence punctuation
|
|
304
|
+
and <= 8 words -> heading at level 1. */
|
|
305
|
+
let level = 0;
|
|
306
|
+
if (p.outline >= 0) {
|
|
307
|
+
level = p.outline + 1;
|
|
308
|
+
}
|
|
309
|
+
else if (p.bold) {
|
|
310
|
+
const words = p.text.split(/\s+/).length;
|
|
311
|
+
if (words <= 8 && !/[.;:?!]$/.test(p.text)) {
|
|
312
|
+
level = 1;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
const block = level > 0
|
|
316
|
+
? { kind: 'heading', level, text: p.text, id: nextId('h') }
|
|
317
|
+
: { kind: 'paragraph', level: 0, text: p.text, id: nextId('p') };
|
|
318
|
+
if (level > 0) {
|
|
319
|
+
if (!firstHeading)
|
|
320
|
+
firstHeading = p.text;
|
|
321
|
+
openSection(p.text, level);
|
|
322
|
+
continue;
|
|
323
|
+
}
|
|
324
|
+
current.blocks.push(block);
|
|
325
|
+
}
|
|
326
|
+
flush();
|
|
327
|
+
if (sections.length === 0) {
|
|
328
|
+
sections.push({ id: 's-0', heading: '', level: 0, blocks: [] });
|
|
329
|
+
}
|
|
330
|
+
const docId = (opts.filename.split(/[\\/]/).pop() || 'doc')
|
|
331
|
+
.replace(/\.[^.]+$/, '')
|
|
332
|
+
.toLowerCase()
|
|
333
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
334
|
+
.replace(/^-+|-+$/g, '') || 'doc';
|
|
335
|
+
const doc = {
|
|
336
|
+
id: docId,
|
|
337
|
+
filename: opts.filename,
|
|
338
|
+
format: 'rtf',
|
|
339
|
+
bytes: opts.buffer.length,
|
|
340
|
+
title: firstHeading,
|
|
341
|
+
sections,
|
|
342
|
+
};
|
|
343
|
+
if (opts.language !== undefined)
|
|
344
|
+
doc.language = opts.language;
|
|
345
|
+
return doc;
|
|
346
|
+
}
|
|
347
|
+
//# sourceMappingURL=rtf.js.map
|