@brightspace-ui/core 2.27.1 → 2.28.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.
@@ -0,0 +1,47 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <title>d2l-html-block (code samples)</title>
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <meta charset="UTF-8">
7
+ <link rel="stylesheet" href="../../demo/styles.css" type="text/css">
8
+ <script type="module">
9
+ import '../../colors/colors.js';
10
+ import '../../typography/typography.js';
11
+ import '../html-block.js';
12
+ </script>
13
+ <style>
14
+ html {
15
+ font-size: 20px;
16
+ }
17
+ body {
18
+ padding: 1rem;
19
+ }
20
+ </style>
21
+ </head>
22
+ <body class="d2l-typography">
23
+
24
+ <h1 class="d2l-heading-2">d2l-html-block (code)</h1>
25
+
26
+ <h2 class="d2l-heading-3">Block Samples</h2>
27
+
28
+ <d2l-html-block>
29
+ <pre class="d2l-code d2l-code-dark"><code class="language-javascript">function helloGrumpy(name) {
30
+ console.log(`Hi there ${name}.`);
31
+ }
32
+ helloGrumpy('Wizard');</code></pre>
33
+ <br>
34
+ <pre class="d2l-code d2l-code-dark"><code class="language-javascript line-numbers">function helloGrumpy(name) {
35
+ console.log(`Hi there ${name}. Here's some really long text to test overflowing the bounding container.`);
36
+ }
37
+ helloGrumpy('Wizard');</code></pre>
38
+ </d2l-html-block>
39
+
40
+ <h2 class="d2l-heading-3">Inline Samples</h2>
41
+
42
+ <d2l-html-block>
43
+ The best type of donuts are he kind you assign in code, for example: <code class="d2l-code d2l-code-dark language-javascript">const jelly = 'donuts';</code>. The next best type of thing you can assign in code is stuff you can ferment. <code class="d2l-code d2l-code-dark language-javascript">let beer = hopsAndWater.map(ingredients => ferment(ingredients));</code>
44
+ </d2l-html-block>
45
+
46
+ </body>
47
+ </html>
@@ -1,4 +1,5 @@
1
1
  import '../colors/colors.js';
2
+ import { codeStyles, HtmlBlockCodeRenderer } from '../../helpers/prism.js';
2
3
  import { css, LitElement } from 'lit';
3
4
  import { HtmlAttributeObserverController } from '../../controllers/attributeObserver/htmlAttributeObserverController.js';
4
5
  import { HtmlBlockMathRenderer } from '../../helpers/mathjax.js';
@@ -111,6 +112,7 @@ export const htmlBlockContentStyles = css`
111
112
  mjx-assistive-mml math {
112
113
  position: absolute;
113
114
  }
115
+ ${codeStyles}
114
116
  `;
115
117
 
116
118
  let renderers;
@@ -118,8 +120,8 @@ let renderers;
118
120
  const getRenderers = () => {
119
121
  if (renderers) return renderers;
120
122
  const tempRenderers = requestInstance(document, 'html-block-renderers');
121
- const htmlBlockMathRenderer = new HtmlBlockMathRenderer();
122
- renderers = (tempRenderers ? [ htmlBlockMathRenderer, ...tempRenderers ] : [ htmlBlockMathRenderer ]);
123
+ const defaultRenderers = [ new HtmlBlockMathRenderer(), new HtmlBlockCodeRenderer() ];
124
+ renderers = (tempRenderers ? [ ...defaultRenderers, ...tempRenderers ] : defaultRenderers);
123
125
  return renderers;
124
126
  };
125
127
 
