mirror of
https://github.com/murashit/codex-panel.git
synced 2026-07-22 06:57:10 +00:00
Build ignored stylesheet from CSS modules
This commit is contained in:
parent
caabcb6e64
commit
ff08d411fa
5 changed files with 79 additions and 2348 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -1,6 +1,7 @@
|
|||
node_modules/
|
||||
.jj/
|
||||
main.js
|
||||
styles.css
|
||||
data.json
|
||||
*.log
|
||||
.DS_Store
|
||||
|
|
|
|||
|
|
@ -10,7 +10,8 @@ npm run build
|
|||
Run `npm run format` after edits and before `npm run check` so Prettier-only issues are fixed upfront. `npm run check` runs TypeScript type checking, unit tests, ESLint, Prettier check, and a production esbuild bundle.
|
||||
The local `npm run check` path runs checks in parallel and uses local caches for TypeScript, Vitest, ESLint, and Prettier. Use `npm run check:ci` when you need to reproduce the sequential, non-cached CI validation path.
|
||||
|
||||
`main.js`, `data.json`, and `node_modules/` are ignored by Git. `main.js` is still the file Obsidian loads, so run `npm run build` or `npm run build:prod` after source changes.
|
||||
`main.js`, `styles.css`, `data.json`, and `node_modules/` are ignored by Git. `main.js` and `styles.css` are still the files Obsidian loads, so run `npm run build` after source changes.
|
||||
CSS is authored in `src/styles/` and generated into the ignored root `styles.css` release asset. Use `npm run build:styles` when only regenerating CSS, or `npm run build:styles:check` to verify that the authored CSS can be rendered.
|
||||
|
||||
## Source Layout
|
||||
|
||||
|
|
@ -25,6 +26,7 @@ The source tree is organized by responsibility rather than by the original singl
|
|||
- `src/shared/` contains feature-neutral helpers, including reusable DOM pieces and unified diff display helpers shared by chat and selection rewrite.
|
||||
- `src/settings/` contains Obsidian settings models, settings-tab rendering, and app-server-backed dynamic settings data.
|
||||
- `src/domain/threads/` contains thread title, reference, and archive export helpers shared outside the chat feature.
|
||||
- `src/styles/` contains the authored CSS modules and `manifest.json` concatenation order. `scripts/build-styles.mjs` concatenates them into the ignored root `styles.css`, which remains the Obsidian release asset.
|
||||
|
||||
Keep new code near the state or API it owns. Feature code should not import from another feature directly; move shared behavior to `src/shared/`, `src/domain/`, `src/app-server/`, or `src/runtime/` when more than one feature needs it.
|
||||
|
||||
|
|
|
|||
71
scripts/build-styles.mjs
Normal file
71
scripts/build-styles.mjs
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
import { mkdir, readdir, readFile, writeFile } from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
const sourceDir = path.join("src", "styles");
|
||||
const manifestPath = path.join(sourceDir, "manifest.json");
|
||||
const outputPath = "styles.css";
|
||||
const checkMode = process.argv.includes("--check");
|
||||
const validArgs = new Set(["--check"]);
|
||||
|
||||
if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
|
||||
for (const arg of process.argv.slice(2)) {
|
||||
if (!validArgs.has(arg)) {
|
||||
console.error("Usage: node scripts/build-styles.mjs [--check]");
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (checkMode) {
|
||||
await checkStyles();
|
||||
} else {
|
||||
await buildStyles();
|
||||
}
|
||||
}
|
||||
|
||||
export async function buildStyles() {
|
||||
await mkdir(path.dirname(outputPath), { recursive: true });
|
||||
await writeFile(outputPath, await renderStyles());
|
||||
}
|
||||
|
||||
async function checkStyles() {
|
||||
await checkStyleManifest();
|
||||
await renderStyles();
|
||||
}
|
||||
|
||||
export async function renderStyles() {
|
||||
const parts = [];
|
||||
|
||||
const sourceFiles = await readStyleManifest();
|
||||
for (const file of sourceFiles) {
|
||||
const content = await readFile(path.join(sourceDir, file), "utf8");
|
||||
parts.push(content.trimEnd());
|
||||
}
|
||||
|
||||
return `${parts.join("\n\n")}\n`;
|
||||
}
|
||||
|
||||
async function readStyleManifest() {
|
||||
const value = JSON.parse(await readFile(manifestPath, "utf8"));
|
||||
if (!Array.isArray(value) || !value.every((item) => typeof item === "string")) {
|
||||
throw new Error(`${manifestPath} must be a JSON array of CSS file names.`);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
async function checkStyleManifest() {
|
||||
const sourceFiles = await readStyleManifest();
|
||||
const listed = new Set(sourceFiles);
|
||||
const duplicates = sourceFiles.filter((file, index) => sourceFiles.indexOf(file) !== index);
|
||||
const actual = (await readdir(sourceDir)).filter((file) => file.endsWith(".css")).sort((left, right) => left.localeCompare(right));
|
||||
|
||||
const missing = sourceFiles.filter((file) => !actual.includes(file));
|
||||
const unlisted = actual.filter((file) => !listed.has(file));
|
||||
|
||||
if (duplicates.length === 0 && missing.length === 0 && unlisted.length === 0) return;
|
||||
|
||||
if (duplicates.length > 0) console.error(`Duplicate entries in ${manifestPath}: ${[...new Set(duplicates)].join(", ")}`);
|
||||
if (missing.length > 0) console.error(`Listed CSS files missing from ${sourceDir}: ${missing.join(", ")}`);
|
||||
if (unlisted.length > 0) console.error(`CSS files missing from ${manifestPath}: ${unlisted.join(", ")}`);
|
||||
process.exit(1);
|
||||
}
|
||||
2346
styles.css
2346
styles.css
File diff suppressed because it is too large
Load diff
|
|
@ -1,8 +1,11 @@
|
|||
import { readFileSync } from "node:fs";
|
||||
import path from "node:path";
|
||||
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
const styles = readFileSync("styles.css", "utf8");
|
||||
const sourceDir = path.join("src", "styles");
|
||||
const sourceFiles = JSON.parse(readFileSync(path.join(sourceDir, "manifest.json"), "utf8")) as string[];
|
||||
const styles = `${sourceFiles.map((file) => readFileSync(path.join(sourceDir, file), "utf8").trimEnd()).join("\n\n")}\n`;
|
||||
|
||||
describe("panel CSS token scope", () => {
|
||||
it("defines design tokens on every standalone UI root", () => {
|
||||
|
|
|
|||
Loading…
Reference in a new issue