Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .frontmatter/database/mediaDb.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"template":{}}
{ "template": {} }
2 changes: 1 addition & 1 deletion .frontmatter/database/pinnedItemsDb.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{}
{}
2 changes: 1 addition & 1 deletion .frontmatter/database/taxonomyDb.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{}
{}
15 changes: 7 additions & 8 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
{
"[markdown]": {
},
"typescript.surveys.enabled": false,
"typescript.disableAutomaticTypeAcquisition": true,
"output.smartScroll.enabled": false,
"problems.autoReveal": false,
"terminal.integrated.focusAfterRun": "terminal",
"biome.lspBin": null
"[markdown]": {},
"typescript.surveys.enabled": false,
"typescript.disableAutomaticTypeAcquisition": true,
"output.smartScroll.enabled": false,
"problems.autoReveal": false,
"terminal.integrated.focusAfterRun": "terminal",
"biome.lspBin": null
}
4 changes: 2 additions & 2 deletions bin/docstatic.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#!/usr/bin/env node

const fs = require("fs-extra");
const path = require("path");
const { execSync } = require("child_process");
const path = require("node:path");
const { execSync } = require("node:child_process");

const projectName = process.argv[2];
if (!projectName) {
Expand Down
43 changes: 30 additions & 13 deletions biome.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,32 +4,47 @@
"maxSize": 10485760,
"includes": [
"**",
"!**/.next/**",
"!**/node_modules/**",
"!**/dist/**",
"!**/public/**",
"!**/content/**",
"!**/coverage/**",
"!**/tina/__generated__/**",
"!**/.next",
"!**/node_modules",
"!**/dist",
"!**/public",
"!**/content",
"!**/coverage",
"!**/tina/__generated__",
"!**/tina/tina-lock.json",
"!**/src/styles/**",
"!**/src/styles",
"!**/reuse/code-files.json",
"!**/reuse/snippets-files.json",
"!**/reuse/media/index.json",
"!**/src/data/docs-metadata.json",
"!**/config/**/*.json"
"!**/config/**/*.json",
"!**/static/admin",
"!**/build",
"!**/.docusaurus",
"!**/src/css/theme-variables.css",
"!**/update-manifest.json"
]
},
"overrides": [
{
"includes": ["scripts/**", "bin/**", "create-docstatic/**"],
"includes": ["**/scripts/**", "**/bin/**", "**/create-docstatic/**"],
"linter": {
"rules": {
"suspicious": {
"noConsole": "off"
}
}
}
},
{
"includes": ["**/src/css/custom.css"],
"linter": {
"rules": {
"style": {
"noDescendingSpecificity": "off"
}
}
}
}
],
"formatter": {
Expand All @@ -53,7 +68,7 @@
"linter": {
"enabled": true,
"rules": {
"recommended": true,
"preset": "recommended",
"suspicious": {
"noConsole": "error",
"noExplicitAny": "off",
Expand All @@ -79,7 +94,8 @@
"complexity": {
"noForEach": "error",
"useOptionalChain": "error",
"noBannedTypes": "off"
"noBannedTypes": "off",
"noImportantStyles": "off"
}
}
},
Expand All @@ -94,6 +110,7 @@
"quoteStyle": "double",
"attributePosition": "auto",
"bracketSpacing": true
}
},
"jsxRuntime": "reactClassic"
}
}
90 changes: 84 additions & 6 deletions create-docstatic/index.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
#!/usr/bin/env node

const fs = require("fs");
const os = require("os");
const path = require("path");
const { execSync, execFileSync } = require("child_process");
const fs = require("node:fs");
const os = require("node:os");
const path = require("node:path");
const { execSync, execFileSync } = require("node:child_process");

