@record-evolution/widget-markdown 1.0.4 → 1.0.5
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/widget-markdown.js +410 -390
- package/dist/widget-markdown.js.map +1 -1
- package/package.json +5 -1
- package/src/definition-schema.d.ts +9 -3
- package/src/definition-schema.json +5 -3
- package/src/widget-markdown.ts +46 -24
package/package.json
CHANGED
|
@@ -3,7 +3,11 @@
|
|
|
3
3
|
"description": "Webcomponent widget-markdown following open-wc recommendations",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"author": "widget-markdown",
|
|
6
|
-
"version": "1.0.
|
|
6
|
+
"version": "1.0.5",
|
|
7
|
+
"engines": {
|
|
8
|
+
"node": ">=24.9.0",
|
|
9
|
+
"npm": ">=10.0.2"
|
|
10
|
+
},
|
|
7
11
|
"type": "module",
|
|
8
12
|
"main": "dist/widget-markdown.js",
|
|
9
13
|
"types": "dist/src/widget-markdown.d.ts",
|
|
@@ -6,15 +6,15 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
|
-
*
|
|
9
|
+
* The variable name used in the markdown text. Reference this in your markdown using the {{label}} syntax. Use descriptive names like 'temperature', 'status', 'deviceName'.
|
|
10
10
|
*/
|
|
11
11
|
export type Label = string;
|
|
12
12
|
/**
|
|
13
|
-
*
|
|
13
|
+
* The replacement text that will appear in place of {{label}} in the rendered output. Can be a static value or bound to a data column for dynamic updates.
|
|
14
14
|
*/
|
|
15
15
|
export type Value = string;
|
|
16
16
|
/**
|
|
17
|
-
*
|
|
17
|
+
* Array of variable definitions for dynamic text substitution. Each variable has a label (used in the markdown as {{label}}) and a value (the replacement text). Values can be static or bound to data columns for real-time updates.
|
|
18
18
|
*/
|
|
19
19
|
export type Variables = {
|
|
20
20
|
label?: Label;
|
|
@@ -22,11 +22,17 @@ export type Variables = {
|
|
|
22
22
|
[k: string]: unknown;
|
|
23
23
|
}[];
|
|
24
24
|
|
|
25
|
+
/**
|
|
26
|
+
* A markdown rendering widget for displaying formatted text with dynamic variable substitution. Use this widget for documentation, instructions, dynamic reports, or any rich text content on dashboards. Supports full Markdown syntax including headers, lists, tables, links, and code blocks. Variables can be embedded using {{variableName}} notation and bound to data sources for real-time updates. Ideal for creating contextual help, status summaries, or narrative text that incorporates live data values.
|
|
27
|
+
*/
|
|
25
28
|
export interface InputData {
|
|
26
29
|
markdown?: Markdown;
|
|
27
30
|
data?: Variables;
|
|
28
31
|
[k: string]: unknown;
|
|
29
32
|
}
|
|
33
|
+
/**
|
|
34
|
+
* The markdown-formatted text content to display. Supports all standard Markdown syntax: headers (#), bold (**text**), italic (*text*), lists (- item), links ([text](url)), code blocks (```), tables, and more. Use {{variableName}} to insert dynamic variables.
|
|
35
|
+
*/
|
|
30
36
|
export interface Markdown {
|
|
31
37
|
[k: string]: unknown;
|
|
32
38
|
}
|
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"title": "InputData",
|
|
3
|
+
"description": "A markdown rendering widget for displaying formatted text with dynamic variable substitution. Use this widget for documentation, instructions, dynamic reports, or any rich text content on dashboards. Supports full Markdown syntax including headers, lists, tables, links, and code blocks. Variables can be embedded using {{variableName}} notation and bound to data sources for real-time updates. Ideal for creating contextual help, status summaries, or narrative text that incorporates live data values.",
|
|
3
4
|
"type": "object",
|
|
4
5
|
"properties": {
|
|
5
6
|
"markdown": {
|
|
6
7
|
"title": "Markdown",
|
|
8
|
+
"description": "The markdown-formatted text content to display. Supports all standard Markdown syntax: headers (#), bold (**text**), italic (*text*), lists (- item), links ([text](url)), code blocks (```), tables, and more. Use {{variableName}} to insert dynamic variables.",
|
|
7
9
|
"order": 1,
|
|
8
10
|
"type": "textarea"
|
|
9
11
|
},
|
|
10
12
|
"data": {
|
|
11
13
|
"title": "Variables",
|
|
12
|
-
"description": "
|
|
14
|
+
"description": "Array of variable definitions for dynamic text substitution. Each variable has a label (used in the markdown as {{label}}) and a value (the replacement text). Values can be static or bound to data columns for real-time updates.",
|
|
13
15
|
"type": "array",
|
|
14
16
|
"order": 2,
|
|
15
17
|
"items": {
|
|
@@ -17,13 +19,13 @@
|
|
|
17
19
|
"properties": {
|
|
18
20
|
"label": {
|
|
19
21
|
"title": "Label",
|
|
20
|
-
"description": "
|
|
22
|
+
"description": "The variable name used in the markdown text. Reference this in your markdown using the {{label}} syntax. Use descriptive names like 'temperature', 'status', 'deviceName'.",
|
|
21
23
|
"type": "string",
|
|
22
24
|
"order": 1
|
|
23
25
|
},
|
|
24
26
|
"value": {
|
|
25
27
|
"title": "Value",
|
|
26
|
-
"description": "
|
|
28
|
+
"description": "The replacement text that will appear in place of {{label}} in the rendered output. Can be a static value or bound to a data column for dynamic updates.",
|
|
27
29
|
"type": "string",
|
|
28
30
|
"order": 2
|
|
29
31
|
}
|
package/src/widget-markdown.ts
CHANGED
|
@@ -45,6 +45,8 @@ export class WidgetMarkdown extends LitElement {
|
|
|
45
45
|
@state() private themeBgColor?: string
|
|
46
46
|
@state() private themeTitleColor?: string
|
|
47
47
|
@state() private themeSubtitleColor?: string
|
|
48
|
+
@state() private cachedHtmlTemplate?: string
|
|
49
|
+
@state() private lastMarkdown?: string
|
|
48
50
|
|
|
49
51
|
version: string = 'versionplaceholder'
|
|
50
52
|
marked: Marked
|
|
@@ -92,33 +94,47 @@ export class WidgetMarkdown extends LitElement {
|
|
|
92
94
|
}
|
|
93
95
|
|
|
94
96
|
/**
|
|
95
|
-
*
|
|
96
|
-
*
|
|
97
|
+
* Converts {{variableName}} to spans with data attributes for efficient updating.
|
|
98
|
+
* Markdown is parsed once, then only variable spans are updated.
|
|
97
99
|
*/
|
|
98
|
-
|
|
99
|
-
if (!this.inputData) return text
|
|
100
|
-
|
|
100
|
+
convertVariablesToSpans(text: string): string {
|
|
101
101
|
return text.replace(/\{\{([^}]+)\}\}/g, (match, varName) => {
|
|
102
102
|
const key = varName.trim()
|
|
103
|
-
|
|
104
|
-
const value = dataItem?.value
|
|
105
|
-
|
|
106
|
-
// If variable doesn't exist, return the original placeholder
|
|
107
|
-
if (value === null || value === undefined) {
|
|
108
|
-
return match
|
|
109
|
-
} else if (typeof value === 'object') {
|
|
110
|
-
// For objects/arrays, return JSON representation
|
|
111
|
-
try {
|
|
112
|
-
return JSON.stringify(value)
|
|
113
|
-
} catch {
|
|
114
|
-
return match
|
|
115
|
-
}
|
|
116
|
-
} else {
|
|
117
|
-
return String(value)
|
|
118
|
-
}
|
|
103
|
+
return `<span class="md-var" data-var="${key}"></span>`
|
|
119
104
|
})
|
|
120
105
|
}
|
|
121
106
|
|
|
107
|
+
/**
|
|
108
|
+
* Updates variable spans in the rendered DOM without recreating the entire structure.
|
|
109
|
+
*/
|
|
110
|
+
protected updated(changedProperties: PropertyValues): void {
|
|
111
|
+
super.updated(changedProperties)
|
|
112
|
+
|
|
113
|
+
if (changedProperties.has('inputData')) {
|
|
114
|
+
// Update only the variable spans
|
|
115
|
+
const varSpans = this.shadowRoot?.querySelectorAll('.md-var')
|
|
116
|
+
varSpans?.forEach((span) => {
|
|
117
|
+
const varName = span.getAttribute('data-var')
|
|
118
|
+
if (varName) {
|
|
119
|
+
const dataItem = this.inputData?.data?.find((item) => item.label === varName)
|
|
120
|
+
const value = dataItem?.value
|
|
121
|
+
|
|
122
|
+
if (value === null || value === undefined) {
|
|
123
|
+
span.textContent = `{{${varName}}}`
|
|
124
|
+
} else if (typeof value === 'object') {
|
|
125
|
+
try {
|
|
126
|
+
span.textContent = JSON.stringify(value)
|
|
127
|
+
} catch {
|
|
128
|
+
span.textContent = `{{${varName}}}`
|
|
129
|
+
}
|
|
130
|
+
} else {
|
|
131
|
+
span.textContent = String(value)
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
})
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
122
138
|
static styles = [
|
|
123
139
|
unsafeCSS(githubCss),
|
|
124
140
|
unsafeCSS(highlightCSS),
|
|
@@ -172,12 +188,18 @@ export class WidgetMarkdown extends LitElement {
|
|
|
172
188
|
|
|
173
189
|
render() {
|
|
174
190
|
const mdText: string = String(this.inputData?.markdown ?? '')
|
|
175
|
-
|
|
176
|
-
|
|
191
|
+
|
|
192
|
+
// Only re-parse markdown if the markdown text actually changed
|
|
193
|
+
if (mdText !== this.lastMarkdown) {
|
|
194
|
+
this.lastMarkdown = mdText
|
|
195
|
+
const textWithSpans: string = this.convertVariablesToSpans(mdText)
|
|
196
|
+
this.cachedHtmlTemplate = this.marked.parse(textWithSpans) as string
|
|
197
|
+
}
|
|
198
|
+
|
|
177
199
|
return html`
|
|
178
200
|
<div class="wrapper" style="background-color: ${this.themeBgColor}">
|
|
179
201
|
<div class="paging markdown-body" ?active=${this.inputData?.markdown}>
|
|
180
|
-
${unsafeHTML(
|
|
202
|
+
${unsafeHTML(this.cachedHtmlTemplate ?? '')}
|
|
181
203
|
</div>
|
|
182
204
|
</div>
|
|
183
205
|
`
|