mirror of
https://github.com/garrytan/gstack.git
synced 2026-09-12 07:59:02 +02:00
fix(design-md): edits follow a symlinked DESIGN.md, keep the BOM and the majority line ending, refuse an unclosed fence
- `mark`, `convert --write`, and the design binary's extraction replaced a symlinked DESIGN.md (a docs-site layout) with a regular file and left the real target untouched; both writers resolve the link first. - A single stray CRLF flipped a whole LF file to CRLF: the editors now keep the majority ending. A UTF-8 BOM broke format detection and ended up mid-file after `mark`; it is recognized and kept at byte 0. - Re-running `mark` on a marked file deleted the blank line after the marker (`\s*$` matched across the newline); the marker regexes use `[ \t]*`. - Fences: readers follow markdown (an unclosed fence runs to EOF); the text-level editors refuse such a file with DesignMdEditRefused (DESIGN_MD_EDIT_REFUSED) instead of splicing the wrong section, and the design binary reports that and leaves the file alone. - needsQuotes also quotes a scalar containing ` #` (an inline-comment shape parsed back as a truncated value). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
8d709c8f29
commit
cb9ba7a3e2
+13
-4
@@ -15,7 +15,7 @@ import fs from "fs";
|
||||
import path from "path";
|
||||
import { requireApiKey } from "./auth";
|
||||
import { receiptedFetch } from "./receipted-fetch";
|
||||
import { parseDesignMd, detectFormat, renderDesignMd, spliceSection, specSkeleton, tokensFlat, slug } from "../../lib/design-md";
|
||||
import { parseDesignMd, detectFormat, renderDesignMd, spliceSection, specSkeleton, tokensFlat, slug, DesignMdEditRefused } from "../../lib/design-md";
|
||||
import { atomicWriteSync } from "../../lib/fs-atomic";
|
||||
|
||||
/** The section the extraction owns in DESIGN.md (replaced on every run). */
|
||||
@@ -118,15 +118,24 @@ export function updateDesignMd(
|
||||
extracted: ExtractedDesign,
|
||||
sourceMockup: string,
|
||||
): void {
|
||||
const designPath = path.join(repoRoot, "DESIGN.md");
|
||||
const linkPath = path.join(repoRoot, "DESIGN.md");
|
||||
const timestamp = new Date().toISOString().split("T")[0];
|
||||
const body = formatExtractedSection(extracted, sourceMockup, timestamp);
|
||||
|
||||
if (fs.existsSync(designPath)) {
|
||||
atomicWriteSync(designPath, spliceSection(fs.readFileSync(designPath, "utf-8"), EXTRACTED_SECTION_HEADING, body));
|
||||
if (fs.existsSync(linkPath)) {
|
||||
const designPath = fs.realpathSync(linkPath); // edit the file behind a symlink, never replace the link
|
||||
let next: string;
|
||||
try {
|
||||
next = spliceSection(fs.readFileSync(designPath, "utf-8"), EXTRACTED_SECTION_HEADING, body);
|
||||
} catch (err) {
|
||||
if (err instanceof DesignMdEditRefused) { console.error(`DESIGN.md not updated: ${err.message}`); return; }
|
||||
throw err;
|
||||
}
|
||||
atomicWriteSync(designPath, next);
|
||||
console.error(`Updated DESIGN.md with extracted design language`);
|
||||
return;
|
||||
}
|
||||
const designPath = linkPath;
|
||||
|
||||
const colors: Record<string, string> = {};
|
||||
for (const c of extracted.colors) {
|
||||
|
||||
Reference in New Issue
Block a user