Implements Phases 1-8 of the TFTSR implementation plan. Rust backend (Tauri 2.x, src-tauri/): - Multi-provider AI: OpenAI-compatible, Anthropic, Gemini, Mistral, Ollama - PII detection engine: 11 regex patterns with overlap resolution - SQLCipher AES-256 encrypted database with 10 versioned migrations - 28 Tauri IPC commands for triage, analysis, document, and system ops - Ollama: hardware probe, model recommendations, pull/delete with events - RCA and blameless post-mortem Markdown document generators - PDF export via printpdf - Audit log: SHA-256 hash of every external data send - Integration stubs for Confluence, ServiceNow, Azure DevOps (v0.2) Frontend (React 18 + TypeScript + Vite, src/): - 9 pages: full triage workflow NewIssue→LogUpload→Triage→Resolution→RCA→Postmortem→History+Settings - 7 components: ChatWindow, TriageProgress, PiiDiffViewer, DocEditor, HardwareReport, ModelSelector, UI primitives - 3 Zustand stores: session, settings (persisted), history - Type-safe tauriCommands.ts matching Rust backend types exactly - 8 IT domain system prompts (Linux, Windows, Network, K8s, DB, Virt, HW, Obs) DevOps: - .woodpecker/test.yml: rustfmt, clippy, cargo test, tsc, vitest on every push - .woodpecker/release.yml: linux/amd64 + linux/arm64 builds, Gogs release upload Verified: - cargo check: zero errors - tsc --noEmit: zero errors - vitest run: 13/13 unit tests passing Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
119 lines
3.3 KiB
JavaScript
119 lines
3.3 KiB
JavaScript
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.css = css;
|
|
const utils_js_1 = require("../utils.js");
|
|
const domhandler_1 = require("domhandler");
|
|
/**
|
|
* Set multiple CSS properties for every matched element.
|
|
*
|
|
* @category CSS
|
|
* @param prop - The names of the properties.
|
|
* @param val - The new values.
|
|
* @returns The instance itself.
|
|
* @see {@link https://api.jquery.com/css/}
|
|
*/
|
|
function css(prop, val) {
|
|
if ((prop != null && val != null) ||
|
|
// When `prop` is a "plain" object
|
|
(typeof prop === 'object' && !Array.isArray(prop))) {
|
|
return (0, utils_js_1.domEach)(this, (el, i) => {
|
|
if ((0, domhandler_1.isTag)(el)) {
|
|
// `prop` can't be an array here anymore.
|
|
setCss(el, prop, val, i);
|
|
}
|
|
});
|
|
}
|
|
if (this.length === 0) {
|
|
return undefined;
|
|
}
|
|
return getCss(this[0], prop);
|
|
}
|
|
/**
|
|
* Set styles of all elements.
|
|
*
|
|
* @private
|
|
* @param el - Element to set style of.
|
|
* @param prop - Name of property.
|
|
* @param value - Value to set property to.
|
|
* @param idx - Optional index within the selection.
|
|
*/
|
|
function setCss(el, prop, value, idx) {
|
|
if (typeof prop === 'string') {
|
|
const styles = getCss(el);
|
|
const val = typeof value === 'function' ? value.call(el, idx, styles[prop]) : value;
|
|
if (val === '') {
|
|
delete styles[prop];
|
|
}
|
|
else if (val != null) {
|
|
styles[prop] = val;
|
|
}
|
|
el.attribs['style'] = stringify(styles);
|
|
}
|
|
else if (typeof prop === 'object') {
|
|
const keys = Object.keys(prop);
|
|
for (let i = 0; i < keys.length; i++) {
|
|
const k = keys[i];
|
|
setCss(el, k, prop[k], i);
|
|
}
|
|
}
|
|
}
|
|
function getCss(el, prop) {
|
|
if (!el || !(0, domhandler_1.isTag)(el))
|
|
return;
|
|
const styles = parse(el.attribs['style']);
|
|
if (typeof prop === 'string') {
|
|
return styles[prop];
|
|
}
|
|
if (Array.isArray(prop)) {
|
|
const newStyles = {};
|
|
for (const item of prop) {
|
|
if (styles[item] != null) {
|
|
newStyles[item] = styles[item];
|
|
}
|
|
}
|
|
return newStyles;
|
|
}
|
|
return styles;
|
|
}
|
|
/**
|
|
* Stringify `obj` to styles.
|
|
*
|
|
* @private
|
|
* @category CSS
|
|
* @param obj - Object to stringify.
|
|
* @returns The serialized styles.
|
|
*/
|
|
function stringify(obj) {
|
|
return Object.keys(obj).reduce((str, prop) => `${str}${str ? ' ' : ''}${prop}: ${obj[prop]};`, '');
|
|
}
|
|
/**
|
|
* Parse `styles`.
|
|
*
|
|
* @private
|
|
* @category CSS
|
|
* @param styles - Styles to be parsed.
|
|
* @returns The parsed styles.
|
|
*/
|
|
function parse(styles) {
|
|
styles = (styles || '').trim();
|
|
if (!styles)
|
|
return {};
|
|
const obj = {};
|
|
let key;
|
|
for (const str of styles.split(';')) {
|
|
const n = str.indexOf(':');
|
|
// If there is no :, or if it is the first/last character, add to the previous item's value
|
|
if (n < 1 || n === str.length - 1) {
|
|
const trimmed = str.trimEnd();
|
|
if (trimmed.length > 0 && key !== undefined) {
|
|
obj[key] += `;${trimmed}`;
|
|
}
|
|
}
|
|
else {
|
|
key = str.slice(0, n).trim();
|
|
obj[key] = str.slice(n + 1).trim();
|
|
}
|
|
}
|
|
return obj;
|
|
}
|
|
//# sourceMappingURL=css.js.map
|