@hraness/slopcamera 3.10.2 → 3.10.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -12
- package/apps/desktop/application/operation.ts +1 -1
- package/apps/desktop/cli/asset-ingest.ts +31 -7
- package/apps/desktop/cli/commands.ts +1 -1
- package/apps/desktop/dist/cli/main.js +243 -243
- package/apps/desktop/workflows/fragments.ts +5 -1
- package/dist/cli.js +1 -1
- package/dist/{index-6a3k1hvj.js → index-xm1zqhzc.js} +1 -1
- package/dist/index.js +1 -1
- package/docs/README.md +8 -8
- package/package.json +1 -1
- package/src/version.ts +1 -1
package/README.md
CHANGED
|
@@ -365,15 +365,3 @@ to support development and opens no browser. `support dismiss` opts out across
|
|
|
365
365
|
the local suite, `support snooze` pauses the notice for 30 days, and
|
|
366
366
|
`HRANESS_SUPPORT_AUDIENCE=off` disables ambient notices. Agents follow the
|
|
367
367
|
[support reference](skills/slopcamera/references/support.md).
|
|
368
|
-
|
|
369
|
-
## Former name
|
|
370
|
-
|
|
371
|
-
<details>
|
|
372
|
-
<summary>Historical Atet release evidence</summary>
|
|
373
|
-
|
|
374
|
-
SlopCamera was called Atet until September 2026.
|
|
375
|
-
[Atet v3.2.3](https://github.com/hraness/atet/releases/tag/v3.2.3) and its
|
|
376
|
-
[original archive](https://github.com/hraness/atet/releases/download/v3.2.3/hraness-atet-3.2.3.tgz)
|
|
377
|
-
still install Atet, not SlopCamera.
|
|
378
|
-
|
|
379
|
-
</details>
|
|
@@ -4,7 +4,7 @@ import type { z } from "zod";
|
|
|
4
4
|
|
|
5
5
|
import type { ApplicationContext } from "./context";
|
|
6
6
|
|
|
7
|
-
export const SLOPCAMERA_APPLICATION_TOOL_VERSION = "slopcamera-3.10.
|
|
7
|
+
export const SLOPCAMERA_APPLICATION_TOOL_VERSION = "slopcamera-3.10.3" as const;
|
|
8
8
|
|
|
9
9
|
export const OPERATION_KINDS = [
|
|
10
10
|
"scene.audit",
|
|
@@ -93,6 +93,31 @@ function isWithin(root: string, candidate: string): boolean {
|
|
|
93
93
|
return pathRelative === "" || (!pathRelative.startsWith("..") && !isAbsolute(pathRelative));
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
+
function svgRootAttributes(contents: string): string | undefined {
|
|
97
|
+
let offset = 0;
|
|
98
|
+
const whitespace = /\s+/uy;
|
|
99
|
+
const skipWhitespace = (): void => {
|
|
100
|
+
whitespace.lastIndex = offset;
|
|
101
|
+
offset += whitespace.exec(contents)?.[0].length ?? 0;
|
|
102
|
+
};
|
|
103
|
+
skipWhitespace();
|
|
104
|
+
const declaration = /<\?xml[^>]*>\s*/iuy;
|
|
105
|
+
declaration.lastIndex = offset;
|
|
106
|
+
offset += declaration.exec(contents)?.[0].length ?? 0;
|
|
107
|
+
|
|
108
|
+
// Consume each comment once. A repeated lazy regex can reconsider every
|
|
109
|
+
// earlier comment terminator when the SVG root is missing.
|
|
110
|
+
while (contents.startsWith("<!--", offset)) {
|
|
111
|
+
const end = contents.indexOf("-->", offset + 4);
|
|
112
|
+
if (end === -1) return undefined;
|
|
113
|
+
offset = end + 3;
|
|
114
|
+
skipWhitespace();
|
|
115
|
+
}
|
|
116
|
+
const root = /<svg(?=[\s>])([^>]*)>/iuy;
|
|
117
|
+
root.lastIndex = offset;
|
|
118
|
+
return root.exec(contents)?.[1];
|
|
119
|
+
}
|
|
120
|
+
|
|
96
121
|
function validateSvg(bytes: Uint8Array): boolean {
|
|
97
122
|
if (bytes.length > MAX_SVG_BYTES) return false;
|
|
98
123
|
let contents: string;
|
|
@@ -101,8 +126,7 @@ function validateSvg(bytes: Uint8Array): boolean {
|
|
|
101
126
|
} catch {
|
|
102
127
|
return false;
|
|
103
128
|
}
|
|
104
|
-
|
|
105
|
-
if (!/^(?:<\?xml[^>]*>\s*)?(?:<!--[\s\S]*?-->\s*)*<svg(?:\s|>)/iu.test(start)) return false;
|
|
129
|
+
if (svgRootAttributes(contents) === undefined) return false;
|
|
106
130
|
if (
|
|
107
131
|
/<!DOCTYPE|<!ENTITY|<\?xml-stylesheet|<\s*(?:script|foreignObject|iframe|object|embed)\b/iu.test(contents)
|
|
108
132
|
|| /\s+on[a-z][a-z0-9_-]*\s*=/iu.test(contents)
|
|
@@ -227,13 +251,13 @@ export function parseSvgIntrinsicSize(bytes: Uint8Array): OverlayIntrinsicSize {
|
|
|
227
251
|
throw new CliError("invalid-data", "SVG overlay is not valid UTF-8.");
|
|
228
252
|
}
|
|
229
253
|
if (!validateSvg(bytes)) throw new CliError("invalid-data", "SVG overlay failed the safe SVG profile.");
|
|
230
|
-
const
|
|
231
|
-
if (
|
|
254
|
+
const attributes = svgRootAttributes(contents);
|
|
255
|
+
if (attributes === undefined) {
|
|
232
256
|
throw new CliError("invalid-data", "SVG overlay omits its root element.");
|
|
233
257
|
}
|
|
234
|
-
const width = svgLength(svgAttribute(
|
|
235
|
-
const height = svgLength(svgAttribute(
|
|
236
|
-
const viewBox = svgAttribute(
|
|
258
|
+
const width = svgLength(svgAttribute(attributes, "width"));
|
|
259
|
+
const height = svgLength(svgAttribute(attributes, "height"));
|
|
260
|
+
const viewBox = svgAttribute(attributes, "viewBox")
|
|
237
261
|
?.split(/[\s,]+/u)
|
|
238
262
|
.filter(Boolean)
|
|
239
263
|
.map(Number);
|
|
@@ -365,7 +365,7 @@ import {
|
|
|
365
365
|
workflowRunStore,
|
|
366
366
|
} from "./workflow-runs";
|
|
367
367
|
|
|
368
|
-
export const SLOPCAMERA_VERSION = "3.10.
|
|
368
|
+
export const SLOPCAMERA_VERSION = "3.10.3";
|
|
369
369
|
|
|
370
370
|
// Legacy direct renders predate per-target output contracts. Keep them
|
|
371
371
|
// bounded generously enough for long-form production while preventing one
|