arcane-os 0.45.0 → 0.47.0
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/CHANGELOG.md +39 -0
- package/README.md +1 -1
- package/browser-runtime/ai/browser-speech-recognition.mjs +495 -0
- package/browser-runtime/ai/browser-speech.mjs +1 -0
- package/docs/reference/ai/browser-speech.md +80 -2
- package/docs/reference/availability-and-normalization.md +2 -1
- package/docs/reference/inventory/package-api.json +14 -0
- package/docs/reference/runtime-components.md +59 -4
- package/docs/reference/runtime-modules.md +78 -10
- package/docs/reference/sdk-api.md +57 -0
- package/package.json +2 -2
- package/runtime/arcane/components/file-manager.html +35 -3
- package/runtime/arcane/components/speech.html +141 -11
- package/runtime/arcane/components/voice-transcription.html +77 -8
- package/runtime/arcane/css/theme.css +41 -0
- package/runtime/arcane/modules/AI.js +15 -4
- package/runtime/arcane/modules/AIProviderRuntime.js +118 -0
- package/runtime/arcane/modules/MD.js +14 -0
- package/runtime/arcane/modules/MarkdownMedia.js +41 -13
- package/runtime/arcane/modules/PrintView.js +23 -3
|
@@ -59,24 +59,28 @@ export async function saveMarkdownMedia({
|
|
|
59
59
|
};
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
-
/**
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
if (
|
|
71
|
-
|
|
62
|
+
/**
|
|
63
|
+
* Decode a complete local media record or its JSON text without storage or
|
|
64
|
+
* network access. Unrecognized content returns null; recognized records with
|
|
65
|
+
* unreadable encoding throw. Records carry dataUrl and an optional mediaType;
|
|
66
|
+
* omitting mediaType preserves Blob's empty type. No source content is changed.
|
|
67
|
+
*/
|
|
68
|
+
export function decodeMarkdownMediaRecord(value) {
|
|
69
|
+
let record = value;
|
|
70
|
+
if (is.string(record)) {
|
|
71
|
+
try {
|
|
72
|
+
record = JSON.parse(record);
|
|
73
|
+
} catch {
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
72
76
|
}
|
|
73
77
|
// DBOPFS parses JSONL/NDJSON as record arrays; restoring a parsed backup can
|
|
74
78
|
// wrap its one record again. Never choose one image from multiple records.
|
|
75
|
-
let record = is.string(stored) ? JSON.parse(stored) : stored;
|
|
76
79
|
while (is.array(record) && record.length === 1) record = record[0];
|
|
77
|
-
|
|
80
|
+
if (!record || !is.object(record) || is.array(record) || !('dataUrl' in record)) return null;
|
|
81
|
+
const encoded = /^data:[^,]*;base64,([\s\S]*)$/u.exec(record.dataUrl);
|
|
78
82
|
if (!encoded) {
|
|
79
|
-
throw new TypeError(
|
|
83
|
+
throw new TypeError('Markdown image has an unreadable data URL.');
|
|
80
84
|
}
|
|
81
85
|
// Decode locally; a stored string is never passed to Fetch or a network API.
|
|
82
86
|
const decoded = atob(encoded[1]);
|
|
@@ -86,6 +90,30 @@ export async function readMarkdownMedia(reference) {
|
|
|
86
90
|
return new Blob([content], {type: record.mediaType});
|
|
87
91
|
}
|
|
88
92
|
|
|
93
|
+
/** Read the complete local image for display or application-owned export. */
|
|
94
|
+
export async function readMarkdownMedia(reference) {
|
|
95
|
+
const address = parseMarkdownMediaReference(reference);
|
|
96
|
+
if (!address) {
|
|
97
|
+
throw new TypeError('Expected an arcane-media: reference.');
|
|
98
|
+
}
|
|
99
|
+
const {default: DBOPFS} = await import('./DBOPFS.js');
|
|
100
|
+
const stored = await new DBOPFS().get(address.tableName, address.fileName);
|
|
101
|
+
if (stored === null || stored === undefined) {
|
|
102
|
+
throw new DOMException(`Markdown image was not found: ${reference}`, 'NotFoundError');
|
|
103
|
+
}
|
|
104
|
+
// Preserve the strict stored-JSON parser boundary for explicit reads.
|
|
105
|
+
const record = is.string(stored) ? JSON.parse(stored) : stored;
|
|
106
|
+
const unreadable = `Markdown image has an unreadable data URL: ${reference}`;
|
|
107
|
+
try {
|
|
108
|
+
const blob = decodeMarkdownMediaRecord(record);
|
|
109
|
+
if (blob) return blob;
|
|
110
|
+
} catch (error) {
|
|
111
|
+
if (!(error instanceof TypeError)) throw error;
|
|
112
|
+
throw new TypeError(unreadable, {cause: error});
|
|
113
|
+
}
|
|
114
|
+
throw new TypeError(unreadable);
|
|
115
|
+
}
|
|
116
|
+
|
|
89
117
|
/**
|
|
90
118
|
* Resolve only local Markdown IMG references beneath a rendered root (including
|
|
91
119
|
* an IMG root). Markdown source and ordinary URLs are never changed. Independent
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import Is from 'strong-type';
|
|
2
|
+
import {arcaneLightThemeTokens} from '../entities/Theme.js';
|
|
2
3
|
|
|
3
4
|
const is=new Is(false);
|
|
4
5
|
const registries=new WeakMap();
|
|
@@ -400,17 +401,36 @@ function capture(registry,session){
|
|
|
400
401
|
const heading=document.createElement('h1');
|
|
401
402
|
heading.textContent=session.title;
|
|
402
403
|
const rendered=copyRendered(session.content,state,true);
|
|
403
|
-
|
|
404
|
+
// Screen layout and fonts describe the rendered content; screen-theme paint
|
|
405
|
+
// does not describe a readable paper surface. Keep this palette in the
|
|
406
|
+
// snapshot, including its pseudo-elements, without recoloring SVG artwork.
|
|
407
|
+
styles.textContent=`
|
|
408
|
+
:host{color-scheme:light!important;color:${arcaneLightThemeTokens.text}!important;background:${arcaneLightThemeTokens.surface}!important;font:12pt/1.5 serif}
|
|
409
|
+
:host>h1{margin:0 0 .75em;font-size:1.5em;line-height:1.2}
|
|
410
|
+
[data-arcane-print-node]:not(svg,svg *,img,video,audio),
|
|
411
|
+
[data-arcane-print-node]:not(svg,svg *,img,video,audio)::before,
|
|
412
|
+
[data-arcane-print-node]:not(svg,svg *,img,video,audio)::after{
|
|
413
|
+
color:${arcaneLightThemeTokens.text}!important;background-color:transparent!important;
|
|
414
|
+
border-color:${arcaneLightThemeTokens.border}!important;color-scheme:light!important;
|
|
415
|
+
-webkit-text-fill-color:currentColor!important;-webkit-text-stroke:0!important;
|
|
416
|
+
text-decoration-color:currentColor!important;text-shadow:none!important;box-shadow:none!important
|
|
417
|
+
}
|
|
418
|
+
a[data-arcane-print-node]:not(svg *){text-decoration:underline!important}
|
|
419
|
+
table[data-arcane-print-node]:not(svg *){border-collapse:collapse!important}
|
|
420
|
+
th[data-arcane-print-node]:not(svg *),td[data-arcane-print-node]:not(svg *){border:1px solid ${arcaneLightThemeTokens.border}!important;padding:.35em .5em!important}
|
|
421
|
+
${state.rules.join('\n')}
|
|
422
|
+
`;
|
|
404
423
|
root.append(styles,heading,rendered);
|
|
405
424
|
const sheet=document.createElement('style');
|
|
406
425
|
session.sheet=sheet;
|
|
407
426
|
sheet.textContent=`
|
|
408
427
|
[data-arcane-print-stage]{display:none!important}
|
|
409
428
|
@media print{
|
|
410
|
-
|
|
429
|
+
@page{margin:15mm}
|
|
430
|
+
html:root,html:root>body{display:block!important;height:auto!important;min-height:0!important;max-height:none!important;overflow:visible!important;contain:none!important;margin:0!important;padding:0!important;border:0!important;background:${arcaneLightThemeTokens.surface}!important;color:${arcaneLightThemeTokens.text}!important;color-scheme:light!important}
|
|
411
431
|
html:root>body>*:not([data-arcane-print-stage]){display:none!important}
|
|
412
432
|
html:root>body::before,html:root>body::after{display:none!important}
|
|
413
|
-
html:root>body>[data-arcane-print-stage]{display:block!important;position:static!important;width:auto!important;height:auto!important;overflow:visible!important}
|
|
433
|
+
html:root>body>[data-arcane-print-stage]{display:block!important;position:static!important;width:auto!important;height:auto!important;overflow:visible!important;margin:0!important;padding:0!important;border:0!important}
|
|
414
434
|
}
|
|
415
435
|
`;
|
|
416
436
|
document.head.append(sheet);
|