fix(report): make density facts readable and printable
Unify reader cleanup rules, lock writer table guards, and register the exact fictional timestamp collision. Preserve existing ordinary-report safety contracts and source-data gaps. Validation: report Node 165/165, final safety 29/29, Python 101/101, Chrome 28/28; both PDFs retain all 130 rows. Full Node 3704 tests with the same 91 baseline failures. Privacy test: 62 passed, 1 failed due to 17 protected-file READ_ERRORs; not a green gate. Build, DB, manual checklist and controlled-login gaps remain documented. User explicitly authorized staging push with these gaps disclosed. Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -1,27 +1,32 @@
|
||||
/** Cache compatibility for the Python reader-only vocabulary projection. */
|
||||
const STATUS_LABELS: Readonly<Record<string, string>> = {
|
||||
parameter_sensitive: "参数敏感",
|
||||
pyjhora_behavior_only: "仅单一外部参照,未做多引擎核对",
|
||||
not_multiengine_parity: "仅单一外部参照,未做多引擎核对",
|
||||
unresolved_external_tuple_boundary: "外部边界未对齐",
|
||||
partial_verified: "部分核验",
|
||||
raw_appendix_only: "仅原始附录可见",
|
||||
missing_in_local: "本地暂无",
|
||||
internal_reference_omitted: "内部参照已省略",
|
||||
};
|
||||
const CELL_LABELS: Readonly<Record<string, string>> = {
|
||||
blocked: "暂不可用", executed: "已执行", available: "可用", computed: "已计算",
|
||||
};
|
||||
import vocabulary from "../../../scripts/reader_appendix_language.rules.json";
|
||||
|
||||
type VocabularyRule = Readonly<{
|
||||
pattern: string;
|
||||
ignoreCase?: boolean;
|
||||
replacement?: string;
|
||||
labels?: Readonly<Record<string, string>>;
|
||||
labelGroup?: number;
|
||||
prefix?: string;
|
||||
beforeGroups?: readonly number[];
|
||||
afterGroups?: readonly number[];
|
||||
}>;
|
||||
|
||||
// One rule source for Python and TS; the JSON ships in both existing images.
|
||||
const chartFence = new RegExp(vocabulary.chartFencePattern, "m");
|
||||
const replacements = (vocabulary.rules as readonly VocabularyRule[]).map((rule) => ({
|
||||
rule,
|
||||
pattern: new RegExp(rule.pattern, rule.ignoreCase ? "gi" : "g"),
|
||||
}));
|
||||
|
||||
export function cleanReaderAppendixMarkdown(markdown: string): string {
|
||||
return markdown.split(/(^[ \t]*```jyotish-chart[^\n]*\n[\s\S]*?^[ \t]*```[^\n]*(?:\n|$))/m)
|
||||
.map((part, index) => index % 2 ? part : part
|
||||
.replace(new RegExp(`\\b(${Object.keys(STATUS_LABELS).join("|")})\\b`, "g"), (value) => STATUS_LABELS[value])
|
||||
.replace(/\b(?:jyotish_engine\.)?(?:cmd_[a-z0-9_]+|render_pl9_markdown|build_professional_report_reference_packet)\b/g, "本地计算")
|
||||
.replace(/\b(?:[a-z0-9_]+pl9[a-z0-9_]*|pl9_[a-z0-9_]+)(?:\.v\d+)?\b/gi, "外部参照资料")
|
||||
.replace(/\bPL9\b(?:\.pdf)?(?:[ \t]*(?:第[ \t]*\d+(?:[ \t]*[–—/-][ \t]*\d+)*[ \t]*页|(?:pages?|p)[ \t-]*\d+(?:[ \t]*[–—/-][ \t]*\d+)*))?/gi, "外部参照资料")
|
||||
.replace(/\b(?:PyJHora|JHora)\b/gi, "外部参照引擎")
|
||||
.replace(/\|([ \t]*)(`?)(blocked|executed|available|computed)\2([ \t]*)(?=\|)/g,
|
||||
(_match, before: string, quote: string, value: string, after: string) => `|${before}${quote}${CELL_LABELS[value]}${quote}${after}`))
|
||||
.join("");
|
||||
return markdown.split(chartFence).map((part, index) => {
|
||||
if (index % 2) return part;
|
||||
return replacements.reduce((value, { pattern, rule }) => value.replace(pattern, (...match) => {
|
||||
if (rule.replacement !== undefined) return rule.replacement;
|
||||
return (rule.prefix ?? "")
|
||||
+ (rule.beforeGroups ?? []).map((group) => match[group]).join("")
|
||||
+ rule.labels![match[rule.labelGroup!]]
|
||||
+ (rule.afterGroups ?? []).map((group) => match[group]).join("");
|
||||
}), part);
|
||||
}).join("");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user