presently 0.1.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.
Files changed (215) hide show
  1. checksums.yaml +7 -0
  2. data/bin/presently +13 -0
  3. data/lib/presently/application.rb +104 -0
  4. data/lib/presently/clock.rb +77 -0
  5. data/lib/presently/display_view.rb +73 -0
  6. data/lib/presently/environment/application.rb +62 -0
  7. data/lib/presently/page.rb +38 -0
  8. data/lib/presently/page.xrb +31 -0
  9. data/lib/presently/presentation.rb +72 -0
  10. data/lib/presently/presentation_controller.rb +181 -0
  11. data/lib/presently/presenter_view.rb +264 -0
  12. data/lib/presently/slide.rb +148 -0
  13. data/lib/presently/slide_view.rb +92 -0
  14. data/lib/presently/state.rb +66 -0
  15. data/lib/presently/version.rb +9 -0
  16. data/lib/presently.rb +9 -0
  17. data/license.md +21 -0
  18. data/public/_components/@socketry/syntax/Syntax/CodeElement.js +337 -0
  19. data/public/_components/@socketry/syntax/Syntax/Errors.js +52 -0
  20. data/public/_components/@socketry/syntax/Syntax/Language/apache.js +49 -0
  21. data/public/_components/@socketry/syntax/Syntax/Language/applescript.js +157 -0
  22. data/public/_components/@socketry/syntax/Syntax/Language/assembly.js +42 -0
  23. data/public/_components/@socketry/syntax/Syntax/Language/bash-script.js +108 -0
  24. data/public/_components/@socketry/syntax/Syntax/Language/bash.js +32 -0
  25. data/public/_components/@socketry/syntax/Syntax/Language/basic.js +232 -0
  26. data/public/_components/@socketry/syntax/Syntax/Language/c++.js +1 -0
  27. data/public/_components/@socketry/syntax/Syntax/Language/c.js +1 -0
  28. data/public/_components/@socketry/syntax/Syntax/Language/clang.js +201 -0
  29. data/public/_components/@socketry/syntax/Syntax/Language/cpp.js +1 -0
  30. data/public/_components/@socketry/syntax/Syntax/Language/csharp.js +166 -0
  31. data/public/_components/@socketry/syntax/Syntax/Language/css.js +244 -0
  32. data/public/_components/@socketry/syntax/Syntax/Language/diff.js +24 -0
  33. data/public/_components/@socketry/syntax/Syntax/Language/go.js +135 -0
  34. data/public/_components/@socketry/syntax/Syntax/Language/haskell.js +110 -0
  35. data/public/_components/@socketry/syntax/Syntax/Language/html.js +69 -0
  36. data/public/_components/@socketry/syntax/Syntax/Language/io.js +68 -0
  37. data/public/_components/@socketry/syntax/Syntax/Language/java.js +134 -0
  38. data/public/_components/@socketry/syntax/Syntax/Language/javascript.js +89 -0
  39. data/public/_components/@socketry/syntax/Syntax/Language/json.js +36 -0
  40. data/public/_components/@socketry/syntax/Syntax/Language/lisp.js +38 -0
  41. data/public/_components/@socketry/syntax/Syntax/Language/lua.js +87 -0
  42. data/public/_components/@socketry/syntax/Syntax/Language/markdown.js +112 -0
  43. data/public/_components/@socketry/syntax/Syntax/Language/nginx.js +37 -0
  44. data/public/_components/@socketry/syntax/Syntax/Language/objective-c.js +1 -0
  45. data/public/_components/@socketry/syntax/Syntax/Language/ocaml.js +225 -0
  46. data/public/_components/@socketry/syntax/Syntax/Language/pascal.js +166 -0
  47. data/public/_components/@socketry/syntax/Syntax/Language/patch.js +2 -0
  48. data/public/_components/@socketry/syntax/Syntax/Language/perl5.js +317 -0
  49. data/public/_components/@socketry/syntax/Syntax/Language/php-script.js +112 -0
  50. data/public/_components/@socketry/syntax/Syntax/Language/php.js +18 -0
  51. data/public/_components/@socketry/syntax/Syntax/Language/plain.js +20 -0
  52. data/public/_components/@socketry/syntax/Syntax/Language/protobuf.js +77 -0
  53. data/public/_components/@socketry/syntax/Syntax/Language/python.js +208 -0
  54. data/public/_components/@socketry/syntax/Syntax/Language/ruby.js +124 -0
  55. data/public/_components/@socketry/syntax/Syntax/Language/scala.js +81 -0
  56. data/public/_components/@socketry/syntax/Syntax/Language/smalltalk.js +30 -0
  57. data/public/_components/@socketry/syntax/Syntax/Language/sql.js +865 -0
  58. data/public/_components/@socketry/syntax/Syntax/Language/super-collider.js +70 -0
  59. data/public/_components/@socketry/syntax/Syntax/Language/swift.js +176 -0
  60. data/public/_components/@socketry/syntax/Syntax/Language/xml.js +76 -0
  61. data/public/_components/@socketry/syntax/Syntax/Language/xrb.js +33 -0
  62. data/public/_components/@socketry/syntax/Syntax/Language/yaml.js +29 -0
  63. data/public/_components/@socketry/syntax/Syntax/Language.js +276 -0
  64. data/public/_components/@socketry/syntax/Syntax/Loader.js +78 -0
  65. data/public/_components/@socketry/syntax/Syntax/Match.js +546 -0
  66. data/public/_components/@socketry/syntax/Syntax/Rule.js +306 -0
  67. data/public/_components/@socketry/syntax/Syntax.js +356 -0
  68. data/public/_components/@socketry/syntax/bin/syntax-ast.js +42 -0
  69. data/public/_components/@socketry/syntax/examples/_template.html +53 -0
  70. data/public/_components/@socketry/syntax/examples/apache.html +72 -0
  71. data/public/_components/@socketry/syntax/examples/applescript.html +72 -0
  72. data/public/_components/@socketry/syntax/examples/assembly.html +74 -0
  73. data/public/_components/@socketry/syntax/examples/bash.html +90 -0
  74. data/public/_components/@socketry/syntax/examples/basic.html +87 -0
  75. data/public/_components/@socketry/syntax/examples/c.html +141 -0
  76. data/public/_components/@socketry/syntax/examples/clang.html +202 -0
  77. data/public/_components/@socketry/syntax/examples/csharp.html +110 -0
  78. data/public/_components/@socketry/syntax/examples/css-colors.html +179 -0
  79. data/public/_components/@socketry/syntax/examples/custom-theme.html +155 -0
  80. data/public/_components/@socketry/syntax/examples/diff.html +142 -0
  81. data/public/_components/@socketry/syntax/examples/examples.css +216 -0
  82. data/public/_components/@socketry/syntax/examples/go.html +413 -0
  83. data/public/_components/@socketry/syntax/examples/haskell.html +373 -0
  84. data/public/_components/@socketry/syntax/examples/html.html +316 -0
  85. data/public/_components/@socketry/syntax/examples/index.html +97 -0
  86. data/public/_components/@socketry/syntax/examples/io.html +552 -0
  87. data/public/_components/@socketry/syntax/examples/java.html +786 -0
  88. data/public/_components/@socketry/syntax/examples/javascript.html +199 -0
  89. data/public/_components/@socketry/syntax/examples/json.html +150 -0
  90. data/public/_components/@socketry/syntax/examples/lisp.html +476 -0
  91. data/public/_components/@socketry/syntax/examples/lua.html +737 -0
  92. data/public/_components/@socketry/syntax/examples/markdown.html +121 -0
  93. data/public/_components/@socketry/syntax/examples/mixed.html +306 -0
  94. data/public/_components/@socketry/syntax/examples/nginx.html +554 -0
  95. data/public/_components/@socketry/syntax/examples/ocaml.html +596 -0
  96. data/public/_components/@socketry/syntax/examples/pascal.html +762 -0
  97. data/public/_components/@socketry/syntax/examples/perl5.html +488 -0
  98. data/public/_components/@socketry/syntax/examples/php-script.html +142 -0
  99. data/public/_components/@socketry/syntax/examples/php.html +95 -0
  100. data/public/_components/@socketry/syntax/examples/plain.html +222 -0
  101. data/public/_components/@socketry/syntax/examples/protobuf.html +405 -0
  102. data/public/_components/@socketry/syntax/examples/python.html +82 -0
  103. data/public/_components/@socketry/syntax/examples/readme.md +79 -0
  104. data/public/_components/@socketry/syntax/examples/ruby.html +58 -0
  105. data/public/_components/@socketry/syntax/examples/scala.html +41 -0
  106. data/public/_components/@socketry/syntax/examples/smalltalk.html +436 -0
  107. data/public/_components/@socketry/syntax/examples/sql.html +373 -0
  108. data/public/_components/@socketry/syntax/examples/super-collider.html +55 -0
  109. data/public/_components/@socketry/syntax/examples/swift.html +176 -0
  110. data/public/_components/@socketry/syntax/examples/wrap-demo.html +103 -0
  111. data/public/_components/@socketry/syntax/examples/xml.html +112 -0
  112. data/public/_components/@socketry/syntax/examples/xrb.html +37 -0
  113. data/public/_components/@socketry/syntax/examples/yaml.html +72 -0
  114. data/public/_components/@socketry/syntax/license.md +21 -0
  115. data/public/_components/@socketry/syntax/package-lock.json +834 -0
  116. data/public/_components/@socketry/syntax/package.json +43 -0
  117. data/public/_components/@socketry/syntax/readme.md +162 -0
  118. data/public/_components/@socketry/syntax/test/Syntax/CodeElement.js +306 -0
  119. data/public/_components/@socketry/syntax/test/Syntax/ErrorHandling.js +85 -0
  120. data/public/_components/@socketry/syntax/test/Syntax/Language/apache.js +153 -0
  121. data/public/_components/@socketry/syntax/test/Syntax/Language/applescript.js +198 -0
  122. data/public/_components/@socketry/syntax/test/Syntax/Language/assembly.js +209 -0
  123. data/public/_components/@socketry/syntax/test/Syntax/Language/bash-script.js +225 -0
  124. data/public/_components/@socketry/syntax/test/Syntax/Language/bash.js +162 -0
  125. data/public/_components/@socketry/syntax/test/Syntax/Language/basic.js +265 -0
  126. data/public/_components/@socketry/syntax/test/Syntax/Language/clang.js +390 -0
  127. data/public/_components/@socketry/syntax/test/Syntax/Language/csharp.js +436 -0
  128. data/public/_components/@socketry/syntax/test/Syntax/Language/css.js +431 -0
  129. data/public/_components/@socketry/syntax/test/Syntax/Language/diff.js +206 -0
  130. data/public/_components/@socketry/syntax/test/Syntax/Language/go.js +386 -0
  131. data/public/_components/@socketry/syntax/test/Syntax/Language/haskell.js +454 -0
  132. data/public/_components/@socketry/syntax/test/Syntax/Language/html.js +111 -0
  133. data/public/_components/@socketry/syntax/test/Syntax/Language/io.js +229 -0
  134. data/public/_components/@socketry/syntax/test/Syntax/Language/java.js +362 -0
  135. data/public/_components/@socketry/syntax/test/Syntax/Language/javascript.js +101 -0
  136. data/public/_components/@socketry/syntax/test/Syntax/Language/json.js +101 -0
  137. data/public/_components/@socketry/syntax/test/Syntax/Language/lisp.js +224 -0
  138. data/public/_components/@socketry/syntax/test/Syntax/Language/lua.js +307 -0
  139. data/public/_components/@socketry/syntax/test/Syntax/Language/markdown.js +163 -0
  140. data/public/_components/@socketry/syntax/test/Syntax/Language/nginx.js +267 -0
  141. data/public/_components/@socketry/syntax/test/Syntax/Language/ocaml.js +299 -0
  142. data/public/_components/@socketry/syntax/test/Syntax/Language/pascal.js +311 -0
  143. data/public/_components/@socketry/syntax/test/Syntax/Language/perl5.js +333 -0
  144. data/public/_components/@socketry/syntax/test/Syntax/Language/php-script.js +197 -0
  145. data/public/_components/@socketry/syntax/test/Syntax/Language/php.js +92 -0
  146. data/public/_components/@socketry/syntax/test/Syntax/Language/plain.js +327 -0
  147. data/public/_components/@socketry/syntax/test/Syntax/Language/protobuf.js +294 -0
  148. data/public/_components/@socketry/syntax/test/Syntax/Language/python.js +213 -0
  149. data/public/_components/@socketry/syntax/test/Syntax/Language/ruby.js +70 -0
  150. data/public/_components/@socketry/syntax/test/Syntax/Language/scala.js +75 -0
  151. data/public/_components/@socketry/syntax/test/Syntax/Language/smalltalk.js +223 -0
  152. data/public/_components/@socketry/syntax/test/Syntax/Language/sql.js +281 -0
  153. data/public/_components/@socketry/syntax/test/Syntax/Language/super-collider.js +66 -0
  154. data/public/_components/@socketry/syntax/test/Syntax/Language/swift.js +71 -0
  155. data/public/_components/@socketry/syntax/test/Syntax/Language/xml.js +170 -0
  156. data/public/_components/@socketry/syntax/test/Syntax/Language/xrb.js +57 -0
  157. data/public/_components/@socketry/syntax/test/Syntax/Language/yaml.js +123 -0
  158. data/public/_components/@socketry/syntax/test/Syntax/Language.js +62 -0
  159. data/public/_components/@socketry/syntax/test/Syntax/Match.js +40 -0
  160. data/public/_components/@socketry/syntax/test/Syntax/Rule.js +251 -0
  161. data/public/_components/@socketry/syntax/test/Syntax.js +38 -0
  162. data/public/_components/@socketry/syntax/test/helpers/ast-matcher.js +90 -0
  163. data/public/_components/@socketry/syntax/themes/base/apache.css +1 -0
  164. data/public/_components/@socketry/syntax/themes/base/applescript.css +1 -0
  165. data/public/_components/@socketry/syntax/themes/base/assembly.css +1 -0
  166. data/public/_components/@socketry/syntax/themes/base/bash.css +1 -0
  167. data/public/_components/@socketry/syntax/themes/base/basic.css +1 -0
  168. data/public/_components/@socketry/syntax/themes/base/c.css +1 -0
  169. data/public/_components/@socketry/syntax/themes/base/clang.css +0 -0
  170. data/public/_components/@socketry/syntax/themes/base/csharp.css +1 -0
  171. data/public/_components/@socketry/syntax/themes/base/css.css +22 -0
  172. data/public/_components/@socketry/syntax/themes/base/diff.css +48 -0
  173. data/public/_components/@socketry/syntax/themes/base/go.css +1 -0
  174. data/public/_components/@socketry/syntax/themes/base/haskell.css +1 -0
  175. data/public/_components/@socketry/syntax/themes/base/html.css +1 -0
  176. data/public/_components/@socketry/syntax/themes/base/io.css +1 -0
  177. data/public/_components/@socketry/syntax/themes/base/java.css +1 -0
  178. data/public/_components/@socketry/syntax/themes/base/javascript.css +1 -0
  179. data/public/_components/@socketry/syntax/themes/base/json.css +41 -0
  180. data/public/_components/@socketry/syntax/themes/base/lisp.css +1 -0
  181. data/public/_components/@socketry/syntax/themes/base/lua.css +1 -0
  182. data/public/_components/@socketry/syntax/themes/base/markdown.css +16 -0
  183. data/public/_components/@socketry/syntax/themes/base/nginx.css +1 -0
  184. data/public/_components/@socketry/syntax/themes/base/ocaml.css +1 -0
  185. data/public/_components/@socketry/syntax/themes/base/pascal.css +1 -0
  186. data/public/_components/@socketry/syntax/themes/base/perl5.css +1 -0
  187. data/public/_components/@socketry/syntax/themes/base/php-script.css +1 -0
  188. data/public/_components/@socketry/syntax/themes/base/php.css +1 -0
  189. data/public/_components/@socketry/syntax/themes/base/plain.css +1 -0
  190. data/public/_components/@socketry/syntax/themes/base/protobuf.css +1 -0
  191. data/public/_components/@socketry/syntax/themes/base/python.css +1 -0
  192. data/public/_components/@socketry/syntax/themes/base/ruby.css +23 -0
  193. data/public/_components/@socketry/syntax/themes/base/scala.css +3 -0
  194. data/public/_components/@socketry/syntax/themes/base/smalltalk.css +1 -0
  195. data/public/_components/@socketry/syntax/themes/base/sql.css +1 -0
  196. data/public/_components/@socketry/syntax/themes/base/super-collider.css +33 -0
  197. data/public/_components/@socketry/syntax/themes/base/swift.css +1 -0
  198. data/public/_components/@socketry/syntax/themes/base/syntax.css +63 -0
  199. data/public/_components/@socketry/syntax/themes/base/xml.css +1 -0
  200. data/public/_components/@socketry/syntax/themes/base/xrb.css +29 -0
  201. data/public/_components/@socketry/syntax/themes/base/yaml.css +1 -0
  202. data/public/_components/@socketry/syntax/themes/theming.md +233 -0
  203. data/public/_components/@socketry/syntax/update-examples.js +135 -0
  204. data/public/_static/index.css +593 -0
  205. data/public/application.js +147 -0
  206. data/readme.md +69 -0
  207. data/releases.md +3 -0
  208. data/templates/code.xrb +12 -0
  209. data/templates/default.xrb +5 -0
  210. data/templates/image.xrb +8 -0
  211. data/templates/section.xrb +5 -0
  212. data/templates/title.xrb +8 -0
  213. data/templates/translation.xrb +8 -0
  214. data/templates/two_column.xrb +8 -0
  215. metadata +280 -0
