@dotsetlabs/bellwether 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +291 -0
- package/LICENSE +21 -0
- package/README.md +739 -0
- package/dist/auth/credentials.d.ts +64 -0
- package/dist/auth/credentials.js +218 -0
- package/dist/auth/index.d.ts +6 -0
- package/dist/auth/index.js +6 -0
- package/dist/auth/keychain.d.ts +64 -0
- package/dist/auth/keychain.js +268 -0
- package/dist/baseline/ab-testing.d.ts +80 -0
- package/dist/baseline/ab-testing.js +236 -0
- package/dist/baseline/ai-compatibility-scorer.d.ts +95 -0
- package/dist/baseline/ai-compatibility-scorer.js +606 -0
- package/dist/baseline/calibration.d.ts +77 -0
- package/dist/baseline/calibration.js +136 -0
- package/dist/baseline/category-matching.d.ts +85 -0
- package/dist/baseline/category-matching.js +289 -0
- package/dist/baseline/change-impact-analyzer.d.ts +98 -0
- package/dist/baseline/change-impact-analyzer.js +592 -0
- package/dist/baseline/comparator.d.ts +64 -0
- package/dist/baseline/comparator.js +916 -0
- package/dist/baseline/confidence.d.ts +55 -0
- package/dist/baseline/confidence.js +122 -0
- package/dist/baseline/converter.d.ts +61 -0
- package/dist/baseline/converter.js +585 -0
- package/dist/baseline/dependency-analyzer.d.ts +89 -0
- package/dist/baseline/dependency-analyzer.js +567 -0
- package/dist/baseline/deprecation-tracker.d.ts +133 -0
- package/dist/baseline/deprecation-tracker.js +322 -0
- package/dist/baseline/diff.d.ts +55 -0
- package/dist/baseline/diff.js +1584 -0
- package/dist/baseline/documentation-scorer.d.ts +205 -0
- package/dist/baseline/documentation-scorer.js +466 -0
- package/dist/baseline/embeddings.d.ts +118 -0
- package/dist/baseline/embeddings.js +251 -0
- package/dist/baseline/error-analyzer.d.ts +198 -0
- package/dist/baseline/error-analyzer.js +721 -0
- package/dist/baseline/evaluation/evaluator.d.ts +42 -0
- package/dist/baseline/evaluation/evaluator.js +323 -0
- package/dist/baseline/evaluation/expanded-dataset.d.ts +45 -0
- package/dist/baseline/evaluation/expanded-dataset.js +1164 -0
- package/dist/baseline/evaluation/golden-dataset.d.ts +58 -0
- package/dist/baseline/evaluation/golden-dataset.js +717 -0
- package/dist/baseline/evaluation/index.d.ts +15 -0
- package/dist/baseline/evaluation/index.js +15 -0
- package/dist/baseline/evaluation/types.d.ts +186 -0
- package/dist/baseline/evaluation/types.js +8 -0
- package/dist/baseline/external-dependency-detector.d.ts +181 -0
- package/dist/baseline/external-dependency-detector.js +524 -0
- package/dist/baseline/golden-output.d.ts +162 -0
- package/dist/baseline/golden-output.js +636 -0
- package/dist/baseline/health-scorer.d.ts +174 -0
- package/dist/baseline/health-scorer.js +451 -0
- package/dist/baseline/incremental-checker.d.ts +97 -0
- package/dist/baseline/incremental-checker.js +174 -0
- package/dist/baseline/index.d.ts +31 -0
- package/dist/baseline/index.js +42 -0
- package/dist/baseline/migration-generator.d.ts +137 -0
- package/dist/baseline/migration-generator.js +554 -0
- package/dist/baseline/migrations.d.ts +60 -0
- package/dist/baseline/migrations.js +197 -0
- package/dist/baseline/performance-tracker.d.ts +214 -0
- package/dist/baseline/performance-tracker.js +577 -0
- package/dist/baseline/pr-comment-generator.d.ts +117 -0
- package/dist/baseline/pr-comment-generator.js +546 -0
- package/dist/baseline/response-fingerprint.d.ts +127 -0
- package/dist/baseline/response-fingerprint.js +728 -0
- package/dist/baseline/response-schema-tracker.d.ts +129 -0
- package/dist/baseline/response-schema-tracker.js +420 -0
- package/dist/baseline/risk-scorer.d.ts +54 -0
- package/dist/baseline/risk-scorer.js +434 -0
- package/dist/baseline/saver.d.ts +89 -0
- package/dist/baseline/saver.js +554 -0
- package/dist/baseline/scenario-generator.d.ts +151 -0
- package/dist/baseline/scenario-generator.js +905 -0
- package/dist/baseline/schema-compare.d.ts +86 -0
- package/dist/baseline/schema-compare.js +557 -0
- package/dist/baseline/schema-evolution.d.ts +189 -0
- package/dist/baseline/schema-evolution.js +467 -0
- package/dist/baseline/semantic.d.ts +203 -0
- package/dist/baseline/semantic.js +908 -0
- package/dist/baseline/synonyms.d.ts +60 -0
- package/dist/baseline/synonyms.js +386 -0
- package/dist/baseline/telemetry.d.ts +165 -0
- package/dist/baseline/telemetry.js +294 -0
- package/dist/baseline/test-pruner.d.ts +120 -0
- package/dist/baseline/test-pruner.js +387 -0
- package/dist/baseline/types.d.ts +449 -0
- package/dist/baseline/types.js +5 -0
- package/dist/baseline/version.d.ts +138 -0
- package/dist/baseline/version.js +206 -0
- package/dist/cache/index.d.ts +5 -0
- package/dist/cache/index.js +5 -0
- package/dist/cache/response-cache.d.ts +151 -0
- package/dist/cache/response-cache.js +287 -0
- package/dist/ci/index.d.ts +60 -0
- package/dist/ci/index.js +342 -0
- package/dist/cli/commands/auth.d.ts +12 -0
- package/dist/cli/commands/auth.js +352 -0
- package/dist/cli/commands/badge.d.ts +3 -0
- package/dist/cli/commands/badge.js +74 -0
- package/dist/cli/commands/baseline-accept.d.ts +15 -0
- package/dist/cli/commands/baseline-accept.js +178 -0
- package/dist/cli/commands/baseline-migrate.d.ts +12 -0
- package/dist/cli/commands/baseline-migrate.js +164 -0
- package/dist/cli/commands/baseline.d.ts +14 -0
- package/dist/cli/commands/baseline.js +449 -0
- package/dist/cli/commands/beta.d.ts +10 -0
- package/dist/cli/commands/beta.js +231 -0
- package/dist/cli/commands/check.d.ts +11 -0
- package/dist/cli/commands/check.js +820 -0
- package/dist/cli/commands/cloud/badge.d.ts +3 -0
- package/dist/cli/commands/cloud/badge.js +74 -0
- package/dist/cli/commands/cloud/diff.d.ts +6 -0
- package/dist/cli/commands/cloud/diff.js +79 -0
- package/dist/cli/commands/cloud/history.d.ts +6 -0
- package/dist/cli/commands/cloud/history.js +102 -0
- package/dist/cli/commands/cloud/link.d.ts +9 -0
- package/dist/cli/commands/cloud/link.js +119 -0
- package/dist/cli/commands/cloud/login.d.ts +7 -0
- package/dist/cli/commands/cloud/login.js +499 -0
- package/dist/cli/commands/cloud/projects.d.ts +6 -0
- package/dist/cli/commands/cloud/projects.js +44 -0
- package/dist/cli/commands/cloud/shared.d.ts +7 -0
- package/dist/cli/commands/cloud/shared.js +42 -0
- package/dist/cli/commands/cloud/teams.d.ts +8 -0
- package/dist/cli/commands/cloud/teams.js +169 -0
- package/dist/cli/commands/cloud/upload.d.ts +8 -0
- package/dist/cli/commands/cloud/upload.js +181 -0
- package/dist/cli/commands/contract.d.ts +11 -0
- package/dist/cli/commands/contract.js +280 -0
- package/dist/cli/commands/discover.d.ts +3 -0
- package/dist/cli/commands/discover.js +82 -0
- package/dist/cli/commands/eval.d.ts +9 -0
- package/dist/cli/commands/eval.js +187 -0
- package/dist/cli/commands/explore.d.ts +11 -0
- package/dist/cli/commands/explore.js +437 -0
- package/dist/cli/commands/feedback.d.ts +9 -0
- package/dist/cli/commands/feedback.js +174 -0
- package/dist/cli/commands/golden.d.ts +12 -0
- package/dist/cli/commands/golden.js +407 -0
- package/dist/cli/commands/history.d.ts +10 -0
- package/dist/cli/commands/history.js +202 -0
- package/dist/cli/commands/init.d.ts +9 -0
- package/dist/cli/commands/init.js +219 -0
- package/dist/cli/commands/interview.d.ts +3 -0
- package/dist/cli/commands/interview.js +903 -0
- package/dist/cli/commands/link.d.ts +10 -0
- package/dist/cli/commands/link.js +169 -0
- package/dist/cli/commands/login.d.ts +7 -0
- package/dist/cli/commands/login.js +499 -0
- package/dist/cli/commands/preset.d.ts +33 -0
- package/dist/cli/commands/preset.js +297 -0
- package/dist/cli/commands/profile.d.ts +33 -0
- package/dist/cli/commands/profile.js +286 -0
- package/dist/cli/commands/registry.d.ts +11 -0
- package/dist/cli/commands/registry.js +146 -0
- package/dist/cli/commands/shared.d.ts +79 -0
- package/dist/cli/commands/shared.js +196 -0
- package/dist/cli/commands/teams.d.ts +8 -0
- package/dist/cli/commands/teams.js +169 -0
- package/dist/cli/commands/test.d.ts +9 -0
- package/dist/cli/commands/test.js +500 -0
- package/dist/cli/commands/upload.d.ts +8 -0
- package/dist/cli/commands/upload.js +223 -0
- package/dist/cli/commands/validate-config.d.ts +6 -0
- package/dist/cli/commands/validate-config.js +35 -0
- package/dist/cli/commands/verify.d.ts +11 -0
- package/dist/cli/commands/verify.js +283 -0
- package/dist/cli/commands/watch.d.ts +12 -0
- package/dist/cli/commands/watch.js +253 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.js +178 -0
- package/dist/cli/interactive.d.ts +47 -0
- package/dist/cli/interactive.js +216 -0
- package/dist/cli/output/terminal-reporter.d.ts +19 -0
- package/dist/cli/output/terminal-reporter.js +104 -0
- package/dist/cli/output.d.ts +226 -0
- package/dist/cli/output.js +438 -0
- package/dist/cli/utils/env.d.ts +5 -0
- package/dist/cli/utils/env.js +14 -0
- package/dist/cli/utils/progress.d.ts +59 -0
- package/dist/cli/utils/progress.js +206 -0
- package/dist/cli/utils/server-context.d.ts +10 -0
- package/dist/cli/utils/server-context.js +36 -0
- package/dist/cloud/auth.d.ts +144 -0
- package/dist/cloud/auth.js +374 -0
- package/dist/cloud/client.d.ts +24 -0
- package/dist/cloud/client.js +65 -0
- package/dist/cloud/http-client.d.ts +38 -0
- package/dist/cloud/http-client.js +215 -0
- package/dist/cloud/index.d.ts +23 -0
- package/dist/cloud/index.js +25 -0
- package/dist/cloud/mock-client.d.ts +107 -0
- package/dist/cloud/mock-client.js +545 -0
- package/dist/cloud/types.d.ts +515 -0
- package/dist/cloud/types.js +15 -0
- package/dist/config/defaults.d.ts +160 -0
- package/dist/config/defaults.js +169 -0
- package/dist/config/loader.d.ts +24 -0
- package/dist/config/loader.js +122 -0
- package/dist/config/template.d.ts +42 -0
- package/dist/config/template.js +647 -0
- package/dist/config/validator.d.ts +2112 -0
- package/dist/config/validator.js +658 -0
- package/dist/constants/cloud.d.ts +107 -0
- package/dist/constants/cloud.js +110 -0
- package/dist/constants/core.d.ts +521 -0
- package/dist/constants/core.js +556 -0
- package/dist/constants/testing.d.ts +1283 -0
- package/dist/constants/testing.js +1568 -0
- package/dist/constants.d.ts +10 -0
- package/dist/constants.js +10 -0
- package/dist/contract/index.d.ts +6 -0
- package/dist/contract/index.js +5 -0
- package/dist/contract/validator.d.ts +177 -0
- package/dist/contract/validator.js +574 -0
- package/dist/cost/index.d.ts +6 -0
- package/dist/cost/index.js +5 -0
- package/dist/cost/tracker.d.ts +134 -0
- package/dist/cost/tracker.js +313 -0
- package/dist/discovery/discovery.d.ts +16 -0
- package/dist/discovery/discovery.js +173 -0
- package/dist/discovery/types.d.ts +51 -0
- package/dist/discovery/types.js +2 -0
- package/dist/docs/agents.d.ts +3 -0
- package/dist/docs/agents.js +995 -0
- package/dist/docs/contract.d.ts +51 -0
- package/dist/docs/contract.js +1681 -0
- package/dist/docs/generator.d.ts +4 -0
- package/dist/docs/generator.js +4 -0
- package/dist/docs/html-reporter.d.ts +9 -0
- package/dist/docs/html-reporter.js +757 -0
- package/dist/docs/index.d.ts +10 -0
- package/dist/docs/index.js +11 -0
- package/dist/docs/junit-reporter.d.ts +18 -0
- package/dist/docs/junit-reporter.js +210 -0
- package/dist/docs/report.d.ts +14 -0
- package/dist/docs/report.js +44 -0
- package/dist/docs/sarif-reporter.d.ts +19 -0
- package/dist/docs/sarif-reporter.js +335 -0
- package/dist/docs/shared.d.ts +35 -0
- package/dist/docs/shared.js +162 -0
- package/dist/docs/templates.d.ts +12 -0
- package/dist/docs/templates.js +76 -0
- package/dist/errors/index.d.ts +6 -0
- package/dist/errors/index.js +6 -0
- package/dist/errors/retry.d.ts +92 -0
- package/dist/errors/retry.js +323 -0
- package/dist/errors/types.d.ts +321 -0
- package/dist/errors/types.js +584 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.js +32 -0
- package/dist/interview/dependency-resolver.d.ts +11 -0
- package/dist/interview/dependency-resolver.js +32 -0
- package/dist/interview/interviewer.d.ts +232 -0
- package/dist/interview/interviewer.js +1939 -0
- package/dist/interview/mock-response-generator.d.ts +7 -0
- package/dist/interview/mock-response-generator.js +102 -0
- package/dist/interview/orchestrator.d.ts +237 -0
- package/dist/interview/orchestrator.js +1296 -0
- package/dist/interview/rate-limiter.d.ts +15 -0
- package/dist/interview/rate-limiter.js +55 -0
- package/dist/interview/response-validator.d.ts +10 -0
- package/dist/interview/response-validator.js +132 -0
- package/dist/interview/schema-inferrer.d.ts +8 -0
- package/dist/interview/schema-inferrer.js +71 -0
- package/dist/interview/schema-test-generator.d.ts +71 -0
- package/dist/interview/schema-test-generator.js +834 -0
- package/dist/interview/smart-value-generator.d.ts +155 -0
- package/dist/interview/smart-value-generator.js +554 -0
- package/dist/interview/stateful-test-runner.d.ts +19 -0
- package/dist/interview/stateful-test-runner.js +106 -0
- package/dist/interview/types.d.ts +561 -0
- package/dist/interview/types.js +2 -0
- package/dist/llm/anthropic.d.ts +41 -0
- package/dist/llm/anthropic.js +355 -0
- package/dist/llm/client.d.ts +123 -0
- package/dist/llm/client.js +42 -0
- package/dist/llm/factory.d.ts +38 -0
- package/dist/llm/factory.js +145 -0
- package/dist/llm/fallback.d.ts +140 -0
- package/dist/llm/fallback.js +379 -0
- package/dist/llm/index.d.ts +18 -0
- package/dist/llm/index.js +15 -0
- package/dist/llm/ollama.d.ts +37 -0
- package/dist/llm/ollama.js +330 -0
- package/dist/llm/openai.d.ts +25 -0
- package/dist/llm/openai.js +320 -0
- package/dist/llm/token-budget.d.ts +161 -0
- package/dist/llm/token-budget.js +395 -0
- package/dist/logging/logger.d.ts +70 -0
- package/dist/logging/logger.js +130 -0
- package/dist/metrics/collector.d.ts +106 -0
- package/dist/metrics/collector.js +547 -0
- package/dist/metrics/index.d.ts +7 -0
- package/dist/metrics/index.js +7 -0
- package/dist/metrics/prometheus.d.ts +20 -0
- package/dist/metrics/prometheus.js +241 -0
- package/dist/metrics/types.d.ts +209 -0
- package/dist/metrics/types.js +5 -0
- package/dist/persona/builtins.d.ts +54 -0
- package/dist/persona/builtins.js +219 -0
- package/dist/persona/index.d.ts +8 -0
- package/dist/persona/index.js +8 -0
- package/dist/persona/loader.d.ts +30 -0
- package/dist/persona/loader.js +190 -0
- package/dist/persona/types.d.ts +144 -0
- package/dist/persona/types.js +5 -0
- package/dist/persona/validation.d.ts +94 -0
- package/dist/persona/validation.js +332 -0
- package/dist/prompts/index.d.ts +5 -0
- package/dist/prompts/index.js +5 -0
- package/dist/prompts/templates.d.ts +180 -0
- package/dist/prompts/templates.js +431 -0
- package/dist/registry/client.d.ts +49 -0
- package/dist/registry/client.js +191 -0
- package/dist/registry/index.d.ts +7 -0
- package/dist/registry/index.js +6 -0
- package/dist/registry/types.d.ts +140 -0
- package/dist/registry/types.js +6 -0
- package/dist/scenarios/evaluator.d.ts +43 -0
- package/dist/scenarios/evaluator.js +206 -0
- package/dist/scenarios/index.d.ts +10 -0
- package/dist/scenarios/index.js +9 -0
- package/dist/scenarios/loader.d.ts +20 -0
- package/dist/scenarios/loader.js +285 -0
- package/dist/scenarios/types.d.ts +153 -0
- package/dist/scenarios/types.js +8 -0
- package/dist/security/index.d.ts +17 -0
- package/dist/security/index.js +18 -0
- package/dist/security/payloads.d.ts +61 -0
- package/dist/security/payloads.js +268 -0
- package/dist/security/security-tester.d.ts +42 -0
- package/dist/security/security-tester.js +582 -0
- package/dist/security/types.d.ts +166 -0
- package/dist/security/types.js +8 -0
- package/dist/transport/base-transport.d.ts +59 -0
- package/dist/transport/base-transport.js +38 -0
- package/dist/transport/http-transport.d.ts +67 -0
- package/dist/transport/http-transport.js +238 -0
- package/dist/transport/mcp-client.d.ts +141 -0
- package/dist/transport/mcp-client.js +496 -0
- package/dist/transport/sse-transport.d.ts +88 -0
- package/dist/transport/sse-transport.js +316 -0
- package/dist/transport/stdio-transport.d.ts +43 -0
- package/dist/transport/stdio-transport.js +238 -0
- package/dist/transport/types.d.ts +125 -0
- package/dist/transport/types.js +16 -0
- package/dist/utils/concurrency.d.ts +123 -0
- package/dist/utils/concurrency.js +213 -0
- package/dist/utils/formatters.d.ts +16 -0
- package/dist/utils/formatters.js +37 -0
- package/dist/utils/index.d.ts +8 -0
- package/dist/utils/index.js +8 -0
- package/dist/utils/jsonpath.d.ts +87 -0
- package/dist/utils/jsonpath.js +326 -0
- package/dist/utils/markdown.d.ts +113 -0
- package/dist/utils/markdown.js +265 -0
- package/dist/utils/network.d.ts +14 -0
- package/dist/utils/network.js +17 -0
- package/dist/utils/sanitize.d.ts +92 -0
- package/dist/utils/sanitize.js +191 -0
- package/dist/utils/semantic.d.ts +194 -0
- package/dist/utils/semantic.js +1051 -0
- package/dist/utils/smart-truncate.d.ts +94 -0
- package/dist/utils/smart-truncate.js +361 -0
- package/dist/utils/timeout.d.ts +153 -0
- package/dist/utils/timeout.js +205 -0
- package/dist/utils/yaml-parser.d.ts +58 -0
- package/dist/utils/yaml-parser.js +86 -0
- package/dist/validation/index.d.ts +32 -0
- package/dist/validation/index.js +32 -0
- package/dist/validation/semantic-test-generator.d.ts +50 -0
- package/dist/validation/semantic-test-generator.js +176 -0
- package/dist/validation/semantic-types.d.ts +66 -0
- package/dist/validation/semantic-types.js +94 -0
- package/dist/validation/semantic-validator.d.ts +38 -0
- package/dist/validation/semantic-validator.js +340 -0
- package/dist/verification/index.d.ts +6 -0
- package/dist/verification/index.js +5 -0
- package/dist/verification/types.d.ts +133 -0
- package/dist/verification/types.js +5 -0
- package/dist/verification/verifier.d.ts +30 -0
- package/dist/verification/verifier.js +309 -0
- package/dist/version.d.ts +19 -0
- package/dist/version.js +48 -0
- package/dist/workflow/auto-generator.d.ts +27 -0
- package/dist/workflow/auto-generator.js +513 -0
- package/dist/workflow/discovery.d.ts +40 -0
- package/dist/workflow/discovery.js +195 -0
- package/dist/workflow/executor.d.ts +82 -0
- package/dist/workflow/executor.js +611 -0
- package/dist/workflow/index.d.ts +10 -0
- package/dist/workflow/index.js +10 -0
- package/dist/workflow/loader.d.ts +24 -0
- package/dist/workflow/loader.js +194 -0
- package/dist/workflow/state-tracker.d.ts +98 -0
- package/dist/workflow/state-tracker.js +424 -0
- package/dist/workflow/types.d.ts +337 -0
- package/dist/workflow/types.js +5 -0
- package/package.json +94 -0
- package/schemas/bellwether-check.schema.json +651 -0
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JSONPath parsing utilities.
|
|
3
|
+
*
|
|
4
|
+
* Supports a subset of JSONPath syntax for accessing nested values:
|
|
5
|
+
* - Dot notation: "foo.bar.baz"
|
|
6
|
+
* - Bracket notation: "foo['bar']" or "foo[\"bar\"]"
|
|
7
|
+
* - Array indices: "items[0]" or "items['0']"
|
|
8
|
+
* - Mixed: "foo.items[0].bar"
|
|
9
|
+
* - Escaped characters: "foo['bar.baz']" for keys containing dots
|
|
10
|
+
* - Special characters: "foo['key with spaces']" or "foo['key\"with\"quotes']"
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Parse a JSONPath expression into segments.
|
|
14
|
+
*
|
|
15
|
+
* @param path - The JSONPath expression to parse
|
|
16
|
+
* @returns ParseResult with segments or error
|
|
17
|
+
*/
|
|
18
|
+
export function parsePath(path) {
|
|
19
|
+
if (!path || path.length === 0) {
|
|
20
|
+
return { segments: [], error: 'Empty path' };
|
|
21
|
+
}
|
|
22
|
+
const segments = [];
|
|
23
|
+
let i = 0;
|
|
24
|
+
// Handle optional root ($)
|
|
25
|
+
if (path[0] === '$') {
|
|
26
|
+
i++;
|
|
27
|
+
// Skip optional leading dot after $
|
|
28
|
+
if (path[i] === '.') {
|
|
29
|
+
i++;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
while (i < path.length) {
|
|
33
|
+
// Skip leading dot (for dot notation)
|
|
34
|
+
if (path[i] === '.') {
|
|
35
|
+
i++;
|
|
36
|
+
if (i >= path.length) {
|
|
37
|
+
return { segments, error: 'Unexpected end after dot' };
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
// Handle bracket notation
|
|
41
|
+
if (path[i] === '[') {
|
|
42
|
+
const result = parseBracket(path, i);
|
|
43
|
+
if (result.error) {
|
|
44
|
+
return { segments, error: result.error };
|
|
45
|
+
}
|
|
46
|
+
segments.push(result.segment);
|
|
47
|
+
i = result.endIndex;
|
|
48
|
+
}
|
|
49
|
+
// Handle property name (dot notation)
|
|
50
|
+
else {
|
|
51
|
+
const result = parseProperty(path, i);
|
|
52
|
+
if (result.error) {
|
|
53
|
+
return { segments, error: result.error };
|
|
54
|
+
}
|
|
55
|
+
segments.push(result.segment);
|
|
56
|
+
i = result.endIndex;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return { segments };
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Parse a bracket expression starting at the given index.
|
|
63
|
+
*/
|
|
64
|
+
function parseBracket(path, start) {
|
|
65
|
+
// Skip the opening bracket
|
|
66
|
+
let i = start + 1;
|
|
67
|
+
// Skip whitespace
|
|
68
|
+
while (i < path.length && isWhitespace(path[i])) {
|
|
69
|
+
i++;
|
|
70
|
+
}
|
|
71
|
+
if (i >= path.length) {
|
|
72
|
+
return { endIndex: i, error: 'Unexpected end in bracket expression' };
|
|
73
|
+
}
|
|
74
|
+
// Check for string literal (single or double quotes)
|
|
75
|
+
if (path[i] === "'" || path[i] === '"') {
|
|
76
|
+
const quote = path[i];
|
|
77
|
+
i++;
|
|
78
|
+
let value = '';
|
|
79
|
+
while (i < path.length && path[i] !== quote) {
|
|
80
|
+
// Handle escape sequences
|
|
81
|
+
if (path[i] === '\\' && i + 1 < path.length) {
|
|
82
|
+
const next = path[i + 1];
|
|
83
|
+
if (next === quote || next === '\\') {
|
|
84
|
+
value += next;
|
|
85
|
+
i += 2;
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
// Handle common escape sequences
|
|
89
|
+
if (next === 'n') {
|
|
90
|
+
value += '\n';
|
|
91
|
+
i += 2;
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
if (next === 't') {
|
|
95
|
+
value += '\t';
|
|
96
|
+
i += 2;
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
if (next === 'r') {
|
|
100
|
+
value += '\r';
|
|
101
|
+
i += 2;
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
value += path[i];
|
|
106
|
+
i++;
|
|
107
|
+
}
|
|
108
|
+
if (i >= path.length) {
|
|
109
|
+
return { endIndex: i, error: `Unterminated string in bracket expression` };
|
|
110
|
+
}
|
|
111
|
+
// Skip the closing quote
|
|
112
|
+
i++;
|
|
113
|
+
// Skip whitespace before closing bracket
|
|
114
|
+
while (i < path.length && isWhitespace(path[i])) {
|
|
115
|
+
i++;
|
|
116
|
+
}
|
|
117
|
+
if (i >= path.length || path[i] !== ']') {
|
|
118
|
+
return { endIndex: i, error: 'Expected closing bracket' };
|
|
119
|
+
}
|
|
120
|
+
// Skip the closing bracket
|
|
121
|
+
i++;
|
|
122
|
+
return {
|
|
123
|
+
segment: { type: 'bracket_property', value },
|
|
124
|
+
endIndex: i,
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
// Check for numeric index
|
|
128
|
+
let numStr = '';
|
|
129
|
+
while (i < path.length && isDigit(path[i])) {
|
|
130
|
+
numStr += path[i];
|
|
131
|
+
i++;
|
|
132
|
+
}
|
|
133
|
+
if (numStr.length > 0) {
|
|
134
|
+
// Skip whitespace before closing bracket
|
|
135
|
+
while (i < path.length && isWhitespace(path[i])) {
|
|
136
|
+
i++;
|
|
137
|
+
}
|
|
138
|
+
if (i >= path.length || path[i] !== ']') {
|
|
139
|
+
return { endIndex: i, error: 'Expected closing bracket after index' };
|
|
140
|
+
}
|
|
141
|
+
// Skip the closing bracket
|
|
142
|
+
i++;
|
|
143
|
+
return {
|
|
144
|
+
segment: { type: 'index', value: parseInt(numStr, 10) },
|
|
145
|
+
endIndex: i,
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
// Invalid bracket content
|
|
149
|
+
return { endIndex: i, error: 'Invalid bracket expression: expected string or number' };
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Parse a property name in dot notation starting at the given index.
|
|
153
|
+
*/
|
|
154
|
+
function parseProperty(path, start) {
|
|
155
|
+
let i = start;
|
|
156
|
+
let name = '';
|
|
157
|
+
// Property names can contain alphanumeric, underscore, hyphen, and dollar sign
|
|
158
|
+
// They cannot start with a digit
|
|
159
|
+
while (i < path.length && isPropertyChar(path[i])) {
|
|
160
|
+
name += path[i];
|
|
161
|
+
i++;
|
|
162
|
+
}
|
|
163
|
+
if (name.length === 0) {
|
|
164
|
+
return {
|
|
165
|
+
endIndex: i,
|
|
166
|
+
error: `Invalid character at position ${start}: ${path[start]}`,
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
return {
|
|
170
|
+
segment: { type: 'property', value: name },
|
|
171
|
+
endIndex: i,
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Check if a character is a valid property name character.
|
|
176
|
+
*/
|
|
177
|
+
function isPropertyChar(char) {
|
|
178
|
+
const code = char.charCodeAt(0);
|
|
179
|
+
// alphanumeric, underscore, dollar sign, hyphen
|
|
180
|
+
return ((code >= 65 && code <= 90) || // A-Z
|
|
181
|
+
(code >= 97 && code <= 122) || // a-z
|
|
182
|
+
(code >= 48 && code <= 57) || // 0-9
|
|
183
|
+
code === 95 || // _
|
|
184
|
+
code === 36 || // $
|
|
185
|
+
code === 45 // -
|
|
186
|
+
);
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Check if a character is a digit.
|
|
190
|
+
*/
|
|
191
|
+
function isDigit(char) {
|
|
192
|
+
const code = char.charCodeAt(0);
|
|
193
|
+
return code >= 48 && code <= 57;
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Check if a character is whitespace.
|
|
197
|
+
*/
|
|
198
|
+
function isWhitespace(char) {
|
|
199
|
+
return char === ' ' || char === '\t' || char === '\n' || char === '\r';
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Get a value from an object using a parsed path.
|
|
203
|
+
*
|
|
204
|
+
* @param obj - The object to access
|
|
205
|
+
* @param segments - The parsed path segments
|
|
206
|
+
* @returns The value at the path, or undefined if not found
|
|
207
|
+
*/
|
|
208
|
+
export function getValueBySegments(obj, segments) {
|
|
209
|
+
let current = obj;
|
|
210
|
+
for (const segment of segments) {
|
|
211
|
+
if (current === null || current === undefined) {
|
|
212
|
+
return undefined;
|
|
213
|
+
}
|
|
214
|
+
if (typeof current !== 'object') {
|
|
215
|
+
return undefined;
|
|
216
|
+
}
|
|
217
|
+
if (segment.type === 'index') {
|
|
218
|
+
if (!Array.isArray(current)) {
|
|
219
|
+
return undefined;
|
|
220
|
+
}
|
|
221
|
+
current = current[segment.value];
|
|
222
|
+
}
|
|
223
|
+
else {
|
|
224
|
+
// Both 'property' and 'bracket_property' access object keys
|
|
225
|
+
current = current[segment.value];
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
return current;
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Get a value from an object using a JSONPath expression.
|
|
232
|
+
*
|
|
233
|
+
* This is the main API function combining parsing and value retrieval.
|
|
234
|
+
*
|
|
235
|
+
* @param obj - The object to access
|
|
236
|
+
* @param path - The JSONPath expression
|
|
237
|
+
* @returns The value at the path, or undefined if not found or path is invalid
|
|
238
|
+
*
|
|
239
|
+
* @example
|
|
240
|
+
* // Simple paths
|
|
241
|
+
* getValueAtPath({ a: { b: 1 } }, 'a.b') // => 1
|
|
242
|
+
*
|
|
243
|
+
* @example
|
|
244
|
+
* // Array access
|
|
245
|
+
* getValueAtPath({ items: [1, 2, 3] }, 'items[1]') // => 2
|
|
246
|
+
*
|
|
247
|
+
* @example
|
|
248
|
+
* // Keys with dots
|
|
249
|
+
* getValueAtPath({ 'key.with.dots': 42 }, "['key.with.dots']") // => 42
|
|
250
|
+
*
|
|
251
|
+
* @example
|
|
252
|
+
* // Keys with spaces
|
|
253
|
+
* getValueAtPath({ 'my key': 'value' }, "['my key']") // => 'value'
|
|
254
|
+
*/
|
|
255
|
+
export function getValueAtPath(obj, path) {
|
|
256
|
+
if (!path || typeof obj !== 'object' || obj === null) {
|
|
257
|
+
return undefined;
|
|
258
|
+
}
|
|
259
|
+
const parseResult = parsePath(path);
|
|
260
|
+
if (parseResult.error) {
|
|
261
|
+
return undefined;
|
|
262
|
+
}
|
|
263
|
+
return getValueBySegments(obj, parseResult.segments);
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Check if a path is valid JSONPath syntax.
|
|
267
|
+
*
|
|
268
|
+
* @param path - The path to validate
|
|
269
|
+
* @returns True if the path is valid, false otherwise
|
|
270
|
+
*/
|
|
271
|
+
export function isValidPath(path) {
|
|
272
|
+
const result = parsePath(path);
|
|
273
|
+
return !result.error;
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Convert a JSONPath expression to a normalized form.
|
|
277
|
+
* Useful for comparing paths that may use different notations.
|
|
278
|
+
*
|
|
279
|
+
* @param path - The path to normalize
|
|
280
|
+
* @returns Normalized path string, or the original if parsing fails
|
|
281
|
+
*/
|
|
282
|
+
export function normalizePath(path) {
|
|
283
|
+
const result = parsePath(path);
|
|
284
|
+
if (result.error) {
|
|
285
|
+
return path;
|
|
286
|
+
}
|
|
287
|
+
return result.segments
|
|
288
|
+
.map((seg) => {
|
|
289
|
+
if (seg.type === 'index') {
|
|
290
|
+
return `[${seg.value}]`;
|
|
291
|
+
}
|
|
292
|
+
// Use bracket notation for properties with special characters
|
|
293
|
+
const value = seg.value;
|
|
294
|
+
if (needsBracketNotation(value)) {
|
|
295
|
+
return `['${escapeString(value)}']`;
|
|
296
|
+
}
|
|
297
|
+
return `.${value}`;
|
|
298
|
+
})
|
|
299
|
+
.join('')
|
|
300
|
+
.replace(/^\./, ''); // Remove leading dot
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* Check if a property name needs bracket notation.
|
|
304
|
+
*/
|
|
305
|
+
function needsBracketNotation(name) {
|
|
306
|
+
if (name.length === 0)
|
|
307
|
+
return true;
|
|
308
|
+
// Check first character (can't be a digit)
|
|
309
|
+
const first = name.charCodeAt(0);
|
|
310
|
+
if (first >= 48 && first <= 57)
|
|
311
|
+
return true;
|
|
312
|
+
// Check all characters
|
|
313
|
+
for (let i = 0; i < name.length; i++) {
|
|
314
|
+
if (!isPropertyChar(name[i])) {
|
|
315
|
+
return true;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
return false;
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* Escape a string for use in bracket notation.
|
|
322
|
+
*/
|
|
323
|
+
function escapeString(str) {
|
|
324
|
+
return str.replace(/\\/g, '\\\\').replace(/'/g, "\\'");
|
|
325
|
+
}
|
|
326
|
+
//# sourceMappingURL=jsonpath.js.map
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Markdown output escaping utilities.
|
|
3
|
+
*
|
|
4
|
+
* Provides functions to safely escape content for Markdown output,
|
|
5
|
+
* including tables, code blocks, and Mermaid diagrams.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Escape a string for use in a Markdown table cell.
|
|
9
|
+
* Handles pipe characters and other special characters that break table structure.
|
|
10
|
+
*
|
|
11
|
+
* @param text - The text to escape
|
|
12
|
+
* @returns Escaped text safe for table cells
|
|
13
|
+
*/
|
|
14
|
+
export declare function escapeTableCell(text: string): string;
|
|
15
|
+
/**
|
|
16
|
+
* Escape a string for use inside a code block.
|
|
17
|
+
* Handles backticks that would prematurely close the code block.
|
|
18
|
+
*
|
|
19
|
+
* @param text - The text to escape
|
|
20
|
+
* @returns Escaped text safe for code blocks
|
|
21
|
+
*/
|
|
22
|
+
export declare function escapeCodeBlock(text: string): string;
|
|
23
|
+
/**
|
|
24
|
+
* Escape a string for use in a Mermaid diagram.
|
|
25
|
+
* Handles quotes, brackets, and other special characters.
|
|
26
|
+
*
|
|
27
|
+
* @param text - The text to escape
|
|
28
|
+
* @returns Escaped text safe for Mermaid
|
|
29
|
+
*/
|
|
30
|
+
export declare function escapeMermaid(text: string): string;
|
|
31
|
+
/**
|
|
32
|
+
* Escape a string for use as a Mermaid node label.
|
|
33
|
+
* Wraps in quotes and escapes special characters.
|
|
34
|
+
*
|
|
35
|
+
* @param text - The text to use as a label
|
|
36
|
+
* @returns Safe Mermaid node label
|
|
37
|
+
*/
|
|
38
|
+
export declare function mermaidLabel(text: string): string;
|
|
39
|
+
/**
|
|
40
|
+
* Options for JSON code block validation.
|
|
41
|
+
*/
|
|
42
|
+
export interface JsonCodeBlockOptions {
|
|
43
|
+
/** Maximum length before truncating (default: unlimited) */
|
|
44
|
+
maxLength?: number;
|
|
45
|
+
/** Truncation indicator (default: '...(truncated)') */
|
|
46
|
+
truncationIndicator?: string;
|
|
47
|
+
/** Whether to pretty-print the JSON (default: true) */
|
|
48
|
+
prettyPrint?: boolean;
|
|
49
|
+
/** Indentation for pretty-printing (default: 2) */
|
|
50
|
+
indent?: number;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Result of validating JSON for a code block.
|
|
54
|
+
*/
|
|
55
|
+
export interface JsonCodeBlockResult {
|
|
56
|
+
/** Whether the JSON is valid */
|
|
57
|
+
valid: boolean;
|
|
58
|
+
/** The formatted JSON string (or original if invalid) */
|
|
59
|
+
content: string;
|
|
60
|
+
/** Whether the content was truncated */
|
|
61
|
+
truncated: boolean;
|
|
62
|
+
/** Error message if JSON is invalid */
|
|
63
|
+
error?: string;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Validate and format JSON for output in a code block.
|
|
67
|
+
* Returns safe content even if JSON is invalid.
|
|
68
|
+
*
|
|
69
|
+
* @param json - The JSON string or object to validate
|
|
70
|
+
* @param options - Formatting options
|
|
71
|
+
* @returns Validation result with safe content
|
|
72
|
+
*/
|
|
73
|
+
export declare function validateJsonForCodeBlock(json: string | unknown, options?: JsonCodeBlockOptions): JsonCodeBlockResult;
|
|
74
|
+
/**
|
|
75
|
+
* Escape special characters in inline code.
|
|
76
|
+
*
|
|
77
|
+
* @param text - The text to escape
|
|
78
|
+
* @returns Escaped text safe for inline code
|
|
79
|
+
*/
|
|
80
|
+
export declare function escapeInlineCode(text: string): string;
|
|
81
|
+
/**
|
|
82
|
+
* Escape text for use in a Markdown link title.
|
|
83
|
+
*
|
|
84
|
+
* @param text - The text to escape
|
|
85
|
+
* @returns Escaped text safe for link titles
|
|
86
|
+
*/
|
|
87
|
+
export declare function escapeLinkTitle(text: string): string;
|
|
88
|
+
/**
|
|
89
|
+
* Escape text for use in a Markdown bullet list item.
|
|
90
|
+
*
|
|
91
|
+
* @param text - The text to escape
|
|
92
|
+
* @returns Escaped text safe for list items
|
|
93
|
+
*/
|
|
94
|
+
export declare function escapeListItem(text: string): string;
|
|
95
|
+
/**
|
|
96
|
+
* Wrap text to ensure it fits within table cell width constraints.
|
|
97
|
+
*
|
|
98
|
+
* @param text - The text to wrap
|
|
99
|
+
* @param maxWidth - Maximum width (default: 50)
|
|
100
|
+
* @returns Wrapped text with <br> for line breaks
|
|
101
|
+
*/
|
|
102
|
+
export declare function wrapTableCell(text: string, maxWidth?: number): string;
|
|
103
|
+
/**
|
|
104
|
+
* Build a Markdown table from headers and rows.
|
|
105
|
+
* Automatically escapes cell content.
|
|
106
|
+
*
|
|
107
|
+
* @param headers - Array of header strings
|
|
108
|
+
* @param rows - 2D array of cell values
|
|
109
|
+
* @param alignments - Optional array of column alignments ('left', 'center', 'right')
|
|
110
|
+
* @returns Complete Markdown table string
|
|
111
|
+
*/
|
|
112
|
+
export declare function buildTable(headers: string[], rows: string[][], alignments?: Array<'left' | 'center' | 'right'>): string;
|
|
113
|
+
//# sourceMappingURL=markdown.d.ts.map
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Markdown output escaping utilities.
|
|
3
|
+
*
|
|
4
|
+
* Provides functions to safely escape content for Markdown output,
|
|
5
|
+
* including tables, code blocks, and Mermaid diagrams.
|
|
6
|
+
*/
|
|
7
|
+
import { DISPLAY_LIMITS } from '../constants.js';
|
|
8
|
+
/**
|
|
9
|
+
* Escape a string for use in a Markdown table cell.
|
|
10
|
+
* Handles pipe characters and other special characters that break table structure.
|
|
11
|
+
*
|
|
12
|
+
* @param text - The text to escape
|
|
13
|
+
* @returns Escaped text safe for table cells
|
|
14
|
+
*/
|
|
15
|
+
export function escapeTableCell(text) {
|
|
16
|
+
if (!text)
|
|
17
|
+
return '';
|
|
18
|
+
return text
|
|
19
|
+
// Escape pipe characters (break table columns)
|
|
20
|
+
.replace(/\|/g, '\\|')
|
|
21
|
+
// Escape newlines (break table rows)
|
|
22
|
+
.replace(/\r?\n/g, '<br>')
|
|
23
|
+
// Escape leading/trailing whitespace that might affect rendering
|
|
24
|
+
.trim();
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Escape a string for use inside a code block.
|
|
28
|
+
* Handles backticks that would prematurely close the code block.
|
|
29
|
+
*
|
|
30
|
+
* @param text - The text to escape
|
|
31
|
+
* @returns Escaped text safe for code blocks
|
|
32
|
+
*/
|
|
33
|
+
export function escapeCodeBlock(text) {
|
|
34
|
+
if (!text)
|
|
35
|
+
return '';
|
|
36
|
+
// Replace triple backticks with escaped version
|
|
37
|
+
// Use Unicode zero-width space to break the sequence
|
|
38
|
+
return text.replace(/```/g, '`\u200B`\u200B`');
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Escape a string for use in a Mermaid diagram.
|
|
42
|
+
* Handles quotes, brackets, and other special characters.
|
|
43
|
+
*
|
|
44
|
+
* @param text - The text to escape
|
|
45
|
+
* @returns Escaped text safe for Mermaid
|
|
46
|
+
*/
|
|
47
|
+
export function escapeMermaid(text) {
|
|
48
|
+
if (!text)
|
|
49
|
+
return '';
|
|
50
|
+
return text
|
|
51
|
+
// Escape double quotes (break Mermaid string literals)
|
|
52
|
+
.replace(/"/g, '#quot;')
|
|
53
|
+
// Escape square brackets (node syntax)
|
|
54
|
+
.replace(/\[/g, '#lsqb;')
|
|
55
|
+
.replace(/\]/g, '#rsqb;')
|
|
56
|
+
// Escape parentheses (node syntax)
|
|
57
|
+
.replace(/\(/g, '#lpar;')
|
|
58
|
+
.replace(/\)/g, '#rpar;')
|
|
59
|
+
// Escape curly braces (subgraph syntax)
|
|
60
|
+
.replace(/\{/g, '#lcub;')
|
|
61
|
+
.replace(/\}/g, '#rcub;')
|
|
62
|
+
// Escape arrows and pipes
|
|
63
|
+
.replace(/-->/g, '#arrow;')
|
|
64
|
+
.replace(/->/g, '#rarr;')
|
|
65
|
+
.replace(/\|/g, '#pipe;')
|
|
66
|
+
// Escape newlines
|
|
67
|
+
.replace(/\r?\n/g, ' ');
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Escape a string for use as a Mermaid node label.
|
|
71
|
+
* Wraps in quotes and escapes special characters.
|
|
72
|
+
*
|
|
73
|
+
* @param text - The text to use as a label
|
|
74
|
+
* @returns Safe Mermaid node label
|
|
75
|
+
*/
|
|
76
|
+
export function mermaidLabel(text) {
|
|
77
|
+
if (!text)
|
|
78
|
+
return '""';
|
|
79
|
+
// For simple alphanumeric text, no escaping needed
|
|
80
|
+
if (/^[a-zA-Z0-9_-]+$/.test(text)) {
|
|
81
|
+
return text;
|
|
82
|
+
}
|
|
83
|
+
// Escape and wrap in quotes for complex text
|
|
84
|
+
const escaped = text
|
|
85
|
+
.replace(/"/g, "'")
|
|
86
|
+
.replace(/\r?\n/g, ' ')
|
|
87
|
+
.trim();
|
|
88
|
+
return `"${escaped}"`;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Validate and format JSON for output in a code block.
|
|
92
|
+
* Returns safe content even if JSON is invalid.
|
|
93
|
+
*
|
|
94
|
+
* @param json - The JSON string or object to validate
|
|
95
|
+
* @param options - Formatting options
|
|
96
|
+
* @returns Validation result with safe content
|
|
97
|
+
*/
|
|
98
|
+
export function validateJsonForCodeBlock(json, options = {}) {
|
|
99
|
+
const { maxLength, truncationIndicator = '...(truncated)', prettyPrint = true, indent = 2, } = options;
|
|
100
|
+
let content;
|
|
101
|
+
let valid = true;
|
|
102
|
+
let error;
|
|
103
|
+
// Parse if string, stringify if object
|
|
104
|
+
if (typeof json === 'string') {
|
|
105
|
+
try {
|
|
106
|
+
const parsed = JSON.parse(json);
|
|
107
|
+
content = prettyPrint
|
|
108
|
+
? JSON.stringify(parsed, null, indent)
|
|
109
|
+
: JSON.stringify(parsed);
|
|
110
|
+
}
|
|
111
|
+
catch (e) {
|
|
112
|
+
valid = false;
|
|
113
|
+
error = e instanceof Error ? e.message : 'Invalid JSON';
|
|
114
|
+
content = escapeCodeBlock(json);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
try {
|
|
119
|
+
content = prettyPrint
|
|
120
|
+
? JSON.stringify(json, null, indent)
|
|
121
|
+
: JSON.stringify(json);
|
|
122
|
+
}
|
|
123
|
+
catch (e) {
|
|
124
|
+
valid = false;
|
|
125
|
+
error = e instanceof Error ? e.message : 'Cannot stringify value';
|
|
126
|
+
content = String(json);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
// Truncate if needed
|
|
130
|
+
let truncated = false;
|
|
131
|
+
if (maxLength && content.length > maxLength) {
|
|
132
|
+
content = content.substring(0, maxLength) + '\n' + truncationIndicator;
|
|
133
|
+
truncated = true;
|
|
134
|
+
}
|
|
135
|
+
// Escape any backticks that might break the code block
|
|
136
|
+
content = escapeCodeBlock(content);
|
|
137
|
+
return { valid, content, truncated, error };
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Escape special characters in inline code.
|
|
141
|
+
*
|
|
142
|
+
* @param text - The text to escape
|
|
143
|
+
* @returns Escaped text safe for inline code
|
|
144
|
+
*/
|
|
145
|
+
export function escapeInlineCode(text) {
|
|
146
|
+
// Empty string returns double backticks (minimal valid inline code)
|
|
147
|
+
if (!text)
|
|
148
|
+
return '``';
|
|
149
|
+
// Single backticks can be escaped by using double backticks
|
|
150
|
+
if (text.includes('`')) {
|
|
151
|
+
// If text contains backticks, wrap with double backticks and padding spaces.
|
|
152
|
+
// Spaces are always added for clarity and to handle edge cases where
|
|
153
|
+
// text starts/ends with backticks (CommonMark strips one padding space each side).
|
|
154
|
+
return `\`\` ${text} \`\``;
|
|
155
|
+
}
|
|
156
|
+
return `\`${text}\``;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Escape text for use in a Markdown link title.
|
|
160
|
+
*
|
|
161
|
+
* @param text - The text to escape
|
|
162
|
+
* @returns Escaped text safe for link titles
|
|
163
|
+
*/
|
|
164
|
+
export function escapeLinkTitle(text) {
|
|
165
|
+
if (!text)
|
|
166
|
+
return '';
|
|
167
|
+
return text
|
|
168
|
+
// Escape quotes
|
|
169
|
+
.replace(/"/g, '\\"')
|
|
170
|
+
// Escape parentheses
|
|
171
|
+
.replace(/\)/g, '\\)')
|
|
172
|
+
.replace(/\(/g, '\\(');
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Escape text for use in a Markdown bullet list item.
|
|
176
|
+
*
|
|
177
|
+
* @param text - The text to escape
|
|
178
|
+
* @returns Escaped text safe for list items
|
|
179
|
+
*/
|
|
180
|
+
export function escapeListItem(text) {
|
|
181
|
+
if (!text)
|
|
182
|
+
return '';
|
|
183
|
+
// Handle leading characters that could be interpreted as list markers
|
|
184
|
+
let escaped = text;
|
|
185
|
+
// Leading dash, asterisk, plus (unordered list)
|
|
186
|
+
if (/^[-*+]\s/.test(escaped)) {
|
|
187
|
+
escaped = '\\' + escaped;
|
|
188
|
+
}
|
|
189
|
+
// Leading number with period (ordered list)
|
|
190
|
+
if (/^\d+\.\s/.test(escaped)) {
|
|
191
|
+
escaped = escaped.replace(/^(\d+)\./, '$1\\.');
|
|
192
|
+
}
|
|
193
|
+
// Newlines in list items
|
|
194
|
+
escaped = escaped.replace(/\r?\n/g, ' \n ');
|
|
195
|
+
return escaped;
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Wrap text to ensure it fits within table cell width constraints.
|
|
199
|
+
*
|
|
200
|
+
* @param text - The text to wrap
|
|
201
|
+
* @param maxWidth - Maximum width (default: 50)
|
|
202
|
+
* @returns Wrapped text with <br> for line breaks
|
|
203
|
+
*/
|
|
204
|
+
export function wrapTableCell(text, maxWidth = DISPLAY_LIMITS.TABLE_CELL_MAX_WIDTH) {
|
|
205
|
+
if (!text || text.length <= maxWidth) {
|
|
206
|
+
return escapeTableCell(text);
|
|
207
|
+
}
|
|
208
|
+
const words = text.split(/\s+/);
|
|
209
|
+
const lines = [];
|
|
210
|
+
let currentLine = '';
|
|
211
|
+
for (const word of words) {
|
|
212
|
+
if (currentLine.length + word.length + 1 <= maxWidth) {
|
|
213
|
+
currentLine += (currentLine ? ' ' : '') + word;
|
|
214
|
+
}
|
|
215
|
+
else {
|
|
216
|
+
if (currentLine) {
|
|
217
|
+
lines.push(currentLine);
|
|
218
|
+
}
|
|
219
|
+
currentLine = word.length > maxWidth ? word.substring(0, maxWidth) + '...' : word;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
if (currentLine) {
|
|
223
|
+
lines.push(currentLine);
|
|
224
|
+
}
|
|
225
|
+
return escapeTableCell(lines.join('\n'));
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Build a Markdown table from headers and rows.
|
|
229
|
+
* Automatically escapes cell content.
|
|
230
|
+
*
|
|
231
|
+
* @param headers - Array of header strings
|
|
232
|
+
* @param rows - 2D array of cell values
|
|
233
|
+
* @param alignments - Optional array of column alignments ('left', 'center', 'right')
|
|
234
|
+
* @returns Complete Markdown table string
|
|
235
|
+
*/
|
|
236
|
+
export function buildTable(headers, rows, alignments) {
|
|
237
|
+
const lines = [];
|
|
238
|
+
// Header row
|
|
239
|
+
const escapedHeaders = headers.map(h => escapeTableCell(h));
|
|
240
|
+
lines.push(`| ${escapedHeaders.join(' | ')} |`);
|
|
241
|
+
// Separator row with alignment
|
|
242
|
+
const separators = headers.map((_, i) => {
|
|
243
|
+
const align = alignments?.[i] ?? 'left';
|
|
244
|
+
switch (align) {
|
|
245
|
+
case 'center':
|
|
246
|
+
return ':---:';
|
|
247
|
+
case 'right':
|
|
248
|
+
return '---:';
|
|
249
|
+
default:
|
|
250
|
+
return '---';
|
|
251
|
+
}
|
|
252
|
+
});
|
|
253
|
+
lines.push(`| ${separators.join(' | ')} |`);
|
|
254
|
+
// Data rows
|
|
255
|
+
for (const row of rows) {
|
|
256
|
+
const escapedCells = row.map(cell => escapeTableCell(cell));
|
|
257
|
+
// Pad row if needed
|
|
258
|
+
while (escapedCells.length < headers.length) {
|
|
259
|
+
escapedCells.push('');
|
|
260
|
+
}
|
|
261
|
+
lines.push(`| ${escapedCells.join(' | ')} |`);
|
|
262
|
+
}
|
|
263
|
+
return lines.join('\n');
|
|
264
|
+
}
|
|
265
|
+
//# sourceMappingURL=markdown.js.map
|