hyperbook 0.99.0 → 0.100.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/dist/assets/codemirror/codemirror.bundle.js +10 -10
- package/dist/assets/directive-abc-music/style.css +23 -0
- package/dist/assets/directive-archive/style.css +9 -3
- package/dist/assets/directive-download/style.css +9 -3
- package/dist/assets/directive-openscad/client.js +77 -40
- package/dist/assets/directive-openscad/style.css +36 -3
- package/dist/assets/directive-p5/client.js +8 -7
- package/dist/assets/directive-p5/style.css +25 -0
- package/dist/assets/directive-protect/style.css +11 -5
- package/dist/assets/directive-pyide/client.js +1207 -170
- package/dist/assets/directive-pyide/style.css +158 -2
- package/dist/assets/directive-typst/style.css +44 -2
- package/dist/assets/directive-webide/client.js +40 -18
- package/dist/assets/directive-webide/style.css +31 -1
- package/dist/assets/shell.css +16 -16
- package/dist/index.js +558 -318
- package/dist/locales/de.json +1 -0
- package/dist/locales/en.json +1 -0
- package/package.json +7 -5
|
@@ -249,3 +249,26 @@
|
|
|
249
249
|
.directive-abc-music .buttons button:hover {
|
|
250
250
|
background-color: var(--color-spacer);
|
|
251
251
|
}
|
|
252
|
+
|
|
253
|
+
/* Icon-only toolbar: the written labels made this row wrap on narrow screens,
|
|
254
|
+
so the wording moved into title/aria-label. */
|
|
255
|
+
.directive-abc-music .buttons.bottom button {
|
|
256
|
+
flex: 0 0 auto;
|
|
257
|
+
min-width: 42px;
|
|
258
|
+
width: 42px;
|
|
259
|
+
padding: 8px 0;
|
|
260
|
+
display: flex;
|
|
261
|
+
align-items: center;
|
|
262
|
+
justify-content: center;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
.directive-abc-music .buttons.bottom button .icon {
|
|
266
|
+
width: 18px;
|
|
267
|
+
height: 18px;
|
|
268
|
+
display: block;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/* Fullscreen sits apart, at the trailing edge of the toolbar. */
|
|
272
|
+
.directive-abc-music .buttons.bottom button.fullscreen {
|
|
273
|
+
margin-inline-start: auto;
|
|
274
|
+
}
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
background: transparent;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
.directive-archive
|
|
15
|
+
.directive-archive > .icon {
|
|
16
16
|
display: flex;
|
|
17
17
|
border-right-color: var(--color-spacer);
|
|
18
18
|
align-items: center;
|
|
@@ -22,11 +22,17 @@
|
|
|
22
22
|
border-right-width: 1px;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
.directive-archive
|
|
25
|
+
.directive-archive > .label {
|
|
26
26
|
flex: 1;
|
|
27
27
|
padding: 12px 16px;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
.directive-archive
|
|
30
|
+
.directive-archive > .offline {
|
|
31
31
|
text-decoration: line-through;
|
|
32
32
|
}
|
|
33
|
+
|
|
34
|
+
.directive-archive > .icon .icon {
|
|
35
|
+
width: 26px;
|
|
36
|
+
height: 26px;
|
|
37
|
+
display: block;
|
|
38
|
+
}
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
background: transparent;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
.directive-download
|
|
15
|
+
.directive-download > .icon {
|
|
16
16
|
display: flex;
|
|
17
17
|
border-right-color: var(--color-spacer);
|
|
18
18
|
align-items: center;
|
|
@@ -22,11 +22,17 @@
|
|
|
22
22
|
border-right-width: 1px;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
.directive-download
|
|
25
|
+
.directive-download > .label {
|
|
26
26
|
flex: 1;
|
|
27
27
|
padding: 12px 16px;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
.directive-download
|
|
30
|
+
.directive-download > .offline {
|
|
31
31
|
text-decoration: line-through;
|
|
32
32
|
}
|
|
33
|
+
|
|
34
|
+
.directive-download > .icon .icon {
|
|
35
|
+
width: 26px;
|
|
36
|
+
height: 26px;
|
|
37
|
+
display: block;
|
|
38
|
+
}
|
|
@@ -34436,12 +34436,68 @@ void main() {
|
|
|
34436
34436
|
}
|
|
34437
34437
|
return { vertices, faces, colors };
|
|
34438
34438
|
};
|
|
34439
|
+
var splitByColor = (vertices, faces, colorCount) => {
|
|
34440
|
+
const groups = Array.from({ length: colorCount }, () => ({ faceIndices: [] }));
|
|
34441
|
+
faces.forEach((face, faceIdx) => {
|
|
34442
|
+
groups[face.colorIndex].faceIndices.push(faceIdx);
|
|
34443
|
+
});
|
|
34444
|
+
return groups.filter((g) => g.faceIndices.length > 0).map(({ faceIndices }, groupIdx) => {
|
|
34445
|
+
const oldToNew = /* @__PURE__ */ new Map();
|
|
34446
|
+
const groupVertices = [];
|
|
34447
|
+
for (const faceIdx of faceIndices) {
|
|
34448
|
+
for (const vIdx of faces[faceIdx].vertices) {
|
|
34449
|
+
if (!oldToNew.has(vIdx)) {
|
|
34450
|
+
oldToNew.set(vIdx, groupVertices.length);
|
|
34451
|
+
groupVertices.push(vertices[vIdx]);
|
|
34452
|
+
}
|
|
34453
|
+
}
|
|
34454
|
+
}
|
|
34455
|
+
const groupFaces = faceIndices.map((faceIdx) => ({
|
|
34456
|
+
...faces[faceIdx],
|
|
34457
|
+
vertices: faces[faceIdx].vertices.map((vIdx) => oldToNew.get(vIdx))
|
|
34458
|
+
}));
|
|
34459
|
+
return { vertices: groupVertices, faces: groupFaces };
|
|
34460
|
+
});
|
|
34461
|
+
};
|
|
34439
34462
|
var exportIndexedPolyhedronTo3mf = (polyhedron) => {
|
|
34440
|
-
const objectUuid = createUuid();
|
|
34441
34463
|
const buildUuid = createUuid();
|
|
34442
34464
|
const extruderIndexByColorIndex = polyhedron.colors.map(
|
|
34443
34465
|
(_, idx) => idx % PAINT_COLOR_MAP.length
|
|
34444
34466
|
);
|
|
34467
|
+
const materialsId = 1;
|
|
34468
|
+
const components = splitByColor(polyhedron.vertices, polyhedron.faces, polyhedron.colors.length);
|
|
34469
|
+
const objectXmls = components.map((comp, compIdx) => {
|
|
34470
|
+
const objectId = compIdx + 2;
|
|
34471
|
+
const objectUuid = createUuid();
|
|
34472
|
+
const colorIndex = comp.faces[0]?.colorIndex ?? 0;
|
|
34473
|
+
const paintColor = PAINT_COLOR_MAP[extruderIndexByColorIndex[colorIndex]];
|
|
34474
|
+
return [
|
|
34475
|
+
`<object id="${objectId}" name="OpenSCAD Model ${compIdx + 1}" type="model" p:UUID="${objectUuid}" pid="${materialsId}" pindex="${colorIndex}">`,
|
|
34476
|
+
"<mesh>",
|
|
34477
|
+
"<vertices>",
|
|
34478
|
+
...comp.vertices.map(
|
|
34479
|
+
(vertex2) => `<vertex x="${vertex2.x}" y="${vertex2.y}" z="${vertex2.z}" />`
|
|
34480
|
+
),
|
|
34481
|
+
"</vertices>",
|
|
34482
|
+
"<triangles>",
|
|
34483
|
+
...comp.faces.map((face) => {
|
|
34484
|
+
const [v1, v2, v3] = face.vertices;
|
|
34485
|
+
const attrs = [`v1="${v1}"`, `v2="${v2}"`, `v3="${v3}"`];
|
|
34486
|
+
if (paintColor) {
|
|
34487
|
+
attrs.push(`paint_color="${paintColor}"`);
|
|
34488
|
+
}
|
|
34489
|
+
return `<triangle ${attrs.join(" ")} />`;
|
|
34490
|
+
}),
|
|
34491
|
+
"</triangles>",
|
|
34492
|
+
"</mesh>",
|
|
34493
|
+
"</object>"
|
|
34494
|
+
].join("\n");
|
|
34495
|
+
});
|
|
34496
|
+
const buildItems = components.map((_, compIdx) => {
|
|
34497
|
+
const objectId = compIdx + 2;
|
|
34498
|
+
const objectUuid = createUuid();
|
|
34499
|
+
return `<item objectid="${objectId}" p:UUID="${objectUuid}"/>`;
|
|
34500
|
+
});
|
|
34445
34501
|
const modelXml = [
|
|
34446
34502
|
'<?xml version="1.0" encoding="utf-8"?>',
|
|
34447
34503
|
'<model unit="millimeter" xml:lang="en-US" xmlns="http://schemas.microsoft.com/3dmanufacturing/core/2015/02" xmlns:p="http://schemas.microsoft.com/3dmanufacturing/production/2015/06">',
|
|
@@ -34449,37 +34505,15 @@ void main() {
|
|
|
34449
34505
|
'<meta name="slic3rpe:Version3mf" value="1"/>',
|
|
34450
34506
|
'<meta name="slic3rpe:MmPaintingVersion" value="1"/>',
|
|
34451
34507
|
"<resources>",
|
|
34452
|
-
|
|
34508
|
+
`<basematerials id="${materialsId}">`,
|
|
34453
34509
|
...polyhedron.colors.map(
|
|
34454
34510
|
(color, i) => `<base name="color_${i}" displaycolor="${colorToDisplayColor(color)}"/>`
|
|
34455
34511
|
),
|
|
34456
34512
|
"</basematerials>",
|
|
34457
|
-
|
|
34458
|
-
"<mesh>",
|
|
34459
|
-
"<vertices>",
|
|
34460
|
-
...polyhedron.vertices.map(
|
|
34461
|
-
(vertex2) => `<vertex x="${vertex2.x}" y="${vertex2.y}" z="${vertex2.z}" />`
|
|
34462
|
-
),
|
|
34463
|
-
"</vertices>",
|
|
34464
|
-
"<triangles>",
|
|
34465
|
-
...polyhedron.faces.map((face) => {
|
|
34466
|
-
const [v1, v2, v3] = face.vertices;
|
|
34467
|
-
const attrs = [`v1="${v1}"`, `v2="${v2}"`, `v3="${v3}"`];
|
|
34468
|
-
if (face.colorIndex > 0) {
|
|
34469
|
-
attrs.push(`pid="2"`, `p1="${face.colorIndex}"`);
|
|
34470
|
-
}
|
|
34471
|
-
const paintColor = PAINT_COLOR_MAP[extruderIndexByColorIndex[face.colorIndex]];
|
|
34472
|
-
if (paintColor) {
|
|
34473
|
-
attrs.push(`paint_color="${paintColor}"`);
|
|
34474
|
-
}
|
|
34475
|
-
return `<triangle ${attrs.join(" ")} />`;
|
|
34476
|
-
}),
|
|
34477
|
-
"</triangles>",
|
|
34478
|
-
"</mesh>",
|
|
34479
|
-
"</object>",
|
|
34513
|
+
...objectXmls,
|
|
34480
34514
|
"</resources>",
|
|
34481
34515
|
`<build p:UUID="${buildUuid}">`,
|
|
34482
|
-
|
|
34516
|
+
...buildItems,
|
|
34483
34517
|
"</build>",
|
|
34484
34518
|
"</model>"
|
|
34485
34519
|
].join("\n");
|
|
@@ -34661,10 +34695,7 @@ void main() {
|
|
|
34661
34695
|
const applySplitSize = (rawSize, isHorizontal) => {
|
|
34662
34696
|
const total = isHorizontal ? elem.clientWidth : elem.clientHeight;
|
|
34663
34697
|
const splitterSize = isHorizontal ? splitter.offsetWidth : splitter.offsetHeight;
|
|
34664
|
-
const maxSize = Math.max(
|
|
34665
|
-
minPanelSize,
|
|
34666
|
-
total - splitterSize - minPanelSize
|
|
34667
|
-
);
|
|
34698
|
+
const maxSize = Math.max(minPanelSize, total - splitterSize - minPanelSize);
|
|
34668
34699
|
const clamped = Math.max(minPanelSize, Math.min(rawSize, maxSize));
|
|
34669
34700
|
previewContainer.style.flex = `0 0 ${clamped}px`;
|
|
34670
34701
|
return clamped;
|
|
@@ -34722,7 +34753,6 @@ void main() {
|
|
|
34722
34753
|
if (!elem || !button) return;
|
|
34723
34754
|
const isFullscreen = document.fullscreenElement === elem;
|
|
34724
34755
|
const label = i18nGet("ide-fullscreen-enter", "Fullscreen");
|
|
34725
|
-
button.textContent = "\u26F6";
|
|
34726
34756
|
button.title = label;
|
|
34727
34757
|
button.setAttribute("aria-label", label);
|
|
34728
34758
|
button.classList.toggle("active", isFullscreen);
|
|
@@ -34802,7 +34832,9 @@ void main() {
|
|
|
34802
34832
|
bottomButtons.insertBefore(downloadFormatSelect, downloadBtn);
|
|
34803
34833
|
}
|
|
34804
34834
|
if (downloadBtn) {
|
|
34805
|
-
|
|
34835
|
+
const downloadLabel = i18nGet("openscad-download", "Download");
|
|
34836
|
+
downloadBtn.title = downloadLabel;
|
|
34837
|
+
downloadBtn.setAttribute("aria-label", downloadLabel);
|
|
34806
34838
|
}
|
|
34807
34839
|
const normalizeBinaryDest = (dest) => {
|
|
34808
34840
|
if (typeof dest !== "string") return null;
|
|
@@ -35222,14 +35254,19 @@ void main() {
|
|
|
35222
35254
|
userBinaryFiles,
|
|
35223
35255
|
buildAutoBinaryFiles(cm?.getValue() || "", basePath, pagePath)
|
|
35224
35256
|
);
|
|
35225
|
-
const result = await callWorker(
|
|
35226
|
-
|
|
35227
|
-
|
|
35228
|
-
|
|
35229
|
-
|
|
35230
|
-
|
|
35231
|
-
|
|
35232
|
-
|
|
35257
|
+
const result = await callWorker(
|
|
35258
|
+
"render",
|
|
35259
|
+
"render",
|
|
35260
|
+
{
|
|
35261
|
+
code: cm?.getValue() || "",
|
|
35262
|
+
format,
|
|
35263
|
+
libraryNames: libraryNames2,
|
|
35264
|
+
binaryFiles: resolvedBinaryFiles,
|
|
35265
|
+
paramDefinitions: [],
|
|
35266
|
+
isPreview
|
|
35267
|
+
},
|
|
35268
|
+
_scriptBase
|
|
35269
|
+
);
|
|
35233
35270
|
const stderr = getInvocationStderr(result);
|
|
35234
35271
|
if (result?.error || result?.exitCode !== 0) {
|
|
35235
35272
|
const error = new Error(
|
|
@@ -131,7 +131,9 @@
|
|
|
131
131
|
}
|
|
132
132
|
|
|
133
133
|
@keyframes openscad-spin {
|
|
134
|
-
to {
|
|
134
|
+
to {
|
|
135
|
+
transform: rotate(360deg);
|
|
136
|
+
}
|
|
135
137
|
}
|
|
136
138
|
|
|
137
139
|
/* Splitter between canvas and parameters card */
|
|
@@ -246,6 +248,31 @@
|
|
|
246
248
|
border-top-right-radius: 0;
|
|
247
249
|
}
|
|
248
250
|
|
|
251
|
+
/* Icon-only toolbar: the written labels (Reset/Copy/Download) made this row
|
|
252
|
+
wrap on narrow screens, so the wording moved into title/aria-label. */
|
|
253
|
+
.directive-openscad .buttons.bottom button {
|
|
254
|
+
flex: 0 0 auto;
|
|
255
|
+
min-width: 42px;
|
|
256
|
+
width: 42px;
|
|
257
|
+
padding: 8px 0;
|
|
258
|
+
display: flex;
|
|
259
|
+
align-items: center;
|
|
260
|
+
justify-content: center;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
.directive-openscad .buttons.bottom button .icon {
|
|
264
|
+
width: 18px;
|
|
265
|
+
height: 18px;
|
|
266
|
+
display: block;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/* Fullscreen sits apart, at the trailing edge of the toolbar. */
|
|
270
|
+
.directive-openscad .buttons.bottom button.fullscreen {
|
|
271
|
+
margin-inline-start: auto;
|
|
272
|
+
border-right: none;
|
|
273
|
+
border-left: 1px solid var(--color-spacer);
|
|
274
|
+
}
|
|
275
|
+
|
|
249
276
|
.directive-openscad button {
|
|
250
277
|
flex: 1;
|
|
251
278
|
padding: 8px 16px;
|
|
@@ -303,8 +330,14 @@
|
|
|
303
330
|
|
|
304
331
|
.directive-openscad .binary-files-section summary .summary-indicator {
|
|
305
332
|
transition: transform 0.2s;
|
|
306
|
-
display: inline-
|
|
307
|
-
|
|
333
|
+
display: inline-flex;
|
|
334
|
+
align-items: center;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
.directive-openscad .binary-files-section summary .summary-indicator .icon {
|
|
338
|
+
width: 14px;
|
|
339
|
+
height: 14px;
|
|
340
|
+
display: block;
|
|
308
341
|
}
|
|
309
342
|
|
|
310
343
|
.directive-openscad .binary-files-section[open] summary .summary-indicator {
|
|
@@ -29,8 +29,13 @@ hyperbook.p5 = (function () {
|
|
|
29
29
|
|
|
30
30
|
const applySplitSize = (rawSize, isHorizontal) => {
|
|
31
31
|
const total = isHorizontal ? elem.clientWidth : elem.clientHeight;
|
|
32
|
-
const splitterSize = isHorizontal
|
|
33
|
-
|
|
32
|
+
const splitterSize = isHorizontal
|
|
33
|
+
? splitter.offsetWidth
|
|
34
|
+
: splitter.offsetHeight;
|
|
35
|
+
const maxSize = Math.max(
|
|
36
|
+
minPanelSize,
|
|
37
|
+
total - splitterSize - minPanelSize,
|
|
38
|
+
);
|
|
34
39
|
const clamped = Math.max(minPanelSize, Math.min(rawSize, maxSize));
|
|
35
40
|
container.style.flex = `0 0 ${clamped}px`;
|
|
36
41
|
return clamped;
|
|
@@ -90,7 +95,6 @@ hyperbook.p5 = (function () {
|
|
|
90
95
|
if (!elem || !button) return;
|
|
91
96
|
const isFullscreen = document.fullscreenElement === elem;
|
|
92
97
|
const label = hyperbook.i18n.get("ide-fullscreen-enter");
|
|
93
|
-
button.textContent = "⛶";
|
|
94
98
|
button.title = label;
|
|
95
99
|
button.setAttribute("aria-label", label);
|
|
96
100
|
button.classList.toggle("active", isFullscreen);
|
|
@@ -219,10 +223,7 @@ hyperbook.p5 = (function () {
|
|
|
219
223
|
const observer = new MutationObserver((mutations) => {
|
|
220
224
|
mutations.forEach((mutation) => {
|
|
221
225
|
mutation.addedNodes.forEach((node) => {
|
|
222
|
-
if (
|
|
223
|
-
node.nodeType === 1 &&
|
|
224
|
-
node.classList.contains("directive-p5")
|
|
225
|
-
) {
|
|
226
|
+
if (node.nodeType === 1 && node.classList.contains("directive-p5")) {
|
|
226
227
|
initElement(node);
|
|
227
228
|
}
|
|
228
229
|
});
|
|
@@ -100,6 +100,31 @@ code-input {
|
|
|
100
100
|
border-top-right-radius: 0;
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
+
/* Icon-only toolbar: the written labels (Reset/Copy/Download) made this row
|
|
104
|
+
wrap on narrow screens, so the wording moved into title/aria-label. */
|
|
105
|
+
.directive-p5 .buttons.bottom button {
|
|
106
|
+
flex: 0 0 auto;
|
|
107
|
+
min-width: 42px;
|
|
108
|
+
width: 42px;
|
|
109
|
+
padding: 8px 0;
|
|
110
|
+
display: flex;
|
|
111
|
+
align-items: center;
|
|
112
|
+
justify-content: center;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.directive-p5 .buttons.bottom button .icon {
|
|
116
|
+
width: 18px;
|
|
117
|
+
height: 18px;
|
|
118
|
+
display: block;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/* Fullscreen sits apart, at the trailing edge of the toolbar. */
|
|
122
|
+
.directive-p5 .buttons.bottom button.fullscreen {
|
|
123
|
+
margin-inline-start: auto;
|
|
124
|
+
border-right: none;
|
|
125
|
+
border-left: 1px solid var(--color-spacer);
|
|
126
|
+
}
|
|
127
|
+
|
|
103
128
|
.directive-p5 button {
|
|
104
129
|
flex: 1;
|
|
105
130
|
padding: 8px 16px;
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
border-width: 1px;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
.directive-protect .password-input>input {
|
|
15
|
+
.directive-protect .password-input > input {
|
|
16
16
|
text-align: center;
|
|
17
17
|
border-radius: 10px;
|
|
18
18
|
font-size: 1.125rem;
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
border-style: solid;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
.directive-protect .password-input
|
|
23
|
+
.directive-protect .password-input > .icon {
|
|
24
24
|
position: absolute;
|
|
25
25
|
user-select: none;
|
|
26
26
|
left: -14px;
|
|
@@ -33,17 +33,17 @@
|
|
|
33
33
|
margin-bottom: 10px;
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
.directive-protect .password-input
|
|
36
|
+
.directive-protect .password-input > .description {
|
|
37
37
|
margin-bottom: 10px;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
.directive-protect .password-input>input {
|
|
40
|
+
.directive-protect .password-input > input {
|
|
41
41
|
color: var(--color-text);
|
|
42
42
|
background: var(--color-nav);
|
|
43
43
|
border-color: var(--color-spacer);
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
.directive-protect .password-input
|
|
46
|
+
.directive-protect .password-input > .icon {
|
|
47
47
|
background: white;
|
|
48
48
|
border-color: var(--color-spacer);
|
|
49
49
|
}
|
|
@@ -52,3 +52,9 @@
|
|
|
52
52
|
visibility: hidden;
|
|
53
53
|
display: none;
|
|
54
54
|
}
|
|
55
|
+
|
|
56
|
+
.directive-protect .password-input > .icon .icon {
|
|
57
|
+
width: 16px;
|
|
58
|
+
height: 16px;
|
|
59
|
+
display: block;
|
|
60
|
+
}
|