Files
oikos/web/node_modules/enhanced-resolve/lib/util/strip-json-comments.js
dtoro d4d99a7473
Some checks failed
ci / build-test (push) Has been cancelled
ci / docker-build (push) Has been cancelled
feat: Phase 1 — extract the client (web SPA + desktop) to dtoro/oikos-web
Problem: the hexagonal refactor churns the backend tree for nine more
phases; the UI delivery stack (web/ SPA, cmd/desktop Wails wrapper,
compose/web image) must move to its own repo first so doc/layout
rewrites land once on a backend-only tree.

Change:
- New repo git.hubris.network/dtoro/oikos-web (v0.33.0): web/, desktop/
  (updateURL repointed to oikos-web releases), compose/, own CI (web +
  desktop jobs), own deploy script (CI-green gate, TOCTOU guard,
  version-tagged images, prune-to-3), own webhook receiver on :9798 +
  launchd unit, own compose project publishing the same 8091:80.
- Cutover executed on mac-mini in order: oikos stack's web service
  stopped+removed, oikos-web project brought up on 8091; outer Caddy
  untouched (targets the published port) — serving + Authentik flow +
  /wails 404 quirk verified post-cutover.
- Stripped from oikos: web/, cmd/desktop/, compose/web/, desktop CI
  workflow, ci.yml web job, Makefile ui/desktop/desktop-package/install
  targets, the compose web service, oikos-web from deploy.sh's fallback
  prune list; wails + go-keyring dropped from go.mod, vendor synced.
- README / CONTRIBUTING / AGENTS.md / .agents dev+operations docs now
  point at the new repo; mbse + mascot design docs carry a path note.

Risk: production SPA serving depends on the new pipeline now; rollback
is versioned-image re-up of the old web service from a pre-split
checkout (port 8091). Desktop builds installed before the split still
check dtoro/oikos releases — one manual reinstall, noted in the
oikos-web release notes.

Verification: go vet, make test (race), make generate-check, golangci
(no new findings; baseline down 400→365); post-cutover curls —
localhost:8091 200, /wails/runtime.js 404, outer Caddy 302 Authentik.
2026-08-15 22:27:52 +02:00

178 lines
5.0 KiB
JavaScript

/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Natsu @xiaoxiaojx
This file contains code ported from strip-json-comments:
https://github.com/sindresorhus/strip-json-comments
Original license: MIT
Original author: Sindre Sorhus
*/
"use strict";
/**
* @typedef {object} StripJsonCommentsOptions
* @property {boolean=} whitespace Replace comments with whitespace
* @property {boolean=} trailingCommas Strip trailing commas
*/
const singleComment = Symbol("singleComment");
const multiComment = Symbol("multiComment");
/**
* Strip without whitespace (returns empty string)
* @param {string} _string Unused
* @param {number} _start Unused
* @param {number} _end Unused
* @returns {string} Empty string for all input
*/
const stripWithoutWhitespace = (_string, _start, _end) => "";
/**
* Replace all characters except ASCII spaces, tabs and line endings with regular spaces to ensure valid JSON output.
* @param {string} string String to process
* @param {number} start Start index
* @param {number} end End index
* @returns {string} Processed string with comments replaced by whitespace
*/
const stripWithWhitespace = (string, start, end) =>
string.slice(start, end).replace(/[^ \t\r\n]/g, " ");
/**
* Check if a quote is escaped
* @param {string} jsonString JSON string
* @param {number} quotePosition Position of the quote
* @returns {boolean} True if the quote at the given position is escaped
*/
const isEscaped = (jsonString, quotePosition) => {
let index = quotePosition - 1;
let backslashCount = 0;
while (jsonString[index] === "\\") {
index -= 1;
backslashCount += 1;
}
return Boolean(backslashCount % 2);
};
/**
* Strip comments from JSON string
* @param {string} jsonString JSON string with potential comments
* @param {StripJsonCommentsOptions} options Options
* @returns {string} JSON string without comments
*/
function stripJsonComments(
jsonString,
{ whitespace = true, trailingCommas = false } = {},
) {
if (typeof jsonString !== "string") {
throw new TypeError(
`Expected argument \`jsonString\` to be a \`string\`, got \`${typeof jsonString}\``,
);
}
const strip = whitespace ? stripWithWhitespace : stripWithoutWhitespace;
let isInsideString = false;
/** @type {false | typeof singleComment | typeof multiComment} */
let isInsideComment = false;
let offset = 0;
let buffer = "";
let result = "";
let commaIndex = -1;
for (let index = 0; index < jsonString.length; index++) {
const currentCharacter = jsonString[index];
const nextCharacter = jsonString[index + 1];
if (!isInsideComment && currentCharacter === '"') {
// Enter or exit string
const escaped = isEscaped(jsonString, index);
if (!escaped) {
isInsideString = !isInsideString;
}
}
if (isInsideString) {
continue;
}
if (!isInsideComment && currentCharacter + nextCharacter === "//") {
// Enter single-line comment
buffer += jsonString.slice(offset, index);
offset = index;
isInsideComment = singleComment;
index++;
} else if (
isInsideComment === singleComment &&
currentCharacter + nextCharacter === "\r\n"
) {
// Exit single-line comment via \r\n
index++;
isInsideComment = false;
buffer += strip(jsonString, offset, index);
offset = index;
continue;
} else if (isInsideComment === singleComment && currentCharacter === "\n") {
// Exit single-line comment via \n
isInsideComment = false;
buffer += strip(jsonString, offset, index);
offset = index;
} else if (!isInsideComment && currentCharacter + nextCharacter === "/*") {
// Enter multiline comment
buffer += jsonString.slice(offset, index);
offset = index;
isInsideComment = multiComment;
index++;
continue;
} else if (
isInsideComment === multiComment &&
currentCharacter + nextCharacter === "*/"
) {
// Exit multiline comment
index++;
isInsideComment = false;
buffer += strip(jsonString, offset, index + 1);
offset = index + 1;
continue;
} else if (trailingCommas && !isInsideComment) {
if (commaIndex !== -1) {
if (currentCharacter === "}" || currentCharacter === "]") {
// Strip trailing comma
buffer += jsonString.slice(offset, index);
result += strip(buffer, 0, 1) + buffer.slice(1);
buffer = "";
offset = index;
commaIndex = -1;
} else if (
currentCharacter !== " " &&
currentCharacter !== "\t" &&
currentCharacter !== "\r" &&
currentCharacter !== "\n"
) {
// Hit non-whitespace following a comma; comma is not trailing
buffer += jsonString.slice(offset, index);
offset = index;
commaIndex = -1;
}
} else if (currentCharacter === ",") {
// Flush buffer prior to this point, and save new comma index
result += buffer + jsonString.slice(offset, index);
buffer = "";
offset = index;
commaIndex = index;
}
}
}
const remaining =
isInsideComment === singleComment
? strip(jsonString, offset, jsonString.length)
: jsonString.slice(offset);
return result + buffer + remaining;
}
module.exports = stripJsonComments;