@gramlot/gramlot-examples 0.3.5 → 0.3.6
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
CHANGED
|
@@ -12,7 +12,7 @@ npm install @gramlot/gramlot-examples
|
|
|
12
12
|
[](https://pypi.org/project/gramlot-examples/)
|
|
13
13
|
[](https://www.npmjs.com/package/@gramlot/gramlot-examples)
|
|
14
14
|
|
|
15
|
-
Current release: 0.3.
|
|
15
|
+
Current release: 0.3.6.
|
|
16
16
|
|
|
17
17
|
[Documentation and learning sequence](https://gramlot-examples.readthedocs.io/en/latest/)
|
|
18
18
|
include every lesson, its Python and JavaScript source, and the gallery guide.
|
package/package.json
CHANGED
|
@@ -6879,11 +6879,101 @@ Please report this to https://github.com/markedjs/marked.`, e) {
|
|
|
6879
6879
|
element.innerHTML = purifier.sanitize(markdown.parse(element.textContent), { USE_PROFILES: { html: true } });
|
|
6880
6880
|
}
|
|
6881
6881
|
|
|
6882
|
+
// src/gramlot_examples/gallery/browser/gallery-content.js
|
|
6883
|
+
var pending = /* @__PURE__ */ new WeakMap();
|
|
6884
|
+
function mountGalleryContent(renderer, root) {
|
|
6885
|
+
const document2 = renderer.destination.ownerDocument;
|
|
6886
|
+
const byId = (id) => document2.getElementById(id);
|
|
6887
|
+
const node = (element) => renderer.elements.get(element).node;
|
|
6888
|
+
const entries2 = /* @__PURE__ */ new Map();
|
|
6889
|
+
let disposed = false;
|
|
6890
|
+
function format({ key, view }) {
|
|
6891
|
+
if (view === "description") {
|
|
6892
|
+
const readme = byId(`readme-${key}`);
|
|
6893
|
+
readme.textContent = node(readme).value;
|
|
6894
|
+
renderReadme(readme);
|
|
6895
|
+
return;
|
|
6896
|
+
}
|
|
6897
|
+
const code = byId(`code-${key}`);
|
|
6898
|
+
code.textContent = node(code).value;
|
|
6899
|
+
highlightCode(code);
|
|
6900
|
+
const logic = byId(`logic-${key}`);
|
|
6901
|
+
if (logic) {
|
|
6902
|
+
const source = logicSource(node(logic).value);
|
|
6903
|
+
node(byId(`logic-panel-${key}`)).setAttr({ hidden: source === null });
|
|
6904
|
+
logic.textContent = source ?? "";
|
|
6905
|
+
if (source !== null) highlightCode(logic);
|
|
6906
|
+
}
|
|
6907
|
+
}
|
|
6908
|
+
async function load(entry) {
|
|
6909
|
+
if (entry.loading) return;
|
|
6910
|
+
entry.loading = true;
|
|
6911
|
+
const targetId = entry.view === "code" ? `code-tabs-${entry.key}` : entry.element.id;
|
|
6912
|
+
const target = node(byId(targetId));
|
|
6913
|
+
const current = () => {
|
|
6914
|
+
const element = byId(targetId);
|
|
6915
|
+
return element && renderer.elements.get(element)?.node === target ? element : null;
|
|
6916
|
+
};
|
|
6917
|
+
let request = pending.get(target);
|
|
6918
|
+
if (!request) {
|
|
6919
|
+
request = renderer.binding.gramlot.src.remoteSource(target, "lesson", { key: entry.key, view: entry.view });
|
|
6920
|
+
pending.set(target, request);
|
|
6921
|
+
}
|
|
6922
|
+
try {
|
|
6923
|
+
const mounted = await request;
|
|
6924
|
+
if (disposed || !current() || !mounted) return;
|
|
6925
|
+
format(entry);
|
|
6926
|
+
observer.unobserve(entry.element);
|
|
6927
|
+
entries2.delete(entry.element);
|
|
6928
|
+
} catch {
|
|
6929
|
+
if (disposed || !current()) return;
|
|
6930
|
+
const status = current().querySelector('[role="status"]');
|
|
6931
|
+
node(status).setValue("Could not load this content. Close and reopen the panel to retry.");
|
|
6932
|
+
} finally {
|
|
6933
|
+
if (pending.get(target) === request) pending.delete(target);
|
|
6934
|
+
entry.loading = false;
|
|
6935
|
+
}
|
|
6936
|
+
}
|
|
6937
|
+
const observer = new document2.defaultView.IntersectionObserver((records) => {
|
|
6938
|
+
for (const record of records) {
|
|
6939
|
+
const entry = entries2.get(record.target);
|
|
6940
|
+
if (!entry) continue;
|
|
6941
|
+
const visible = record.isIntersecting && record.intersectionRect.width > 0 && record.intersectionRect.height > 0;
|
|
6942
|
+
if (visible && !entry.visible) void load(entry);
|
|
6943
|
+
entry.visible = visible;
|
|
6944
|
+
}
|
|
6945
|
+
});
|
|
6946
|
+
const dispose = () => {
|
|
6947
|
+
disposed = true;
|
|
6948
|
+
observer.disconnect();
|
|
6949
|
+
entries2.clear();
|
|
6950
|
+
};
|
|
6951
|
+
renderer.onDispose(root, dispose);
|
|
6952
|
+
return {
|
|
6953
|
+
observe(key) {
|
|
6954
|
+
for (const [view, id, loaded] of [
|
|
6955
|
+
["code", `codepane-${key}`, `code-${key}`],
|
|
6956
|
+
["description", `description-${key}`, `readme-${key}`]
|
|
6957
|
+
]) {
|
|
6958
|
+
const element = byId(id);
|
|
6959
|
+
const entry = { key, view, element, visible: false, loading: false };
|
|
6960
|
+
if (byId(loaded)) format(entry);
|
|
6961
|
+
else if (!entries2.has(element)) {
|
|
6962
|
+
entries2.set(element, entry);
|
|
6963
|
+
observer.observe(element);
|
|
6964
|
+
}
|
|
6965
|
+
}
|
|
6966
|
+
},
|
|
6967
|
+
dispose
|
|
6968
|
+
};
|
|
6969
|
+
}
|
|
6970
|
+
|
|
6882
6971
|
// src/gramlot_examples/gallery/browser/gallery.js
|
|
6883
6972
|
function mountGallery(renderer, root, inspector) {
|
|
6884
6973
|
const state = root.builder.data.getItem("galleryIndex");
|
|
6885
6974
|
const settings = mountGallerySettings(renderer, root, state);
|
|
6886
6975
|
let guide = null;
|
|
6976
|
+
const content = mountGalleryContent(renderer, root);
|
|
6887
6977
|
const mobile = mountGalleryMobile(renderer, root, inspector, state, (visible) => {
|
|
6888
6978
|
if (!visible) guide?.pause();
|
|
6889
6979
|
});
|
|
@@ -6891,19 +6981,14 @@ Please report this to https://github.com/markedjs/marked.`, e) {
|
|
|
6891
6981
|
inspector.update(entries2, active);
|
|
6892
6982
|
mobile.update(entries2, active);
|
|
6893
6983
|
guide?.update(entries2, active);
|
|
6894
|
-
}, (entry, { byId
|
|
6984
|
+
}, (entry, { byId }) => {
|
|
6895
6985
|
const { key } = entry;
|
|
6896
6986
|
if (key === "l04" && !guide) guide = mountGuidedDemo(renderer, root);
|
|
6897
|
-
|
|
6898
|
-
|
|
6899
|
-
|
|
6900
|
-
const logic = byId(`logic-${key}`);
|
|
6901
|
-
if (logic) {
|
|
6902
|
-
const source = logicSource(node(logic).value);
|
|
6903
|
-
set(byId(`logic-panel-${key}`), { hidden: source === null });
|
|
6904
|
-
logic.textContent = source ?? "";
|
|
6905
|
-
if (source !== null) highlightCode(logic);
|
|
6987
|
+
if (entry.panel.classList.contains("index-category")) {
|
|
6988
|
+
renderReadme(byId(`readme-${key}`));
|
|
6989
|
+
return;
|
|
6906
6990
|
}
|
|
6991
|
+
content.observe(entry.key);
|
|
6907
6992
|
}, {
|
|
6908
6993
|
containerLayout: true,
|
|
6909
6994
|
state,
|
|
@@ -6919,20 +7004,22 @@ Please report this to https://github.com/markedjs/marked.`, e) {
|
|
|
6919
7004
|
hidden: true,
|
|
6920
7005
|
class: category ? "index-category" : "gallery-panel"
|
|
6921
7006
|
});
|
|
6922
|
-
const code = category ? null : source("gallery-code-pages").
|
|
7007
|
+
const code = category ? null : source("gallery-code-pages").div({
|
|
6923
7008
|
id: `codepane-${entry.key}`,
|
|
6924
|
-
class: "gallery-codepane
|
|
7009
|
+
class: "gallery-codepane",
|
|
6925
7010
|
hidden: true,
|
|
7011
|
+
height: "100%"
|
|
7012
|
+
});
|
|
7013
|
+
if (code) code.tabContainer({
|
|
7014
|
+
id: `code-tabs-${entry.key}`,
|
|
7015
|
+
class: "gallery-source-tabs",
|
|
6926
7016
|
height: "100%",
|
|
6927
7017
|
tabMode: "underline"
|
|
6928
|
-
});
|
|
7018
|
+
}).contentPane({ title: "Code" }).p("Loading code\u2026", { role: "status" });
|
|
6929
7019
|
try {
|
|
6930
7020
|
const runtime = renderer.binding.gramlot;
|
|
6931
|
-
const
|
|
6932
|
-
|
|
6933
|
-
...code ? [runtime.src.remoteSource(node(`codepane-${entry.key}`), "lesson", { key: entry.key, view: "code" })] : []
|
|
6934
|
-
]);
|
|
6935
|
-
if (results.some((mounted) => !mounted)) throw new Error("Lesson loading was cancelled");
|
|
7021
|
+
const mounted = await runtime.src.remoteSource(node(`panel-${entry.key}`), "lesson", { key: entry.key });
|
|
7022
|
+
if (!mounted) throw new Error("Lesson loading was cancelled");
|
|
6936
7023
|
} catch (error) {
|
|
6937
7024
|
for (const target of [pane, code]) if (target?.parentBag) target.parentBag.popNode(target.label);
|
|
6938
7025
|
throw error;
|
|
@@ -6945,6 +7032,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
|
|
|
6945
7032
|
});
|
|
6946
7033
|
return { dispose() {
|
|
6947
7034
|
guide?.dispose();
|
|
7035
|
+
content.dispose();
|
|
6948
7036
|
settings.dispose();
|
|
6949
7037
|
index.dispose();
|
|
6950
7038
|
mobile.dispose();
|
|
@@ -7550,11 +7638,11 @@ Please report this to https://github.com/markedjs/marked.`, e) {
|
|
|
7550
7638
|
this.error = error.message;
|
|
7551
7639
|
}
|
|
7552
7640
|
if (message.type === "result") {
|
|
7553
|
-
const
|
|
7554
|
-
if (
|
|
7641
|
+
const pending2 = this.#pending.get(message.id);
|
|
7642
|
+
if (pending2) {
|
|
7555
7643
|
this.#pending.delete(message.id);
|
|
7556
|
-
if (message.ok && !this.error)
|
|
7557
|
-
else
|
|
7644
|
+
if (message.ok && !this.error) pending2.resolve(message);
|
|
7645
|
+
else pending2.reject(new Error(message.error || this.error));
|
|
7558
7646
|
}
|
|
7559
7647
|
}
|
|
7560
7648
|
this.#notify();
|
|
@@ -7611,7 +7699,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
|
|
|
7611
7699
|
this.#port.removeEventListener("message", this.#receive);
|
|
7612
7700
|
this.#port.close();
|
|
7613
7701
|
this.state = "disposed";
|
|
7614
|
-
for (const
|
|
7702
|
+
for (const pending2 of this.#pending.values()) pending2.reject(new Error("Inspected page disconnected"));
|
|
7615
7703
|
this.#pending.clear();
|
|
7616
7704
|
this.#notify();
|
|
7617
7705
|
}
|
|
@@ -7690,9 +7778,9 @@ Please report this to https://github.com/markedjs/marked.`, e) {
|
|
|
7690
7778
|
_subscribe() {
|
|
7691
7779
|
if (this._store) this._store.subscribe(this._subId, { any: () => {
|
|
7692
7780
|
if (this._pendingRender) return;
|
|
7693
|
-
const
|
|
7781
|
+
const pending2 = this._pendingRender = {};
|
|
7694
7782
|
queueMicrotask(() => {
|
|
7695
|
-
if (this._pendingRender ===
|
|
7783
|
+
if (this._pendingRender === pending2 && this.isConnected) this._render();
|
|
7696
7784
|
});
|
|
7697
7785
|
} });
|
|
7698
7786
|
}
|
|
@@ -102,6 +102,7 @@ export class GalleryPage extends IndexPage {
|
|
|
102
102
|
lesson(root, {key, view = 'example'}) {
|
|
103
103
|
const item = this.galleryItem(key);
|
|
104
104
|
if (view === 'code' && !item.examples) this.codePanel(root, item);
|
|
105
|
+
else if (view === 'description' && !item.examples) root.div(item.readme, {id: `readme-${key}`});
|
|
105
106
|
else if (view === 'example') {
|
|
106
107
|
if (item.examples) this.groupPanel(root, item);
|
|
107
108
|
else this.panel(root, item);
|
|
@@ -124,8 +125,8 @@ export class GalleryPage extends IndexPage {
|
|
|
124
125
|
guidedDemo(layout);
|
|
125
126
|
}
|
|
126
127
|
stage.iframe({title: `${example.title} preview`, name: `example-${key}`, id: `frame-${key}`});
|
|
127
|
-
preview.contentPane({title: 'Explanation', pageName: 'explanation', class: 'gallery-lesson', overflow: 'auto'})
|
|
128
|
-
.
|
|
128
|
+
preview.contentPane({title: 'Explanation', pageName: 'explanation', class: 'gallery-lesson', overflow: 'auto', id: `description-${key}`})
|
|
129
|
+
.p('Loading explanation…', {role: 'status'});
|
|
129
130
|
}
|
|
130
131
|
codePanel(parent, example) {
|
|
131
132
|
const key = example.key;
|