@hyperbook/markdown 0.23.1 → 0.24.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.
@@ -1,9 +1,19 @@
1
1
  hyperbook.mermaid = (function () {
2
2
  const elementCode = ".directive-mermaid";
3
3
 
4
- const loadMermaid = function (theme) {
5
- window.mermaid.initialize({ theme });
6
- window.mermaid.init({ theme }, document.querySelectorAll(elementCode));
4
+ const loadMermaid = async function (theme) {
5
+ window.mermaid.initialize({ theme, startOnLoad: false });
6
+ let i = 0;
7
+ for (const el of document.querySelectorAll(elementCode)) {
8
+ if (el.getAttribute("data-processed")) return;
9
+
10
+ el.setAttribute("data-processed", true);
11
+ let id = `graph-` + Date.now() + i++;
12
+
13
+ mermaid.render(id, el.innerText).then(({ svg }) => {
14
+ el.innerHTML = svg;
15
+ });
16
+ }
7
17
  };
8
18
 
9
19
  const resetProcessed = function () {
@@ -0,0 +1,144 @@
1
+ hyperbook.webide = (function () {
2
+ window.codeInput?.registerTemplate(
3
+ "webide-highlighted",
4
+ codeInput.templates.prism(window.Prism, [
5
+ new codeInput.plugins.AutoCloseBrackets(),
6
+ new codeInput.plugins.Indent(true, 2),
7
+ ])
8
+ );
9
+
10
+ const elems = document.getElementsByClassName("directive-webide");
11
+
12
+ for (let elem of elems) {
13
+ const title = elem.getElementsByClassName("container-title")[0];
14
+ /** @type {HTMLTextAreaElement | null} */
15
+ const editorHTML = elem.querySelector(".editor.html");
16
+ /** @type {HTMLTextAreaElement | null} */
17
+ const editorCSS = elem.querySelector(".editor.css");
18
+ /** @type {HTMLTextAreaElement | null} */
19
+ const editorJS = elem.querySelector(".editor.js");
20
+ /** @type {HTMLButtonElement | null} */
21
+ const btnHTML = elem.querySelector("button.html");
22
+ /** @type {HTMLButtonElement | null} */
23
+ const btnCSS = elem.querySelector("button.css");
24
+ /** @type {HTMLButtonElement | null} */
25
+ const btnJS = elem.querySelector("button.js");
26
+
27
+ const frame = elem.getElementsByTagName("iframe")[0];
28
+ const template = elem.getAttribute("data-template");
29
+ const id = elem.getAttribute("data-id");
30
+ /** @type {HTMLButtonElement} */
31
+ const resetEl = elem.querySelector("button.reset");
32
+ /** @type {HTMLButtonElement} */
33
+ const downloadEl = elem.querySelector("button.download");
34
+
35
+ resetEl?.addEventListener("click", () => {
36
+ if (window.confirm(i18n.get("webide-reset-prompt"))) {
37
+ store.webide.delete(id);
38
+ window.location.reload();
39
+ }
40
+ });
41
+
42
+ btnHTML?.addEventListener("click", () => {
43
+ btnHTML?.classList.add("active");
44
+ btnCSS?.classList.remove("active");
45
+ btnJS?.classList.remove("active");
46
+
47
+ editorHTML?.classList.add("active");
48
+ editorCSS?.classList.remove("active");
49
+ editorJS?.classList.remove("active");
50
+ });
51
+
52
+ btnCSS?.addEventListener("click", () => {
53
+ btnHTML?.classList.remove("active");
54
+ btnCSS?.classList.add("active");
55
+ btnJS?.classList.remove("active");
56
+
57
+ editorHTML?.classList.remove("active");
58
+ editorCSS?.classList.add("active");
59
+ editorJS?.classList.remove("active");
60
+ });
61
+
62
+ btnJS?.addEventListener("click", () => {
63
+ btnHTML?.classList.remove("active");
64
+ btnCSS?.classList.remove("active");
65
+ btnJS?.classList.add("active");
66
+
67
+ editorHTML?.classList.remove("active");
68
+ editorCSS?.classList.remove("active");
69
+ editorJS?.classList.add("active");
70
+ });
71
+
72
+ const load = async () => {
73
+ const result = await store.webide.get(id);
74
+ if (!result) return;
75
+ const website = template
76
+ .replace("###HTML###", result.html)
77
+ .replace("###CSS###", result.css)
78
+ .replace("###JS###", result.js);
79
+ frame.srcdoc = website;
80
+ };
81
+
82
+ load();
83
+
84
+ const update = () => {
85
+ store.webide.put({
86
+ id,
87
+ html: editorHTML?.value,
88
+ css: editorCSS?.value,
89
+ js: editorJS?.value,
90
+ });
91
+ const website = template
92
+ .replace("###HTML###", editorHTML?.value)
93
+ .replace("###CSS###", editorCSS?.value)
94
+ .replace("###JS###", editorJS?.value);
95
+ frame.srcdoc = website;
96
+ };
97
+
98
+ frame.addEventListener("load", () => {
99
+ title.textContent = frame.contentDocument.title;
100
+ });
101
+
102
+ editorHTML?.addEventListener("code-input_load", async () => {
103
+ const result = await store.webide.get(id);
104
+ if (result) {
105
+ editorHTML.value = result.html;
106
+ }
107
+
108
+ editorHTML.addEventListener("input", () => {
109
+ update();
110
+ });
111
+ });
112
+
113
+ editorCSS?.addEventListener("code-input_load", async () => {
114
+ const result = await store.webide.get(id);
115
+ if (result) {
116
+ editorCSS.value = result.css;
117
+ }
118
+
119
+ editorCSS.addEventListener("input", () => {
120
+ update();
121
+ });
122
+ });
123
+
124
+ editorJS?.addEventListener("code-input_load", async () => {
125
+ const result = await store.webide.get(id);
126
+ if (result) {
127
+ editorJS.value = result.js;
128
+ }
129
+
130
+ editorJS.addEventListener("input", () => {
131
+ update();
132
+ });
133
+ });
134
+
135
+ downloadEl?.addEventListener("click", async () => {
136
+ const a = document.createElement("a");
137
+ const website = frame.srcdoc;
138
+ const blob = new Blob([website], { type: "text/html" });
139
+ a.href = URL.createObjectURL(blob);
140
+ a.download = `website-${id}.html`;
141
+ a.click();
142
+ });
143
+ }
144
+ })();
@@ -0,0 +1,125 @@
1
+ .directive-webide {
2
+ display: flex;
3
+ justify-content: center;
4
+ align-items: center;
5
+ flex-direction: column;
6
+ margin-bottom: 16px;
7
+ overflow: hidden;
8
+ gap: 8px;
9
+ }
10
+
11
+ code-input {
12
+ margin: 0;
13
+ }
14
+
15
+ .directive-webide .container {
16
+ width: 100%;
17
+ border: 1px solid var(--color-spacer);
18
+ border-radius: 8px;
19
+ overflow: hidden;
20
+ }
21
+
22
+ .directive-webide .container-title {
23
+ border-bottom: 1px solid var(--color-spacer);
24
+ padding: 8px 16px;
25
+ padding-left: 0px;
26
+ overflow: hidden;
27
+ white-space:nowrap;
28
+ text-overflow: ellipsis;
29
+ background-color: var(--color-background);
30
+ color: var(--color-text);
31
+ }
32
+
33
+ .directive-webide .container-title::before {
34
+ content: "";
35
+ margin-right: 4.4rem;
36
+ display: inline-block;
37
+ aspect-ratio: 1 / 1;
38
+ height: 0.75rem;
39
+ border-radius: 9999px;
40
+ opacity: 0.3;
41
+ box-shadow:
42
+ 0.8em 0,
43
+ 2.2em 0,
44
+ 3.6em 0;
45
+ }
46
+
47
+ .directive-webide .editor-container {
48
+ width: 100%;
49
+ display: flex;
50
+ flex-direction: column;
51
+ height: 400px;
52
+ }
53
+
54
+ .directive-webide .editor {
55
+ width: 100%;
56
+ border: 1px solid var(--color-spacer);
57
+ flex: 1;
58
+ }
59
+
60
+ .directive-webide .editor:not(.active) {
61
+ display: none;
62
+ }
63
+
64
+ .directive-webide .buttons {
65
+ display: flex;
66
+ border: 1px solid var(--color-spacer);
67
+ border-radius: 8px;
68
+ border-bottom: none;
69
+ border-bottom-left-radius: 0;
70
+ border-bottom-right-radius: 0;
71
+ }
72
+
73
+ .directive-webide .buttons.bottom {
74
+ border: 1px solid var(--color-spacer);
75
+ border-radius: 8px;
76
+ border-top: none;
77
+ border-top-left-radius: 0;
78
+ border-top-right-radius: 0;
79
+ }
80
+
81
+ .directive-webide button {
82
+ flex: 1;
83
+ padding: 8px 16px;
84
+ border: none;
85
+ border-right: 1px solid var(--color-spacer);
86
+ background-color: var(--color--background);
87
+ color: var(--color-text);
88
+ cursor: pointer;
89
+ }
90
+
91
+ .directive-webide button:not(.active) {
92
+ opacity: 0.6;
93
+ }
94
+
95
+ .directive-webide .buttons:last-child {
96
+ border-right: none;
97
+ }
98
+
99
+ .directive-webide button:hover {
100
+ background-color: var(--color-spacer);
101
+ }
102
+
103
+ .directive-webide iframe {
104
+ border: none;
105
+ width: 100%;
106
+ height: 100%;
107
+ background-color: white;
108
+ }
109
+
110
+ @media screen and (min-width: 1024px) {
111
+ .directive-webide:not(.standalone) {
112
+ flex-direction: row;
113
+ height: calc(100dvh - 128px);
114
+ .container {
115
+ flex: 1;
116
+ height: 100% !important;
117
+ }
118
+
119
+ .editor-container {
120
+ flex: 1;
121
+ height: 100%;
122
+ overflow: hidden;
123
+ }
124
+ }
125
+ }
@@ -23,6 +23,7 @@ store.version(1).stores({
23
23
  slideshow: `id,active`,
24
24
  tabs: `id,active`,
25
25
  excalidraw: `id,excalidrawElements,appState,files`,
26
+ webide: `id,html,css,js`
26
27
  });
27
28
  var sqlIdeDB = new Dexie("SQL-IDE");
28
29
  sqlIdeDB.version(0.1).stores({