const HELP = `
Usage: npx create-docstatic@latest <project-name> [options]
Expand Down Expand Up @@ -38,6 +38,33 @@ function fail(message) {
process.exit(1);
}

// Minimal numeric semver compare; enough for the x.y.z versions we publish.
function compareVersions(a, b) {
const pa = String(a).split("-")[0].split(".").map(Number);
const pb = String(b).split("-")[0].split(".").map(Number);
for (let i = 0; i < 3; i++) {
const d = (pa[i] || 0) - (pb[i] || 0);
if (d !== 0) return d < 0 ? -1 : 1;
}
return 0;
}

// A docstatic release can require a newer CLI than the one being run — for
// example when the template starts shipping a file under a new name that only
// a newer CLI knows to rename. Refuse by name rather than producing a subtly
// broken site. Manifests without the field predate the check and are allowed.
function assertManifestSupported(manifest) {
const required = manifest.minCreateVersion;
if (!required) return;
const current = require("./package.json").version;
if (compareVersions(current, required) < 0) {
fail(
`This docstatic release needs create-docstatic ${required} or later, but you are running ${current}.\n` +
"Re-run with: npx create-docstatic@latest"
);
}
}

function parseArgs(argv) {
const options = {
projectName: null,
Expand Down Expand Up @@ -248,13 +275,18 @@ function runUpdate(options) {
);
}
const manifest = JSON.parse(fs.readFileSync(manifestPath, "utf8"));
assertManifestSupported(manifest);
const templateDir = path.join(packageDir, "template");

// Some files ship under a different name than they take in the site (see
// renameFiles in the manifest, e.g. biome.template.json -> biome.json).
const renames = manifest.renameFiles || {};
const copy = (rel) => {
const src = path.join(templateDir, rel);
const dest = path.join(siteDir, rel);
const destRel = renames[rel] || rel;
const dest = path.join(siteDir, destRel);
if (!fs.existsSync(src) || filesEqual(src, dest)) return;
log(fs.existsSync(dest) ? "update" : "add", rel);
log(fs.existsSync(dest) ? "update" : "add", destRel);
if (dryRun) return;
fs.mkdirSync(path.dirname(dest), { recursive: true });
fs.copyFileSync(src, dest);
Expand Down Expand Up @@ -378,6 +410,13 @@ function main() {
const packageDir = downloadTemplate(options.tag, tmpDir);
const templateDir = resolveTemplateDir(packageDir, options.template);

// Checked before anything is written, so a refusal leaves no debris.
const scaffoldManifestPath = path.join(packageDir, "update-manifest.json");
const scaffoldManifest = fs.existsSync(scaffoldManifestPath)
? JSON.parse(fs.readFileSync(scaffoldManifestPath, "utf8"))
: null;
if (scaffoldManifest) assertManifestSupported(scaffoldManifest);

console.log(`Creating a new docStatic site in ${targetDir}...`);
fs.mkdirSync(targetDir, { recursive: true });
fs.cpSync(templateDir, targetDir, { recursive: true });
Expand All @@ -389,6 +428,45 @@ function main() {
fs.renameSync(gitignorePath, path.join(targetDir, ".gitignore"));
}

// Files the template ships under a different name (biome.template.json ->
// biome.json, so Biome does not discover it inside the docstatic repo).
if (scaffoldManifest) {
const renameFiles = scaffoldManifest.renameFiles || {};
for (const [from, to] of Object.entries(renameFiles)) {
const fromPath = path.join(targetDir, from);
if (fs.existsSync(fromPath)) {
fs.renameSync(fromPath, path.join(targetDir, to));
}
}

// Every declared rename must have landed. Without this a mismatch
// between the manifest and this CLI ships a site missing the renamed
// file entirely (a scaffolded site with no biome.json, say) and says
// nothing about it.
for (const [from, to] of Object.entries(renameFiles)) {
if (fs.existsSync(path.join(targetDir, from))) {
fail(`Template file "${from}" was not renamed to "${to}".`);
}
if (!fs.existsSync(path.join(targetDir, to))) {
fail(
`Template file "${to}" is missing after renaming from "${from}".`
);
}
}

// Catch-all for a *.template.json added to the template but never
// declared in renameFiles.
const stray = fs
.readdirSync(targetDir)
.filter((f) => f.endsWith(".template.json"));
if (stray.length) {
fail(
`Template shipped ${stray.join(", ")} without a renameFiles entry. ` +
"This is a docstatic packaging bug; try npx create-docstatic@latest."
);
}
}

const packageJsonPath = path.join(targetDir, "package.json");
if (fs.existsSync(packageJsonPath)) {
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf8"));
Expand Down
2 changes: 1 addition & 1 deletion create-docstatic/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "create-docstatic",
"version": "0.2.0",
"version": "0.2.1",
"description": "Create a docStatic documentation site with one command.",
"author": "aowendev <aowen@ieee.org>",
"license": "MIT",
Expand Down
Loading
Loading