@@ -0,0 +1,417 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <title>Prism Helper</title>
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <meta charset="UTF-8">
7
+ <link rel="stylesheet" href="../../components/demo/styles.css" type="text/css">
8
+ <script type="module">
9
+ import '../../components/colors/colors.js';
10
+ import '../../components/switch/switch.js';
11
+ import '../../components/typography/typography.js';
12
+ import { codeStyles, formatCodeElement } from '../prism.js';
13
+ import { css, html, LitElement } from 'lit';
14
+ import { classMap } from 'lit/directives/class-map.js';
15
+
16
+ class DemoPrism extends LitElement {
17
+ static get properties() {
18
+ return {
19
+ dark: { type: Boolean, reflect: true }
20
+ };
21
+ }
22
+ static get styles() {
23
+ return [codeStyles, css`
24
+ :host {
25
+ display: block;
26
+ }
27
+ `];
28
+ }
29
+ render() {
30
+ const classes = { 'd2l-code': true, 'd2l-code-dark': this.dark };
31
+ return html`
32
+ <pre class="${classMap(classes)}"><code class="language-javascript line-numbers">function helloGrumpy(name) {
33
+ console.log(\`Hi there \${name}. Here's some really long text to test overflowing the bounding container.\`);
34
+ }
35
+ helloGrumpy('Wizard');
36
+ </code></pre>
37
+
38
+ <pre class="${classMap(classes)}"><code class="language-bash line-numbers">#!/bin/bash
39
+ if [ -d $directory ]; then
40
+ echo "Directory exists"
41
+ else
42
+ echo "Directory does not exists"
43
+ fi</code></pre>
44
+
45
+ <pre class="${classMap(classes)}"><code class="language-css line-numbers">.grumpy > img {
46
+ height: 100%;
47
+ width: 100%;
48
+ }</code></pre>
49
+
50
+ <pre class="${classMap(classes)}"><code class="language-json line-numbers">{
51
+ "jinxed": "gnomes",
52
+ "grumpy": [ "wizards" ]
53
+ }
54
+ </code></pre>
55
+
56
+ <pre class="${classMap(classes)}"><code class="language-sql line-numbers">DECLARE @MyCounter INT; /* keyword, variable, punctuation */
57
+
58
+ SELECT AVG(Calories) AS AverageCalories FROM Desserts; /* keyword, function */
59
+
60
+ SELECT * FROM Desserts /* keyword, operator */
61
+
62
+ SET ROWCOUNT 4; /* keyword, number */
63
+
64
+ SET @Hidden = FALSE; /* keyword, variable, boolean */
65
+
66
+ SET @Donuts = 'Yummy'; /* keyword, variable, string */
67
+ </code></pre>
68
+ `;
69
+ }
70
+ updated(changedProperties) {
71
+ super.updated(changedProperties);
72
+ this.shadowRoot.querySelectorAll('pre').forEach(code => formatCodeElement(code));
73
+ }
74
+ }
75
+ customElements.define('d2l-demo-prism', DemoPrism);
76
+ </script>
77
+ <style>
78
+ html {
79
+ font-size: 20px;
80
+ }
81
+ body {
82
+ padding: 1rem;
83
+ }
84
+ .heading-container {
85
+ display: flex;
86
+ }
87
+ .heading-container > h1 {
88
+ flex: auto;
89
+ }
90
+ .heading-container > d2l-switch {
91
+ align-self: center;
92
+ flex: none;
93
+ }
94
+ table {
95
+ font-family: 'Lato', 'Lucida Sans Unicode', 'Lucida Grande', sans-serif;
96
+ font-size: 16px;
97
+ }
98
+ th {
99
+ text-align: left;
100
+ }
101
+ tr > td:first-child {
102
+ width: 300px;
103
+ }
104
+ </style>
105
+ </head>
106
+ <body class="d2l-typography">
107
+
108
+ <!-- This page intentionally does not use d2l-demo-page so we can properly demo/test the loader without PrismJS being loaded by those components -->
109
+
110
+ <div class="heading-container">
111
+ <h1 class="d2l-heading-2">Prism Helper</h1>
112
+ <d2l-switch text="Dark" on text-position="start" on></d2l-switch>
113
+ </div>
114
+
115
+ <h2 class="d2l-heading-3">Tokens</h2>
116
+
117
+ <table style="width: 100%;">
118
+ <thead>
119
+ <tr>
120
+ <th>Token</th>
121
+ <th>Example</th>
122
+ </tr>
123
+ </thead>
124
+ <tbody>
125
+ <tr>
126
+ <td>keyword</td>
127
+ <td>
128
+ <pre class="d2l-code d2l-code-dark"><code class="language-javascript">import { stuff } from 'some/where.js';</code></pre>
129
+ </td>
130
+ </tr>
131
+ <tr>
132
+ <td>builtin</td>
133
+ <td>
134
+ <pre class="d2l-code d2l-code-dark"><code class="language-python">pi = round(float('3.14159'), 2)</code></pre>
135
+ </td>
136
+ </tr>
137
+ <tr>
138
+ <td>class-name</td>
139
+ <td>
140
+ <pre class="d2l-code d2l-code-dark"><code class="language-javascript">class Wizard extends Human { /* ... */ }</code></pre>
141
+ </td>
142
+ </tr>
143
+ <tr>
144
+ <td>function</td>
145
+ <td>
146
+ <pre class="d2l-code d2l-code-dark"><code class="language-javascript">function helloGrumpy(name) { /* ... */ }
147
+ helloGrumpy('Wizard');</code></pre>
148
+ </td>
149
+ </tr>
150
+ <tr>
151
+ <td>parameter</td>
152
+ <td>
153
+ <pre class="d2l-code d2l-code-dark"><code class="language-javascript">function helloGrumpy(name) { /* ... */ }</code></pre>
154
+ </td>
155
+ </tr>
156
+ <tr>
157
+ <td>boolean</td>
158
+ <td>
159
+ <pre class="d2l-code d2l-code-dark"><code class="language-javascript">const wizardsLikeBeer = false;</code></pre>
160
+ </td>
161
+ </tr>
162
+ <tr>
163
+ <td>number</td>
164
+ <td>
165
+ <pre class="d2l-code d2l-code-dark"><code class="language-javascript">const favouriteNumber = 3.14159;</code></pre>
166
+ </td>
167
+ </tr>
168
+ <tr>
169
+ <td>string</td>
170
+ <td>
171
+ <pre class="d2l-code d2l-code-dark"><code class="language-javascript">const hiGrumpy = 'Hi Grumpy!';</code></pre>
172
+ </td>
173
+ </tr>
174
+ <tr>
175
+ <td>template-string, template-punctuation</td>
176
+ <td>
177
+ <pre class="d2l-code d2l-code-dark"><code class="language-javascript">const hiGrumpy = `Hi Grumpy!`;</code></pre>
178
+ </td>
179
+ </tr>
180
+ <tr>
181
+ <td>interpolation, interpolation-punctuation</td>
182
+ <td>
183
+ <pre class="d2l-code d2l-code-dark"><code class="language-javascript">console.log(`Hi there ${name}.`);</code></pre>
184
+ </td>
185
+ </tr>
186
+ <tr>
187
+ <td>char</td>
188
+ <td>
189
+ <pre class="d2l-code d2l-code-dark"><code class="language-javascript"></code></pre>
190
+ </td>
191
+ </tr>
192
+ <tr>
193
+ <td>symbol</td>
194
+ <td>
195
+ <pre class="d2l-code d2l-code-dark"><code class="language-javascript"></code></pre>
196
+ </td>
197
+ </tr>
198
+ <tr>
199
+ <td>regex</td>
200
+ <td>
201
+ <pre class="d2l-code d2l-code-dark"><code class="language-javascript">let entity = /&amp;#x?[\da-f]{1,8};/;</code></pre>
202
+ </td>
203
+ </tr>
204
+ <tr>
205
+ <td>url</td>
206
+ <td>
207
+ <pre class="d2l-code d2l-code-dark"><code class="language-css">body { background: url("wizard.png"); }</code></pre>
208
+ </td>
209
+ </tr>
210
+ <tr>
211
+ <td>operator</td>
212
+ <td>
213
+ <pre class="d2l-code d2l-code-dark"><code class="language-javascript">x += (y + 4 &gt;&gt; -z === w) ? b ** c : ~a;</code></pre>
214
+ </td>
215
+ </tr>
216
+ <tr>
217
+ <td>variable</td>
218
+ <td>
219
+ <pre class="d2l-code d2l-code-dark"><code class="language-sql">DECLARE @MyCounter INT;</code></pre>
220
+ </td>
221
+ </tr>
222
+ <tr>
223
+ <td>constant</td>
224
+ <td>
225
+ <pre class="d2l-code d2l-code-dark"><code class="language-javascript">const PI = 3.14159;</code></pre>
226
+ </td>
227
+ </tr>
228
+ <tr>
229
+ <td>property</td>
230
+ <td>
231
+ <pre class="d2l-code d2l-code-dark"><code class="language-css">.grumpy > img { height: 100%; }</code></pre>
232
+ </td>
233
+ </tr>
234
+ <tr>
235
+ <td>punctuation</td>
236
+ <td>
237
+ <pre class="d2l-code d2l-code-dark"><code class="language-javascript">import { stuff } from 'some/where.js';</code></pre>
238
+ </td>
239
+ </tr>
240
+ <tr>
241
+ <td>important</td>
242
+ <td>
243
+ <pre class="d2l-code d2l-code-dark"><code class="language-css">.grumpy > img { height: 100% !important; }</code></pre>
244
+ </td>
245
+ </tr>
246
+ <tr>
247
+ <td>comment</td>
248
+ <td>
249
+ <pre class="d2l-code d2l-code-dark"><code class="language-javascript">/* grump wizards */</code></pre>
250
+ </td>
251
+ </tr>
252
+ <tr>
253
+ <td>tag</td>
254
+ <td>
255
+ <pre class="d2l-code d2l-code-dark"><code class="language-markup">&lt;h1&gt;Grumpy Wizards&lt;/h1&gt;</code></pre>
256
+ </td>
257
+ </tr>
258
+ <tr>
259
+ <td>attr-name, attr-value</td>
260
+ <td>
261
+ <pre class="d2l-code d2l-code-dark"><code class="language-markup">&lt;h1 class="dangerous"&gt;Grumpy Wizards&lt;/h1&gt;</code></pre>
262
+ </td>
263
+ </tr>
264
+ <tr>
265
+ <td>namespace</td>
266
+ <td>
267
+ <pre class="d2l-code d2l-code-dark"><code class="language-java">throw new java.lang.UnsupportedOperationException();</code></pre>
268
+ </td>
269
+ </tr>
270
+ <tr>
271
+ <td>prolog</td>
272
+ <td>
273
+ <pre class="d2l-code d2l-code-dark"><code class="language-markup">&lt?xml version="1.0" encoding="utf-8"?&gt;</code></pre>
274
+ </td>
275
+ </tr>
276
+ <tr>
277
+ <td>doctype</td>
278
+ <td>
279
+ <pre class="d2l-code d2l-code-dark"><code class="language-markup">&lt;!DOCTYPE html&gt;</code></pre>
280
+ </td>
281
+ </tr>
282
+ <tr>
283
+ <td>cdata</td>
284
+ <td>
285
+ <pre class="d2l-code d2l-code-dark"><code class="language-markup">&lt;![CDATA[ grumpy wizards eat donuts ]]&gt;</code></pre>
286
+ </td>
287
+ </tr>
288
+ <tr>
289
+ <td>entity</td>
290
+ <td>
291
+ <pre class="d2l-code d2l-code-dark"><code class="language-markup">&amp;pound; &amp;#163;</code></pre>
292
+ </td>
293
+ </tr>
294
+ <tr>
295
+ <td>atrule</td>
296
+ <td>
297
+ <pre class="d2l-code d2l-code-dark"><code class="language-css">@media (prefers-reduced-motion: reduce) { /* no animations */ }</code></pre>
298
+ </td>
299
+ </tr>
300
+ <tr>
301
+ <td>selector</td>
302
+ <td>
303
+ <pre class="d2l-code d2l-code-dark"><code class="language-css">.grumpy > img { /* ... */ }</code></pre>
304
+ </td>
305
+ </tr>
306
+ <tr>
307
+ <td>null</td>
308
+ <td>
309
+ <pre class="d2l-code d2l-code-dark"><code class="language-json">{ "fritter": null }</code></pre>
310
+ </td>
311
+ </tr>
312
+ </tbody>
313
+ </table>
314
+
315
+ <h2 class="d2l-heading-3">More Samples (Global Scope)</h2>
316
+
317
+ <pre class="d2l-code"><code class="language-javascript line-numbers">// comment
318
+ /* comment */
319
+
320
+ import { stuff } from 'some/where.js'; // keyword, punctuation, string
321
+
322
+ function helloGrumpy(name) { // keyword, function, parameter
323
+ console.log(`Hi there ${name}.`); // template-string, template-punctuation, interpolation, interpolation-punctuation
324
+ }
325
+
326
+ class Wizard extends Human { } // keyword, class-name
327
+
328
+ const grumpy = new Wizard(); // keyword, operator, class-name
329
+
330
+ let wizardFoods = [...donuts, ... cakes, ...pies]; // keyword, operator
331
+
332
+ const wizardsLikeBeer = false; // keyword, operator, boolean
333
+
334
+ const favouriteNumber = 3.14159; // keyword, operator, number
335
+
336
+ const PI = 3.14159; // keyword, operator, constant
337
+
338
+ const regex = /[^\w\s]/g; // keyword, operator, regex, regex-delimiter, regex-source, regex-flags
339
+ </code></pre>
340
+
341
+ <pre class="d2l-code"><code class="language-css line-numbers">.grumpy > img { /* selector */
342
+ background-image: url("smile.png"); /* property, url, string */
343
+ height: 100%; /* property, punctuation */
344
+ width: var(--some-var); /* property, punctuation, function */
345
+ }
346
+ @font-face { /* atrule, rule */
347
+ font-family: 'Lato'; /* property, punctuation, string */
348
+ font-style: normal;
349
+ src: local('Lato Regular'); /* property, function, string */
350
+ }
351
+ @media (prefers-reduced-motion: reduce) { /* atrule, rule, property */
352
+ :host([opened]), :host([opened-above]) {
353
+ animation: none !important; /* property, important */
354
+ }
355
+ }
356
+ </code></pre>
357
+
358
+ <pre class="d2l-code"><code class="language-markup line-numbers">&lt;!DOCTYPE html&gt; &lt;!-- doctype, doctype-tag, name --&gt;
359
+ &lt;html&gt; &lt;!-- tag, punctuation --&gt;
360
+ &lt;body class="typography"&gt; &lt;!-- attr-name, attr-value --&gt;
361
+ &lt;![CDATA[ some cdata section ]]&gt; &lt;!-- cdata --&gt;
362
+ &lt;div style="color: blue;"&gt; &lt;!-- attr-name, attr-value, attr-equals, value, css, property --&gt;
363
+ &amp;pound; &lt;!-- entity, named-entity --&gt;
364
+ &amp;#163; &lt;!-- entity --&gt;
365
+ &lt;/div&gt;
366
+ &lt;/body&gt;
367
+ &lt;/html&gt;
368
+ </code></pre>
369
+
370
+ <pre class="d2l-code d2l-code-dark"><code class="language-sql line-numbers">DECLARE @MyCounter INT; /* keyword, variable, punctuation */
371
+
372
+ SELECT AVG(Calories) AS AverageCalories FROM Desserts; /* keyword, function */
373
+
374
+ SELECT * FROM Desserts /* keyword, operator */
375
+
376
+ SET ROWCOUNT 4; /* keyword, number */
377
+
378
+ SET @Hidden = FALSE; /* keyword, variable, boolean */
379
+
380
+ SET @Donuts = 'Yummy'; /* keyword, variable, string */
381
+ </code></pre>
382
+
383
+ <pre class="d2l-code d2l-code-dark"><code class="language-json line-numbers">{ /* punctuation */
384
+ "jinxed": "gnomes", /* property, operator, string */
385
+ "grumpy": [ "wizards" ],
386
+ "jelly": 99, /* property, operator, number */
387
+ "donut": true, /* property, operator, boolean */
388
+ "fritter": null /* property, operator, null, keyword */
389
+ }
390
+ </code></pre>
391
+
392
+ <h2 class="d2l-heading-3">More Samples (Web Component Scope)</h2>
393
+
394
+ <d2l-demo-prism dark></d2l-demo-prism>
395
+
396
+ <script type="module">
397
+ import { formatCodeElement } from '../prism.js';
398
+
399
+ const formatCodeElements = () => {
400
+ const darkSwitch = document.querySelector('d2l-switch');
401
+ const codeElements = document.querySelectorAll('pre');
402
+ codeElements.forEach(codeElement => {
403
+ if (darkSwitch.on) codeElement.classList.add('d2l-code-dark');
404
+ else codeElement.classList.remove('d2l-code-dark');
405
+ formatCodeElement(codeElement);
406
+ });
407
+ document.querySelector('d2l-demo-prism').dark = darkSwitch.on;
408
+ };
409
+
410
+ formatCodeElements();
411
+
412
+ const darkSwitch = document.querySelector('d2l-switch');
413
+ darkSwitch.addEventListener('change', formatCodeElements);
414
+
415
+ </script>
416
+ </body>
417
+ </html>
@@ -0,0 +1,430 @@
1
+ import { css, unsafeCSS } from 'lit-element/lit-element.js';
2
+
3
+ window.Prism = window.Prism || {};
4
+ Prism.manual = true;
5
+
6
+ const prismLocation = 'https://s.brightspace.com/lib/prismjs/1.28.0';
7
+ //const prismLocation = '/node_modules/prismjs'; // for local debugging
8
+
9
+ // If adding a language, check its Prism dependencies and modify languageDependencies below if necessary
10
+ export const codeLanguages = new Map();
11
+ codeLanguages.set('arduino', 'Arduino');
12
+ codeLanguages.set('armasm', 'ARM Assembly');
13
+ codeLanguages.set('bash', 'Bash');
14
+ codeLanguages.set('c', 'C');
15
+ codeLanguages.set('clike', 'C-like');
16
+ codeLanguages.set('cpp', 'C++');
17
+ codeLanguages.set('csharp', 'C#');
18
+ codeLanguages.set('css', 'CSS');
19
+ codeLanguages.set('haskell', 'Haskell');
20
+ codeLanguages.set('java', 'Java');
21
+ codeLanguages.set('javascript', 'JavaScript');
22
+ codeLanguages.set('json', 'JSON');
23
+ codeLanguages.set('kotlin', 'Kotlin');
24
+ codeLanguages.set('latex', 'LaTeX');
25
+ codeLanguages.set('markup', 'Markup');
26
+ codeLanguages.set('matlab', 'MATLAB');
27
+ codeLanguages.set('plain', 'Plain Text');
28
+ codeLanguages.set('python', 'Python');
29
+ codeLanguages.set('r', 'R');
30
+ codeLanguages.set('racket', 'Racket');
31
+ codeLanguages.set('sql', 'SQL');
32
+ codeLanguages.set('wolfram', 'Wolfram');
33
+
34
+ export const colorModes = {
35
+ LIGHT: 'light',
36
+ DARK: 'dark'
37
+ };
38
+
39
+ const darkColors = Object.freeze({
40
+ background: '#2d2d2d',
41
+ language: '#6e7376',
42
+ lineNumbers: '#ffffff',
43
+ lineNumbersSeparator: '#999999',
44
+ tokenDefault: '#cccccc',
45
+ tokenComment: '#808080',
46
+ tokenPunctuation: '#d4d4d4',
47
+ tokenNumber: '#d4d4d4',
48
+ tokenUrl: '#d4d4d4',
49
+ tokenOperator: '#d4d4d4',
50
+ tokenInterpolation: '#9cdcfe',
51
+ tokenAttributeName: '#9cdcfe',
52
+ tokenConstant: '#9cdcfe',
53
+ tokenProperty: '#9cdcfe',
54
+ tokenTag: '#569cd6',
55
+ tokenBoolean: '#569cd6',
56
+ tokenEntity: '#569cd6',
57
+ tokenInterpolationPunctuation: '#569cd6',
58
+ tokenFunction: '#dcdcaa',
59
+ tokenClassName: '#4ec9b0',
60
+ tokenSymbol: '#4ec9b0',
61
+ tokenBuiltin: '#c586c0',
62
+ tokenKeyword: '#c586c0',
63
+ tokenAtRule: '#c586c0',
64
+ tokenSelector: '#d7ba7d',
65
+ tokenImportant: '#d16969',
66
+ tokenRegex: '#d16969',
67
+ tokenString: '#ce9178',
68
+ tokenChar: '#ce9178',
69
+ tokenAttributeValue: '#ce9178'
70
+ });
71
+
72
+ const lightColors = Object.freeze({
73
+ background: '#f2f1f1',
74
+ language: '#1b1b1b',
75
+ lineNumbers: '#1b1b1b',
76
+ lineNumbersSeparator: '#1b1b1b',
77
+ tokenDefault: '#1b1b1b',
78
+ tokenComment: '#9e9e9e',
79
+ tokenPunctuation: '#9e9e9e',
80
+ tokenNumber: '#007936',
81
+ tokenUrl: '#9e9e9e',
82
+ tokenOperator: '#9e9e9e',
83
+ tokenInterpolation: '#872bff',
84
+ tokenAttributeName: '#d30038',
85
+ tokenConstant: '#007936',
86
+ tokenProperty: '#d30038',
87
+ tokenTag: '#007936',
88
+ tokenBoolean: '#007936',
89
+ tokenEntity: 'inherit',
90
+ tokenInterpolationPunctuation: '#872bff',
91
+ tokenFunction: '#d30038',
92
+ tokenClassName: '#d30038',
93
+ tokenSymbol: '#007936',
94
+ tokenBuiltin: '#872bff',
95
+ tokenKeyword: '#0069c2',
96
+ tokenAtRule: '#007936',
97
+ tokenSelector: '#872bff',
98
+ tokenImportant: 'inherit',
99
+ tokenRegex: 'inherit',
100
+ tokenString: '#007936',
101
+ tokenChar: '#007936',
102
+ tokenAttributeValue: '#007936'
103
+ });
104
+
105
+ export const getCodeColors = mode => {
106
+ return mode === colorModes.DARK ? darkColors : lightColors;
107
+ };
108
+
109
+ const generateColorVariables = mode => {
110
+ const colors = getCodeColors(mode);
111
+ const keySelector = mode === colorModes.DARK ? '.d2l-code-dark' : '.d2l-code';
112
+ return `
113
+ pre[class*="language-"]${keySelector},
114
+ code[class*="language-"]${keySelector} {
115
+ --d2l-code-background: ${colors.background};
116
+ --d2l-code-language: ${colors.language};
117
+ --d2l-code-line-numbers: ${colors.lineNumbers};
118
+ --d2l-code-line-numbers-separator: ${colors.lineNumbersSeparator};
119
+ --d2l-code-token-atrule: ${colors.tokenAtRule};
120
+ --d2l-code-token-attribute-name: ${colors.tokenAttributeName};
121
+ --d2l-code-token-attribute-value: ${colors.tokenAttributeValue};
122
+ --d2l-code-token-boolean: ${colors.tokenBoolean};
123
+ --d2l-code-token-builtin: ${colors.tokenBuiltin};
124
+ --d2l-code-token-char: ${colors.tokenChar};
125
+ --d2l-code-token-class-name: ${colors.tokenClassName};
126
+ --d2l-code-token-comment: ${colors.tokenComment};
127
+ --d2l-code-token-constant: ${colors.tokenConstant};
128
+ --d2l-code-token-default: ${colors.tokenDefault};
129
+ --d2l-code-token-entity: ${colors.tokenEntity};
130
+ --d2l-code-token-function: ${colors.tokenFunction};
131
+ --d2l-code-token-important: ${colors.tokenImportant};
132
+ --d2l-code-token-interpolation: ${colors.tokenInterpolation};
133
+ --d2l-code-token-interpolation-punctuation: ${colors.tokenInterpolationPunctuation};
134
+ --d2l-code-token-keyword: ${colors.tokenKeyword};
135
+ --d2l-code-token-number: ${colors.tokenNumber};
136
+ --d2l-code-token-operator: ${colors.tokenOperator};
137
+ --d2l-code-token-property: ${colors.tokenProperty};
138
+ --d2l-code-token-punctuation: ${colors.tokenPunctuation};
139
+ --d2l-code-token-regex: ${colors.tokenRegex};
140
+ --d2l-code-token-selector: ${colors.tokenSelector};
141
+ --d2l-code-token-string: ${colors.tokenString};
142
+ --d2l-code-token-symbol: ${colors.tokenSymbol};
143
+ --d2l-code-token-tag: ${colors.tokenTag};
144
+ --d2l-code-token-url: ${colors.tokenUrl};
145
+ }
146
+ `;
147
+ };
148
+
149
+ export const codeStyles = css`
150
+
151
+ ${unsafeCSS(generateColorVariables(colorModes.LIGHT))}
152
+
153
+ ${unsafeCSS(generateColorVariables(colorModes.DARK))}
154
+
155
+ pre[class*="language-"].d2l-code,
156
+ pre[class*="language-"].d2l-code > code[class*="language-"],
157
+ code[class*="language-"].d2l-code {
158
+ font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
159
+ line-height: 1.5;
160
+ text-shadow: none;
161
+ }
162
+
163
+ pre[class*="language-"].d2l-code > code[class*="language-"],
164
+ code[class*="language-"].d2l-code {
165
+ color: var(--d2l-code-token-default);
166
+ -webkit-hyphens: none;
167
+ -moz-hyphens: none;
168
+ -ms-hyphens: none;
169
+ hyphens: none;
170
+ white-space: pre;
171
+ word-break: normal;
172
+ word-spacing: normal;
173
+ word-wrap: normal;
174
+ }
175
+
176
+ pre[class*="language-"].d2l-code {
177
+ background-color: var(--d2l-code-background);
178
+ border-radius: 6px;
179
+ box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 1px 5px 0 rgba(0, 0, 0, 0.12), 0 3px 1px -2px rgba(0, 0, 0, 0.2);
180
+ font-size: 14px;
181
+ margin: 0.5em 0;
182
+ overflow: auto;
183
+ padding: 1em;
184
+ position: relative;
185
+ -moz-tab-size: 4;
186
+ -o-tab-size: 4;
187
+ tab-size: 4;
188
+ text-align: left;
189
+ }
190
+
191
+ pre[class*="language-"].d2l-code::before {
192
+ color: var(--d2l-code-language);
193
+ content: attr(data-language);
194
+ font-family: 'Lato', 'Lucida Sans Unicode', 'Lucida Grande', sans-serif;
195
+ margin: 0.1rem 0.4rem;
196
+ position: absolute;
197
+ right: 0;
198
+ top: 0;
199
+ }
200
+
201
+ code[class*="language-"].d2l-code {
202
+ background-color: var(--d2l-code-background);
203
+ border-radius: 6px;
204
+ padding: 0.1em;
205
+ white-space: normal;
206
+ }
207
+
208
+ .token.comment,
209
+ .token.block-comment,
210
+ .token.prolog,
211
+ .token.doctype,
212
+ .token.cdata {
213
+ color: var(--d2l-code-token-comment);
214
+ }
215
+
216
+ .token.punctuation { color: var(--d2l-code-token-punctuation); }
217
+ .token.number { color: var(--d2l-code-token-number); }
218
+ .token.operator { color: var(--d2l-code-token-operator); }
219
+
220
+ .token.interpolation { color: var(--d2l-code-token-interpolation); }
221
+ .token.attr-name { color: var(--d2l-code-token-attribute-name); }
222
+ .token.constant { color: var(--d2l-code-token-constant); }
223
+ .token.property { color: var(--d2l-code-token-property); }
224
+
225
+ .token.tag { color: var(--d2l-code-token-tag); }
226
+ .token.boolean { color: var(--d2l-code-token-boolean); }
227
+ .token.entity { color: var(--d2l-code-token-entity); }
228
+ .token.interpolation-punctuation { color: var(--d2l-code-token-interpolation-punctuation); }
229
+
230
+ .token.function { color: var(--d2l-code-token-function); }
231
+
232
+ .token.class-name { color: var(--d2l-code-token-class-name); }
233
+ .token.symbol { color: var(--d2l-code-token-symbol); }
234
+
235
+ .token.builtin { color: var(--d2l-code-token-builtin); }
236
+ .token.keyword { color: var(--d2l-code-token-keyword); }
237
+ .token.atrule { color: var(--d2l-code-token-atrule); }
238
+
239
+ .token.selector { color: var(--d2l-code-token-selector); }
240
+
241
+ .token.important { color: var(--d2l-code-token-important); }
242
+ .token.regex { color: var(--d2l-code-token-regex); }
243
+
244
+ .token.string { color: var(--d2l-code-token-string); }
245
+ .token.char { color: var(--d2l-code-token-char); }
246
+ .token.attr-value { color: var(--d2l-code-token-attribute-value); }
247
+
248
+ .token.url { color: var(--d2l-code-token-url); }
249
+
250
+ .language-css .token.string,
251
+ .style .token.string,
252
+ .token.entity,
253
+ .token.operator,
254
+ .token.url {
255
+ background-color: transparent;
256
+ }
257
+
258
+ pre[class*="language-"].line-numbers {
259
+ counter-reset: linenumber;
260
+ padding-left: 3.8em;
261
+ position: relative;
262
+ }
263
+
264
+ pre[class*="language-"].line-numbers > code {
265
+ position: relative;
266
+ white-space: inherit;
267
+ }
268
+
269
+ .line-numbers .line-numbers-rows {
270
+ border-right: 1px solid var(--d2l-code-line-numbers-separator);
271
+ font-size: 100%;
272
+ left: -3.8em;
273
+ letter-spacing: -1px;
274
+ pointer-events: none;
275
+ position: absolute;
276
+ top: 0;
277
+ -webkit-user-select: none;
278
+ -moz-user-select: none;
279
+ -ms-user-select: none;
280
+ user-select: none;
281
+ width: 3em; /* works for line-numbers below 1000 lines */
282
+ }
283
+
284
+ .line-numbers-rows > span {
285
+ counter-increment: linenumber;
286
+ display: block;
287
+ }
288
+
289
+ .line-numbers-rows > span::before {
290
+ color: var(--d2l-code-line-numbers);
291
+ content: counter(linenumber);
292
+ display: block;
293
+ padding-right: 0.8em;
294
+ text-align: right;
295
+ }
296
+ `;
297
+
298
+ const getLanguageInfo = elem => {
299
+ const classes = elem.classList;
300
+ for (let i = 0; i < classes.length; i++) {
301
+ if (classes[i].startsWith('language-')) {
302
+ const key = classes[i].substring(9);
303
+ const desc = codeLanguages.get(key);
304
+ if (desc) return { key: key, desc: desc };
305
+ }
306
+ }
307
+ return { key: 'plain', desc: codeLanguages.get('plain') };
308
+ };
309
+
310
+ const languageDependencies = {
311
+ arduino: [ 'cpp' ],
312
+ cpp: [ 'c' ],
313
+ racket: [ 'scheme' ]
314
+ };
315
+
316
+ const languagesLoaded = {
317
+ clike: Promise.resolve(),
318
+ css: Promise.resolve(),
319
+ javascript: Promise.resolve(),
320
+ markup: Promise.resolve(),
321
+ plain: Promise.resolve()
322
+ };
323
+
324
+ const loadLanguage = async key => {
325
+ if (languagesLoaded[key]) return languagesLoaded[key];
326
+
327
+ // Prism languages can extend other anguages and must be loaded in order
328
+
329
+ // eslint-disable-next-line no-async-promise-executor
330
+ languagesLoaded[key] = new Promise(async resolve => {
331
+ if (languageDependencies[key]) {
332
+ await Promise.all(languageDependencies[key].map(dependencyKey => loadLanguage(dependencyKey)));
333
+ }
334
+
335
+ const script = document.createElement('script');
336
+ script.async = 'async';
337
+ script.onload = resolve;
338
+ script.src = `${prismLocation}/components/prism-${key}.min.js`;
339
+ document.head.appendChild(script);
340
+ });
341
+
342
+ return languagesLoaded[key];
343
+ };
344
+
345
+ const pluginsLoaded = {};
346
+
347
+ const loadPlugin = async plugin => {
348
+ if (pluginsLoaded[plugin]) return pluginsLoaded[plugin];
349
+
350
+ pluginsLoaded[plugin] = new Promise(resolve => {
351
+ const script = document.createElement('script');
352
+ script.async = 'async';
353
+ script.onload = resolve;
354
+ script.src = `${prismLocation}/plugins/${plugin}/prism-${plugin}.min.js`;
355
+ document.head.appendChild(script);
356
+ });
357
+
358
+ return pluginsLoaded[plugin];
359
+ };
360
+
361
+ let prismLoaded;
362
+
363
+ const loadPrism = () => {
364
+ if (prismLoaded) return prismLoaded;
365
+
366
+ prismLoaded = Promise.all([
367
+ new Promise(resolve => {
368
+ const script = document.createElement('script');
369
+ script.async = 'async';
370
+ script.onload = resolve;
371
+ script.src = `${prismLocation}/prism.js`;
372
+ document.head.appendChild(script);
373
+ }),
374
+ new Promise(resolve => {
375
+ const style = document.createElement('style');
376
+ style.textContent = codeStyles.cssText;
377
+ style.onload = resolve;
378
+ document.head.appendChild(style);
379
+ })
380
+ ]);
381
+
382
+ return prismLoaded;
383
+ };
384
+
385
+ const getCodeElement = elem => {
386
+ if (!elem) return;
387
+ if (elem.tagName === 'CODE') return elem;
388
+ if (elem.tagName !== 'PRE') return;
389
+ return elem.querySelector('code');
390
+ };
391
+
392
+ export async function formatCodeElement(elem) {
393
+ const code = getCodeElement(elem);
394
+
395
+ if (code.className.indexOf('language-') === -1) return;
396
+
397
+ const languageInfo = getLanguageInfo(code);
398
+ const lineNumbers = elem.classList.contains('line-numbers') || code.classList.contains('line-numbers');
399
+
400
+ await loadPrism(); // must be loaded before loading plugins or languages
401
+ await Promise.all([
402
+ loadLanguage(languageInfo.key),
403
+ lineNumbers ? loadPlugin('line-numbers') : null
404
+ ]);
405
+
406
+ if (!elem.dataset.language && languageInfo.key !== 'plain') elem.dataset.language = languageInfo.desc;
407
+ Prism.highlightElement(code);
408
+
409
+ return elem;
410
+ }
411
+
412
+ export class HtmlBlockCodeRenderer {
413
+
414
+ get canRenderInline() {
415
+ return true;
416
+ }
417
+
418
+ async render(elem) {
419
+ const codeElements = [...elem.querySelectorAll('.d2l-code')];
420
+ if (codeElements.length === 0) return elem;
421
+
422
+ // wait; formatting is not synchronous due to lazy loading of Prism, languages, plugins
423
+ await Promise.all(codeElements.map(codeElement => {
424
+ return formatCodeElement(codeElement);
425
+ }));
426
+
427
+ return elem;
428
+ }
429
+
430
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brightspace-ui/core",
3
- "version": "2.27.1",
3
+ "version": "2.28.0",
4
4
  "description": "A collection of accessible, free, open-source web components for building Brightspace applications",
5
5
  "type": "module",
6
6
  "repository": "https://github.com/BrightspaceUI/core.git",