mirror of
https://github.com/alexandrev/xslt-lab.git
synced 2026-09-21 13:03:15 +00:00
fix .gitignore to be able to compile
This commit is contained in:
@@ -199,3 +199,6 @@ backend/server
|
|||||||
backend/src/.gocache
|
backend/src/.gocache
|
||||||
/config/credentials.json
|
/config/credentials.json
|
||||||
credentials.json
|
credentials.json
|
||||||
|
# Allow frontend source utilities
|
||||||
|
!frontend/src/lib/
|
||||||
|
!frontend/src/lib/**
|
||||||
|
|||||||
@@ -0,0 +1,107 @@
|
|||||||
|
const PARAM_START = "<!--PARAMS_START-->";
|
||||||
|
const PARAM_END = "<!--PARAMS_END-->";
|
||||||
|
|
||||||
|
export function parseErrorLines(txt) {
|
||||||
|
if (!txt) return [];
|
||||||
|
const starts = [];
|
||||||
|
const regex = /(^|\r?\n)(Warning|Error)\b/g;
|
||||||
|
let m;
|
||||||
|
while ((m = regex.exec(txt)) !== null) {
|
||||||
|
const start = m.index + (m[1] ? m[1].length : 0);
|
||||||
|
starts.push(start);
|
||||||
|
}
|
||||||
|
if (starts.length === 0) {
|
||||||
|
return [txt.trim()].filter(Boolean);
|
||||||
|
}
|
||||||
|
const lines = [];
|
||||||
|
const leading = txt.slice(0, starts[0]).trim();
|
||||||
|
if (leading) lines.push(leading);
|
||||||
|
for (let i = 0; i < starts.length; i++) {
|
||||||
|
const s = starts[i];
|
||||||
|
const e = i + 1 < starts.length ? starts[i + 1] : txt.length;
|
||||||
|
const chunk = txt.slice(s, e).trim();
|
||||||
|
if (chunk) lines.push(chunk);
|
||||||
|
}
|
||||||
|
return lines;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function stripParamBlock(text) {
|
||||||
|
const start = text.indexOf(PARAM_START);
|
||||||
|
const end = text.indexOf(PARAM_END);
|
||||||
|
let result = text;
|
||||||
|
if (start !== -1 && end !== -1 && end > start) {
|
||||||
|
let before = text.slice(0, start);
|
||||||
|
let after = text.slice(end + PARAM_END.length);
|
||||||
|
if (before.endsWith("\n")) before = before.slice(0, -1);
|
||||||
|
if (after.startsWith("\n")) after = after.slice(1);
|
||||||
|
result = before + after;
|
||||||
|
}
|
||||||
|
return result.replace(
|
||||||
|
/[ \t]*<xsl:param\b[^>]*?(?:\/>|>[\s\S]*?<\/xsl:param>)[ \t]*(?:\r?\n)?/g,
|
||||||
|
"",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getParamBlock(text) {
|
||||||
|
const start = text.indexOf(PARAM_START);
|
||||||
|
const end = text.indexOf(PARAM_END);
|
||||||
|
if (start !== -1 && end !== -1 && end > start) {
|
||||||
|
return text.slice(start, end);
|
||||||
|
}
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function injectParamBlock(text, params) {
|
||||||
|
const clean = stripParamBlock(text);
|
||||||
|
const match = clean.match(/<xsl:stylesheet[^>]*>/);
|
||||||
|
if (!match) return clean;
|
||||||
|
const idx = match.index + match[0].length;
|
||||||
|
const paramLines = params
|
||||||
|
.filter((p) => p.name)
|
||||||
|
.map((p) => `<xsl:param name="${p.name}"/>`)
|
||||||
|
.join("\n");
|
||||||
|
const block = `\n${PARAM_START}\n${paramLines}\n${PARAM_END}`;
|
||||||
|
return clean.slice(0, idx) + block + clean.slice(idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function extractParamNames(text) {
|
||||||
|
const clean = getParamBlock(text);
|
||||||
|
const names = new Set();
|
||||||
|
const regex = /<xsl:param[^>]*name="([^"]+)"[^>]*>/g;
|
||||||
|
let m;
|
||||||
|
while ((m = regex.exec(clean))) {
|
||||||
|
names.add(m[1]);
|
||||||
|
}
|
||||||
|
return Array.from(names);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function addParams(text, tab) {
|
||||||
|
const extractedParams = extractParamNames(text);
|
||||||
|
const existingNames = new Set(tab.params.map((p) => p.name));
|
||||||
|
const newParams = [...tab.params];
|
||||||
|
|
||||||
|
extractedParams.forEach((name) => {
|
||||||
|
if (!existingNames.has(name)) {
|
||||||
|
newParams.push({ name, value: "<root/>", open: false });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return newParams;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setStylesheetVersion(text, version) {
|
||||||
|
const regex = /<xsl:stylesheet\b([^>]*)>/;
|
||||||
|
const match = text.match(regex);
|
||||||
|
if (!match) return text;
|
||||||
|
let attrs = match[1];
|
||||||
|
if (/version=['"][^'"]*['"]/.test(attrs)) {
|
||||||
|
attrs = attrs.replace(/version=['"][^'"]*['"]/, `version="${version}"`);
|
||||||
|
} else {
|
||||||
|
attrs += ` version="${version}"`;
|
||||||
|
}
|
||||||
|
return text.replace(regex, `<xsl:stylesheet${attrs}>`);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getParamBlockMarkers() {
|
||||||
|
return { PARAM_START, PARAM_END };
|
||||||
|
}
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
import { describe, it, expect } from "vitest";
|
||||||
|
import {
|
||||||
|
addParams,
|
||||||
|
extractParamNames,
|
||||||
|
injectParamBlock,
|
||||||
|
parseErrorLines,
|
||||||
|
setStylesheetVersion,
|
||||||
|
stripParamBlock,
|
||||||
|
} from "./workspaceUtils";
|
||||||
|
|
||||||
|
const SAMPLE_STYLESHEET = `<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
|
||||||
|
<xsl:param name="foo"/>
|
||||||
|
<xsl:param name="bar"/>
|
||||||
|
<xsl:template match="/">
|
||||||
|
<root/>
|
||||||
|
</xsl:template>
|
||||||
|
</xsl:stylesheet>`;
|
||||||
|
|
||||||
|
describe("workspace utils", () => {
|
||||||
|
it("parses error lines with warning/error prefixes", () => {
|
||||||
|
const lines = parseErrorLines("intro\nWarning test 1\nError details\n");
|
||||||
|
expect(lines).toEqual(["intro", "Warning test 1", "Error details"]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("strips injected param blocks and inline params", () => {
|
||||||
|
const injected = injectParamBlock(SAMPLE_STYLESHEET, [
|
||||||
|
{ name: "alpha" },
|
||||||
|
{ name: "beta" },
|
||||||
|
]);
|
||||||
|
const cleaned = stripParamBlock(injected);
|
||||||
|
expect(cleaned).not.toContain("PARAMS_START");
|
||||||
|
expect(cleaned).not.toContain("alpha");
|
||||||
|
expect(cleaned).not.toContain("beta");
|
||||||
|
expect(cleaned).not.toMatch(/<xsl:param/);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("extracts params from existing definitions", () => {
|
||||||
|
expect(extractParamNames(SAMPLE_STYLESHEET).sort()).toEqual(["bar", "foo"]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("adds new params discovered in xslt", () => {
|
||||||
|
const tab = {
|
||||||
|
params: [{ name: "foo", value: "value", open: false }],
|
||||||
|
};
|
||||||
|
const params = addParams(SAMPLE_STYLESHEET, tab);
|
||||||
|
expect(params).toHaveLength(2);
|
||||||
|
expect(params.some((p) => p.name === "bar")).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("updates or injects stylesheet version attribute", () => {
|
||||||
|
const noVersion = SAMPLE_STYLESHEET.replace(`version="1.0"`, "");
|
||||||
|
expect(setStylesheetVersion(noVersion, "2.0")).toContain(`version="2.0"`);
|
||||||
|
expect(setStylesheetVersion(SAMPLE_STYLESHEET, "3.0")).toContain(
|
||||||
|
`version="3.0"`,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user