kempo-ui 0.4.4 → 0.4.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/Chat.js +201 -0
- package/dist/components/CodeEditor.js +21 -2
- package/dist/components/Dropdown.js +1 -1
- package/dist/components/HtmlEditor.js +42 -3
- package/dist/components/MarkdownEditor.js +173 -0
- package/dist/components/Resize.js +12 -2
- package/dist/components/TextToSpeech.js +4 -4
- package/dist/components/VoiceSelector.js +49 -0
- package/dist/components/markdownEditorControls/Bold.js +11 -0
- package/dist/components/markdownEditorControls/BulletList.js +11 -0
- package/dist/components/markdownEditorControls/Code.js +11 -0
- package/dist/components/markdownEditorControls/FormatBlock.js +30 -0
- package/dist/components/markdownEditorControls/Heading.js +11 -0
- package/dist/components/markdownEditorControls/Image.js +93 -0
- package/dist/components/markdownEditorControls/Italic.js +11 -0
- package/dist/components/markdownEditorControls/Link.js +11 -0
- package/dist/components/markdownEditorControls/MarkdownEditorControl.js +39 -0
- package/dist/components/markdownEditorControls/Menu.js +30 -0
- package/dist/components/markdownEditorControls/NumberedList.js +11 -0
- package/dist/components/markdownEditorControls/Quote.js +11 -0
- package/dist/components/markdownEditorControls/SpeechToText.js +16 -0
- package/dist/components/markdownEditorControls/Strikethrough.js +11 -0
- package/dist/components/markdownEditorControls/Table.js +80 -0
- package/dist/utils/marked.esm.js +1 -0
- package/dist/utils/renderMarkdown.js +1 -0
- package/dist/utils/sanitizeHtml.js +1 -0
- package/dist/utils/voice.js +1 -0
- package/docs/components/accordion.html +19 -0
- package/docs/components/aside.html +19 -0
- package/docs/components/calendar.html +19 -0
- package/docs/components/card.html +19 -0
- package/docs/components/chat.html +715 -0
- package/docs/components/code-editor.html +55 -0
- package/docs/components/color-picker.html +19 -0
- package/docs/components/combobox.html +19 -0
- package/docs/components/content-slider.html +19 -0
- package/docs/components/context.html +19 -0
- package/docs/components/dialog.html +19 -0
- package/docs/components/dropdown.html +19 -0
- package/docs/components/filter-list.html +19 -0
- package/docs/components/focus-capture.html +19 -0
- package/docs/components/html-editor.html +60 -0
- package/docs/components/hybrid-component.html +19 -0
- package/docs/components/icon.html +19 -0
- package/docs/components/import.html +19 -0
- package/docs/components/light-component.html +19 -0
- package/docs/components/markdown-editor.html +924 -0
- package/docs/components/nav-spacer.html +19 -0
- package/docs/components/nav.html +19 -0
- package/docs/components/photo-viewer.html +19 -0
- package/docs/components/progress.html +19 -0
- package/docs/components/resize.html +22 -0
- package/docs/components/rich-textarea.html +650 -0
- package/docs/components/shadow-component.html +19 -0
- package/docs/components/show-more.html +19 -0
- package/docs/components/slider.html +19 -0
- package/docs/components/sortable.html +19 -0
- package/docs/components/speech-to-text.html +19 -0
- package/docs/components/spinner.html +19 -0
- package/docs/components/split.html +19 -0
- package/docs/components/table.html +19 -0
- package/docs/components/tableControls.html +19 -0
- package/docs/components/tableCustomFields.html +19 -0
- package/docs/components/tableFetchRecords.html +19 -0
- package/docs/components/tableFieldSortHide.html +19 -0
- package/docs/components/tablePagination.html +19 -0
- package/docs/components/tablePlaceholder.html +19 -0
- package/docs/components/tableRecordEditing.html +19 -0
- package/docs/components/tableRecordFiltering.html +19 -0
- package/docs/components/tableRecordHiding.html +19 -0
- package/docs/components/tableRecordSearching.html +19 -0
- package/docs/components/tableRecordSelection.html +19 -0
- package/docs/components/tableRowControls.html +19 -0
- package/docs/components/tableServerSync.html +19 -0
- package/docs/components/tableSorting.html +19 -0
- package/docs/components/tabs.html +19 -0
- package/docs/components/tags.html +19 -0
- package/docs/components/text-to-speech.html +63 -1
- package/docs/components/theme-select.html +19 -0
- package/docs/components/theme-switcher.html +19 -0
- package/docs/components/time.html +19 -0
- package/docs/components/timestamp.html +19 -0
- package/docs/components/toast.html +19 -0
- package/docs/components/toggle.html +19 -0
- package/docs/components/tree.html +19 -0
- package/docs/components/voice-selector.html +610 -0
- package/docs/icons/done_all.svg +1 -0
- package/docs/icons/format_quote.svg +1 -0
- package/docs/icons/format_strikethrough.svg +1 -0
- package/docs/icons/send.svg +1 -0
- package/docs/icons/text_fields.svg +1 -0
- package/docs/index.html +49 -0
- package/docs/src/components/Chat.js +201 -0
- package/docs/src/components/CodeEditor.js +21 -2
- package/docs/src/components/Dropdown.js +1 -1
- package/docs/src/components/HtmlEditor.js +42 -3
- package/docs/src/components/MarkdownEditor.js +173 -0
- package/docs/src/components/Resize.js +12 -2
- package/docs/src/components/TextToSpeech.js +4 -4
- package/docs/src/components/VoiceSelector.js +49 -0
- package/docs/src/components/markdownEditorControls/Bold.js +11 -0
- package/docs/src/components/markdownEditorControls/BulletList.js +11 -0
- package/docs/src/components/markdownEditorControls/Code.js +11 -0
- package/docs/src/components/markdownEditorControls/FormatBlock.js +30 -0
- package/docs/src/components/markdownEditorControls/Heading.js +11 -0
- package/docs/src/components/markdownEditorControls/Image.js +93 -0
- package/docs/src/components/markdownEditorControls/Italic.js +11 -0
- package/docs/src/components/markdownEditorControls/Link.js +11 -0
- package/docs/src/components/markdownEditorControls/MarkdownEditorControl.js +39 -0
- package/docs/src/components/markdownEditorControls/Menu.js +30 -0
- package/docs/src/components/markdownEditorControls/NumberedList.js +11 -0
- package/docs/src/components/markdownEditorControls/Quote.js +11 -0
- package/docs/src/components/markdownEditorControls/SpeechToText.js +16 -0
- package/docs/src/components/markdownEditorControls/Strikethrough.js +11 -0
- package/docs/src/components/markdownEditorControls/Table.js +80 -0
- package/docs/src/utils/marked.esm.js +1 -0
- package/docs/src/utils/renderMarkdown.js +1 -0
- package/docs/src/utils/sanitizeHtml.js +1 -0
- package/docs/src/utils/voice.js +1 -0
- package/docs/utils/context.html +19 -0
- package/docs/utils/cookie.html +19 -0
- package/docs/utils/debounce.html +19 -0
- package/docs/utils/drag.html +19 -0
- package/docs/utils/elevation.html +23 -10
- package/docs/utils/formatTimestamp.html +19 -0
- package/docs/utils/object.html +19 -0
- package/docs/utils/propConverters.html +19 -0
- package/docs/utils/sanitizeHtml.html +555 -0
- package/docs/utils/string.html +19 -0
- package/docs/utils/theme.html +19 -0
- package/docs/utils/toTitleCase.html +19 -0
- package/docs/utils/type.html +19 -0
- package/docs/utils/voice.html +548 -0
- package/docs/utils/wait.html +19 -0
- package/docs-src/components/chat.page.html +230 -0
- package/docs-src/components/code-editor.page.html +36 -0
- package/docs-src/components/html-editor.page.html +41 -0
- package/docs-src/components/markdown-editor.page.html +439 -0
- package/docs-src/components/resize.page.html +3 -0
- package/docs-src/components/text-to-speech.page.html +44 -1
- package/docs-src/components/voice-selector.page.html +125 -0
- package/docs-src/index.page.html +30 -0
- package/docs-src/nav.fragment.html +19 -0
- package/docs-src/utils/elevation.page.html +4 -10
- package/docs-src/utils/sanitizeHtml.page.html +73 -0
- package/docs-src/utils/voice.page.html +66 -0
- package/icons/done_all.svg +1 -0
- package/icons/format_quote.svg +1 -0
- package/icons/format_strikethrough.svg +1 -0
- package/icons/send.svg +1 -0
- package/icons/text_fields.svg +1 -0
- package/llms.txt +7 -2
- package/package.json +3 -2
- package/src/components/Chat.js +435 -0
- package/src/components/CodeEditor.js +58 -2
- package/src/components/Dropdown.js +1 -1
- package/src/components/HtmlEditor.js +84 -4
- package/src/components/MarkdownEditor.js +654 -0
- package/src/components/Resize.js +17 -1
- package/src/components/TextToSpeech.js +13 -2
- package/src/components/VoiceSelector.js +271 -0
- package/src/components/markdownEditorControls/Bold.js +30 -0
- package/src/components/markdownEditorControls/BulletList.js +30 -0
- package/src/components/markdownEditorControls/Code.js +39 -0
- package/src/components/markdownEditorControls/FormatBlock.js +102 -0
- package/src/components/markdownEditorControls/Heading.js +45 -0
- package/src/components/markdownEditorControls/Image.js +250 -0
- package/src/components/markdownEditorControls/Italic.js +30 -0
- package/src/components/markdownEditorControls/Link.js +74 -0
- package/src/components/markdownEditorControls/MarkdownEditorControl.js +158 -0
- package/src/components/markdownEditorControls/Menu.js +86 -0
- package/src/components/markdownEditorControls/NumberedList.js +69 -0
- package/src/components/markdownEditorControls/Quote.js +30 -0
- package/src/components/markdownEditorControls/SpeechToText.js +65 -0
- package/src/components/markdownEditorControls/Strikethrough.js +35 -0
- package/src/components/markdownEditorControls/Table.js +164 -0
- package/src/utils/marked.esm.js +77 -0
- package/src/utils/renderMarkdown.js +29 -0
- package/src/utils/sanitizeHtml.js +137 -0
- package/src/utils/voice.js +103 -0
- package/tests/components/Chat.browser-test.js +540 -0
- package/tests/components/TextToSpeech.browser-test.js +150 -1
- package/tests/components/VoiceSelector.browser-test.js +374 -0
- package/tests/utils/sanitizeHtml.browser-test.js +179 -0
- package/tests/utils/voice.browser-test.js +128 -0
|
@@ -0,0 +1,924 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>Markdown Editor - Components - Kempo Docs - A Web Components Solution</title>
|
|
7
|
+
<link rel="icon" type="image/png" sizes="48x48" href="../media/icon48.png">
|
|
8
|
+
<link rel="manifest" href="../manifest.json" />
|
|
9
|
+
<link rel="stylesheet" href="../kempo-vars.css" />
|
|
10
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/kempo-css@2/dist/kempo.min.css" />
|
|
11
|
+
<link rel="stylesheet" href="../kempo-hljs.css" />
|
|
12
|
+
<link rel="stylesheet" href="../styles.css" />
|
|
13
|
+
<script>window.litDisableBundleWarning = true;</script>
|
|
14
|
+
|
|
15
|
+
</head>
|
|
16
|
+
<body>
|
|
17
|
+
|
|
18
|
+
<k-nav
|
|
19
|
+
fixed
|
|
20
|
+
class="bg-primary"
|
|
21
|
+
>
|
|
22
|
+
<button
|
|
23
|
+
id="toggleNavSideMenu"
|
|
24
|
+
class="link"
|
|
25
|
+
>
|
|
26
|
+
<k-icon name="menu"></k-icon>
|
|
27
|
+
</button>
|
|
28
|
+
<a
|
|
29
|
+
href="../"
|
|
30
|
+
class="d-if ph"
|
|
31
|
+
style="align-items: center"
|
|
32
|
+
>
|
|
33
|
+
<img
|
|
34
|
+
src="../media/icon32.png"
|
|
35
|
+
alt="Kempo UI Icon"
|
|
36
|
+
class="pr"
|
|
37
|
+
/>
|
|
38
|
+
Kempo UI
|
|
39
|
+
</a>
|
|
40
|
+
<div
|
|
41
|
+
style="position:relative;margin:0 .25rem;align-self:center;"
|
|
42
|
+
theme="light"
|
|
43
|
+
>
|
|
44
|
+
<input
|
|
45
|
+
id="navSearchInput"
|
|
46
|
+
type="search"
|
|
47
|
+
placeholder="Search docs..."
|
|
48
|
+
autocomplete="off"
|
|
49
|
+
style="width:11rem;"
|
|
50
|
+
/>
|
|
51
|
+
<div
|
|
52
|
+
id="navSearchDropdown"
|
|
53
|
+
hidden
|
|
54
|
+
theme="light"
|
|
55
|
+
style="position:absolute;top:calc(100% + 4px);left:0;width:min(480px,90vw);max-height:70vh;background:var(--c_bg);border:1px solid var(--c_border);border-radius:var(--radius);overflow:auto;z-index:9999;box-shadow:0 4px 12px rgba(0,0,0,.3);"
|
|
56
|
+
>
|
|
57
|
+
<k-filter-list
|
|
58
|
+
id="navSearchList"
|
|
59
|
+
style="display:block;padding:.25rem 0;"
|
|
60
|
+
>
|
|
61
|
+
<k-filter-item filter-keywords="accordion components"><a
|
|
62
|
+
href="../components/accordion.html">Accordion<br><small>Component</small></a></k-filter-item>
|
|
63
|
+
<k-filter-item filter-keywords="aside sidebar components"><a
|
|
64
|
+
href="../components/aside.html">Aside<br><small>Component</small></a></k-filter-item>
|
|
65
|
+
<k-filter-item filter-keywords="calendar date picker range month day components"><a
|
|
66
|
+
href="../components/calendar.html"
|
|
67
|
+
>Calendar<br><small>Component</small></a></k-filter-item>
|
|
68
|
+
<k-filter-item filter-keywords="card components"><a
|
|
69
|
+
href="../components/card.html">Card<br><small>Component</small></a></k-filter-item>
|
|
70
|
+
<k-filter-item filter-keywords="chat message conversation messaging components"><a
|
|
71
|
+
href="../components/chat.html"
|
|
72
|
+
>Chat<br><small>Component</small></a></k-filter-item>
|
|
73
|
+
<k-filter-item filter-keywords="code editor codeeditor monaco components"><a
|
|
74
|
+
href="../components/code-editor.html"
|
|
75
|
+
>Code Editor<br><small>Component</small></a></k-filter-item>
|
|
76
|
+
<k-filter-item filter-keywords="combobox combo box search autocomplete components"><a
|
|
77
|
+
href="../components/combobox.html"
|
|
78
|
+
>Combobox<br><small>Component</small></a></k-filter-item>
|
|
79
|
+
<k-filter-item filter-keywords="color picker colorpicker components"><a
|
|
80
|
+
href="../components/color-picker.html"
|
|
81
|
+
>Color Picker<br><small>Component</small></a></k-filter-item>
|
|
82
|
+
<k-filter-item filter-keywords="content slider components"><a
|
|
83
|
+
href="../components/content-slider.html"
|
|
84
|
+
>Content Slider<br><small>Component</small></a></k-filter-item>
|
|
85
|
+
<k-filter-item filter-keywords="context state global components"><a
|
|
86
|
+
href="../components/context.html"
|
|
87
|
+
>Context<br><small>Component</small></a></k-filter-item>
|
|
88
|
+
<k-filter-item filter-keywords="dialog modal popup components"><a
|
|
89
|
+
href="../components/dialog.html">Dialog<br><small>Component</small></a></k-filter-item>
|
|
90
|
+
<k-filter-item filter-keywords="dropdown select components"><a
|
|
91
|
+
href="../components/dropdown.html">Dropdown<br><small>Component</small></a></k-filter-item>
|
|
92
|
+
<k-filter-item filter-keywords="filter list filterlist components"><a
|
|
93
|
+
href="../components/filter-list.html"
|
|
94
|
+
>Filter List<br><small>Component</small></a></k-filter-item>
|
|
95
|
+
<k-filter-item filter-keywords="focus capture focuscapture components"><a
|
|
96
|
+
href="../components/focus-capture.html"
|
|
97
|
+
>Focus Capture<br><small>Component</small></a></k-filter-item>
|
|
98
|
+
<k-filter-item filter-keywords="html editor components"><a
|
|
99
|
+
href="../components/html-editor.html">HTML
|
|
100
|
+
Editor<br><small>Component</small></a></k-filter-item>
|
|
101
|
+
<k-filter-item filter-keywords="markdown editor markdowneditor write preview marked gfm tables components"><a
|
|
102
|
+
href="../components/markdown-editor.html"
|
|
103
|
+
>Markdown Editor<br><small>Component</small></a></k-filter-item>
|
|
104
|
+
<k-filter-item filter-keywords="icon components"><a
|
|
105
|
+
href="../components/icon.html">Icon<br><small>Component</small></a></k-filter-item>
|
|
106
|
+
<k-filter-item filter-keywords="import components"><a
|
|
107
|
+
href="../components/import.html">Import<br><small>Component</small></a></k-filter-item>
|
|
108
|
+
<k-filter-item filter-keywords="nav navbar navigation components"><a
|
|
109
|
+
href="../components/nav.html">Nav<br><small>Component</small></a></k-filter-item>
|
|
110
|
+
<k-filter-item filter-keywords="nav spacer navbar spacer navspacer components"><a
|
|
111
|
+
href="../components/nav-spacer.html"
|
|
112
|
+
>Nav Spacer<br><small>Component</small></a></k-filter-item>
|
|
113
|
+
<k-filter-item filter-keywords="photo viewer photoviewer components"><a
|
|
114
|
+
href="../components/photo-viewer.html"
|
|
115
|
+
>Photo Viewer<br><small>Component</small></a></k-filter-item>
|
|
116
|
+
<k-filter-item filter-keywords="progress loading components"><a
|
|
117
|
+
href="../components/progress.html">Progress<br><small>Component</small></a></k-filter-item>
|
|
118
|
+
<k-filter-item filter-keywords="resize components"><a
|
|
119
|
+
href="../components/resize.html">Resize<br><small>Component</small></a></k-filter-item>
|
|
120
|
+
<k-filter-item filter-keywords="show more showmore components"><a
|
|
121
|
+
href="../components/show-more.html"
|
|
122
|
+
>Show More<br><small>Component</small></a></k-filter-item>
|
|
123
|
+
<k-filter-item filter-keywords="slider range input step components"><a
|
|
124
|
+
href="../components/slider.html"
|
|
125
|
+
>Slider<br><small>Component</small></a></k-filter-item>
|
|
126
|
+
<k-filter-item filter-keywords="sortable drag drop sort components"><a
|
|
127
|
+
href="../components/sortable.html"
|
|
128
|
+
>Sortable<br><small>Component</small></a></k-filter-item>
|
|
129
|
+
<k-filter-item filter-keywords="speech to text speechtotext microphone voice recognition transcription components"><a
|
|
130
|
+
href="../components/speech-to-text.html"
|
|
131
|
+
>Speech To Text<br><small>Component</small></a></k-filter-item>
|
|
132
|
+
<k-filter-item filter-keywords="spinner loading components"><a
|
|
133
|
+
href="../components/spinner.html">Spinner<br><small>Component</small></a></k-filter-item>
|
|
134
|
+
<k-filter-item filter-keywords="split pane components"><a
|
|
135
|
+
href="../components/split.html">Split<br><small>Component</small></a></k-filter-item>
|
|
136
|
+
<k-filter-item filter-keywords="table data grid components"><a
|
|
137
|
+
href="../components/table.html">Table<br><small>Component</small></a></k-filter-item>
|
|
138
|
+
<k-filter-item filter-keywords="table controls advanced example"><a
|
|
139
|
+
href="../components/tableControls.html"
|
|
140
|
+
>Table — Controls<br><small>Advanced Example</small></a></k-filter-item>
|
|
141
|
+
<k-filter-item filter-keywords="table custom fields advanced example"><a
|
|
142
|
+
href="../components/tableCustomFields.html"
|
|
143
|
+
>Table — Custom Fields<br><small>Advanced Example</small></a></k-filter-item>
|
|
144
|
+
<k-filter-item filter-keywords="table fetch records advanced example"><a
|
|
145
|
+
href="../components/tableFetchRecords.html"
|
|
146
|
+
>Table — Fetch Records<br><small>Advanced Example</small></a></k-filter-item>
|
|
147
|
+
<k-filter-item filter-keywords="table field sort hide advanced example"><a
|
|
148
|
+
href="../components/tableFieldSortHide.html"
|
|
149
|
+
>Table — Field Sort & Hide<br><small>Advanced Example</small></a></k-filter-item>
|
|
150
|
+
<k-filter-item filter-keywords="table pagination advanced example"><a
|
|
151
|
+
href="../components/tablePagination.html"
|
|
152
|
+
>Table — Pagination<br><small>Advanced Example</small></a></k-filter-item>
|
|
153
|
+
<k-filter-item filter-keywords="table record editing advanced example"><a
|
|
154
|
+
href="../components/tableRecordEditing.html"
|
|
155
|
+
>Table — Record Editing<br><small>Advanced Example</small></a></k-filter-item>
|
|
156
|
+
<k-filter-item filter-keywords="table record filtering advanced example"><a
|
|
157
|
+
href="../components/tableRecordFiltering.html"
|
|
158
|
+
>Table — Record Filtering<br><small>Advanced Example</small></a></k-filter-item>
|
|
159
|
+
<k-filter-item filter-keywords="table record hiding advanced example"><a
|
|
160
|
+
href="../components/tableRecordHiding.html"
|
|
161
|
+
>Table — Record Hiding<br><small>Advanced Example</small></a></k-filter-item>
|
|
162
|
+
<k-filter-item filter-keywords="table record searching advanced example"><a
|
|
163
|
+
href="../components/tableRecordSearching.html"
|
|
164
|
+
>Table — Record Searching<br><small>Advanced Example</small></a></k-filter-item>
|
|
165
|
+
<k-filter-item filter-keywords="table record selection advanced example"><a
|
|
166
|
+
href="../components/tableRecordSelection.html"
|
|
167
|
+
>Table — Record Selection<br><small>Advanced Example</small></a></k-filter-item>
|
|
168
|
+
<k-filter-item filter-keywords="table row controls advanced example"><a
|
|
169
|
+
href="../components/tableRowControls.html"
|
|
170
|
+
>Table — Row Controls<br><small>Advanced Example</small></a></k-filter-item>
|
|
171
|
+
<k-filter-item filter-keywords="table server sync advanced example"><a
|
|
172
|
+
href="../components/tableServerSync.html"
|
|
173
|
+
>Table — Server Sync<br><small>Advanced Example</small></a></k-filter-item>
|
|
174
|
+
<k-filter-item filter-keywords="table sorting advanced example"><a
|
|
175
|
+
href="../components/tableSorting.html"
|
|
176
|
+
>Table — Sorting<br><small>Advanced Example</small></a></k-filter-item>
|
|
177
|
+
<k-filter-item filter-keywords="table placeholder advanced example"><a
|
|
178
|
+
href="../components/tablePlaceholder.html"
|
|
179
|
+
>Table — Placeholder<br><small>Advanced Example</small></a></k-filter-item>
|
|
180
|
+
<k-filter-item filter-keywords="tabs tab panel components"><a
|
|
181
|
+
href="../components/tabs.html">Tabs<br><small>Component</small></a></k-filter-item>
|
|
182
|
+
<k-filter-item filter-keywords="tags tag input components"><a
|
|
183
|
+
href="../components/tags.html">Tags<br><small>Component</small></a></k-filter-item>
|
|
184
|
+
<k-filter-item filter-keywords="text to speech texttospeech tts speak voice synthesis components"><a
|
|
185
|
+
href="../components/text-to-speech.html"
|
|
186
|
+
>Text To Speech<br><small>Component</small></a></k-filter-item>
|
|
187
|
+
<k-filter-item filter-keywords="theme select dropdown dark light components"><a
|
|
188
|
+
href="../components/theme-select.html"
|
|
189
|
+
>Theme Select<br><small>Component</small></a></k-filter-item>
|
|
190
|
+
<k-filter-item filter-keywords="theme switcher dark light components"><a
|
|
191
|
+
href="../components/theme-switcher.html"
|
|
192
|
+
>Theme Switcher<br><small>Component</small></a></k-filter-item>
|
|
193
|
+
<k-filter-item filter-keywords="time picker clock hour minute form components"><a
|
|
194
|
+
href="../components/time.html"
|
|
195
|
+
>Time<br><small>Component</small></a></k-filter-item>
|
|
196
|
+
<k-filter-item filter-keywords="timestamp date time components"><a
|
|
197
|
+
href="../components/timestamp.html"
|
|
198
|
+
>Timestamp<br><small>Component</small></a></k-filter-item>
|
|
199
|
+
<k-filter-item filter-keywords="toast notification alert components"><a
|
|
200
|
+
href="../components/toast.html"
|
|
201
|
+
>Toast<br><small>Component</small></a></k-filter-item>
|
|
202
|
+
<k-filter-item filter-keywords="toggle switch checkbox components"><a
|
|
203
|
+
href="../components/toggle.html"
|
|
204
|
+
>Toggle<br><small>Component</small></a></k-filter-item>
|
|
205
|
+
<k-filter-item filter-keywords="tree treeview components"><a
|
|
206
|
+
href="../components/tree.html">Tree<br><small>Component</small></a></k-filter-item>
|
|
207
|
+
<k-filter-item filter-keywords="voice selector dropdown speech synthesis preference components"><a
|
|
208
|
+
href="../components/voice-selector.html"
|
|
209
|
+
>Voice Selector<br><small>Component</small></a></k-filter-item>
|
|
210
|
+
<k-filter-item filter-keywords="shadow component base"><a
|
|
211
|
+
href="../components/shadow-component.html"
|
|
212
|
+
>Shadow Component<br><small>Base Component</small></a></k-filter-item>
|
|
213
|
+
<k-filter-item filter-keywords="light component base"><a
|
|
214
|
+
href="../components/light-component.html">Light Component<br><small>Base
|
|
215
|
+
Component</small></a></k-filter-item>
|
|
216
|
+
<k-filter-item filter-keywords="hybrid component base"><a
|
|
217
|
+
href="../components/hybrid-component.html"
|
|
218
|
+
>Hybrid Component<br><small>Base Component</small></a></k-filter-item>
|
|
219
|
+
<k-filter-item filter-keywords="cookie utils utility"><a
|
|
220
|
+
href="../utils/cookie.html">cookie<br><small>Utility</small></a></k-filter-item>
|
|
221
|
+
<k-filter-item filter-keywords="context utils utility"><a
|
|
222
|
+
href="../utils/context.html">context<br><small>Utility</small></a></k-filter-item>
|
|
223
|
+
<k-filter-item filter-keywords="debounce utils utility"><a
|
|
224
|
+
href="../utils/debounce.html">debounce<br><small>Utility</small></a></k-filter-item>
|
|
225
|
+
<k-filter-item filter-keywords="drag utils utility"><a
|
|
226
|
+
href="../utils/drag.html">drag<br><small>Utility</small></a></k-filter-item>
|
|
227
|
+
<k-filter-item filter-keywords="elevation z-index stacking utils"><a
|
|
228
|
+
href="../utils/elevation.html">elevation<br><small>Utility</small></a></k-filter-item>
|
|
229
|
+
<k-filter-item filter-keywords="formattimestamp timestamp format date time utils utility"><a
|
|
230
|
+
href="../utils/formatTimestamp.html"
|
|
231
|
+
>formatTimestamp<br><small>Utility</small></a></k-filter-item>
|
|
232
|
+
<k-filter-item filter-keywords="object utils utility"><a
|
|
233
|
+
href="../utils/object.html">object<br><small>Utility</small></a></k-filter-item>
|
|
234
|
+
<k-filter-item filter-keywords="propconverters prop converters utils utility"><a
|
|
235
|
+
href="../utils/propConverters.html"
|
|
236
|
+
>propConverters<br><small>Utility</small></a></k-filter-item>
|
|
237
|
+
<k-filter-item filter-keywords="sanitizehtml sanitize html xss security utils utility"><a
|
|
238
|
+
href="../utils/sanitizeHtml.html"
|
|
239
|
+
>sanitizeHtml<br><small>Utility</small></a></k-filter-item>
|
|
240
|
+
<k-filter-item filter-keywords="string utils utility"><a
|
|
241
|
+
href="../utils/string.html">string<br><small>Utility</small></a></k-filter-item>
|
|
242
|
+
<k-filter-item filter-keywords="theme utils utility"><a
|
|
243
|
+
href="../utils/theme.html">theme<br><small>Utility</small></a></k-filter-item>
|
|
244
|
+
<k-filter-item filter-keywords="type utils utility"><a
|
|
245
|
+
href="../utils/type.html">type<br><small>Utility</small></a></k-filter-item>
|
|
246
|
+
<k-filter-item filter-keywords="voice speech synthesis preference utils utility"><a
|
|
247
|
+
href="../utils/voice.html">voice<br><small>Utility</small></a></k-filter-item>
|
|
248
|
+
<k-filter-item filter-keywords="wait async utils utility"><a
|
|
249
|
+
href="../utils/wait.html">wait<br><small>Utility</small></a></k-filter-item>
|
|
250
|
+
</k-filter-list>
|
|
251
|
+
</div>
|
|
252
|
+
</div>
|
|
253
|
+
<div class="flex"></div>
|
|
254
|
+
<a
|
|
255
|
+
href="https://github.com/dustinpoissant/kempo-ui?tab=License-1-ov-file#creative-commons-attribution-noncommercial-sharealike-20"
|
|
256
|
+
target="_blank"
|
|
257
|
+
><k-icon name="license"></k-icon></a>
|
|
258
|
+
<a
|
|
259
|
+
href="https://www.npmjs.com/package/kempo-ui"
|
|
260
|
+
target="_blank"
|
|
261
|
+
><k-icon name="npm"></k-icon></a>
|
|
262
|
+
<a
|
|
263
|
+
href="https://github.com/dustinpoissant/kempo-ui"
|
|
264
|
+
target="_blank"
|
|
265
|
+
><k-icon name="github-mark"></k-icon></a>
|
|
266
|
+
<k-theme-switcher
|
|
267
|
+
class="mr"
|
|
268
|
+
style="
|
|
269
|
+
--padding: 0.5rem;
|
|
270
|
+
--c_active: var(--tc_on_primary);
|
|
271
|
+
--tc_active: var(--c_primary);
|
|
272
|
+
--c_inactive__hover: rgba(255, 255, 255, 0.1);
|
|
273
|
+
"
|
|
274
|
+
></k-theme-switcher>
|
|
275
|
+
</k-nav>
|
|
276
|
+
<div style="width: 100%; height: 4rem;"></div>
|
|
277
|
+
<k-aside
|
|
278
|
+
id="navSideMenu"
|
|
279
|
+
main="overlay"
|
|
280
|
+
state="offscreen"
|
|
281
|
+
>
|
|
282
|
+
<menu>
|
|
283
|
+
<a
|
|
284
|
+
href="../"
|
|
285
|
+
class="ta-center bb mb r0"
|
|
286
|
+
>
|
|
287
|
+
<h1 class="tc-primary">Kempo UI</h1>
|
|
288
|
+
<img
|
|
289
|
+
src="../media/icon128.png"
|
|
290
|
+
alt="Kempo UI Icon"
|
|
291
|
+
/>
|
|
292
|
+
</a>
|
|
293
|
+
|
|
294
|
+
<div class="pl mb">
|
|
295
|
+
<h3>Components</h3>
|
|
296
|
+
<a href="../components/accordion.html">Accordion</a>
|
|
297
|
+
<a href="../components/aside.html">Aside</a>
|
|
298
|
+
<a href="../components/calendar.html">Calendar</a>
|
|
299
|
+
<a href="../components/card.html">Card</a>
|
|
300
|
+
<a href="../components/chat.html">Chat</a>
|
|
301
|
+
<a href="../components/code-editor.html">Code Editor</a>
|
|
302
|
+
<a href="../components/combobox.html">Combobox</a>
|
|
303
|
+
<a href="../components/color-picker.html">ColorPicker</a>
|
|
304
|
+
<a href="../components/content-slider.html">Content Slider</a>
|
|
305
|
+
<a href="../components/context.html">Context</a>
|
|
306
|
+
<a href="../components/dialog.html">Dialog</a>
|
|
307
|
+
<a href="../components/dropdown.html">Dropdown</a>
|
|
308
|
+
<a href="../components/filter-list.html">Filter List</a>
|
|
309
|
+
<a href="../components/focus-capture.html">FocusCapture</a>
|
|
310
|
+
<a href="../components/html-editor.html">HTML Editor</a>
|
|
311
|
+
<a href="../components/markdown-editor.html">Markdown Editor</a>
|
|
312
|
+
<a href="../components/icon.html">Icon</a>
|
|
313
|
+
<a href="../components/import.html">Import</a>
|
|
314
|
+
<a href="../components/nav.html">Nav</a>
|
|
315
|
+
<a href="../components/nav-spacer.html">Nav Spacer</a>
|
|
316
|
+
<a href="../components/photo-viewer.html">Photo Viewer</a>
|
|
317
|
+
<a href="../components/progress.html">Progress</a>
|
|
318
|
+
<a href="../components/resize.html">Resize</a>
|
|
319
|
+
<a href="../components/show-more.html">Show More</a>
|
|
320
|
+
<a href="../components/slider.html">Slider</a>
|
|
321
|
+
<a href="../components/sortable.html">Sortable</a>
|
|
322
|
+
<a href="../components/speech-to-text.html">Speech To Text</a>
|
|
323
|
+
<a href="../components/spinner.html">Spinner</a>
|
|
324
|
+
<a href="../components/split.html">Split</a>
|
|
325
|
+
<a href="../components/table.html">Table</a>
|
|
326
|
+
<a href="../components/tabs.html">Tabs</a>
|
|
327
|
+
<a href="../components/tags.html">Tags</a>
|
|
328
|
+
<a href="../components/text-to-speech.html">Text To Speech</a>
|
|
329
|
+
<a href="../components/theme-select.html">Theme Select</a>
|
|
330
|
+
<a href="../components/theme-switcher.html">Theme Switcher</a>
|
|
331
|
+
<a href="../components/time.html">Time</a>
|
|
332
|
+
<a href="../components/timestamp.html">Timestamp</a>
|
|
333
|
+
<a href="../components/toast.html">Toast</a>
|
|
334
|
+
<a href="../components/toggle.html">Toggle</a>
|
|
335
|
+
<a href="../components/tree.html">Tree</a>
|
|
336
|
+
<a href="../components/voice-selector.html">Voice Selector</a>
|
|
337
|
+
</div>
|
|
338
|
+
|
|
339
|
+
<h5 class="mb0">Base Components</h5>
|
|
340
|
+
<div class="pl mb">
|
|
341
|
+
<a href="../components/shadow-component.html">Shadow Component</a>
|
|
342
|
+
<a href="../components/light-component.html">Light Component</a>
|
|
343
|
+
<a href="../components/hybrid-component.html">Hybrid Component</a>
|
|
344
|
+
</div>
|
|
345
|
+
|
|
346
|
+
<h5 class="mb0">Utils</h5>
|
|
347
|
+
<div class="pl mb">
|
|
348
|
+
<a href="../utils/cookie.html">cookie</a>
|
|
349
|
+
<a href="../utils/context.html">context</a>
|
|
350
|
+
<a href="../utils/debounce.html">debounce</a>
|
|
351
|
+
<a href="../utils/drag.html">drag</a>
|
|
352
|
+
<a href="../utils/elevation.html">elevation</a>
|
|
353
|
+
<a href="../utils/formatTimestamp.html">formatTimestamp</a>
|
|
354
|
+
<a href="../utils/object.html">object</a>
|
|
355
|
+
<a href="../utils/propConverters.html">propConverters</a>
|
|
356
|
+
<a href="../utils/sanitizeHtml.html">sanitizeHtml</a>
|
|
357
|
+
<a href="../utils/string.html">string</a>
|
|
358
|
+
<a href="../utils/theme.html">theme</a>
|
|
359
|
+
<a href="../utils/type.html">type</a>
|
|
360
|
+
<a href="../utils/voice.html">voice</a>
|
|
361
|
+
<a href="../utils/wait.html">wait</a>
|
|
362
|
+
</div>
|
|
363
|
+
</menu>
|
|
364
|
+
</k-aside>
|
|
365
|
+
<style>
|
|
366
|
+
#navSearchList a {
|
|
367
|
+
display: block;
|
|
368
|
+
padding: .25rem .5rem;
|
|
369
|
+
border-radius: var(--radius);
|
|
370
|
+
text-decoration: none;
|
|
371
|
+
color: var(--tc);
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
#navSearchList a:hover {
|
|
375
|
+
background: rgba(128, 128, 128, .15);
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
#navSearchList a small {
|
|
379
|
+
display: block;
|
|
380
|
+
color: var(--tc_muted);
|
|
381
|
+
}
|
|
382
|
+
</style>
|
|
383
|
+
<script
|
|
384
|
+
src="../src/components/Nav.js"
|
|
385
|
+
type="module"
|
|
386
|
+
></script>
|
|
387
|
+
<script
|
|
388
|
+
src="../src/components/FilterList.js"
|
|
389
|
+
type="module"
|
|
390
|
+
></script>
|
|
391
|
+
<script
|
|
392
|
+
src="../src/components/FilterItem.js"
|
|
393
|
+
type="module"
|
|
394
|
+
></script>
|
|
395
|
+
<script
|
|
396
|
+
src="../src/components/Aside.js"
|
|
397
|
+
type="module"
|
|
398
|
+
></script>
|
|
399
|
+
<script
|
|
400
|
+
src="../src/components/Icon.js"
|
|
401
|
+
type="module"
|
|
402
|
+
></script>
|
|
403
|
+
<script
|
|
404
|
+
src="../src/components/ThemeSwitcher.js"
|
|
405
|
+
type="module"
|
|
406
|
+
></script>
|
|
407
|
+
<script type="module">
|
|
408
|
+
import debounce from '../src/utils/debounce.js';
|
|
409
|
+
|
|
410
|
+
document.getElementById('toggleNavSideMenu').addEventListener('click', async () => {
|
|
411
|
+
await window.customElements.whenDefined('k-aside');
|
|
412
|
+
document.getElementById('navSideMenu').toggle();
|
|
413
|
+
});
|
|
414
|
+
|
|
415
|
+
document.addEventListener('click', function (e) {
|
|
416
|
+
if (e.target.matches('a[href^="#"]')) {
|
|
417
|
+
e.preventDefault();
|
|
418
|
+
const targetId = e.target.getAttribute('href').replace('#', '');
|
|
419
|
+
const target = document.getElementById(targetId);
|
|
420
|
+
if (target) {
|
|
421
|
+
target.scrollIntoView({ behavior: 'smooth' });
|
|
422
|
+
const url = window.location.pathname + window.location.search + '#' + targetId;
|
|
423
|
+
history.replaceState(null, '', url);
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
});
|
|
427
|
+
|
|
428
|
+
/*
|
|
429
|
+
Nav Search
|
|
430
|
+
*/
|
|
431
|
+
const searchInput = document.getElementById('navSearchInput');
|
|
432
|
+
const searchDropdown = document.getElementById('navSearchDropdown');
|
|
433
|
+
let navSearchList = null;
|
|
434
|
+
|
|
435
|
+
const openSearch = async () => {
|
|
436
|
+
await customElements.whenDefined('k-filter-list');
|
|
437
|
+
if (!navSearchList) navSearchList = document.getElementById('navSearchList');
|
|
438
|
+
navSearchList.filter(searchInput.value);
|
|
439
|
+
searchDropdown.hidden = false;
|
|
440
|
+
};
|
|
441
|
+
|
|
442
|
+
const closeSearch = () => {
|
|
443
|
+
searchDropdown.hidden = true;
|
|
444
|
+
navSearchList?.clearFocus();
|
|
445
|
+
};
|
|
446
|
+
|
|
447
|
+
searchInput.addEventListener('focus', openSearch);
|
|
448
|
+
|
|
449
|
+
searchInput.addEventListener('input', debounce(e => {
|
|
450
|
+
navSearchList?.filter(e.target.value);
|
|
451
|
+
}, 150));
|
|
452
|
+
|
|
453
|
+
searchInput.addEventListener('keydown', e => {
|
|
454
|
+
if (e.key === 'Escape') {
|
|
455
|
+
searchInput.value = '';
|
|
456
|
+
searchInput.blur();
|
|
457
|
+
closeSearch();
|
|
458
|
+
} else if (e.key === 'ArrowDown' || e.key === 'ArrowUp' || e.key === 'Enter') {
|
|
459
|
+
navSearchList?.handleKeydown(e);
|
|
460
|
+
}
|
|
461
|
+
});
|
|
462
|
+
|
|
463
|
+
searchInput.addEventListener('blur', () => {
|
|
464
|
+
setTimeout(closeSearch, 150);
|
|
465
|
+
});
|
|
466
|
+
|
|
467
|
+
document.addEventListener('keydown', e => {
|
|
468
|
+
let active = document.activeElement;
|
|
469
|
+
while (active?.shadowRoot?.activeElement) active = active.shadowRoot.activeElement;
|
|
470
|
+
const tag = active?.tagName;
|
|
471
|
+
if (tag === 'INPUT' || tag === 'TEXTAREA' || active?.isContentEditable) return;
|
|
472
|
+
if (e.metaKey || e.ctrlKey || e.altKey) return;
|
|
473
|
+
if (e.key.length === 1) {
|
|
474
|
+
searchInput.focus();
|
|
475
|
+
}
|
|
476
|
+
});
|
|
477
|
+
</script>
|
|
478
|
+
|
|
479
|
+
|
|
480
|
+
<h1 class="ta-center">Markdown Editor</h1>
|
|
481
|
+
|
|
482
|
+
<k-main>
|
|
483
|
+
|
|
484
|
+
<k-accordion persistent-id="toc" class="b r mb">
|
|
485
|
+
<k-accordion-header for-panel="toc-panel">Table of Contents</k-accordion-header>
|
|
486
|
+
<k-accordion-panel name="toc-panel">
|
|
487
|
+
<div class="m pl">
|
|
488
|
+
<h6>Examples</h6>
|
|
489
|
+
<a href="#basicUsage">Basic Usage</a><br />
|
|
490
|
+
<a href="#withControls">With Controls</a><br />
|
|
491
|
+
<a href="#preConfigured">Pre-Configured Controls</a><br />
|
|
492
|
+
<a href="#bottomControls">Bottom Controls</a><br />
|
|
493
|
+
<a href="#defaultValue">Default Value</a><br />
|
|
494
|
+
<a href="#formUsage">Form Usage</a><br />
|
|
495
|
+
<a href="#disabled">Disabled / Read-only</a><br />
|
|
496
|
+
<a href="#tagFiltering">Tag Filtering</a><br />
|
|
497
|
+
<a href="#customControls">Custom Controls</a><br />
|
|
498
|
+
|
|
499
|
+
<h6 class="mt"><a href="#jsRef" class="no-link">JavaScript Reference</a></h6>
|
|
500
|
+
<a href="#constructor">Constructor</a><br />
|
|
501
|
+
<a href="#requirements">Requirements</a><br />
|
|
502
|
+
<a href="#properties">Properties</a><br />
|
|
503
|
+
<a href="#methods">Methods</a><br />
|
|
504
|
+
<a href="#cssVariables">CSS Variables</a><br />
|
|
505
|
+
<a href="#events">Events</a><br />
|
|
506
|
+
<a href="#controls">Built-in Controls</a><br />
|
|
507
|
+
</div>
|
|
508
|
+
</k-accordion-panel>
|
|
509
|
+
</k-accordion>
|
|
510
|
+
|
|
511
|
+
<p>A markdown editor with GitHub-style <strong>Write</strong> and <strong>Preview</strong> tabs. The user types markdown in the textarea and can flip to a live preview at any time. Markdown is parsed by <a href="https://marked.js.org" target="_blank">marked</a> — a full CommonMark + GFM parser — so tables, task lists, fenced code blocks, autolinks, and inline HTML all work out of the box. The rendered output runs through <a href="../utils/sanitizeHtml.html"><code>sanitizeHtml</code></a> using <code>allowed-tags</code> (an allowlist) <em>or</em> <code>disallowed-tags</code> (a denylist) — the two are mutually exclusive. <code><script></code> tags are <strong>always</strong> stripped unless you opt in via the <code>scripts-enabled</code> attribute, and <code><iframe></code> / <code><style></code> / similar dangerous tags are always stripped regardless of any setting.</p>
|
|
512
|
+
<p>Toolbar buttons are slotted via <code>controls-top</code> and <code>controls-bottom</code> — mix and match the built-in controls listed below or write your own by extending <a href="#customControls"><code>MarkdownEditorControl</code></a>.</p>
|
|
513
|
+
|
|
514
|
+
<h3 id="basicUsage"><a href="#basicUsage" class="no-link">Basic Usage</a></h3>
|
|
515
|
+
<p>Drop in the tag with a <code>placeholder</code> and you get a markdown textarea with a Write/Preview toggle. No toolbars, no controls — just the bare editor.</p>
|
|
516
|
+
<div class="row -mx">
|
|
517
|
+
<div class="col m-span-12 px">
|
|
518
|
+
<k-card label="HTML">
|
|
519
|
+
<pre><code class="hljs xml"><span class="hljs-tag"><<span class="hljs-name">k-markdown-editor</span> <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Type some **markdown**..."</span>></span><span class="hljs-tag"></<span class="hljs-name">k-markdown-editor</span>></span></code></pre>
|
|
520
|
+
</k-card>
|
|
521
|
+
</div>
|
|
522
|
+
<div class="col m-span-12 px">
|
|
523
|
+
<k-card label="Output">
|
|
524
|
+
<k-markdown-editor placeholder="Type some **markdown**..."></k-markdown-editor>
|
|
525
|
+
</k-card>
|
|
526
|
+
</div>
|
|
527
|
+
</div>
|
|
528
|
+
|
|
529
|
+
<h3 id="withControls"><a href="#withControls" class="no-link">With Controls</a></h3>
|
|
530
|
+
<p>Wrap your toolbar buttons in a single <code><div slot="controls-top"></code> — that wrapper is the only element placed in the editor's <code>controls-top</code> slot, and you can lay it out however you like (the example below uses kempo-css's <code>d-f</code> for flex). Each control is its own custom element — import only the ones you need.</p>
|
|
531
|
+
<div class="row -mx">
|
|
532
|
+
<div class="col m-span-12 px">
|
|
533
|
+
<k-card label="HTML">
|
|
534
|
+
<pre><code class="hljs xml"><span class="hljs-tag"><<span class="hljs-name">k-markdown-editor</span> <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Write a comment..."</span>></span><br> <span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">slot</span>=<span class="hljs-string">"controls-top"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"d-f"</span>></span><br> <span class="hljs-tag"><<span class="hljs-name">k-md-menu</span> <span class="hljs-attr">label</span>=<span class="hljs-string">"Heading"</span>></span><br> <span class="hljs-tag"><<span class="hljs-name">k-icon</span> <span class="hljs-attr">slot</span>=<span class="hljs-string">"trigger"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"text_fields"</span>></span><span class="hljs-tag"></<span class="hljs-name">k-icon</span>></span><br> <span class="hljs-tag"><<span class="hljs-name">k-md-format-block</span> <span class="hljs-attr">tag</span>=<span class="hljs-string">"h1"</span>></span><span class="hljs-tag"></<span class="hljs-name">k-md-format-block</span>></span><br> <span class="hljs-tag"><<span class="hljs-name">k-md-format-block</span> <span class="hljs-attr">tag</span>=<span class="hljs-string">"h2"</span>></span><span class="hljs-tag"></<span class="hljs-name">k-md-format-block</span>></span><br> <span class="hljs-tag"><<span class="hljs-name">k-md-format-block</span> <span class="hljs-attr">tag</span>=<span class="hljs-string">"h3"</span>></span><span class="hljs-tag"></<span class="hljs-name">k-md-format-block</span>></span><br> <span class="hljs-tag"><<span class="hljs-name">k-md-format-block</span> <span class="hljs-attr">tag</span>=<span class="hljs-string">"h4"</span>></span><span class="hljs-tag"></<span class="hljs-name">k-md-format-block</span>></span><br> <span class="hljs-tag"><<span class="hljs-name">k-md-format-block</span> <span class="hljs-attr">tag</span>=<span class="hljs-string">"h5"</span>></span><span class="hljs-tag"></<span class="hljs-name">k-md-format-block</span>></span><br> <span class="hljs-tag"><<span class="hljs-name">k-md-format-block</span> <span class="hljs-attr">tag</span>=<span class="hljs-string">"h6"</span>></span><span class="hljs-tag"></<span class="hljs-name">k-md-format-block</span>></span><br> <span class="hljs-tag"></<span class="hljs-name">k-md-menu</span>></span><br> <span class="hljs-tag"><<span class="hljs-name">k-md-bold</span>></span><span class="hljs-tag"></<span class="hljs-name">k-md-bold</span>></span><br> <span class="hljs-tag"><<span class="hljs-name">k-md-italic</span>></span><span class="hljs-tag"></<span class="hljs-name">k-md-italic</span>></span><br> <span class="hljs-tag"><<span class="hljs-name">k-md-quote</span>></span><span class="hljs-tag"></<span class="hljs-name">k-md-quote</span>></span><br> <span class="hljs-tag"><<span class="hljs-name">k-md-code</span>></span><span class="hljs-tag"></<span class="hljs-name">k-md-code</span>></span><br> <span class="hljs-tag"><<span class="hljs-name">k-md-link</span>></span><span class="hljs-tag"></<span class="hljs-name">k-md-link</span>></span><br> <span class="hljs-tag"><<span class="hljs-name">k-md-image</span>></span><span class="hljs-tag"></<span class="hljs-name">k-md-image</span>></span><br> <span class="hljs-tag"><<span class="hljs-name">k-md-table</span>></span><span class="hljs-tag"></<span class="hljs-name">k-md-table</span>></span><br> <span class="hljs-tag"><<span class="hljs-name">k-md-bullet-list</span>></span><span class="hljs-tag"></<span class="hljs-name">k-md-bullet-list</span>></span><br> <span class="hljs-tag"><<span class="hljs-name">k-md-numbered-list</span>></span><span class="hljs-tag"></<span class="hljs-name">k-md-numbered-list</span>></span><br> <span class="hljs-tag"></<span class="hljs-name">div</span>></span><br><span class="hljs-tag"></<span class="hljs-name">k-markdown-editor</span>></span></code></pre>
|
|
535
|
+
</k-card>
|
|
536
|
+
</div>
|
|
537
|
+
<div class="col m-span-12 px">
|
|
538
|
+
<k-card label="Output">
|
|
539
|
+
<k-markdown-editor placeholder="Write a comment...">
|
|
540
|
+
<div slot="controls-top" class="d-f">
|
|
541
|
+
<k-md-menu label="Heading">
|
|
542
|
+
<k-icon slot="trigger" name="text_fields"></k-icon>
|
|
543
|
+
<k-md-format-block tag="h1"></k-md-format-block>
|
|
544
|
+
<k-md-format-block tag="h2"></k-md-format-block>
|
|
545
|
+
<k-md-format-block tag="h3"></k-md-format-block>
|
|
546
|
+
<k-md-format-block tag="h4"></k-md-format-block>
|
|
547
|
+
<k-md-format-block tag="h5"></k-md-format-block>
|
|
548
|
+
<k-md-format-block tag="h6"></k-md-format-block>
|
|
549
|
+
</k-md-menu>
|
|
550
|
+
<k-md-bold></k-md-bold>
|
|
551
|
+
<k-md-italic></k-md-italic>
|
|
552
|
+
<k-md-quote></k-md-quote>
|
|
553
|
+
<k-md-code></k-md-code>
|
|
554
|
+
<k-md-link></k-md-link>
|
|
555
|
+
<k-md-image></k-md-image>
|
|
556
|
+
<k-md-table></k-md-table>
|
|
557
|
+
<k-md-bullet-list></k-md-bullet-list>
|
|
558
|
+
<k-md-numbered-list></k-md-numbered-list>
|
|
559
|
+
</div>
|
|
560
|
+
</k-markdown-editor>
|
|
561
|
+
</k-card>
|
|
562
|
+
</div>
|
|
563
|
+
</div>
|
|
564
|
+
|
|
565
|
+
<h3 id="preConfigured"><a href="#preConfigured" class="no-link">Pre-Configured Controls</a></h3>
|
|
566
|
+
<p>The <code>controls</code> attribute lets you opt into a built-in toolbar without writing any slot markup. Set it directly on <code><k-markdown-editor></code> to one of the three levels below; the matching control modules are imported automatically.</p>
|
|
567
|
+
|
|
568
|
+
<h4>controls="full"</h4>
|
|
569
|
+
<p>Every available control: heading menu (H1–H6), bold, italic, strikethrough, quote, code, link, image (with dialog/dropdown), table builder, bulleted and numbered lists, speech-to-text.</p>
|
|
570
|
+
<div class="row -mx">
|
|
571
|
+
<div class="col m-span-12 px">
|
|
572
|
+
<k-card label="HTML">
|
|
573
|
+
<pre><code class="hljs xml"><span class="hljs-tag"><<span class="hljs-name">k-markdown-editor</span> <span class="hljs-attr">controls</span>=<span class="hljs-string">"full"</span>></span><span class="hljs-tag"></<span class="hljs-name">k-markdown-editor</span>></span></code></pre>
|
|
574
|
+
</k-card>
|
|
575
|
+
</div>
|
|
576
|
+
<div class="col m-span-12 px">
|
|
577
|
+
<k-card label="Output">
|
|
578
|
+
<k-markdown-editor controls="full" placeholder="Type some **markdown**..."></k-markdown-editor>
|
|
579
|
+
</k-card>
|
|
580
|
+
</div>
|
|
581
|
+
</div>
|
|
582
|
+
|
|
583
|
+
<h4>controls="normal"</h4>
|
|
584
|
+
<p>A balanced everyday toolbar: heading menu, bold, italic, quote, code, link, and lists.</p>
|
|
585
|
+
<div class="row -mx">
|
|
586
|
+
<div class="col m-span-12 px">
|
|
587
|
+
<k-card label="HTML">
|
|
588
|
+
<pre><code class="hljs xml"><span class="hljs-tag"><<span class="hljs-name">k-markdown-editor</span> <span class="hljs-attr">controls</span>=<span class="hljs-string">"normal"</span>></span><span class="hljs-tag"></<span class="hljs-name">k-markdown-editor</span>></span></code></pre>
|
|
589
|
+
</k-card>
|
|
590
|
+
</div>
|
|
591
|
+
<div class="col m-span-12 px">
|
|
592
|
+
<k-card label="Output">
|
|
593
|
+
<k-markdown-editor controls="normal" placeholder="Type some **markdown**..."></k-markdown-editor>
|
|
594
|
+
</k-card>
|
|
595
|
+
</div>
|
|
596
|
+
</div>
|
|
597
|
+
|
|
598
|
+
<h4>controls="minimal"</h4>
|
|
599
|
+
<p>Essential controls only: heading menu (H1, H3, H5), bold, italic, and lists. Ideal for simple comment forms.</p>
|
|
600
|
+
<div class="row -mx">
|
|
601
|
+
<div class="col m-span-12 px">
|
|
602
|
+
<k-card label="HTML">
|
|
603
|
+
<pre><code class="hljs xml"><span class="hljs-tag"><<span class="hljs-name">k-markdown-editor</span> <span class="hljs-attr">controls</span>=<span class="hljs-string">"minimal"</span>></span><span class="hljs-tag"></<span class="hljs-name">k-markdown-editor</span>></span></code></pre>
|
|
604
|
+
</k-card>
|
|
605
|
+
</div>
|
|
606
|
+
<div class="col m-span-12 px">
|
|
607
|
+
<k-card label="Output">
|
|
608
|
+
<k-markdown-editor controls="minimal" placeholder="Type some **markdown**..."></k-markdown-editor>
|
|
609
|
+
</k-card>
|
|
610
|
+
</div>
|
|
611
|
+
</div>
|
|
612
|
+
|
|
613
|
+
<p>If you provide your own children with <code>slot="controls-top"</code> (or <code>controls-bottom</code>), they replace the corresponding fallback content from the preset — so you can layer custom controls on top of any level.</p>
|
|
614
|
+
|
|
615
|
+
<h3 id="bottomControls"><a href="#bottomControls" class="no-link">Bottom Controls</a></h3>
|
|
616
|
+
<p>Same pattern for the bottom: wrap your action row in a single <code><div slot="controls-bottom"></code>. The footer is hidden until something is slotted in. Mix the built-in markdown controls with your own action buttons to build a Slack/GitHub-style composer.</p>
|
|
617
|
+
<div class="row -mx">
|
|
618
|
+
<div class="col m-span-12 px">
|
|
619
|
+
<k-card label="HTML">
|
|
620
|
+
<pre><code class="hljs xml"><span class="hljs-tag"><<span class="hljs-name">k-markdown-editor</span> <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Write a comment..."</span>></span><br> <span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">slot</span>=<span class="hljs-string">"controls-top"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"d-f"</span>></span><br> <span class="hljs-tag"><<span class="hljs-name">k-md-bold</span>></span><span class="hljs-tag"></<span class="hljs-name">k-md-bold</span>></span><br> <span class="hljs-tag"><<span class="hljs-name">k-md-italic</span>></span><span class="hljs-tag"></<span class="hljs-name">k-md-italic</span>></span><br> <span class="hljs-tag"><<span class="hljs-name">k-md-link</span>></span><span class="hljs-tag"></<span class="hljs-name">k-md-link</span>></span><br> <span class="hljs-tag"></<span class="hljs-name">div</span>></span><br> <span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">slot</span>=<span class="hljs-string">"controls-bottom"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"d-f"</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"align-items:center; width:100%;"</span>></span><br> <span class="hljs-tag"><<span class="hljs-name">small</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"tc-muted"</span>></span>Markdown supported<span class="hljs-tag"></<span class="hljs-name">small</span>></span><br> <span class="hljs-tag"><<span class="hljs-name">button</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"margin-left:auto"</span>></span>Comment<span class="hljs-tag"></<span class="hljs-name">button</span>></span><br> <span class="hljs-tag"></<span class="hljs-name">div</span>></span><br><span class="hljs-tag"></<span class="hljs-name">k-markdown-editor</span>></span></code></pre>
|
|
621
|
+
</k-card>
|
|
622
|
+
</div>
|
|
623
|
+
<div class="col m-span-12 px">
|
|
624
|
+
<k-card label="Output">
|
|
625
|
+
<k-markdown-editor placeholder="Write a comment...">
|
|
626
|
+
<div slot="controls-top" class="d-f">
|
|
627
|
+
<k-md-bold></k-md-bold>
|
|
628
|
+
<k-md-italic></k-md-italic>
|
|
629
|
+
<k-md-link></k-md-link>
|
|
630
|
+
</div>
|
|
631
|
+
<div slot="controls-bottom" class="d-f" style="align-items:center; width:100%;">
|
|
632
|
+
<small class="tc-muted">Markdown supported</small>
|
|
633
|
+
<button style="margin-left:auto">Comment</button>
|
|
634
|
+
</div>
|
|
635
|
+
</k-markdown-editor>
|
|
636
|
+
</k-card>
|
|
637
|
+
</div>
|
|
638
|
+
</div>
|
|
639
|
+
|
|
640
|
+
<h3 id="defaultValue"><a href="#defaultValue" class="no-link">Default Value</a></h3>
|
|
641
|
+
<p>Set initial markdown via the <code>value</code> attribute. Children are reserved for slotted controls (and their own content like icons or labels), so they are <strong>not</strong> read as the editor's value — otherwise icon labels, separators, etc. would leak into what the user sees.</p>
|
|
642
|
+
<div class="row -mx">
|
|
643
|
+
<div class="col m-span-12 px">
|
|
644
|
+
<k-card label="HTML">
|
|
645
|
+
<pre><code class="hljs xml"><span class="hljs-tag"><<span class="hljs-name">k-markdown-editor</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"# Hello&#10;&#10;Seeded from the value attribute. Try the Preview tab."</span>></span><span class="hljs-tag"></<span class="hljs-name">k-markdown-editor</span>></span></code></pre>
|
|
646
|
+
</k-card>
|
|
647
|
+
</div>
|
|
648
|
+
<div class="col m-span-12 px">
|
|
649
|
+
<k-card label="Output">
|
|
650
|
+
<k-markdown-editor value="# Hello Seeded from the value attribute. Try the Preview tab."></k-markdown-editor>
|
|
651
|
+
</k-card>
|
|
652
|
+
</div>
|
|
653
|
+
</div>
|
|
654
|
+
|
|
655
|
+
<h3 id="formUsage"><a href="#formUsage" class="no-link">Form Usage</a></h3>
|
|
656
|
+
<p>The component is form-associated. Set a <code>name</code> and the raw markdown is included in the form's <code>FormData</code>. <code>required</code> participates in the browser's standard validation when the editor is empty.</p>
|
|
657
|
+
<div class="row -mx">
|
|
658
|
+
<div class="col m-span-12 px">
|
|
659
|
+
<k-card label="HTML">
|
|
660
|
+
<pre><code class="hljs xml"><span class="hljs-tag"><<span class="hljs-name">form</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"mdForm"</span>></span><br> <span class="hljs-tag"><<span class="hljs-name">label</span>></span>Comment:<span class="hljs-tag"></<span class="hljs-name">label</span>></span><br> <span class="hljs-tag"><<span class="hljs-name">k-markdown-editor</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"comment"</span> <span class="hljs-attr">required</span> <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Markdown supported"</span>></span><br> <span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">slot</span>=<span class="hljs-string">"controls-top"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"d-f"</span>></span><br> <span class="hljs-tag"><<span class="hljs-name">k-md-bold</span>></span><span class="hljs-tag"></<span class="hljs-name">k-md-bold</span>></span><br> <span class="hljs-tag"><<span class="hljs-name">k-md-italic</span>></span><span class="hljs-tag"></<span class="hljs-name">k-md-italic</span>></span><br> <span class="hljs-tag"></<span class="hljs-name">div</span>></span><br> <span class="hljs-tag"></<span class="hljs-name">k-markdown-editor</span>></span><br> <span class="hljs-tag"><<span class="hljs-name">button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span>></span>Submit<span class="hljs-tag"></<span class="hljs-name">button</span>></span><br><span class="hljs-tag"></<span class="hljs-name">form</span>></span></code></pre>
|
|
661
|
+
</k-card>
|
|
662
|
+
</div>
|
|
663
|
+
<div class="col m-span-12 px">
|
|
664
|
+
<k-card label="Output">
|
|
665
|
+
<form id="mdForm">
|
|
666
|
+
<label class="d-b mb">Comment:</label>
|
|
667
|
+
<k-markdown-editor name="comment" required placeholder="Markdown supported">
|
|
668
|
+
<div slot="controls-top" class="d-f">
|
|
669
|
+
<k-md-bold></k-md-bold>
|
|
670
|
+
<k-md-italic></k-md-italic>
|
|
671
|
+
</div>
|
|
672
|
+
</k-markdown-editor>
|
|
673
|
+
<div class="mt">
|
|
674
|
+
<button type="submit">Submit</button>
|
|
675
|
+
</div>
|
|
676
|
+
</form>
|
|
677
|
+
<p class="mt">Form data: <span id="mdOut">(submit to see)</span></p>
|
|
678
|
+
<script type="module">
|
|
679
|
+
document.getElementById('mdForm').addEventListener('submit', (e) => {
|
|
680
|
+
e.preventDefault();
|
|
681
|
+
const fd = new FormData(e.target);
|
|
682
|
+
document.getElementById('mdOut').textContent = JSON.stringify([...fd.entries()]);
|
|
683
|
+
});
|
|
684
|
+
</script>
|
|
685
|
+
</k-card>
|
|
686
|
+
</div>
|
|
687
|
+
</div>
|
|
688
|
+
|
|
689
|
+
<h3 id="disabled"><a href="#disabled" class="no-link">Disabled / Read-only</a></h3>
|
|
690
|
+
<p>The <code>disabled</code> attribute prevents user interaction (including switching tabs) and excludes the field from form submission. The <code>readonly</code> attribute keeps the editor visible and lets the user switch to Preview, but the textarea cannot be edited; the value is still submitted with the form.</p>
|
|
691
|
+
<div class="row -mx">
|
|
692
|
+
<div class="col m-span-12 px">
|
|
693
|
+
<k-card label="Output">
|
|
694
|
+
<k-markdown-editor disabled value="This is **disabled**." class="mb"></k-markdown-editor>
|
|
695
|
+
<k-markdown-editor readonly value="This is _read-only_ — check the Preview tab."></k-markdown-editor>
|
|
696
|
+
</k-card>
|
|
697
|
+
</div>
|
|
698
|
+
</div>
|
|
699
|
+
|
|
700
|
+
<h3 id="tagFiltering"><a href="#tagFiltering" class="no-link">Tag Filtering</a></h3>
|
|
701
|
+
<p>Inline HTML the user (or a custom control) types is filtered by either an allowlist or a denylist. The two attributes are mutually exclusive — if both are set, <code>allowed-tags</code> wins and a console warning fires.</p>
|
|
702
|
+
|
|
703
|
+
<h4>allowed-tags</h4>
|
|
704
|
+
<p>Permits only the tags you list. Anything else is unwrapped (its text survives, the wrapper is dropped). Type the markdown below and flip to Preview — only <code>strong</code>, <code>em</code>, <code>p</code>, and <code>br</code> get through; the <code><img></code>, <code><table></code>, and <code><script></code> are scrubbed out.</p>
|
|
705
|
+
<div class="row -mx">
|
|
706
|
+
<div class="col m-span-12 px">
|
|
707
|
+
<k-card label="HTML">
|
|
708
|
+
<pre><code class="hljs xml"><span class="hljs-tag"><<span class="hljs-name">k-markdown-editor</span> <span class="hljs-attr">allowed-tags</span>=<span class="hljs-string">"strong,em,p,br"</span>></span><span class="hljs-tag"></<span class="hljs-name">k-markdown-editor</span>></span></code></pre>
|
|
709
|
+
</k-card>
|
|
710
|
+
</div>
|
|
711
|
+
<div class="col m-span-12 px">
|
|
712
|
+
<k-card label="Output">
|
|
713
|
+
<k-markdown-editor
|
|
714
|
+
allowed-tags="strong,em,p,br"
|
|
715
|
+
value="**Bold** and _italic_ pass through. An image is stripped:  A table is stripped: | a | b | | --- | --- | | 1 | 2 | A <script>alert('xss')</script> is always nuked."
|
|
716
|
+
></k-markdown-editor>
|
|
717
|
+
</k-card>
|
|
718
|
+
</div>
|
|
719
|
+
</div>
|
|
720
|
+
|
|
721
|
+
<h4>disallowed-tags</h4>
|
|
722
|
+
<p>Allows everything <em>except</em> the tags you list — useful when you only want to ban a couple of things rather than enumerate the whole set. Below, images are blocked but everything else (tables, code, etc.) renders normally.</p>
|
|
723
|
+
<div class="row -mx">
|
|
724
|
+
<div class="col m-span-12 px">
|
|
725
|
+
<k-card label="HTML">
|
|
726
|
+
<pre><code class="hljs xml"><span class="hljs-tag"><<span class="hljs-name">k-markdown-editor</span> <span class="hljs-attr">disallowed-tags</span>=<span class="hljs-string">"img"</span>></span><span class="hljs-tag"></<span class="hljs-name">k-markdown-editor</span>></span></code></pre>
|
|
727
|
+
</k-card>
|
|
728
|
+
</div>
|
|
729
|
+
<div class="col m-span-12 px">
|
|
730
|
+
<k-card label="Output">
|
|
731
|
+
<k-markdown-editor
|
|
732
|
+
disallowed-tags="img"
|
|
733
|
+
value="Tables still work: | a | b | | --- | --- | | 1 | 2 | Images do not: "
|
|
734
|
+
></k-markdown-editor>
|
|
735
|
+
</k-card>
|
|
736
|
+
</div>
|
|
737
|
+
</div>
|
|
738
|
+
|
|
739
|
+
<h3 id="customControls"><a href="#customControls" class="no-link">Custom Controls</a></h3>
|
|
740
|
+
<p>To write your own toolbar button, extend <code>MarkdownEditorControl</code>. Override <code>command()</code> and use the helpers (<code>wrapSelection</code>, <code>insertLinePrefix</code>, <code>replaceSelection</code>, <code>insertAtCursor</code>) to manipulate the textarea. The base class hides the control automatically when the editor flips to Preview mode.</p>
|
|
741
|
+
<p>Below is a tiny control that drops a horizontal rule (<code>---</code> on its own line) at the cursor — not common enough to ship as a built-in, but a clean example of using <code>insertAtCursor</code>.</p>
|
|
742
|
+
<k-card label="JavaScript">
|
|
743
|
+
<pre><code class="hljs javascript"><span class="hljs-keyword">import</span> <span class="hljs-title class_">MarkdownEditorControl</span> <span class="hljs-keyword">from</span> <span class="hljs-string">'./markdownEditorControls/MarkdownEditorControl.js'</span>;
|
|
744
|
+
<span class="hljs-keyword">import</span> { html } <span class="hljs-keyword">from</span> <span class="hljs-string">'./lit-all.min.js'</span>;
|
|
745
|
+
|
|
746
|
+
<span class="hljs-comment">// Inserts a horizontal rule (`---`) on its own line at the cursor.</span>
|
|
747
|
+
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">MarkdownHr</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_ inherited__">MarkdownEditorControl</span> {
|
|
748
|
+
<span class="hljs-title function_">constructor</span>(<span class="hljs-params"></span>) {
|
|
749
|
+
<span class="hljs-variable language_">super</span>();
|
|
750
|
+
<span class="hljs-variable language_">this</span>.<span class="hljs-property">label</span> = <span class="hljs-string">'Horizontal rule'</span>;
|
|
751
|
+
}
|
|
752
|
+
<span class="hljs-title function_">command</span>(<span class="hljs-params"></span>) {
|
|
753
|
+
<span class="hljs-variable language_">this</span>.<span class="hljs-title function_">insertAtCursor</span>(<span class="hljs-string">'\n\n---\n\n'</span>);
|
|
754
|
+
}
|
|
755
|
+
<span class="hljs-title function_">render</span>(<span class="hljs-params"></span>) {
|
|
756
|
+
<span class="hljs-keyword">return</span> html<span class="hljs-string">`
|
|
757
|
+
<button type="button" class=<span class="hljs-subst">${<span class="hljs-variable language_">this</span>.<span class="hljs-property">btnClass</span>}</span> @click=<span class="hljs-subst">${<span class="hljs-variable language_">this</span>.<span class="hljs-property">handleClick</span>}</span>>—</button>
|
|
758
|
+
`</span>;
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
customElements.<span class="hljs-title function_">define</span>(<span class="hljs-string">'k-md-hr'</span>, <span class="hljs-title class_">MarkdownHr</span>);</code></pre>
|
|
762
|
+
</k-card>
|
|
763
|
+
|
|
764
|
+
<h2 id="jsRef"><a href="#jsRef" class="no-link">JavaScript Reference</a></h2>
|
|
765
|
+
|
|
766
|
+
<h3 id="constructor"><a href="#constructor" class="no-link">Constructor</a></h3>
|
|
767
|
+
<h6>Extends <a href="./shadow-component.html">ShadowComponent</a></h6>
|
|
768
|
+
<h5><code>new MarkdownEditor()</code></h5>
|
|
769
|
+
|
|
770
|
+
<h3 id="requirements"><a href="#requirements" class="no-link">Requirements</a></h3>
|
|
771
|
+
<ul>
|
|
772
|
+
<li><a href="./shadow-component.html">ShadowComponent</a></li>
|
|
773
|
+
<li><code>src/utils/renderMarkdown.js</code> (thin wrapper around marked)</li>
|
|
774
|
+
<li><code>src/utils/marked.esm.js</code> (vendored marked, ~42KB)</li>
|
|
775
|
+
<li><a href="../utils/sanitizeHtml.html"><code>sanitizeHtml</code></a> utility</li>
|
|
776
|
+
</ul>
|
|
777
|
+
|
|
778
|
+
<h3 id="properties"><a href="#properties" class="no-link">Properties</a></h3>
|
|
779
|
+
<h5><code>value<i>: String</i></code></h5>
|
|
780
|
+
<p>The current markdown source. Reading returns whatever the user has typed; writing replaces the editor content. Initial value comes from the <code>value</code> attribute. (Children are reserved for slotted controls and are <em>not</em> read as the editor value — otherwise control content like icons / labels would leak in.)</p>
|
|
781
|
+
|
|
782
|
+
<h5><code>name<i>: String</i></code></h5>
|
|
783
|
+
<p>The form field name. When set inside a <code><form></code>, the component participates in form submission. The submitted value is the raw markdown string. Syncs to <code>name</code> attribute.</p>
|
|
784
|
+
|
|
785
|
+
<h5><code>placeholder<i>: String</i></code></h5>
|
|
786
|
+
<p>Placeholder text shown in the textarea when the editor is empty. Syncs to <code>placeholder</code> attribute.</p>
|
|
787
|
+
|
|
788
|
+
<h5><code>disabled<i>: Boolean</i></code></h5>
|
|
789
|
+
<p>When <code>true</code>, the editor is non-interactive (textarea is disabled, mode tabs are disabled) and excluded from form submission. Syncs to <code>disabled</code> attribute.</p>
|
|
790
|
+
|
|
791
|
+
<h5><code>required<i>: Boolean</i></code></h5>
|
|
792
|
+
<p>When <code>true</code> and the editor is empty, the element reports a <code>valueMissing</code> validity error. Syncs to <code>required</code> attribute.</p>
|
|
793
|
+
|
|
794
|
+
<h5><code>readonly<i>: Boolean</i></code></h5>
|
|
795
|
+
<p>When <code>true</code>, the user can switch to Preview but cannot edit the textarea. Form submission still includes the value. Syncs to <code>readonly</code> attribute.</p>
|
|
796
|
+
|
|
797
|
+
<h5><code>mode<i>: String</i></code></h5>
|
|
798
|
+
<p>Either <code>'write'</code> (default) or <code>'preview'</code>. Syncs to <code>mode</code> attribute.</p>
|
|
799
|
+
|
|
800
|
+
<h5><code>allowedTags<i>: String</i></code></h5>
|
|
801
|
+
<p>Comma-separated <em>allowlist</em> for the rendered preview. Tags outside the list are unwrapped (their text survives, the wrapper is dropped). Pass <code>"*"</code> to allow every tag. Empty / unset uses sanitizeHtml's default (headings, paragraphs, lists, links, code, images, tables, etc.). Mutually exclusive with <code>disallowed-tags</code> — setting both warns and <code>allowed-tags</code> wins. Syncs to <code>allowed-tags</code> attribute.</p>
|
|
802
|
+
|
|
803
|
+
<h5><code>disallowedTags<i>: String</i></code></h5>
|
|
804
|
+
<p>Comma-separated <em>denylist</em>. Allows everything except the listed tags — useful when you want to block a couple of tags rather than enumerate the whole allowed set. Mutually exclusive with <code>allowed-tags</code>. Syncs to <code>disallowed-tags</code> attribute.</p>
|
|
805
|
+
|
|
806
|
+
<h5><code>scriptsEnabled<i>: Boolean</i></code></h5>
|
|
807
|
+
<p>When this attribute is present, <code><script></code> tags survive sanitization (provided they also pass the allow/deny check). When absent (the default), <code><script></code> — including its content — is always stripped to prevent XSS, regardless of any other configuration. Other dangerous tags (<code><iframe></code>, <code><style></code>, etc.) are always stripped. Only enable this for trusted input. Syncs to <code>scripts-enabled</code> attribute.</p>
|
|
808
|
+
|
|
809
|
+
<h5><code>controls<i>: String</i></code></h5>
|
|
810
|
+
<p>Activates a built-in toolbar. Accepted values:</p>
|
|
811
|
+
<ul>
|
|
812
|
+
<li><code>'none'</code> / <code>''</code> (default) — no built-in toolbar; use named slots to build your own.</li>
|
|
813
|
+
<li><code>'minimal'</code> — heading menu (H1, H3, H5), bold, italic, link, bulleted list, numbered list.</li>
|
|
814
|
+
<li><code>'normal'</code> — full heading menu (H1–H6), bold, italic, quote, code, link, lists.</li>
|
|
815
|
+
<li><code>'full'</code> — everything from <code>normal</code> plus strikethrough, image, table builder, and speech-to-text.</li>
|
|
816
|
+
</ul>
|
|
817
|
+
<p>The chosen set renders as fallback content inside the <code>controls-top</code> slot. Providing your own slot content replaces it. Setting a non-empty value also dynamically imports every built-in control module so consumers don't have to remember which imports each preset needs.</p>
|
|
818
|
+
|
|
819
|
+
<h5><code>renderedHtml<i>: String</i></code> (getter)</h5>
|
|
820
|
+
<p>The current value rendered to HTML by <code>renderMarkdown</code> (marked, with GFM enabled) and then run through <code>sanitizeHtml</code> using <code>allowedTags</code>.</p>
|
|
821
|
+
|
|
822
|
+
<h5><code>isEmpty<i>: Boolean</i></code> (getter)</h5>
|
|
823
|
+
<p><code>true</code> when <code>value.trim()</code> is empty.</p>
|
|
824
|
+
|
|
825
|
+
<h3 id="methods"><a href="#methods" class="no-link">Methods</a></h3>
|
|
826
|
+
<h5><code>focus()<i>: void</i></code></h5>
|
|
827
|
+
<p>Switches to write mode (if necessary) and focuses the textarea.</p>
|
|
828
|
+
|
|
829
|
+
<h5><code>blur()<i>: void</i></code></h5>
|
|
830
|
+
<p>Removes focus from the textarea.</p>
|
|
831
|
+
|
|
832
|
+
<h5><code>clear()<i>: void</i></code></h5>
|
|
833
|
+
<p>Empties the editor (equivalent to <code>el.value = ''</code>).</p>
|
|
834
|
+
|
|
835
|
+
<h5><code>setMode(mode)<i>: void</i></code></h5>
|
|
836
|
+
<p>Sets the mode to <code>'write'</code> or <code>'preview'</code>. Other values are ignored.</p>
|
|
837
|
+
|
|
838
|
+
<h5><code>togglePreview()<i>: void</i></code></h5>
|
|
839
|
+
<p>Flips between <code>'write'</code> and <code>'preview'</code>.</p>
|
|
840
|
+
|
|
841
|
+
<h5><code>getSelection()<i>: { start, end, text }</i></code></h5>
|
|
842
|
+
<p>Returns the current textarea selection. Used by control subclasses; in preview mode returns a zero-length selection at index 0.</p>
|
|
843
|
+
|
|
844
|
+
<h5><code>replaceSelection(text, options)<i>: void</i></code></h5>
|
|
845
|
+
<p>Replaces the current selection with <code>text</code>. <code>options.selectInserted</code> (default <code>true</code>) controls whether the inserted text ends up selected or whether the cursor moves to the end of it.</p>
|
|
846
|
+
|
|
847
|
+
<h5><code>wrapSelection(prefix, suffix, placeholder)<i>: void</i></code></h5>
|
|
848
|
+
<p>Wraps the current selection with <code>prefix</code>/<code>suffix</code>. If nothing is selected, inserts <code>placeholder</code> between them and selects it so the user can immediately overtype. <code>suffix</code> defaults to <code>prefix</code>.</p>
|
|
849
|
+
|
|
850
|
+
<h5><code>insertAtCursor(text)<i>: void</i></code></h5>
|
|
851
|
+
<p>Inserts <code>text</code> at the cursor position; selection is collapsed to the end of the inserted text.</p>
|
|
852
|
+
|
|
853
|
+
<h5><code>insertLinePrefix(prefix)<i>: void</i></code></h5>
|
|
854
|
+
<p>Prefixes every selected line (or the current line if no selection) with <code>prefix</code>. Used for headings, blockquotes, list items, etc.</p>
|
|
855
|
+
|
|
856
|
+
<h3 id="cssVariables"><a href="#cssVariables" class="no-link">CSS Variables</a></h3>
|
|
857
|
+
<table class="b">
|
|
858
|
+
<thead><tr><th>Variable</th><th>Default</th><th>Description</th></tr></thead>
|
|
859
|
+
<tbody>
|
|
860
|
+
<tr><td><code>--min_height</code></td><td><code>6rem</code></td><td>Minimum height of the textarea / preview area</td></tr>
|
|
861
|
+
<tr><td><code>--max_height</code></td><td><code>24rem</code></td><td>Maximum height before the editor scrolls internally</td></tr>
|
|
862
|
+
<tr><td><code>--padding</code></td><td><code>0.5rem 0.75rem</code></td><td>Padding inside the textarea / preview</td></tr>
|
|
863
|
+
<tr><td><code>--border</code></td><td><code>1px solid var(--c_border)</code></td><td>Border around the editor</td></tr>
|
|
864
|
+
</tbody>
|
|
865
|
+
</table>
|
|
866
|
+
<p class="mt">The component also uses kempo-css's global <code>--c_border</code>, <code>--c_bg</code>, <code>--tc</code>, <code>--tc_muted</code>, <code>--radius</code>, <code>--animation_ms</code>, and <code>--focus_shadow</code>; override those globally for site-wide tuning.</p>
|
|
867
|
+
|
|
868
|
+
<h3 id="events"><a href="#events" class="no-link">Events</a></h3>
|
|
869
|
+
<h5><code>input</code></h5>
|
|
870
|
+
<p>Fires on every keystroke (or programmatic change via the selection-manipulation API). <code>detail.value</code> is the current markdown.</p>
|
|
871
|
+
|
|
872
|
+
<h5><code>change</code></h5>
|
|
873
|
+
<p>Fires when the textarea blurs. <code>detail.value</code> is the markdown at the moment focus left.</p>
|
|
874
|
+
|
|
875
|
+
<h5><code>mode-change</code></h5>
|
|
876
|
+
<p>Fires when the user switches between Write and Preview tabs. <code>detail.mode</code> is the new mode.</p>
|
|
877
|
+
|
|
878
|
+
<h3 id="controls"><a href="#controls" class="no-link">Built-in Controls</a></h3>
|
|
879
|
+
<p>Each control is a separate custom element under <code>src/components/markdownEditorControls/</code>. Import the ones you want and slot them into <code>controls-top</code> or <code>controls-bottom</code>.</p>
|
|
880
|
+
<table class="b">
|
|
881
|
+
<thead><tr><th>Tag</th><th>File</th><th>Inserts</th></tr></thead>
|
|
882
|
+
<tbody>
|
|
883
|
+
<tr><td><code><k-md-bold></code></td><td><code>Bold.js</code></td><td><code>**bold**</code></td></tr>
|
|
884
|
+
<tr><td><code><k-md-italic></code></td><td><code>Italic.js</code></td><td><code>_italic_</code></td></tr>
|
|
885
|
+
<tr><td><code><k-md-strikethrough></code></td><td><code>Strikethrough.js</code></td><td><code>~~strike~~</code> — GFM strikethrough; renders to <code><del></code>.</td></tr>
|
|
886
|
+
<tr><td><code><k-md-heading></code></td><td><code>Heading.js</code></td><td><code>## </code> on the current line; <code>level</code> attribute (1–6) selects heading depth</td></tr>
|
|
887
|
+
<tr><td><code><k-md-code></code></td><td><code>Code.js</code></td><td>Inline backticks for a single line, fenced <code>```</code> blocks for multi-line selections</td></tr>
|
|
888
|
+
<tr><td><code><k-md-link></code></td><td><code>Link.js</code></td><td><code>[text](url)</code> with the URL portion pre-selected</td></tr>
|
|
889
|
+
<tr><td><code><k-md-image></code></td><td><code>Image.js</code></td><td>Opens a popover (URL + alt text) and inserts <code></code> at the cursor. The popover type is configurable via <code>popup="dropdown"</code> (default, anchored next to the button) or <code>popup="dialog"</code> (modal Dialog).</td></tr>
|
|
890
|
+
<tr><td><code><k-md-table></code></td><td><code>Table.js</code></td><td>Opens a small dropdown with <em>cols × rows</em> inputs and a Create button. Inserts a GFM markdown table (with <code>Header 1</code>, <code>Header 2</code>… placeholders and empty body cells) at the cursor.</td></tr>
|
|
891
|
+
<tr><td><code><k-md-menu></code></td><td><code>Menu.js</code></td><td>Renders a single toolbar button that opens a Dropdown containing whatever child controls you slot into the default slot. The trigger button content is fully customizable via the <code>trigger</code> slot (defaults to a <code>menu</code> icon); <code>label</code> sets the accessible name.</td></tr>
|
|
892
|
+
<tr><td><code><k-md-format-block></code></td><td><code>FormatBlock.js</code></td><td>Heading-block picker designed to go inside a <code><k-md-menu></code>. <code>tag="h1"</code>…<code>"h6"</code> sets the heading level on the current line(s), swapping out any existing heading.</td></tr>
|
|
893
|
+
<tr><td><code><k-md-speech-to-text></code></td><td><code>SpeechToText.js</code></td><td>Reuses the standalone <a href="./speech-to-text.html"><code><k-speech-to-text></code></a> component — click the mic to start recording, click again to stop. The final transcript is inserted at the cursor when the user finishes speaking. Forwards <code>language</code> and <code>continuous</code> attributes through.</td></tr>
|
|
894
|
+
<tr><td><code><k-md-bullet-list></code></td><td><code>BulletList.js</code></td><td><code>- </code> prefix on each selected line</td></tr>
|
|
895
|
+
<tr><td><code><k-md-numbered-list></code></td><td><code>NumberedList.js</code></td><td><code>1. </code>, <code>2. </code>, … numbering each non-empty selected line</td></tr>
|
|
896
|
+
<tr><td><code><k-md-quote></code></td><td><code>Quote.js</code></td><td><code>> </code> prefix on each selected line</td></tr>
|
|
897
|
+
</tbody>
|
|
898
|
+
</table>
|
|
899
|
+
<p class="mt">All controls extend <code>MarkdownEditorControl</code> — see <a href="#customControls">Custom Controls</a> to write your own.</p>
|
|
900
|
+
|
|
901
|
+
</k-main>
|
|
902
|
+
<div style="height:33vh"></div>
|
|
903
|
+
<script type="module" src="../src/components/Main.js"></script>
|
|
904
|
+
|
|
905
|
+
<script type="module" src="../src/components/MarkdownEditor.js"></script>
|
|
906
|
+
<script type="module" src="../src/components/markdownEditorControls/Bold.js"></script>
|
|
907
|
+
<script type="module" src="../src/components/markdownEditorControls/Italic.js"></script>
|
|
908
|
+
<script type="module" src="../src/components/markdownEditorControls/Strikethrough.js"></script>
|
|
909
|
+
<script type="module" src="../src/components/markdownEditorControls/SpeechToText.js"></script>
|
|
910
|
+
<script type="module" src="../src/components/markdownEditorControls/Heading.js"></script>
|
|
911
|
+
<script type="module" src="../src/components/markdownEditorControls/Code.js"></script>
|
|
912
|
+
<script type="module" src="../src/components/markdownEditorControls/Link.js"></script>
|
|
913
|
+
<script type="module" src="../src/components/markdownEditorControls/Image.js"></script>
|
|
914
|
+
<script type="module" src="../src/components/markdownEditorControls/Table.js"></script>
|
|
915
|
+
<script type="module" src="../src/components/markdownEditorControls/Menu.js"></script>
|
|
916
|
+
<script type="module" src="../src/components/markdownEditorControls/FormatBlock.js"></script>
|
|
917
|
+
<script type="module" src="../src/components/markdownEditorControls/BulletList.js"></script>
|
|
918
|
+
<script type="module" src="../src/components/markdownEditorControls/NumberedList.js"></script>
|
|
919
|
+
<script type="module" src="../src/components/markdownEditorControls/Quote.js"></script>
|
|
920
|
+
<script type="module" src="../src/components/Accordion.js"></script>
|
|
921
|
+
<script type="module" src="../src/components/Card.js"></script>
|
|
922
|
+
|
|
923
|
+
</body>
|
|
924
|
+
</html>
|