@stacksjs/defaults 0.75.361 → 0.75.362
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/ai/skills/stacks-ai/SKILL.md +22 -0
- package/ai/skills/stacks-native/CATALOG.md +2 -2
- package/ai/skills/stacks-technical-diagrams/LICENSE +202 -22
- package/ai/skills/stacks-technical-diagrams/LICENSE-MIT +22 -0
- package/ai/skills/stacks-technical-diagrams/NOTICE +26 -0
- package/ai/skills/stacks-technical-diagrams/SKILL.md +106 -266
- package/ai/skills/stacks-technical-diagrams/THIRD_PARTY_NOTICES.md +11 -2
- package/ai/skills/stacks-technical-diagrams/UPSTREAM.json +12 -0
- package/ai/skills/stacks-technical-diagrams/agents/openai.yaml +2 -2
- package/ai/skills/stacks-technical-diagrams/assets/template.html +3655 -3798
- package/ai/skills/stacks-technical-diagrams/bin/archify.mjs +7290 -0
- package/ai/skills/stacks-technical-diagrams/bin/delivery-update.mjs +7 -0
- package/ai/skills/stacks-technical-diagrams/bin/diagrams +1 -0
- package/ai/skills/stacks-technical-diagrams/bin/finalize.mjs +1056 -0
- package/ai/skills/stacks-technical-diagrams/bin/open-artifact.mjs +72 -12
- package/ai/skills/stacks-technical-diagrams/bin/preview.mjs +348 -31
- package/ai/skills/stacks-technical-diagrams/bin/recover-output.mjs +41 -0
- package/ai/skills/stacks-technical-diagrams/bin/technical-diagrams.mjs +3 -2097
- package/ai/skills/stacks-technical-diagrams/bin/visual-check.mjs +2142 -157
- package/ai/skills/stacks-technical-diagrams/brand-marks/README.md +3 -3
- package/ai/skills/stacks-technical-diagrams/delta/architecture-delta.mjs +130 -33
- package/ai/skills/stacks-technical-diagrams/examples/agent-run.lifecycle.json +25 -30
- package/ai/skills/stacks-technical-diagrams/examples/agent-tool-call.workflow.json +0 -20
- package/ai/skills/stacks-technical-diagrams/examples/archify-dev-activity.timeline.json +176 -0
- package/ai/skills/stacks-technical-diagrams/examples/archify-repository.tree.json +197 -0
- package/ai/skills/stacks-technical-diagrams/examples/async-job-roundtrip.sequence.json +1 -6
- package/ai/skills/stacks-technical-diagrams/examples/brand-aware-delivery.architecture.json +3 -16
- package/ai/skills/stacks-technical-diagrams/examples/cache-miss-request.sequence.json +2 -7
- package/ai/skills/stacks-technical-diagrams/examples/checkout-platform.base.architecture.json +2 -1
- package/ai/skills/stacks-technical-diagrams/examples/checkout-platform.head.architecture.json +2 -1
- package/ai/skills/stacks-technical-diagrams/examples/checkout-request.waterfall.json +20 -0
- package/ai/skills/stacks-technical-diagrams/examples/class-payment-processors-rendered.html +14987 -0
- package/ai/skills/stacks-technical-diagrams/examples/class-payments-rendered.html +14787 -0
- package/ai/skills/stacks-technical-diagrams/examples/dataflow-product-analytics.html +14880 -0
- package/ai/skills/stacks-technical-diagrams/examples/delivery.explainer.json +155 -0
- package/ai/skills/stacks-technical-diagrams/examples/deployment-release.lifecycle.json +57 -34
- package/ai/skills/stacks-technical-diagrams/examples/erd-orders-rendered.html +15112 -0
- package/ai/skills/stacks-technical-diagrams/examples/event-stream.dataflow.json +1 -6
- package/ai/skills/stacks-technical-diagrams/examples/example-rebuild.waterfall.json +212 -0
- package/ai/skills/stacks-technical-diagrams/examples/holiday-planning.workflow.json +143 -0
- package/ai/skills/stacks-technical-diagrams/examples/incident-response.workflow.json +1 -6
- package/ai/skills/stacks-technical-diagrams/examples/lifecycle-agent-run.html +14892 -0
- package/ai/skills/stacks-technical-diagrams/examples/locales/de.json +463 -0
- package/ai/skills/stacks-technical-diagrams/examples/locales/fr.json +463 -0
- package/ai/skills/stacks-technical-diagrams/examples/locales/fr.partial.json +22 -0
- package/ai/skills/stacks-technical-diagrams/examples/locales/it.json +463 -0
- package/ai/skills/stacks-technical-diagrams/examples/locales/ja.json +463 -0
- package/ai/skills/stacks-technical-diagrams/examples/locales/pt.json +463 -0
- package/ai/skills/stacks-technical-diagrams/examples/locales/ru.json +463 -0
- package/ai/skills/stacks-technical-diagrams/examples/orders.erd.json +337 -0
- package/ai/skills/stacks-technical-diagrams/examples/payment-incident.timeline.json +24 -0
- package/ai/skills/stacks-technical-diagrams/examples/payment-platform.tree.json +22 -0
- package/ai/skills/stacks-technical-diagrams/examples/payment-processors.class.json +177 -0
- package/ai/skills/stacks-technical-diagrams/examples/payments.class.json +85 -0
- package/ai/skills/stacks-technical-diagrams/examples/product-analytics.dataflow.json +1 -6
- package/ai/skills/stacks-technical-diagrams/examples/production-deployment.architecture.json +3 -23
- package/ai/skills/stacks-technical-diagrams/examples/release-delivery.workflow.json +1 -6
- package/ai/skills/stacks-technical-diagrams/examples/sequence-cache-miss-request.html +14895 -0
- package/ai/skills/stacks-technical-diagrams/examples/subscription-billing-rendered.html +15369 -0
- package/ai/skills/stacks-technical-diagrams/examples/subscription-billing.erd.json +548 -0
- package/ai/skills/stacks-technical-diagrams/examples/timeline-archify-dev-activity-rendered.html +15002 -0
- package/ai/skills/stacks-technical-diagrams/examples/timeline-payment-incident-rendered.html +14772 -0
- package/ai/skills/stacks-technical-diagrams/examples/tree-archify-repository-rendered.html +15071 -0
- package/ai/skills/stacks-technical-diagrams/examples/tree-payment-platform-rendered.html +14810 -0
- package/ai/skills/stacks-technical-diagrams/examples/waterfall-checkout-request-rendered.html +14754 -0
- package/ai/skills/stacks-technical-diagrams/examples/waterfall-example-rebuild-rendered.html +14940 -0
- package/ai/skills/stacks-technical-diagrams/examples/web-app-rendered.html +14889 -0
- package/ai/skills/stacks-technical-diagrams/examples/web-app.architecture.json +1 -6
- package/ai/skills/stacks-technical-diagrams/examples/workflow-agent-tool-call-rendered.html +14907 -0
- package/ai/skills/stacks-technical-diagrams/explainer/browser-check.mjs +208 -0
- package/ai/skills/stacks-technical-diagrams/explainer/charts.mjs +70 -0
- package/ai/skills/stacks-technical-diagrams/explainer/check.mjs +168 -0
- package/ai/skills/stacks-technical-diagrams/explainer/diagrams.mjs +518 -0
- package/ai/skills/stacks-technical-diagrams/explainer/diff.mjs +124 -0
- package/ai/skills/stacks-technical-diagrams/explainer/inline.mjs +155 -0
- package/ai/skills/stacks-technical-diagrams/explainer/layout.mjs +35 -0
- package/ai/skills/stacks-technical-diagrams/explainer/page-bundle.mjs +16 -0
- package/ai/skills/stacks-technical-diagrams/explainer/parse.mjs +300 -0
- package/ai/skills/stacks-technical-diagrams/explainer/patch.mjs +117 -0
- package/ai/skills/stacks-technical-diagrams/explainer/prepare.mjs +131 -0
- package/ai/skills/stacks-technical-diagrams/explainer/reader.css +472 -0
- package/ai/skills/stacks-technical-diagrams/explainer/reader.js +667 -0
- package/ai/skills/stacks-technical-diagrams/explainer/render.mjs +224 -0
- package/ai/skills/stacks-technical-diagrams/explainer/revision.mjs +20 -0
- package/ai/skills/stacks-technical-diagrams/explainer/sources.mjs +318 -0
- package/ai/skills/stacks-technical-diagrams/explainer/validate.mjs +138 -0
- package/ai/skills/stacks-technical-diagrams/explainer/vendor/pele/LICENSE +40 -0
- package/ai/skills/stacks-technical-diagrams/explainer/vendor/pele/README.md +5 -0
- package/ai/skills/stacks-technical-diagrams/explainer/vendor/pele/chunks/3DKXF73K.js +4 -0
- package/ai/skills/stacks-technical-diagrams/explainer/vendor/pele/chunks/42UTT654.js +3 -0
- package/ai/skills/stacks-technical-diagrams/explainer/vendor/pele/chunks/DKTLEL5E.js +1 -0
- package/ai/skills/stacks-technical-diagrams/explainer/vendor/pele/chunks/EEIX5ZYH.js +2 -0
- package/ai/skills/stacks-technical-diagrams/explainer/vendor/pele/chunks/EJ5KOXYD.js +25 -0
- package/ai/skills/stacks-technical-diagrams/explainer/vendor/pele/chunks/GUJTEFZK.js +1 -0
- package/ai/skills/stacks-technical-diagrams/explainer/vendor/pele/chunks/IZOKQ2GT.js +4 -0
- package/ai/skills/stacks-technical-diagrams/explainer/vendor/pele/chunks/L4LY553T.js +3 -0
- package/ai/skills/stacks-technical-diagrams/explainer/vendor/pele/chunks/MSKIJHB2.js +2 -0
- package/ai/skills/stacks-technical-diagrams/explainer/vendor/pele/chunks/RVARI57O.js +1 -0
- package/ai/skills/stacks-technical-diagrams/explainer/vendor/pele/chunks/UKSIWDDN.js +2 -0
- package/ai/skills/stacks-technical-diagrams/explainer/vendor/pele/chunks/UPTXNAXN.js +2 -0
- package/ai/skills/stacks-technical-diagrams/explainer/vendor/pele/chunks/XTDUIGUI.js +9 -0
- package/ai/skills/stacks-technical-diagrams/explainer/vendor/pele/chunks/YAYTP6L5.js +9 -0
- package/ai/skills/stacks-technical-diagrams/explainer/vendor/pele/core.js +1 -0
- package/ai/skills/stacks-technical-diagrams/explainer/vendor/pele/diagrams/pie.js +1 -0
- package/ai/skills/stacks-technical-diagrams/explainer/vendor/pele/diagrams/quadrantChart.js +1 -0
- package/ai/skills/stacks-technical-diagrams/explainer/vendor/pele/diagrams/radar.js +1 -0
- package/ai/skills/stacks-technical-diagrams/explainer/vendor/pele/diagrams/sankey.js +1 -0
- package/ai/skills/stacks-technical-diagrams/explainer/vendor/pele/diagrams/venn.js +1 -0
- package/ai/skills/stacks-technical-diagrams/explainer/vendor/pele/diagrams/xychart.js +1 -0
- package/ai/skills/stacks-technical-diagrams/explainer/writing.mjs +139 -0
- package/ai/skills/stacks-technical-diagrams/locales/README.md +40 -0
- package/ai/skills/stacks-technical-diagrams/locales/ar.json +488 -0
- package/ai/skills/stacks-technical-diagrams/locales/en.json +488 -0
- package/ai/skills/stacks-technical-diagrams/locales/es.json +488 -0
- package/ai/skills/stacks-technical-diagrams/locales/ko.json +488 -0
- package/ai/skills/stacks-technical-diagrams/locales/manifest.json +10 -0
- package/ai/skills/stacks-technical-diagrams/locales/zh-CN.json +488 -0
- package/ai/skills/stacks-technical-diagrams/locales/zh-TW.json +488 -0
- package/ai/skills/stacks-technical-diagrams/migrations/workflow-v2.mjs +1 -0
- package/ai/skills/stacks-technical-diagrams/recipes/scenarios.mjs +115 -51
- package/ai/skills/stacks-technical-diagrams/references/architecture-layout-repair.md +18 -0
- package/ai/skills/stacks-technical-diagrams/references/authoring-contract.md +453 -51
- package/ai/skills/stacks-technical-diagrams/references/authoring-defaults.md +57 -0
- package/ai/skills/stacks-technical-diagrams/references/brand-marks.md +57 -3
- package/ai/skills/stacks-technical-diagrams/references/delivery-contract.md +603 -58
- package/ai/skills/stacks-technical-diagrams/references/explainer-authoring.md +274 -0
- package/ai/skills/stacks-technical-diagrams/references/repository-authoring.md +126 -0
- package/ai/skills/stacks-technical-diagrams/references/update-awareness.md +13 -0
- package/ai/skills/stacks-technical-diagrams/references/viewer-runtime.md +18 -11
- package/ai/skills/stacks-technical-diagrams/renderers/architecture/grid.mjs +1 -1
- package/ai/skills/stacks-technical-diagrams/renderers/architecture/labels.mjs +2 -0
- package/ai/skills/stacks-technical-diagrams/renderers/architecture/render-architecture.mjs +550 -424
- package/ai/skills/stacks-technical-diagrams/renderers/architecture/routing.mjs +1469 -0
- package/ai/skills/stacks-technical-diagrams/renderers/class/README.md +129 -0
- package/ai/skills/stacks-technical-diagrams/renderers/class/render-class.mjs +1095 -0
- package/ai/skills/stacks-technical-diagrams/renderers/dataflow/README.md +89 -17
- package/ai/skills/stacks-technical-diagrams/renderers/dataflow/dataflow-compiler.mjs +1605 -0
- package/ai/skills/stacks-technical-diagrams/renderers/dataflow/joint-label-routing.mjs +165 -0
- package/ai/skills/stacks-technical-diagrams/renderers/dataflow/label-capacity.mjs +81 -0
- package/ai/skills/stacks-technical-diagrams/renderers/dataflow/render-dataflow.mjs +14 -474
- package/ai/skills/stacks-technical-diagrams/renderers/erd/README.md +246 -0
- package/ai/skills/stacks-technical-diagrams/renderers/erd/grid.mjs +150 -0
- package/ai/skills/stacks-technical-diagrams/renderers/erd/render-erd.mjs +1588 -0
- package/ai/skills/stacks-technical-diagrams/renderers/explainer/render-explainer.mjs +42 -0
- package/ai/skills/stacks-technical-diagrams/renderers/lifecycle/README.md +83 -94
- package/ai/skills/stacks-technical-diagrams/renderers/lifecycle/render-lifecycle.mjs +990 -417
- package/ai/skills/stacks-technical-diagrams/renderers/sequence/README.md +49 -17
- package/ai/skills/stacks-technical-diagrams/renderers/sequence/render-sequence.mjs +735 -94
- package/ai/skills/stacks-technical-diagrams/renderers/shared/atomic-output.mjs +1982 -0
- package/ai/skills/stacks-technical-diagrams/renderers/shared/automatic-labels.mjs +290 -0
- package/ai/skills/stacks-technical-diagrams/renderers/shared/brand-marks.mjs +169 -26
- package/ai/skills/stacks-technical-diagrams/renderers/shared/cli.mjs +266 -54
- package/ai/skills/stacks-technical-diagrams/renderers/shared/desktop-readability.mjs +106 -0
- package/ai/skills/stacks-technical-diagrams/renderers/shared/diagnostics.mjs +0 -0
- package/ai/skills/stacks-technical-diagrams/renderers/shared/generated-validators.mjs +268 -2
- package/ai/skills/stacks-technical-diagrams/renderers/shared/geometry.mjs +774 -124
- package/ai/skills/stacks-technical-diagrams/renderers/shared/i18n.mjs +289 -556
- package/ai/skills/stacks-technical-diagrams/renderers/shared/layout-report.mjs +18 -1
- package/ai/skills/stacks-technical-diagrams/renderers/shared/legend.mjs +16 -6
- package/ai/skills/stacks-technical-diagrams/renderers/shared/node-card-style.mjs +32 -0
- package/ai/skills/stacks-technical-diagrams/renderers/shared/output-path.mjs +329 -229
- package/ai/skills/stacks-technical-diagrams/renderers/shared/owned-temp-directory.mjs +82 -0
- package/ai/skills/stacks-technical-diagrams/renderers/shared/path-semantics.mjs +1017 -0
- package/ai/skills/stacks-technical-diagrams/renderers/shared/portable-path.mjs +408 -0
- package/ai/skills/stacks-technical-diagrams/renderers/shared/repository-evidence.mjs +235 -79
- package/ai/skills/stacks-technical-diagrams/renderers/shared/repository-location.mjs +17 -4
- package/ai/skills/stacks-technical-diagrams/renderers/shared/route-quality.mjs +670 -0
- package/ai/skills/stacks-technical-diagrams/renderers/shared/sidecar-path.mjs +38 -0
- package/ai/skills/stacks-technical-diagrams/renderers/shared/software-notices.mjs +6 -0
- package/ai/skills/stacks-technical-diagrams/renderers/shared/spatial-grid.mjs +66 -0
- package/ai/skills/stacks-technical-diagrams/renderers/shared/svg-path-analysis.mjs +135 -0
- package/ai/skills/stacks-technical-diagrams/renderers/shared/text-fit.mjs +59 -3
- package/ai/skills/stacks-technical-diagrams/renderers/shared/utils.mjs +63 -35
- package/ai/skills/stacks-technical-diagrams/renderers/shared/validator.mjs +2 -5
- package/ai/skills/stacks-technical-diagrams/renderers/timeline/README.md +76 -0
- package/ai/skills/stacks-technical-diagrams/renderers/timeline/render-timeline.mjs +576 -0
- package/ai/skills/stacks-technical-diagrams/renderers/tree/README.md +96 -0
- package/ai/skills/stacks-technical-diagrams/renderers/tree/render-tree.mjs +573 -0
- package/ai/skills/stacks-technical-diagrams/renderers/waterfall/README.md +73 -0
- package/ai/skills/stacks-technical-diagrams/renderers/waterfall/render-waterfall.mjs +413 -0
- package/ai/skills/stacks-technical-diagrams/renderers/workflow/README.md +137 -23
- package/ai/skills/stacks-technical-diagrams/renderers/workflow/render-workflow.mjs +18 -6
- package/ai/skills/stacks-technical-diagrams/renderers/workflow/workflow-compiler.mjs +2230 -710
- package/ai/skills/stacks-technical-diagrams/renderers/workflow/workflow-migration-geometry.mjs +17 -0
- package/ai/skills/stacks-technical-diagrams/renderers/workflow/workflow-placement-repair.mjs +94 -0
- package/ai/skills/stacks-technical-diagrams/schemas/README.md +87 -40
- package/ai/skills/stacks-technical-diagrams/schemas/architecture.schema.json +7 -33
- package/ai/skills/stacks-technical-diagrams/schemas/class.schema.json +345 -0
- package/ai/skills/stacks-technical-diagrams/schemas/common.schema.json +68 -2
- package/ai/skills/stacks-technical-diagrams/schemas/dataflow.schema.json +14 -3
- package/ai/skills/stacks-technical-diagrams/schemas/erd.schema.json +381 -0
- package/ai/skills/stacks-technical-diagrams/schemas/explainer.schema.json +927 -0
- package/ai/skills/stacks-technical-diagrams/schemas/lifecycle.schema.json +23 -110
- package/ai/skills/stacks-technical-diagrams/schemas/sequence.schema.json +15 -4
- package/ai/skills/stacks-technical-diagrams/schemas/timeline.schema.json +160 -0
- package/ai/skills/stacks-technical-diagrams/schemas/tree.schema.json +141 -0
- package/ai/skills/stacks-technical-diagrams/schemas/waterfall.schema.json +147 -0
- package/ai/skills/stacks-technical-diagrams/schemas/workflow.schema.json +14 -3
- package/ai/skills/stacks-technical-diagrams/scripts/check-render-output.mjs +876 -243
- package/ai/skills/stacks-technical-diagrams/scripts/check-update.mjs +1717 -0
- package/ai/skills/stacks-technical-diagrams/scripts/delivery-update-child.mjs +26 -0
- package/ai/skills/stacks-technical-diagrams/scripts/generate-brand-marks.mjs +141 -0
- package/ai/skills/stacks-technical-diagrams/scripts/generate-validators.mjs +105 -0
- package/ai/skills/stacks-technical-diagrams/scripts/render-examples.mjs +11 -1
- package/ai/skills/stacks-technical-diagrams/scripts/update-contract.mjs +187 -0
- package/ai/skills/stacks-technical-diagrams/skill-release.json +10 -0
- package/ide/vscode/package.json +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{a as e}from"../chunks/EEIX5ZYH.js";import"../chunks/GUJTEFZK.js";import"../chunks/IZOKQ2GT.js";import"../chunks/XTDUIGUI.js";export{e as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{a}from"../chunks/L4LY553T.js";import"../chunks/RVARI57O.js";import"../chunks/DKTLEL5E.js";import"../chunks/GUJTEFZK.js";import"../chunks/IZOKQ2GT.js";import"../chunks/XTDUIGUI.js";export{a as default};
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/** Independently authored prose hints; no external dictionary or automatic rewriting.
|
|
2
|
+
* Callers select prose entries, excluding code and URL-only fields.
|
|
3
|
+
* locale sets the sentence-limit fallback; bilingual phrase rules always apply.
|
|
4
|
+
*/
|
|
5
|
+
const RULES = [
|
|
6
|
+
{id:'qualification', pattern:/示例|本例|不代表|未实测|仅供参考|\billustrative\b|\bnot measured\b/giu,
|
|
7
|
+
reason:'把限定条件写进 scope 或来源', example:'@answer scope="适用于当前请求路径"', fix:'把限定条件写进 scope 或来源,正文直接解释判断和原因。'},
|
|
8
|
+
{id: 'light-verb', pattern: /进行(?![中时])\p{Script=Han}{2}|(?:加以|予以|做出|作出)\p{Script=Han}{2}|\b(?:perform an analysis of|carry out an investigation of|make a decision|give consideration to|conduct an? (?:review|investigation|analysis) of)\b/giu,
|
|
9
|
+
reason: 'A light-verb construction can obscure the action.', example: '进行检查 → 检查;做出决定 → 决定; make a decision → decide', fix: 'Use the direct action verb where it preserves the meaning; name who performs the action.'},
|
|
10
|
+
{id: 'cliche', pattern: /赋能|抓手|全方位|多维度|深度融合|至关重要|不可或缺|一站式|底层逻辑|\b(?:at the end of the day|in today[’']s fast-paced world|unlock the full potential|game[- ]changer|cutting[- ]edge|seamless(?:ly)?|delve into)\b/giu,
|
|
11
|
+
reason: 'This stock phrase gives little information about the concrete outcome.', example: '赋能业务 → 让客服查到订单状态; seamless → name what no longer needs a manual step', fix: 'Replace the stock phrase with the specific action or outcome the reader needs.'},
|
|
12
|
+
{id: 'filler', pattern: /下面我(?:来|将)|接下来我(?:来|将)|让我(?:们)?来|总的来说|综上所述|总而言之|值得注意的是|众所周知|毋庸置疑|希望(?:这)?(?:对你|对您)有(?:所)?帮助|如有疑问|\b(?:here is an overview|let[’']s (?:dive|take a look)|in conclusion|in summary|it is worth noting that|as we all know|i hope this helps)\b/giu,
|
|
13
|
+
reason: 'Opening, closing or signposting filler delays the facts.', example: '综上所述,选 A → 选 A; In summary, use A → Use A', fix: 'Delete the phrase; open with the claim and stop after the last supported point.'},
|
|
14
|
+
{id: 'vague-quantity', pattern: /大量(?:请求|用户|数据)|很多(?:请求|用户|数据)|若干|尽快|\b(?:many users|a large number of requests|significantly faster|as soon as possible)\b/giu,
|
|
15
|
+
reason: 'The quantity or comparison lacks a stated bound or measurement.', example: '大量请求 → 写明已知请求量或说明未测量;尽快 → 写明期限; significantly faster → give the measured comparison or say it is unmeasured', fix: 'Add a supported quantity, range, deadline or comparison basis; when unknown, state that it is unmeasured. Do not invent a number.'},
|
|
16
|
+
{id: 'number-boundary', pattern: /(?<=\d\s*(?:个|次|秒|天|分钟|小时|倍|人|条|项|%|ms|MB|GB|KB|QPS)?\s*)(?:以上|以下|以内)/gu,
|
|
17
|
+
reason: '“以上/以下/以内” after a number leaves the endpoint unclear.', example: '3 次以上 → 超过 3 次 / 不少于 3 次;1 秒以内 → 不超过 1 秒', fix: 'Say whether the endpoint is included: 超过/不少于, 低于/不超过.'},
|
|
18
|
+
{id: 'plain-word', pattern: /\b(?:utili[sz]e[sd]?|utili[sz]ation|prior to|in order to|commence[sd]?|facilitate[sd]?|subsequently|in the event that|due to the fact that|at this point in time|endeavou?r)\b/giu,
|
|
19
|
+
reason: 'A longer word replaces a common one with the same meaning.', example: 'utilize → use; prior to → before; in order to → to; due to the fact that → because', fix: 'Use the shorter common word.'},
|
|
20
|
+
{id: 'redundancy', pattern: /提前预先|重复重复|基本基础|\b(?:each and every|future plans|completely eliminate)\b/giu,
|
|
21
|
+
reason: 'Adjacent wording may repeat the same meaning.', example: '提前预先 → 提前; each and every → each', fix: 'Keep one expression of the meaning unless both terms carry a necessary distinction.'},
|
|
22
|
+
];
|
|
23
|
+
|
|
24
|
+
// Mask URL bodies without changing offsets or swallowing trailing sentence punctuation.
|
|
25
|
+
function proseMask(text) {
|
|
26
|
+
return text.replace(/https?:\/\/[^\s<>。!?,;、:)]+/giu, value => {
|
|
27
|
+
// A Markdown link's closing parenthesis is outside the URL. Preserve that
|
|
28
|
+
// delimiter and any following prose, while retaining balanced URL paths.
|
|
29
|
+
let depth = 0, end = value.length;
|
|
30
|
+
for (let i = 0; i < value.length; i++) {
|
|
31
|
+
if (value[i] === '(') depth++;
|
|
32
|
+
else if (value[i] === ')') {
|
|
33
|
+
if (depth === 0) { end = i; break; }
|
|
34
|
+
depth--;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
const url = value.slice(0, end);
|
|
38
|
+
const tail = url.match(/[.!?,;]+$/u)?.[0] || '';
|
|
39
|
+
const maskedLength = url.length - tail.length;
|
|
40
|
+
return ' '.repeat(maskedLength) + value.slice(maskedLength);
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function sentences(text) {
|
|
45
|
+
const result = [];
|
|
46
|
+
let start = 0;
|
|
47
|
+
for (let i = 0; i < text.length; i++) {
|
|
48
|
+
const char = text[i];
|
|
49
|
+
const decimal = char === '.' && /\d/u.test(text[i - 1] || '') && /\d/u.test(text[i + 1] || '');
|
|
50
|
+
const paragraph = char === '\n' && /^\s*\n/u.test(text.slice(i + 1));
|
|
51
|
+
if ((/[.!?。!?]/u.test(char) && !decimal) || paragraph) {
|
|
52
|
+
result.push({text: text.slice(start, i + 1), offset: start});
|
|
53
|
+
start = i + 1;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
if (start < text.length) result.push({text: text.slice(start), offset: start});
|
|
57
|
+
return result;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* @param {Array<{text:string,line:number,component:string,panelId?:string}>} entries
|
|
62
|
+
* @param {{mode?:'warn'|'strict'|'off',locale?:string,sentenceLimits?:{zh?:number,en?:number}}} options
|
|
63
|
+
* @returns {Array<object>} Existing Archify diagnostics (warning by default).
|
|
64
|
+
* Length is Han characters plus English words/numeric tokens; punctuation is excluded.
|
|
65
|
+
* A sentence containing Han uses zh limit (50), otherwise en limit (28).
|
|
66
|
+
*/
|
|
67
|
+
export function lintExplainerWriting(entries, {mode = 'warn', locale = 'auto', sentenceLimits = {}} = {}) {
|
|
68
|
+
if (!['warn', 'strict', 'off'].includes(mode)) throw new TypeError('Writing mode must be warn, strict or off');
|
|
69
|
+
if (mode === 'off') return [];
|
|
70
|
+
const limits = {zh: 50, en: 28, ...sentenceLimits};
|
|
71
|
+
for (const value of Object.values(limits)) {
|
|
72
|
+
if (!Number.isSafeInteger(value) || value < 1) throw new TypeError('Sentence limits must be positive integers');
|
|
73
|
+
}
|
|
74
|
+
const diagnostics = [];
|
|
75
|
+
for (const entry of entries) {
|
|
76
|
+
if (typeof entry.text !== 'string') throw new TypeError('Writing entries require text strings');
|
|
77
|
+
if (entry.component === 'source') continue;
|
|
78
|
+
const original = entry.text;
|
|
79
|
+
const text = proseMask(original);
|
|
80
|
+
const found = [];
|
|
81
|
+
const units = value => (value.match(/\p{Script=Han}/gu)?.length || 0) + (value.match(/[\p{Script=Latin}\d]+(?:[’'_-][\p{Script=Latin}\d]+)*(?:\.\d+)?/gu)?.length || 0);
|
|
82
|
+
if (entry.component === 'scope') {
|
|
83
|
+
if (units(text) > 50) found.push({offset: 0, rule: 'scope-length', units: units(text), limit: 50,
|
|
84
|
+
reason: 'The scope reads as a disclaimer rather than a short label.',
|
|
85
|
+
example: '8 人团队 · 上线半年 · 峰值约 300 QPS / Eight people · six months live · ~300 QPS peak',
|
|
86
|
+
fix: 'Keep the conditions a reader must check, as short labels separated by “·”. Drop process notes about how the page was made.'});
|
|
87
|
+
} else {
|
|
88
|
+
for (const rule of RULES) {
|
|
89
|
+
// New regex per entry prevents mutable lastIndex from leaking between calls.
|
|
90
|
+
for (const match of text.matchAll(new RegExp(rule.pattern.source, rule.pattern.flags))) {
|
|
91
|
+
found.push({offset: match.index, rule: rule.id, reason: rule.reason, example: rule.example, fix: rule.fix, matched: match[0]});
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
if (entry.pointer === '/answer/summary' && typeof entry.raw === 'string') {
|
|
96
|
+
const bold = [...entry.raw.matchAll(/\*\*(.+?)\*\*/gu)].reduce((sum, match) => sum + units(match[1]), 0);
|
|
97
|
+
if (units(text) >= 12 && bold / units(text) > .6) found.push({offset: 0, rule: 'verdict-emphasis',
|
|
98
|
+
reason: 'Most of the conclusion is bold, so nothing stands out.',
|
|
99
|
+
example: '先做**模块化单体**,等边界稳定后再拆。 / Keep a **modular monolith** until boundaries settle.',
|
|
100
|
+
fix: 'Bold only the few words that carry the decision.'});
|
|
101
|
+
}
|
|
102
|
+
const sentenceCount = sentences(text).filter(sentence => sentence.text.trim()).length;
|
|
103
|
+
if (entry.component === 'prose' && (units(text) > 120 || sentenceCount > 4)) found.push({offset: 0, rule: 'paragraph-length', units: units(text), limit: 120,
|
|
104
|
+
reason: `This paragraph has ${sentenceCount} sentences and ${units(text)} reading units; long paragraphs are what the page should replace.`,
|
|
105
|
+
example: '把并列要点写成列表,把先后动作写成 @steps,把方案差异写成对比表。 / Turn parallel points into a list, ordered actions into @steps and option differences into a comparison.',
|
|
106
|
+
fix: 'Split the paragraph into a list, steps or a comparison; keep at most two or three short sentences of prose.'});
|
|
107
|
+
if (entry.component !== 'scope') for (const sentence of sentences(text)) {
|
|
108
|
+
const han = sentence.text.match(/\p{Script=Han}/gu)?.length || 0;
|
|
109
|
+
const words = sentence.text.match(/[\p{Script=Latin}\d]+(?:[’'_-][\p{Script=Latin}\d]+)*(?:\.\d+)?/gu)?.length || 0;
|
|
110
|
+
const units = han + words;
|
|
111
|
+
const language = han ? 'zh' : (words ? 'en' : (locale.startsWith('zh') ? 'zh' : 'en'));
|
|
112
|
+
const limit = limits[language];
|
|
113
|
+
const particles = sentence.text.replace(/目的|的确|的话/gu, '').match(/的/gu)?.length || 0;
|
|
114
|
+
if (particles >= 3) found.push({offset: sentence.offset + Math.max(0, sentence.text.search(/\S/u)), rule: 'de-chain',
|
|
115
|
+
reason: `This sentence chains ${particles} “的” modifiers, so the head noun arrives late.`,
|
|
116
|
+
example: '负责处理用户提交的订单的服务的日志 → 订单服务的日志。它记录用户提交的订单。',
|
|
117
|
+
fix: 'Split the sentence or move a modifier into its own clause.', matched: sentence.text.trim()});
|
|
118
|
+
if (units > limit) {
|
|
119
|
+
const leading = sentence.text.search(/\S/u);
|
|
120
|
+
found.push({offset: sentence.offset + Math.max(0, leading), rule: 'sentence-length',
|
|
121
|
+
reason: `Sentence has ${units} reading units, above the configured ${language} limit of ${limit}.`,
|
|
122
|
+
example: '先查缓存。未命中时再查数据库。 / Check the cache first. Query the database on a miss.',
|
|
123
|
+
fix: 'Split at a logical action or condition boundary while preserving qualifications and causal links.', units, limit});
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
found.sort((a, b) => a.offset - b.offset || a.rule.localeCompare(b.rule, 'en'));
|
|
127
|
+
for (const item of found) {
|
|
128
|
+
diagnostics.push({
|
|
129
|
+
code: `explainer/writing-${item.rule}`, severity: mode === 'strict' ? 'error' : 'warning', message: item.reason,
|
|
130
|
+
subject: {line: (Number.isInteger(entry.line) && entry.line > 0 ? entry.line : 1) + (original.slice(0, item.offset).match(/\n/gu)?.length || 0),
|
|
131
|
+
component: entry.component, ...(entry.panelId === undefined ? {} : {panelId: entry.panelId})},
|
|
132
|
+
evidence: {rule: item.rule, reason: item.reason, example: item.example,
|
|
133
|
+
...(item.matched ? {matched: item.matched} : {}), ...(item.units ? {units: item.units, limit: item.limit} : {})},
|
|
134
|
+
supportedFixes: [item.fix],
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return diagnostics;
|
|
139
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Bundled Viewer catalogs
|
|
2
|
+
|
|
3
|
+
`manifest.json` enrolls the catalogs that `meta.locale` selects automatically.
|
|
4
|
+
The renderer reads only the files listed there, relative to this installed
|
|
5
|
+
directory. It never scans this directory, the working directory, or anywhere
|
|
6
|
+
else for language files.
|
|
7
|
+
|
|
8
|
+
`en.json` is the canonical message set and the final fallback. Every other
|
|
9
|
+
catalog is validated against it per key: a missing, unknown, or
|
|
10
|
+
placeholder-mismatched entry falls back to English and is reported when that
|
|
11
|
+
locale is rendered. A new UI key may therefore ship in English first.
|
|
12
|
+
|
|
13
|
+
Each message resolves as: valid `meta.translations` value → selected bundled
|
|
14
|
+
catalog → English. See [the authoring contract](../references/authoring-contract.md).
|
|
15
|
+
|
|
16
|
+
To enroll a language, add its complete catalog here and one manifest entry.
|
|
17
|
+
No renderer or schema change is needed. Locale tags match case-insensitively;
|
|
18
|
+
region and script variants (for example `zh-Hant`) are distinct tags and are
|
|
19
|
+
never collapsed onto another catalog.
|
|
20
|
+
|
|
21
|
+
| Locale | Origin | Review status |
|
|
22
|
+
| --- | --- | --- |
|
|
23
|
+
| `en` | Archify source strings | Canonical |
|
|
24
|
+
| `zh-CN` | #108 | Maintained with the renderer |
|
|
25
|
+
| `zh-TW` | kevinlincg | Complete; OpenCC `s2twp` conversion hand-reviewed for Taiwan terminology; not independently native-reviewed |
|
|
26
|
+
| `es` | Juan Pablo Tamayo (#457, moved to data in #586) | Complete; not independently native-reviewed |
|
|
27
|
+
| `ko` | uygnoey (#457) | Complete; not independently native-reviewed |
|
|
28
|
+
| `ar` | jahfaliabdulrahman-dev | Complete: 486/486 keys with placeholder parity checked mechanically; not independently native-reviewed |
|
|
29
|
+
|
|
30
|
+
Completeness checks prove key and placeholder coverage, not native wording,
|
|
31
|
+
plural grammar, right-to-left layout, or glyph coverage.
|
|
32
|
+
|
|
33
|
+
The Arabic catalog localizes copy only. Reader text/chrome direction and scene
|
|
34
|
+
geometry are unchanged; full RTL support is tracked in [#935](https://github.com/tt-a1i/archify/issues/935).
|
|
35
|
+
Route/reach export summaries and reach controls use count-neutral labels within
|
|
36
|
+
the existing `.one`/`.other` model. Other counted messages still have that
|
|
37
|
+
model's Arabic plural limitations.
|
|
38
|
+
|
|
39
|
+
Other reusable, unenrolled examples live in `../examples/locales/`; supply
|
|
40
|
+
them through `meta.translations`.
|