@aquera/nile-elements 1.8.5 → 1.8.7

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 (115) hide show
  1. package/README.md +8 -0
  2. package/dist/index.cjs.js +1 -1
  3. package/dist/index.esm.js +1 -1
  4. package/dist/index.js +915 -321
  5. package/dist/nile-markdown/index.cjs.js +2 -0
  6. package/dist/nile-markdown/index.cjs.js.map +1 -0
  7. package/dist/nile-markdown/index.esm.js +1 -0
  8. package/dist/nile-markdown/nile-markdown.cjs.js +30 -0
  9. package/dist/nile-markdown/nile-markdown.cjs.js.map +1 -0
  10. package/dist/nile-markdown/nile-markdown.css.cjs.js +2 -0
  11. package/dist/nile-markdown/nile-markdown.css.cjs.js.map +1 -0
  12. package/dist/nile-markdown/nile-markdown.css.esm.js +152 -0
  13. package/dist/nile-markdown/nile-markdown.esm.js +3 -0
  14. package/dist/nile-markdown-editor/index.cjs.js +2 -0
  15. package/dist/nile-markdown-editor/index.cjs.js.map +1 -0
  16. package/dist/nile-markdown-editor/index.esm.js +1 -0
  17. package/dist/nile-markdown-editor/nile-markdown-editor.cjs.js +2 -0
  18. package/dist/nile-markdown-editor/nile-markdown-editor.cjs.js.map +1 -0
  19. package/dist/nile-markdown-editor/nile-markdown-editor.css.cjs.js +2 -0
  20. package/dist/nile-markdown-editor/nile-markdown-editor.css.cjs.js.map +1 -0
  21. package/dist/nile-markdown-editor/nile-markdown-editor.css.esm.js +255 -0
  22. package/dist/nile-markdown-editor/nile-markdown-editor.esm.js +143 -0
  23. package/dist/nile-option/nile-option.cjs.js +1 -1
  24. package/dist/nile-option/nile-option.cjs.js.map +1 -1
  25. package/dist/nile-option/nile-option.css.cjs.js +1 -1
  26. package/dist/nile-option/nile-option.css.cjs.js.map +1 -1
  27. package/dist/nile-option/nile-option.css.esm.js +22 -1
  28. package/dist/nile-option/nile-option.esm.js +12 -2
  29. package/dist/nile-select/nile-select.cjs.js +1 -1
  30. package/dist/nile-select/nile-select.cjs.js.map +1 -1
  31. package/dist/nile-select/nile-select.css.cjs.js +1 -1
  32. package/dist/nile-select/nile-select.css.cjs.js.map +1 -1
  33. package/dist/nile-select/nile-select.css.esm.js +16 -7
  34. package/dist/nile-select/nile-select.esm.js +2 -2
  35. package/dist/nile-select/virtual-scroll-helper.cjs.js +1 -1
  36. package/dist/nile-select/virtual-scroll-helper.cjs.js.map +1 -1
  37. package/dist/nile-select/virtual-scroll-helper.esm.js +2 -0
  38. package/dist/nile-virtual-select/nile-virtual-select.cjs.js +3 -3
  39. package/dist/nile-virtual-select/nile-virtual-select.cjs.js.map +1 -1
  40. package/dist/nile-virtual-select/nile-virtual-select.css.cjs.js +1 -1
  41. package/dist/nile-virtual-select/nile-virtual-select.css.cjs.js.map +1 -1
  42. package/dist/nile-virtual-select/nile-virtual-select.css.esm.js +4 -3
  43. package/dist/nile-virtual-select/nile-virtual-select.esm.js +4 -4
  44. package/dist/nile-virtual-select/renderer.cjs.js +1 -1
  45. package/dist/nile-virtual-select/renderer.cjs.js.map +1 -1
  46. package/dist/nile-virtual-select/renderer.esm.js +14 -12
  47. package/dist/src/index.d.ts +2 -0
  48. package/dist/src/index.js +2 -0
  49. package/dist/src/index.js.map +1 -1
  50. package/dist/src/nile-markdown/index.d.ts +1 -0
  51. package/dist/src/nile-markdown/index.js +2 -0
  52. package/dist/src/nile-markdown/index.js.map +1 -0
  53. package/dist/src/nile-markdown/nile-markdown.css.d.ts +10 -0
  54. package/dist/src/nile-markdown/nile-markdown.css.js +163 -0
  55. package/dist/src/nile-markdown/nile-markdown.css.js.map +1 -0
  56. package/dist/src/nile-markdown/nile-markdown.d.ts +91 -0
  57. package/dist/src/nile-markdown/nile-markdown.js +167 -0
  58. package/dist/src/nile-markdown/nile-markdown.js.map +1 -0
  59. package/dist/src/nile-markdown/nile-markdown.test.d.ts +1 -0
  60. package/dist/src/nile-markdown/nile-markdown.test.js +192 -0
  61. package/dist/src/nile-markdown/nile-markdown.test.js.map +1 -0
  62. package/dist/src/nile-markdown-editor/index.d.ts +1 -0
  63. package/dist/src/nile-markdown-editor/index.js +2 -0
  64. package/dist/src/nile-markdown-editor/index.js.map +1 -0
  65. package/dist/src/nile-markdown-editor/nile-markdown-editor.css.d.ts +10 -0
  66. package/dist/src/nile-markdown-editor/nile-markdown-editor.css.js +266 -0
  67. package/dist/src/nile-markdown-editor/nile-markdown-editor.css.js.map +1 -0
  68. package/dist/src/nile-markdown-editor/nile-markdown-editor.d.ts +121 -0
  69. package/dist/src/nile-markdown-editor/nile-markdown-editor.js +615 -0
  70. package/dist/src/nile-markdown-editor/nile-markdown-editor.js.map +1 -0
  71. package/dist/src/nile-markdown-editor/nile-markdown-editor.test.d.ts +1 -0
  72. package/dist/src/nile-markdown-editor/nile-markdown-editor.test.js +268 -0
  73. package/dist/src/nile-markdown-editor/nile-markdown-editor.test.js.map +1 -0
  74. package/dist/src/nile-option/nile-option.css.js +22 -1
  75. package/dist/src/nile-option/nile-option.css.js.map +1 -1
  76. package/dist/src/nile-option/nile-option.d.ts +3 -0
  77. package/dist/src/nile-option/nile-option.js +21 -0
  78. package/dist/src/nile-option/nile-option.js.map +1 -1
  79. package/dist/src/nile-select/nile-select.css.js +16 -7
  80. package/dist/src/nile-select/nile-select.css.js.map +1 -1
  81. package/dist/src/nile-select/nile-select.d.ts +7 -0
  82. package/dist/src/nile-select/nile-select.js +35 -0
  83. package/dist/src/nile-select/nile-select.js.map +1 -1
  84. package/dist/src/nile-select/virtual-scroll-helper.js +2 -0
  85. package/dist/src/nile-select/virtual-scroll-helper.js.map +1 -1
  86. package/dist/src/nile-virtual-select/nile-virtual-select.css.js +4 -3
  87. package/dist/src/nile-virtual-select/nile-virtual-select.css.js.map +1 -1
  88. package/dist/src/nile-virtual-select/nile-virtual-select.d.ts +4 -0
  89. package/dist/src/nile-virtual-select/nile-virtual-select.js +11 -1
  90. package/dist/src/nile-virtual-select/nile-virtual-select.js.map +1 -1
  91. package/dist/src/nile-virtual-select/renderer.d.ts +2 -2
  92. package/dist/src/nile-virtual-select/renderer.js +6 -4
  93. package/dist/src/nile-virtual-select/renderer.js.map +1 -1
  94. package/dist/src/version.js +1 -1
  95. package/dist/src/version.js.map +1 -1
  96. package/dist/tsconfig.tsbuildinfo +1 -1
  97. package/package.json +2 -1
  98. package/src/index.ts +3 -1
  99. package/src/nile-markdown/index.ts +1 -0
  100. package/src/nile-markdown/nile-markdown.css.ts +164 -0
  101. package/src/nile-markdown/nile-markdown.test.ts +252 -0
  102. package/src/nile-markdown/nile-markdown.ts +179 -0
  103. package/src/nile-markdown-editor/index.ts +1 -0
  104. package/src/nile-markdown-editor/nile-markdown-editor.css.ts +267 -0
  105. package/src/nile-markdown-editor/nile-markdown-editor.test.ts +402 -0
  106. package/src/nile-markdown-editor/nile-markdown-editor.ts +710 -0
  107. package/src/nile-option/nile-option.css.ts +22 -1
  108. package/src/nile-option/nile-option.ts +18 -0
  109. package/src/nile-select/nile-select.css.ts +16 -7
  110. package/src/nile-select/nile-select.ts +32 -0
  111. package/src/nile-select/virtual-scroll-helper.ts +2 -0
  112. package/src/nile-virtual-select/nile-virtual-select.css.ts +4 -3
  113. package/src/nile-virtual-select/nile-virtual-select.ts +9 -1
  114. package/src/nile-virtual-select/renderer.ts +9 -3
  115. package/vscode-html-custom-data.json +115 -3