@@ -0,0 +1,337 @@
1
+ import Syntax from '../Syntax.js';
2
+
3
+ const supportsAdopted =
4
+ typeof CSSStyleSheet !== 'undefined' &&
5
+ 'adoptedStyleSheets' in Document.prototype;
6
+
7
+ /**
8
+ * CodeElement - Web Component for syntax highlighting with isolated styles
9
+ *
10
+ * Usage:
11
+ * <syntax-code language="javascript">const x = 1;</syntax-code>
12
+ * <pre><syntax-code language="ruby">puts "Hello"</syntax-code></pre>
13
+ */
14
+ export class CodeElement extends HTMLElement {
15
+ static get observedAttributes() {
16
+ return ['language', 'theme', 'wrap'];
17
+ }
18
+
19
+ #syntax = null;
20
+ #shadow;
21
+ #adoptedHrefs = new Set();
22
+ #highlighted = false;
23
+ #readyResolve = null;
24
+
25
+ constructor() {
26
+ super();
27
+
28
+ /**
29
+ * A promise that resolves when the element has been fully rendered.
30
+ * Use this to ensure line measurement APIs return valid results.
31
+ * @type {Promise<void>}
32
+ */
33
+ this.ready = new Promise(resolve => {
34
+ this.#readyResolve = resolve;
35
+ });
36
+ }
37
+
38
+ get syntax() {
39
+ return this.#syntax || Syntax.default;
40
+ }
41
+
42
+ set syntax(value) {
43
+ this.#syntax = value;
44
+ // Re-render with new syntax instance if already connected:
45
+ if (this.isConnected && !this.#highlighted) {
46
+ this.#render();
47
+ }
48
+ }
49
+
50
+ get language() {
51
+ return (
52
+ this.getAttribute('language') ||
53
+ this.#detectLanguageFromClass()
54
+ );
55
+ }
56
+
57
+ set language(value) {
58
+ if (value == null) {
59
+ this.removeAttribute('language');
60
+ } else {
61
+ this.setAttribute('language', value);
62
+ }
63
+ }
64
+
65
+ get theme() {
66
+ return this.getAttribute('theme') || this.syntax.defaultOptions.theme;
67
+ }
68
+
69
+ set theme(value) {
70
+ if (value == null) {
71
+ this.removeAttribute('theme');
72
+ } else {
73
+ this.setAttribute('theme', value);
74
+ }
75
+ }
76
+
77
+ get wrap() {
78
+ return this.hasAttribute('wrap');
79
+ }
80
+
81
+ set wrap(value) {
82
+ if (value) {
83
+ this.setAttribute('wrap', '');
84
+ } else {
85
+ this.removeAttribute('wrap');
86
+ }
87
+ }
88
+
89
+ /**
90
+ * Get the bounding client rect of a specific line (1-based).
91
+ * @param {number} lineNumber - The 1-based line number.
92
+ * @returns {DOMRect|null} The bounding rect, or null if not found.
93
+ */
94
+ getLineBoundingClientRect(lineNumber) {
95
+ if (!this.#shadow) return null;
96
+
97
+ const code = this.#shadow.querySelector('code');
98
+ if (!code) return null;
99
+
100
+ const lines = code.children;
101
+ if (lineNumber < 1 || lineNumber > lines.length) return null;
102
+
103
+ return lines[lineNumber - 1].getBoundingClientRect();
104
+ }
105
+
106
+ /**
107
+ * Get the total number of rendered lines.
108
+ * @returns {number} The line count, or 0 if not yet rendered.
109
+ */
110
+ get lineCount() {
111
+ if (!this.#shadow) return 0;
112
+
113
+ const code = this.#shadow.querySelector('code');
114
+ if (!code) return 0;
115
+
116
+ return code.children.length;
117
+ }
118
+
119
+ connectedCallback() {
120
+ // Detect if we're inside a <pre> element and set wrap attribute
121
+ if (this.parentElement?.tagName === 'PRE') {
122
+ this.wrap = true;
123
+ }
124
+
125
+ // Don't re-highlight if already done
126
+ if (this.#highlighted) {
127
+ return;
128
+ }
129
+
130
+ if (!this.#shadow) {
131
+ this.#shadow = this.attachShadow({mode: 'open'});
132
+ }
133
+
134
+ this.#render();
135
+ }
136
+
137
+ attributeChangedCallback(name, oldValue, newValue) {
138
+ if (oldValue === newValue) {
139
+ return;
140
+ }
141
+
142
+ if (
143
+ (name === 'language' || name === 'theme' || name === 'wrap') &&
144
+ this.isConnected &&
145
+ this.#shadow
146
+ ) {
147
+ // Reset highlighted flag and ready promise to allow re-rendering
148
+ this.#highlighted = false;
149
+ this.ready = new Promise(resolve => {
150
+ this.#readyResolve = resolve;
151
+ });
152
+ this.#adoptedHrefs.clear();
153
+ this.#render();
154
+ }
155
+ }
156
+
157
+ /**
158
+ * Detect language from class names (e.g., language-javascript, brush-ruby)
159
+ */
160
+ #detectLanguageFromClass() {
161
+ const classes = this.className.split(/\s+/);
162
+
163
+ for (const cls of classes) {
164
+ // Match language-* or brush-* patterns
165
+ const match = cls.match(/^(?:language|brush)-(.+)$/);
166
+ if (match) {
167
+ return match[1];
168
+ }
169
+ }
170
+
171
+ return null;
172
+ }
173
+
174
+ /**
175
+ * Get the code content to highlight
176
+ */
177
+ #getCodeContent() {
178
+ // Check if there's a <code> child element
179
+ const codeElement = this.querySelector('code');
180
+ if (codeElement) {
181
+ return codeElement.textContent;
182
+ }
183
+
184
+ return this.textContent;
185
+ }
186
+
187
+ /**
188
+ * Load theme CSS into shadow root
189
+ */
190
+ async #loadStylesheets(languageName) {
191
+ // Guard: ensure shadow root exists
192
+ if (!this.#shadow) {
193
+ return;
194
+ }
195
+
196
+ const themeRoot = new URL(
197
+ this.syntax.themeRoot,
198
+ typeof document !== 'undefined' ? document.baseURI : import.meta.url
199
+ );
200
+
201
+ const urls = [
202
+ new URL('syntax.css', themeRoot),
203
+ new URL(`${languageName}.css`, themeRoot)
204
+ ];
205
+
206
+ if (supportsAdopted && this.#shadow.adoptedStyleSheets !== undefined) {
207
+ const sheets = Array.from(this.#shadow.adoptedStyleSheets);
208
+ for (const url of urls) {
209
+ const href = url.toString();
210
+ if (this.#adoptedHrefs.has(href)) continue;
211
+ try {
212
+ const result = await this.syntax.getStyleSheet(url);
213
+ if (result.sheet) {
214
+ sheets.push(result.sheet);
215
+ this.#adoptedHrefs.add(href);
216
+ }
217
+ } catch (error) {
218
+ console.warn(`Failed to load ${href}:`, error);
219
+ }
220
+ }
221
+ this.#shadow.adoptedStyleSheets = sheets;
222
+ } else {
223
+ // Fallback: inline <style> tags in shadow root
224
+ for (const url of urls) {
225
+ const href = url.toString();
226
+ if (this.#adoptedHrefs.has(href)) continue;
227
+ try {
228
+ const result = await this.syntax.getStyleSheet(url);
229
+ const style = document.createElement('style');
230
+ style.textContent = result.cssText;
231
+ this.#shadow.appendChild(style);
232
+ this.#adoptedHrefs.add(href);
233
+ } catch (error) {
234
+ console.warn(`Failed to load ${href}:`, error);
235
+ }
236
+ }
237
+ }
238
+ }
239
+
240
+ /**
241
+ * Perform syntax highlighting and render into shadow DOM
242
+ */
243
+ async #render() {
244
+ try {
245
+ const languageName = this.language;
246
+
247
+ if (!languageName) {
248
+ console.warn('<syntax-code>: No language specified');
249
+ return;
250
+ }
251
+
252
+ // Get or auto-load the language
253
+ const language = await this.syntax.getLanguage(languageName);
254
+
255
+ if (!language) {
256
+ console.warn(
257
+ `<syntax-code>: Language '${languageName}' not found and could not be loaded`
258
+ );
259
+ return;
260
+ }
261
+
262
+ // Load theme CSS into shadow root using the language's canonical name
263
+ await this.#loadStylesheets(language.name);
264
+
265
+ const code = this.#getCodeContent();
266
+
267
+ // Clear shadow DOM before rendering (must happen before appendChild to remove old content, but after loadStylesheets since fallback path may have appended <style> elements):
268
+ this.#shadow.innerHTML = '';
269
+
270
+ // Highlight and append - language.process() returns a <code> element:
271
+ const highlighted = await language.process(this.syntax, code);
272
+ this.#shadow.appendChild(highlighted);
273
+
274
+ // Clear light DOM only after successful render to avoid losing content on errors:
275
+ this.textContent = '';
276
+
277
+ this.#highlighted = true;
278
+ this.#readyResolve?.();
279
+ } catch (error) {
280
+ console.warn('<syntax-code> render failed:', error);
281
+ }
282
+ }
283
+ }
284
+
285
+ /**
286
+ * Auto-register the custom element
287
+ */
288
+ if (
289
+ typeof customElements !== 'undefined' &&
290
+ !customElements.get('syntax-code')
291
+ ) {
292
+ customElements.define('syntax-code', CodeElement);
293
+ }
294
+
295
+ /**
296
+ * Compatibility layer - upgrade existing code blocks to web components
297
+ */
298
+ export function upgradeAll(selector, syntax = null) {
299
+ const elements = document.querySelectorAll(selector);
300
+
301
+ for (const element of elements) {
302
+ // Create a syntax-code wrapper
303
+ const wrapper = document.createElement('syntax-code');
304
+ if (syntax) {
305
+ wrapper.syntax = syntax;
306
+ }
307
+
308
+ // Try to detect language from various sources
309
+ let language = element.getAttribute('lang') || element.getAttribute('language');
310
+
311
+ if (!language) {
312
+ // Check class names
313
+ const classes = element.className.split(/\s+/);
314
+ for (const cls of classes) {
315
+ const match = cls.match(/^(?:language|brush)-(.+)$/);
316
+ if (match) {
317
+ language = match[1];
318
+ break;
319
+ }
320
+ }
321
+ }
322
+
323
+ if (language) {
324
+ wrapper.setAttribute('language', language);
325
+ }
326
+
327
+ // Copy the code content into the wrapper
328
+ wrapper.textContent = element.textContent;
329
+
330
+ // Replace <code> with <syntax-code>, leaving <pre> parent in place
331
+ const parent = element.parentElement;
332
+ parent.replaceChild(wrapper, element);
333
+ }
334
+ }
335
+
336
+ export {Syntax};
337
+ export default CodeElement;
@@ -0,0 +1,52 @@
1
+ export class GenericSyntaxError extends Error {
2
+ constructor(message, options = {}) {
3
+ super(message, options);
4
+ Object.defineProperty(this, 'name', {value: this.constructor.name});
5
+ }
6
+ }
7
+
8
+ export class LanguageNotFoundError extends GenericSyntaxError {
9
+ constructor(language, options = {}) {
10
+ super(`Language not found: ${language}`, options);
11
+ this.language = language;
12
+ }
13
+ }
14
+
15
+ export class LanguageLoadError extends GenericSyntaxError {
16
+ constructor(language, url, options = {}) {
17
+ super(`Failed to load language '${language}' from ${url}`, options);
18
+ this.language = language;
19
+ this.url = url;
20
+ }
21
+ }
22
+
23
+ export class StyleSheetLoadError extends GenericSyntaxError {
24
+ constructor(url, status, options = {}) {
25
+ super(`Failed to load stylesheet ${url} (status: ${status})`, options);
26
+ this.url = url;
27
+ this.status = status;
28
+ }
29
+ }
30
+
31
+ export class RuleApplyError extends GenericSyntaxError {
32
+ constructor(rule, options = {}) {
33
+ const pattern =
34
+ rule?.pattern instanceof RegExp
35
+ ? `/${rule.pattern.source}/${rule.pattern.flags}`
36
+ : String(rule?.pattern);
37
+ const type = rule?.type || rule?.klass || 'unknown';
38
+ super(`Rule apply failed (type=${type}, pattern=${pattern})`, options);
39
+ this.rule = rule;
40
+ }
41
+ }
42
+
43
+ export class HighlightRenderError extends GenericSyntaxError {}
44
+
45
+ export default {
46
+ GenericSyntaxError,
47
+ LanguageNotFoundError,
48
+ LanguageLoadError,
49
+ StyleSheetLoadError,
50
+ RuleApplyError,
51
+ HighlightRenderError
52
+ };
@@ -0,0 +1,49 @@
1
+ import {Language} from '../Language.js';
2
+ import {Rule} from '../Rule.js';
3
+
4
+ const language = new Language('apache');
5
+
6
+ language.push({
7
+ pattern: /(<(\w+).*?>)/i,
8
+ matches: Rule.extractMatches(
9
+ {
10
+ type: 'tag',
11
+ allow: ['attribute', 'tag-name', 'string']
12
+ },
13
+ {
14
+ type: 'tag-name',
15
+ process: Rule.webLinkProcess(
16
+ 'http://httpd.apache.org/docs/trunk/mod/directive-dict.html#'
17
+ )
18
+ }
19
+ )
20
+ });
21
+
22
+ language.push({
23
+ pattern: /(<\/(\w+).*?>)/i,
24
+ matches: Rule.extractMatches(
25
+ {type: 'tag', allow: ['tag-name']},
26
+ {type: 'tag-name'}
27
+ )
28
+ });
29
+
30
+ language.push({
31
+ pattern: /^\s+([A-Z][\w]+)/m,
32
+ matches: Rule.extractMatches({
33
+ type: 'function',
34
+ allow: ['attribute'],
35
+ process: Rule.webLinkProcess(
36
+ 'http://httpd.apache.org/docs/trunk/mod/directive-dict.html#'
37
+ )
38
+ })
39
+ });
40
+
41
+ language.push(Rule.perlStyleComment);
42
+ language.push(Rule.singleQuotedString);
43
+ language.push(Rule.doubleQuotedString);
44
+
45
+ language.push(Rule.webLink);
46
+
47
+ export default function register(syntax) {
48
+ syntax.register('apache', language);
49
+ }
@@ -0,0 +1,157 @@
1
+ import {Language} from '../Language.js';
2
+ import {Rule} from '../Rule.js';
3
+
4
+ const language = new Language('applescript');
5
+
6
+ var keywords = [
7
+ 'after',
8
+ 'before',
9
+ 'beginning',
10
+ 'continue',
11
+ 'copy',
12
+ 'each',
13
+ 'end',
14
+ 'every',
15
+ 'from',
16
+ 'get',
17
+ 'global',
18
+ 'in',
19
+ 'local',
20
+ 'named',
21
+ 'of',
22
+ 'return',
23
+ 'set',
24
+ 'some',
25
+ 'that',
26
+ 'the',
27
+ 'then',
28
+ 'times',
29
+ 'to',
30
+ 'where',
31
+ 'whose',
32
+ 'with',
33
+ 'without'
34
+ ];
35
+
36
+ language.push(keywords, {type: 'keyword'});
37
+
38
+ var ordinals = [
39
+ 'first',
40
+ 'second',
41
+ 'third',
42
+ 'fourth',
43
+ 'fifth',
44
+ 'sixth',
45
+ 'seventh',
46
+ 'eighth',
47
+ 'ninth',
48
+ 'tenth',
49
+ 'last',
50
+ 'front',
51
+ 'back',
52
+ 'middle'
53
+ ];
54
+
55
+ language.push(ordinals, {type: 'keyword'});
56
+
57
+ var specials = [
58
+ 'activate',
59
+ 'add',
60
+ 'alias',
61
+ 'AppleScript',
62
+ 'ask',
63
+ 'attachment',
64
+ 'boolean',
65
+ 'class',
66
+ 'constant',
67
+ 'delete',
68
+ 'duplicate',
69
+ 'empty',
70
+ 'exists',
71
+ 'false',
72
+ 'id',
73
+ 'integer',
74
+ 'list',
75
+ 'make',
76
+ 'message',
77
+ 'modal',
78
+ 'modified',
79
+ 'new',
80
+ 'no',
81
+ 'paragraph',
82
+ 'pi',
83
+ 'properties',
84
+ 'quit',
85
+ 'real',
86
+ 'record',
87
+ 'remove',
88
+ 'rest',
89
+ 'result',
90
+ 'reveal',
91
+ 'reverse',
92
+ 'run',
93
+ 'running',
94
+ 'save',
95
+ 'string',
96
+ 'true',
97
+ 'word',
98
+ 'yes'
99
+ ];
100
+
101
+ language.push(specials, {type: 'keyword'});
102
+
103
+ language.push(Rule.webLink);
104
+
105
+ // AppleScript supports multiple comment styles
106
+ language.push({
107
+ pattern: /(\-\-|#).*$/m,
108
+ type: 'comment',
109
+ allow: ['href']
110
+ });
111
+
112
+ language.push({
113
+ pattern: /\(\*(?:[\s\S]*?\(\*[\s\S]*?\*\))*[\s\S]*?\*\)/m,
114
+ type: 'comment',
115
+ allow: ['href']
116
+ });
117
+
118
+ language.push(Rule.doubleQuotedString);
119
+
120
+ // Ordinal numbers (1st, 2nd, 3rd, etc.)
121
+ language.push({
122
+ pattern: /\b\d+(st|nd|rd|th)\b/,
123
+ type: 'constant'
124
+ });
125
+
126
+ // Regular numbers
127
+ language.push({
128
+ pattern: /\b-?\d+\.?\d*(?:E[+\-]?\d+)?\b/,
129
+ type: 'constant'
130
+ });
131
+
132
+ language.push({
133
+ pattern: /&|¬|=|≠|>|<|≥|>=|≤|<=|\*|\+|-|\/|÷|\^/,
134
+ type: 'operator'
135
+ });
136
+
137
+ language.push({
138
+ pattern:
139
+ /\b(?:and|as|div|mod|not|or|return(?!\s&)(ing)?|equals|(is(n't| not)? )?equal( to)?|does(n't| not) equal|(is(n't| not)? )?(greater|less) than( or equal( to)?)?|(comes|does(n't| not) come) (after|before)|is(n't| not)?( in)? (back|front) of|is(n't| not)? behind|is(n't| not)?( (in|contained by))?|does(n't| not) contain|contain(s)?|(start|begin|end)(s)? with|((but|end) )?(consider|ignor)ing|prop(erty)?|(a )?ref(erence)?( to)?|repeat (until|while|with)|((end|exit) )?repeat|((else|end) )?if|else|(end )?(script|tell|try)|(on )?error|(put )?into|(of )?(it|me)|its|my|with (timeout( of)?|transaction)|end (timeout|transaction))\b/,
140
+ type: 'keyword'
141
+ });
142
+
143
+ language.push({
144
+ pattern:
145
+ /\b(?:about|above|against|around|at|below|beneath|beside|between|by|(apart|aside) from|(instead|out) of|into|on(to)?|over|since|thr(ough|u)|under)\b/,
146
+ type: 'keyword'
147
+ });
148
+
149
+ language.push({
150
+ pattern:
151
+ /\b(?:adding folder items to|after receiving|choose( ((remote )?application|color|folder|from list|URL))?|clipboard info|set the clipboard to|(the )?clipboard|entire contents|display(ing| (alert|dialog|mode))?|document( (edited|file|nib name))?|file( (name|type))?|(info )?for|giving up after|(name )?extension|quoted form|return(ed)?|second(?! item)(s)?|list (disks|folder)|text item(s| delimiters)?|(Unicode )?text|(disk )?item(s)?|((current|list) )?view|((container|key) )?window|with (data|icon( (caution|note|stop))?|parameter(s)?|prompt|properties|seed|title)|case|diacriticals|hyphens|numeric strings|punctuation|white space|folder creation|application(s( folder)?| (processes|scripts position|support))?|((desktop )?(pictures )?|(documents|downloads|favorites|home|keychain|library|movies|music|public|scripts|sites|system|users|utilities|workflows) )folder|desktop|Folder Action scripts|font(s| panel)?|help|internet plugins|modem scripts|(system )?preferences|printer descriptions|scripting (additions|components)|shared (documents|libraries)|startup (disk|items)|temporary items|trash|on server|in AppleTalk zone|((as|long|short) )?user name|user (ID|locale)|(with )?password|in (bundle( with identifier)?|directory)|(close|open for) access|read|write( permission)?|(g|s)et eof|using( delimiters)?|starting at|default (answer|button|color|country code|entr(y|ies)|identifiers|items|name|location|script editor)|hidden( answer)?|open(ed| (location|untitled))?|error (handling|reporting)|(do( shell)?|load|run|store) script|administrator privileges|altering line endings|get volume settings|(alert|boot|input|mount|output|set) volume|output muted|(fax|random )?number|round(ing)?|up|down|toward zero|to nearest|as taught in school|system (attribute|info)|((AppleScript( Studio)?|system) )?version|(home )?directory|(IPv4|primary Ethernet) address|CPU (type|speed)|physical memory|time (stamp|to GMT)|replacing|ASCII (character|number)|localized string|from table|offset|summarize|beep|delay|say|(empty|multiple) selections allowed|(of|preferred) type|invisibles|showing( package contents)?|editable URL|(File|FTP|News|Media|Web) [Ss]ervers|Telnet hosts|Directory services|Remote applications|waiting until completion|saving( (in|to))?|path (for|to( (((current|frontmost) )?application|resource))?)|POSIX (file|path)|(background|RGB) color|(OK|cancel) button name|cancel button|button(s)?|cubic ((centi)?met(re|er)s|yards|feet|inches)|square ((kilo)?met(re|er)s|miles|yards|feet)|(centi|kilo)?met(re|er)s|miles|yards|feet|inches|lit(re|er)s|gallons|quarts|(kilo)?grams|ounces|pounds|degrees (Celsius|Fahrenheit|Kelvin)|print( (dialog|settings))?|clos(e(able)?|ing)|(de)?miniaturized|miniaturizable|zoom(ed|able)|attribute run|action (method|property|title)|phone|email|((start|end)ing|home) page|((birth|creation|current|custom|modification) )?date|((((phonetic )?(first|last|middle))|computer|host|maiden|related) |nick)?name|aim|icq|jabber|msn|yahoo|address(es)?|save addressbook|should enable action|city|country( code)?|formatte(r|d address)|(palette )?label|state|street|zip|AIM [Hh]andle(s)?|my card|select(ion| all)?|unsaved|(alpha )?value|entr(y|ies)|group|(ICQ|Jabber|MSN) handle|person|people|company|department|icon image|job title|note|organization|suffix|vcard|url|copies|collating|pages (across|down)|request print time|target( printer)?|((GUI Scripting|Script menu) )?enabled|show Computer scripts|(de)?activated|awake from nib|became (key|main)|call method|of (class|object)|center|clicked toolbar item|closed|for document|exposed|(can )?hide|idle|keyboard (down|up)|event( (number|type))?|launch(ed)?|load (image|movie|nib|sound)|owner|log|mouse (down|dragged|entered|exited|moved|up)|move|column|localization|resource|script|register|drag (info|types)|resigned (active|key|main)|resiz(e(d)?|able)|right mouse (down|dragged|up)|scroll wheel|(at )?index|should (close|open( untitled)?|quit( after last window closed)?|zoom)|((proposed|screen) )?bounds|show(n)?|behind|in front of|size (mode|to fit)|update(d| toolbar item)?|was (hidden|miniaturized)|will (become active|close|finish launching|hide|miniaturize|move|open|quit|(resign )?active|((maximum|minimum|proposed) )?size|show|zoom)|bundle|data source|movie|pasteboard|sound|tool(bar| tip)|(color|open|save) panel|coordinate system|frontmost|main( (bundle|menu|window))?|((services|(excluded from )?windows) )?menu|((executable|frameworks|resource|scripts|shared (frameworks|support)) )?path|(selected item )?identifier|data|content(s| view)?|character(s)?|click count|(command|control|option|shift) key down|context|delta (x|y|z)|key( code)?|location|pressure|unmodified characters|types|(first )?responder|playing|(allowed|selectable) identifiers|allows customization|(auto saves )?configuration|visible|image( name)?|menu form representation|tag|user(-| )defaults|associated file name|(auto|needs) display|current field editor|floating|has (resize indicator|shadow)|hides when deactivated|level|minimized (image|title)|opaque|position|release when closed|sheet|title(d)?)\b/,
152
+ type: 'keyword'
153
+ });
154
+
155
+ export default function register(syntax) {
156
+ syntax.register('applescript', language);
157
+ }
@@ -0,0 +1,42 @@
1
+ import {Language} from '../Language.js';
2
+ import {Rule} from '../Rule.js';
3
+
4
+ const language = new Language('assembly');
5
+
6
+ language.push(Rule.cStyleComment);
7
+ language.push(Rule.cppStyleComment);
8
+
9
+ language.push({pattern: /\.[a-zA-Z_][a-zA-Z0-9_]*/m, type: 'directive'});
10
+
11
+ language.push({pattern: /^[a-zA-Z_][a-zA-Z0-9_]*:/m, type: 'label'});
12
+
13
+ language.push({
14
+ pattern: /^\s*([a-zA-Z]+)/m,
15
+ matches: Rule.extractMatches({type: 'function'})
16
+ });
17
+
18
+ language.push({pattern: /(-[0-9]+)|(\b[0-9]+)|(\$[0-9]+)/, type: 'constant'});
19
+ language.push({
20
+ pattern: /(\-|\b|\$)(0x[0-9a-f]+|[0-9]+|[a-z0-9_]+)/i,
21
+ type: 'constant'
22
+ });
23
+
24
+ language.push({pattern: /%\w+/, type: 'register'});
25
+
26
+ // Strings
27
+ language.push(Rule.singleQuotedString);
28
+ language.push(Rule.doubleQuotedString);
29
+ language.push(Rule.stringEscape);
30
+
31
+ // Numbers
32
+ language.push(Rule.decimalNumber);
33
+ language.push(Rule.hexNumber);
34
+
35
+ // Comments
36
+ language.push(Rule.perlStyleComment);
37
+ language.push(Rule.webLink);
38
+
39
+ export default function register(syntax) {
40
+ syntax.register('assembly', language);
41
+ syntax.alias('assembly', ['asm']);
42
+ }