@@ -0,0 +1,167 @@
1
+ /**
2
+ * Copyright Aquera Inc 2023
3
+ *
4
+ * This source code is licensed under the BSD-3-Clause license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+ var NileMarkdown_1;
8
+ import { __decorate } from "tslib";
9
+ import { html } from 'lit';
10
+ import { customElement, property, state } from 'lit/decorators.js';
11
+ import { unsafeHTML } from 'lit/directives/unsafe-html.js';
12
+ import { Marked } from 'marked';
13
+ import { styles } from './nile-markdown.css';
14
+ import NileElement from '../internal/nile-element';
15
+ /**
16
+ * Nile markdown component.
17
+ *
18
+ * @tag nile-markdown
19
+ */
20
+ /**
21
+ * @summary Renders markdown content as HTML in the browser using GitHub Flavored Markdown.
22
+ * @status experimental
23
+ *
24
+ * Content can be provided either through the `value` property or through a
25
+ * `<script type="text/markdown">` element placed as a direct child:
26
+ *
27
+ * ```html
28
+ * <nile-markdown>
29
+ * <script type="text/markdown">
30
+ * # Hello
31
+ * This is **markdown**.
32
+ * </script>
33
+ * </nile-markdown>
34
+ * ```
35
+ *
36
+ * Leading whitespace common to all lines is stripped, so the markdown can be
37
+ * indented to match the surrounding HTML without rendering as a code block.
38
+ *
39
+ * All instances share a single Marked parser. Use `NileMarkdown.getMarked()`
40
+ * to customize it (extensions, renderers, etc.) and `NileMarkdown.updateAll()`
41
+ * to re-render existing instances after changing the configuration.
42
+ *
43
+ * WARNING: The markdown is converted to HTML without sanitization. Do not
44
+ * render unsanitized user input, as this can expose users to XSS attacks.
45
+ *
46
+ * @event nile-markdown-rendered - Emitted after the markdown has been parsed and rendered.
47
+ *
48
+ * @csspart base - The component's base wrapper containing the rendered HTML.
49
+ */
50
+ let NileMarkdown = NileMarkdown_1 = class NileMarkdown extends NileElement {
51
+ constructor() {
52
+ super(...arguments);
53
+ /**
54
+ * The markdown to render. Takes precedence over a
55
+ * `<script type="text/markdown">` child when set.
56
+ */
57
+ this.value = '';
58
+ /** Number of spaces a tab is converted to during whitespace normalization. */
59
+ this.tabSize = 4;
60
+ this.renderedHtml = '';
61
+ /** Re-renders automatically when the markdown script child changes. */
62
+ this.mutationObserver = new MutationObserver(() => this.renderMarkdown());
63
+ }
64
+ /**
65
+ * Returns the shared Marked instance so it can be configured with custom
66
+ * options, extensions, or renderers. Changes affect all instances; call
67
+ * `NileMarkdown.updateAll()` afterwards to re-render existing ones.
68
+ */
69
+ static getMarked() {
70
+ if (!NileMarkdown_1.marked) {
71
+ NileMarkdown_1.marked = new Marked({ gfm: true, async: false });
72
+ }
73
+ return NileMarkdown_1.marked;
74
+ }
75
+ /** Re-renders every connected nile-markdown instance. */
76
+ static updateAll() {
77
+ NileMarkdown_1.instances.forEach(instance => instance.renderMarkdown());
78
+ }
79
+ connectedCallback() {
80
+ super.connectedCallback();
81
+ NileMarkdown_1.instances.add(this);
82
+ this.mutationObserver.observe(this, {
83
+ childList: true,
84
+ subtree: true,
85
+ characterData: true,
86
+ });
87
+ this.renderMarkdown();
88
+ }
89
+ disconnectedCallback() {
90
+ this.mutationObserver.disconnect();
91
+ NileMarkdown_1.instances.delete(this);
92
+ super.disconnectedCallback();
93
+ }
94
+ willUpdate(changed) {
95
+ super.willUpdate(changed);
96
+ if (changed.has('value') || changed.has('tabSize')) {
97
+ this.computeHtml();
98
+ }
99
+ }
100
+ updated(changed) {
101
+ super.updated(changed);
102
+ if (changed.has('renderedHtml')) {
103
+ this.emit('nile-markdown-rendered', undefined, true, true);
104
+ }
105
+ }
106
+ /** Reads the markdown source from `value` or the script child. */
107
+ getSource() {
108
+ if (this.value)
109
+ return this.value;
110
+ const script = this.querySelector(':scope > script[type="text/markdown"]');
111
+ return script?.textContent ?? '';
112
+ }
113
+ /**
114
+ * Converts tabs to spaces and removes the leading indentation common to all
115
+ * lines, so markdown indented to match the HTML doesn't render as code.
116
+ */
117
+ normalizeWhitespace(text) {
118
+ const tab = ' '.repeat(Math.max(1, this.tabSize));
119
+ const lines = text.replace(/\t/g, tab).split('\n');
120
+ let minIndent = Infinity;
121
+ for (const line of lines) {
122
+ if (!line.trim())
123
+ continue;
124
+ const indent = line.length - line.trimStart().length;
125
+ minIndent = Math.min(minIndent, indent);
126
+ }
127
+ if (!Number.isFinite(minIndent) || minIndent === 0) {
128
+ return text.trim();
129
+ }
130
+ return lines
131
+ .map(line => line.slice(minIndent))
132
+ .join('\n')
133
+ .trim();
134
+ }
135
+ /** Parses the markdown source into `renderedHtml`. */
136
+ computeHtml() {
137
+ const source = this.normalizeWhitespace(this.getSource());
138
+ this.renderedHtml = NileMarkdown_1.getMarked().parse(source);
139
+ }
140
+ /** Parses the markdown source and renders the resulting HTML. */
141
+ renderMarkdown() {
142
+ this.computeHtml();
143
+ }
144
+ render() {
145
+ return html `
146
+ <div class="markdown" part="base">${unsafeHTML(this.renderedHtml)}</div>
147
+ `;
148
+ }
149
+ };
150
+ NileMarkdown.styles = styles;
151
+ /** All connected instances, used by `updateAll()`. */
152
+ NileMarkdown.instances = new Set();
153
+ __decorate([
154
+ property()
155
+ ], NileMarkdown.prototype, "value", void 0);
156
+ __decorate([
157
+ property({ type: Number, attribute: 'tab-size' })
158
+ ], NileMarkdown.prototype, "tabSize", void 0);
159
+ __decorate([
160
+ state()
161
+ ], NileMarkdown.prototype, "renderedHtml", void 0);
162
+ NileMarkdown = NileMarkdown_1 = __decorate([
163
+ customElement('nile-markdown')
164
+ ], NileMarkdown);
165
+ export { NileMarkdown };
166
+ export default NileMarkdown;
167
+ //# sourceMappingURL=nile-markdown.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nile-markdown.js","sourceRoot":"","sources":["../../../src/nile-markdown/nile-markdown.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Copyright Aquera Inc 2023\n *\n * This source code is licensed under the BSD-3-Clause license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport { html } from 'lit';\nimport { customElement, property, state } from 'lit/decorators.js';\nimport { unsafeHTML } from 'lit/directives/unsafe-html.js';\nimport { Marked } from 'marked';\nimport { styles } from './nile-markdown.css';\nimport NileElement from '../internal/nile-element';\nimport type { CSSResultGroup, PropertyValues, TemplateResult } from 'lit';\n\n/**\n * Nile markdown component.\n *\n * @tag nile-markdown\n */\n\n/**\n * @summary Renders markdown content as HTML in the browser using GitHub Flavored Markdown.\n * @status experimental\n *\n * Content can be provided either through the `value` property or through a\n * `<script type=\"text/markdown\">` element placed as a direct child:\n *\n * ```html\n * <nile-markdown>\n * <script type=\"text/markdown\">\n * # Hello\n * This is **markdown**.\n * </script>\n * </nile-markdown>\n * ```\n *\n * Leading whitespace common to all lines is stripped, so the markdown can be\n * indented to match the surrounding HTML without rendering as a code block.\n *\n * All instances share a single Marked parser. Use `NileMarkdown.getMarked()`\n * to customize it (extensions, renderers, etc.) and `NileMarkdown.updateAll()`\n * to re-render existing instances after changing the configuration.\n *\n * WARNING: The markdown is converted to HTML without sanitization. Do not\n * render unsanitized user input, as this can expose users to XSS attacks.\n *\n * @event nile-markdown-rendered - Emitted after the markdown has been parsed and rendered.\n *\n * @csspart base - The component's base wrapper containing the rendered HTML.\n */\n\n@customElement('nile-markdown')\nexport class NileMarkdown extends NileElement {\n static styles: CSSResultGroup = styles;\n\n /** The shared Marked instance used by every nile-markdown on the page. */\n private static marked: Marked | undefined;\n\n /** All connected instances, used by `updateAll()`. */\n private static instances = new Set<NileMarkdown>();\n\n /**\n * Returns the shared Marked instance so it can be configured with custom\n * options, extensions, or renderers. Changes affect all instances; call\n * `NileMarkdown.updateAll()` afterwards to re-render existing ones.\n */\n static getMarked(): Marked {\n if (!NileMarkdown.marked) {\n NileMarkdown.marked = new Marked({ gfm: true, async: false });\n }\n return NileMarkdown.marked;\n }\n\n /** Re-renders every connected nile-markdown instance. */\n static updateAll(): void {\n NileMarkdown.instances.forEach(instance => instance.renderMarkdown());\n }\n\n /**\n * The markdown to render. Takes precedence over a\n * `<script type=\"text/markdown\">` child when set.\n */\n @property() value = '';\n\n /** Number of spaces a tab is converted to during whitespace normalization. */\n @property({ type: Number, attribute: 'tab-size' }) tabSize = 4;\n\n @state() private renderedHtml = '';\n\n /** Re-renders automatically when the markdown script child changes. */\n private mutationObserver = new MutationObserver(() => this.renderMarkdown());\n\n connectedCallback(): void {\n super.connectedCallback();\n NileMarkdown.instances.add(this);\n this.mutationObserver.observe(this, {\n childList: true,\n subtree: true,\n characterData: true,\n });\n this.renderMarkdown();\n }\n\n disconnectedCallback(): void {\n this.mutationObserver.disconnect();\n NileMarkdown.instances.delete(this);\n super.disconnectedCallback();\n }\n\n protected willUpdate(changed: PropertyValues): void {\n super.willUpdate(changed);\n if (changed.has('value') || changed.has('tabSize')) {\n this.computeHtml();\n }\n }\n\n protected updated(changed: PropertyValues): void {\n super.updated(changed);\n if (changed.has('renderedHtml')) {\n this.emit('nile-markdown-rendered', undefined, true, true);\n }\n }\n\n /** Reads the markdown source from `value` or the script child. */\n private getSource(): string {\n if (this.value) return this.value;\n const script = this.querySelector(':scope > script[type=\"text/markdown\"]');\n return script?.textContent ?? '';\n }\n\n /**\n * Converts tabs to spaces and removes the leading indentation common to all\n * lines, so markdown indented to match the HTML doesn't render as code.\n */\n private normalizeWhitespace(text: string): string {\n const tab = ' '.repeat(Math.max(1, this.tabSize));\n const lines = text.replace(/\\t/g, tab).split('\\n');\n\n let minIndent = Infinity;\n for (const line of lines) {\n if (!line.trim()) continue;\n const indent = line.length - line.trimStart().length;\n minIndent = Math.min(minIndent, indent);\n }\n if (!Number.isFinite(minIndent) || minIndent === 0) {\n return text.trim();\n }\n return lines\n .map(line => line.slice(minIndent))\n .join('\\n')\n .trim();\n }\n\n /** Parses the markdown source into `renderedHtml`. */\n private computeHtml(): void {\n const source = this.normalizeWhitespace(this.getSource());\n this.renderedHtml = NileMarkdown.getMarked().parse(source) as string;\n }\n\n /** Parses the markdown source and renders the resulting HTML. */\n renderMarkdown(): void {\n this.computeHtml();\n }\n\n render(): TemplateResult {\n return html`\n <div class=\"markdown\" part=\"base\">${unsafeHTML(this.renderedHtml)}</div>\n `;\n }\n}\n\nexport default NileMarkdown;\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'nile-markdown': NileMarkdown;\n }\n}\n"]}
@@ -0,0 +1 @@
1
+ import './nile-markdown';
@@ -0,0 +1,192 @@
1
+ import { expect, fixture, html, oneEvent } from '@open-wc/testing';
2
+ import './nile-markdown';
3
+ import NileMarkdown from './nile-markdown';
4
+ describe('NileMarkdown', () => {
5
+ // === RENDERING ===
6
+ it('1. should render without errors', async () => {
7
+ const el = await fixture(html `<nile-markdown></nile-markdown>`);
8
+ expect(el).to.exist;
9
+ });
10
+ it('2. should have a shadow root', async () => {
11
+ const el = await fixture(html `<nile-markdown></nile-markdown>`);
12
+ expect(el.shadowRoot).to.not.be.null;
13
+ });
14
+ it('3. should have base part', async () => {
15
+ const el = await fixture(html `<nile-markdown></nile-markdown>`);
16
+ const base = el.shadowRoot.querySelector('[part~="base"]');
17
+ expect(base).to.exist;
18
+ });
19
+ it('4. should be instance of NileMarkdown', async () => {
20
+ const el = await fixture(html `<nile-markdown></nile-markdown>`);
21
+ expect(el).to.be.instanceOf(NileMarkdown);
22
+ });
23
+ it('5. should have correct tag name', async () => {
24
+ const el = await fixture(html `<nile-markdown></nile-markdown>`);
25
+ expect(el.tagName.toLowerCase()).to.equal('nile-markdown');
26
+ });
27
+ // === DEFAULT PROPERTIES ===
28
+ it('6. should have value default to empty string', async () => {
29
+ const el = await fixture(html `<nile-markdown></nile-markdown>`);
30
+ expect(el.value).to.equal('');
31
+ });
32
+ it('7. should have tabSize default to 4', async () => {
33
+ const el = await fixture(html `<nile-markdown></nile-markdown>`);
34
+ expect(el.tabSize).to.equal(4);
35
+ });
36
+ // === VALUE PROPERTY ===
37
+ it('8. should render markdown from value property', async () => {
38
+ const el = await fixture(html `<nile-markdown value="# Heading"></nile-markdown>`);
39
+ await el.updateComplete;
40
+ const h1 = el.shadowRoot.querySelector('h1');
41
+ expect(h1).to.exist;
42
+ expect(h1.textContent).to.equal('Heading');
43
+ });
44
+ it('9. should render bold text', async () => {
45
+ const el = await fixture(html `<nile-markdown value="This is **bold**"></nile-markdown>`);
46
+ await el.updateComplete;
47
+ const strong = el.shadowRoot.querySelector('strong');
48
+ expect(strong).to.exist;
49
+ expect(strong.textContent).to.equal('bold');
50
+ });
51
+ it('10. should render links', async () => {
52
+ const el = await fixture(html `<nile-markdown value="[link](https://example.com)"></nile-markdown>`);
53
+ await el.updateComplete;
54
+ const a = el.shadowRoot.querySelector('a');
55
+ expect(a).to.exist;
56
+ expect(a.getAttribute('href')).to.equal('https://example.com');
57
+ });
58
+ it('11. should render lists', async () => {
59
+ const el = await fixture(html `<nile-markdown></nile-markdown>`);
60
+ el.value = '- one\n- two\n- three';
61
+ await el.updateComplete;
62
+ const items = el.shadowRoot.querySelectorAll('li');
63
+ expect(items.length).to.equal(3);
64
+ });
65
+ it('12. should render code blocks', async () => {
66
+ const el = await fixture(html `<nile-markdown></nile-markdown>`);
67
+ el.value = '```\nconst a = 1;\n```';
68
+ await el.updateComplete;
69
+ const pre = el.shadowRoot.querySelector('pre code');
70
+ expect(pre).to.exist;
71
+ });
72
+ it('13. should render GFM tables', async () => {
73
+ const el = await fixture(html `<nile-markdown></nile-markdown>`);
74
+ el.value = '| a | b |\n| - | - |\n| 1 | 2 |';
75
+ await el.updateComplete;
76
+ const table = el.shadowRoot.querySelector('table');
77
+ expect(table).to.exist;
78
+ });
79
+ it('14. should render blockquotes', async () => {
80
+ const el = await fixture(html `<nile-markdown></nile-markdown>`);
81
+ el.value = '> quoted';
82
+ await el.updateComplete;
83
+ const quote = el.shadowRoot.querySelector('blockquote');
84
+ expect(quote).to.exist;
85
+ });
86
+ // === SCRIPT CHILD ===
87
+ it('15. should render markdown from a script child', async () => {
88
+ const el = await fixture(html `
89
+ <nile-markdown>
90
+ <script type="text/markdown">
91
+ # From Script
92
+ </script>
93
+ </nile-markdown>
94
+ `);
95
+ await el.updateComplete;
96
+ const h1 = el.shadowRoot.querySelector('h1');
97
+ expect(h1).to.exist;
98
+ expect(h1.textContent).to.equal('From Script');
99
+ });
100
+ it('16. should normalize indented script content', async () => {
101
+ const el = await fixture(html `
102
+ <nile-markdown>
103
+ <script type="text/markdown">
104
+ # Title
105
+
106
+ Paragraph text, indented to match the HTML.
107
+ </script>
108
+ </nile-markdown>
109
+ `);
110
+ await el.updateComplete;
111
+ // Indented content must not be treated as a code block
112
+ expect(el.shadowRoot.querySelector('pre')).to.not.exist;
113
+ expect(el.shadowRoot.querySelector('h1')).to.exist;
114
+ expect(el.shadowRoot.querySelector('p')).to.exist;
115
+ });
116
+ it('17. value should take precedence over script child', async () => {
117
+ const el = await fixture(html `
118
+ <nile-markdown value="# From Value">
119
+ <script type="text/markdown">
120
+ # From Script
121
+ </script>
122
+ </nile-markdown>
123
+ `);
124
+ await el.updateComplete;
125
+ const h1 = el.shadowRoot.querySelector('h1');
126
+ expect(h1.textContent).to.equal('From Value');
127
+ });
128
+ // === DYNAMIC UPDATES ===
129
+ it('18. should re-render when value changes', async () => {
130
+ const el = await fixture(html `<nile-markdown value="# One"></nile-markdown>`);
131
+ await el.updateComplete;
132
+ el.value = '# Two';
133
+ await el.updateComplete;
134
+ await el.updateComplete;
135
+ const h1 = el.shadowRoot.querySelector('h1');
136
+ expect(h1.textContent).to.equal('Two');
137
+ });
138
+ it('19. should re-render when script content changes', async () => {
139
+ const el = await fixture(html `
140
+ <nile-markdown>
141
+ <script type="text/markdown">
142
+ # Before
143
+ </script>
144
+ </nile-markdown>
145
+ `);
146
+ await el.updateComplete;
147
+ const script = el.querySelector('script');
148
+ script.textContent = '# After';
149
+ // MutationObserver fires async
150
+ await new Promise(resolve => setTimeout(resolve, 0));
151
+ await el.updateComplete;
152
+ const h1 = el.shadowRoot.querySelector('h1');
153
+ expect(h1.textContent).to.equal('After');
154
+ });
155
+ it('20. renderMarkdown() should re-parse manually', async () => {
156
+ const el = await fixture(html `<nile-markdown value="# Manual"></nile-markdown>`);
157
+ await el.updateComplete;
158
+ el.renderMarkdown();
159
+ await el.updateComplete;
160
+ expect(el.shadowRoot.querySelector('h1').textContent).to.equal('Manual');
161
+ });
162
+ // === EVENTS ===
163
+ it('21. should emit nile-markdown-rendered after rendering', async () => {
164
+ const el = document.createElement('nile-markdown');
165
+ const listener = oneEvent(el, 'nile-markdown-rendered');
166
+ el.value = '# Event';
167
+ document.body.appendChild(el);
168
+ const event = await listener;
169
+ expect(event).to.exist;
170
+ el.remove();
171
+ });
172
+ // === STATIC API ===
173
+ it('22. getMarked() should return a shared instance', () => {
174
+ const a = NileMarkdown.getMarked();
175
+ const b = NileMarkdown.getMarked();
176
+ expect(a).to.equal(b);
177
+ });
178
+ it('23. updateAll() should not throw', async () => {
179
+ await fixture(html `<nile-markdown value="# A"></nile-markdown>`);
180
+ expect(() => NileMarkdown.updateAll()).to.not.throw();
181
+ });
182
+ // === EDGE CASES ===
183
+ it('24. should handle empty content', async () => {
184
+ const el = await fixture(html `<nile-markdown></nile-markdown>`);
185
+ const base = el.shadowRoot.querySelector('[part~="base"]');
186
+ expect(base.textContent.trim()).to.equal('');
187
+ });
188
+ it('25. should have static styles', () => {
189
+ expect(NileMarkdown.styles).to.exist;
190
+ });
191
+ });
192
+ //# sourceMappingURL=nile-markdown.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nile-markdown.test.js","sourceRoot":"","sources":["../../../src/nile-markdown/nile-markdown.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { expect, fixture, html, oneEvent } from '@open-wc/testing';\nimport './nile-markdown';\nimport NileMarkdown from './nile-markdown';\n\ndescribe('NileMarkdown', () => {\n // === RENDERING ===\n it('1. should render without errors', async () => {\n const el = await fixture<NileMarkdown>(\n html`<nile-markdown></nile-markdown>`\n );\n expect(el).to.exist;\n });\n\n it('2. should have a shadow root', async () => {\n const el = await fixture<NileMarkdown>(\n html`<nile-markdown></nile-markdown>`\n );\n expect(el.shadowRoot).to.not.be.null;\n });\n\n it('3. should have base part', async () => {\n const el = await fixture<NileMarkdown>(\n html`<nile-markdown></nile-markdown>`\n );\n const base = el.shadowRoot!.querySelector('[part~=\"base\"]');\n expect(base).to.exist;\n });\n\n it('4. should be instance of NileMarkdown', async () => {\n const el = await fixture<NileMarkdown>(\n html`<nile-markdown></nile-markdown>`\n );\n expect(el).to.be.instanceOf(NileMarkdown);\n });\n\n it('5. should have correct tag name', async () => {\n const el = await fixture<NileMarkdown>(\n html`<nile-markdown></nile-markdown>`\n );\n expect(el.tagName.toLowerCase()).to.equal('nile-markdown');\n });\n\n // === DEFAULT PROPERTIES ===\n it('6. should have value default to empty string', async () => {\n const el = await fixture<NileMarkdown>(\n html`<nile-markdown></nile-markdown>`\n );\n expect(el.value).to.equal('');\n });\n\n it('7. should have tabSize default to 4', async () => {\n const el = await fixture<NileMarkdown>(\n html`<nile-markdown></nile-markdown>`\n );\n expect(el.tabSize).to.equal(4);\n });\n\n // === VALUE PROPERTY ===\n it('8. should render markdown from value property', async () => {\n const el = await fixture<NileMarkdown>(\n html`<nile-markdown value=\"# Heading\"></nile-markdown>`\n );\n await el.updateComplete;\n const h1 = el.shadowRoot!.querySelector('h1');\n expect(h1).to.exist;\n expect(h1!.textContent).to.equal('Heading');\n });\n\n it('9. should render bold text', async () => {\n const el = await fixture<NileMarkdown>(\n html`<nile-markdown value=\"This is **bold**\"></nile-markdown>`\n );\n await el.updateComplete;\n const strong = el.shadowRoot!.querySelector('strong');\n expect(strong).to.exist;\n expect(strong!.textContent).to.equal('bold');\n });\n\n it('10. should render links', async () => {\n const el = await fixture<NileMarkdown>(\n html`<nile-markdown value=\"[link](https://example.com)\"></nile-markdown>`\n );\n await el.updateComplete;\n const a = el.shadowRoot!.querySelector('a');\n expect(a).to.exist;\n expect(a!.getAttribute('href')).to.equal('https://example.com');\n });\n\n it('11. should render lists', async () => {\n const el = await fixture<NileMarkdown>(\n html`<nile-markdown></nile-markdown>`\n );\n el.value = '- one\\n- two\\n- three';\n await el.updateComplete;\n const items = el.shadowRoot!.querySelectorAll('li');\n expect(items.length).to.equal(3);\n });\n\n it('12. should render code blocks', async () => {\n const el = await fixture<NileMarkdown>(\n html`<nile-markdown></nile-markdown>`\n );\n el.value = '```\\nconst a = 1;\\n```';\n await el.updateComplete;\n const pre = el.shadowRoot!.querySelector('pre code');\n expect(pre).to.exist;\n });\n\n it('13. should render GFM tables', async () => {\n const el = await fixture<NileMarkdown>(\n html`<nile-markdown></nile-markdown>`\n );\n el.value = '| a | b |\\n| - | - |\\n| 1 | 2 |';\n await el.updateComplete;\n const table = el.shadowRoot!.querySelector('table');\n expect(table).to.exist;\n });\n\n it('14. should render blockquotes', async () => {\n const el = await fixture<NileMarkdown>(\n html`<nile-markdown></nile-markdown>`\n );\n el.value = '> quoted';\n await el.updateComplete;\n const quote = el.shadowRoot!.querySelector('blockquote');\n expect(quote).to.exist;\n });\n\n // === SCRIPT CHILD ===\n it('15. should render markdown from a script child', async () => {\n const el = await fixture<NileMarkdown>(html`\n <nile-markdown>\n <script type=\"text/markdown\">\n # From Script\n </script>\n </nile-markdown>\n `);\n await el.updateComplete;\n const h1 = el.shadowRoot!.querySelector('h1');\n expect(h1).to.exist;\n expect(h1!.textContent).to.equal('From Script');\n });\n\n it('16. should normalize indented script content', async () => {\n const el = await fixture<NileMarkdown>(html`\n <nile-markdown>\n <script type=\"text/markdown\">\n # Title\n\n Paragraph text, indented to match the HTML.\n </script>\n </nile-markdown>\n `);\n await el.updateComplete;\n // Indented content must not be treated as a code block\n expect(el.shadowRoot!.querySelector('pre')).to.not.exist;\n expect(el.shadowRoot!.querySelector('h1')).to.exist;\n expect(el.shadowRoot!.querySelector('p')).to.exist;\n });\n\n it('17. value should take precedence over script child', async () => {\n const el = await fixture<NileMarkdown>(html`\n <nile-markdown value=\"# From Value\">\n <script type=\"text/markdown\">\n # From Script\n </script>\n </nile-markdown>\n `);\n await el.updateComplete;\n const h1 = el.shadowRoot!.querySelector('h1');\n expect(h1!.textContent).to.equal('From Value');\n });\n\n // === DYNAMIC UPDATES ===\n it('18. should re-render when value changes', async () => {\n const el = await fixture<NileMarkdown>(\n html`<nile-markdown value=\"# One\"></nile-markdown>`\n );\n await el.updateComplete;\n el.value = '# Two';\n await el.updateComplete;\n await el.updateComplete;\n const h1 = el.shadowRoot!.querySelector('h1');\n expect(h1!.textContent).to.equal('Two');\n });\n\n it('19. should re-render when script content changes', async () => {\n const el = await fixture<NileMarkdown>(html`\n <nile-markdown>\n <script type=\"text/markdown\">\n # Before\n </script>\n </nile-markdown>\n `);\n await el.updateComplete;\n const script = el.querySelector('script')!;\n script.textContent = '# After';\n // MutationObserver fires async\n await new Promise(resolve => setTimeout(resolve, 0));\n await el.updateComplete;\n const h1 = el.shadowRoot!.querySelector('h1');\n expect(h1!.textContent).to.equal('After');\n });\n\n it('20. renderMarkdown() should re-parse manually', async () => {\n const el = await fixture<NileMarkdown>(\n html`<nile-markdown value=\"# Manual\"></nile-markdown>`\n );\n await el.updateComplete;\n el.renderMarkdown();\n await el.updateComplete;\n expect(el.shadowRoot!.querySelector('h1')!.textContent).to.equal('Manual');\n });\n\n // === EVENTS ===\n it('21. should emit nile-markdown-rendered after rendering', async () => {\n const el = document.createElement('nile-markdown') as NileMarkdown;\n const listener = oneEvent(el, 'nile-markdown-rendered');\n el.value = '# Event';\n document.body.appendChild(el);\n const event = await listener;\n expect(event).to.exist;\n el.remove();\n });\n\n // === STATIC API ===\n it('22. getMarked() should return a shared instance', () => {\n const a = NileMarkdown.getMarked();\n const b = NileMarkdown.getMarked();\n expect(a).to.equal(b);\n });\n\n it('23. updateAll() should not throw', async () => {\n await fixture<NileMarkdown>(\n html`<nile-markdown value=\"# A\"></nile-markdown>`\n );\n expect(() => NileMarkdown.updateAll()).to.not.throw();\n });\n\n // === EDGE CASES ===\n it('24. should handle empty content', async () => {\n const el = await fixture<NileMarkdown>(\n html`<nile-markdown></nile-markdown>`\n );\n const base = el.shadowRoot!.querySelector('[part~=\"base\"]');\n expect(base!.textContent!.trim()).to.equal('');\n });\n\n it('25. should have static styles', () => {\n expect(NileMarkdown.styles).to.exist;\n });\n});\n"]}
@@ -0,0 +1 @@
1
+ export { NileMarkdownEditor } from './nile-markdown-editor';
@@ -0,0 +1,2 @@
1
+ export { NileMarkdownEditor } from './nile-markdown-editor';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/nile-markdown-editor/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC","sourcesContent":["export { NileMarkdownEditor } from './nile-markdown-editor';\n"]}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Copyright Aquera Inc 2023
3
+ *
4
+ * This source code is licensed under the BSD-3-Clause license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+ /**
8
+ * Markdown editor CSS
9
+ */
10
+ export declare const styles: import("lit").CSSResult;