lake-html 1.0.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -12
- package/dist/index.d.mts +7 -7
- package/dist/index.d.ts +7 -7
- package/dist/index.js +51 -25
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +50 -24
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -52,19 +52,19 @@ console.log(html);
|
|
|
52
52
|
|
|
53
53
|
## Customization
|
|
54
54
|
|
|
55
|
-
You can customize how specific boxes are rendered or add support for new box types by passing a `
|
|
55
|
+
You can customize how specific boxes are rendered or add support for new box types by passing a `renderers` object as the second argument.
|
|
56
56
|
|
|
57
57
|
### Overriding an existing renderer
|
|
58
58
|
|
|
59
59
|
For example, if you want to wrap all images in a `<figure>` tag:
|
|
60
60
|
|
|
61
61
|
```js
|
|
62
|
-
import { toHTML,
|
|
62
|
+
import { toHTML, getBoxRenderers } from 'lake-html';
|
|
63
63
|
|
|
64
|
-
const
|
|
64
|
+
const renderers = getBoxRenderers();
|
|
65
65
|
|
|
66
66
|
// Override the 'image' renderer
|
|
67
|
-
|
|
67
|
+
renderers.image = (boxValue, encode) => {
|
|
68
68
|
return {
|
|
69
69
|
tagName: 'figure',
|
|
70
70
|
attributes: { class: 'custom-image' },
|
|
@@ -72,38 +72,38 @@ rules.image = (boxValue, encode) => {
|
|
|
72
72
|
};
|
|
73
73
|
};
|
|
74
74
|
|
|
75
|
-
const html = toHTML(content,
|
|
75
|
+
const html = toHTML(content, renderers);
|
|
76
76
|
```
|
|
77
77
|
|
|
78
78
|
### Adding a new box type
|
|
79
79
|
|
|
80
80
|
```js
|
|
81
|
-
import { toHTML,
|
|
81
|
+
import { toHTML, getBoxRenderers } from 'lake-html';
|
|
82
82
|
|
|
83
|
-
const
|
|
83
|
+
const renderers = getBoxRenderers();
|
|
84
84
|
|
|
85
85
|
// Add a custom 'card' box
|
|
86
|
-
|
|
86
|
+
renderers.card = (boxValue, encode) => {
|
|
87
87
|
return `<div class="card">
|
|
88
88
|
<h3>${encode(boxValue.title)}</h3>
|
|
89
89
|
<p>${encode(boxValue.summary)}</p>
|
|
90
90
|
</div>`;
|
|
91
91
|
};
|
|
92
92
|
|
|
93
|
-
const html = toHTML(content,
|
|
93
|
+
const html = toHTML(content, renderers);
|
|
94
94
|
```
|
|
95
95
|
|
|
96
96
|
## API Reference
|
|
97
97
|
|
|
98
|
-
### toHTML(value: string,
|
|
98
|
+
### toHTML(value: string, renderers?: BoxRenderers): string
|
|
99
99
|
|
|
100
100
|
The main conversion function.
|
|
101
101
|
|
|
102
102
|
* `value`: The input LML string.
|
|
103
103
|
|
|
104
|
-
* `
|
|
104
|
+
* `renderers`: (Optional) An object to override default renderers.
|
|
105
105
|
|
|
106
|
-
###
|
|
106
|
+
### getBoxRenderers()
|
|
107
107
|
|
|
108
108
|
Returns the default map of box renderers. Useful when you want to extend the defaults rather than replace them entirely.
|
|
109
109
|
|
package/dist/index.d.mts
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
type AttributeMap = Record<string, string>;
|
|
2
|
-
interface
|
|
2
|
+
interface BoxHTMLNode {
|
|
3
3
|
tagName: string;
|
|
4
4
|
attributes?: AttributeMap;
|
|
5
5
|
isVoid?: boolean;
|
|
6
6
|
innerHTML?: string;
|
|
7
7
|
}
|
|
8
|
-
type
|
|
9
|
-
type
|
|
10
|
-
type BoxRenderers = Record<string,
|
|
8
|
+
type EncodeHTMLEntities = (value: string) => string;
|
|
9
|
+
type RenderBox = (boxValue: AttributeMap, encode: EncodeHTMLEntities) => BoxHTMLNode;
|
|
10
|
+
type BoxRenderers = Record<string, RenderBox>;
|
|
11
11
|
/**
|
|
12
12
|
* Returns the default configuration for rendering various Lake attributes.
|
|
13
13
|
*/
|
|
14
|
-
declare function
|
|
14
|
+
declare function getBoxRenderers(): BoxRenderers;
|
|
15
15
|
/**
|
|
16
16
|
* Main function to convert Lake Markup Language (LML) to standard HTML.
|
|
17
17
|
* It processes custom <lake-box> tags and removes internal anchors.
|
|
18
18
|
*/
|
|
19
|
-
declare function toHTML(value: string,
|
|
19
|
+
declare function toHTML(value: string, renderers?: BoxRenderers): string;
|
|
20
20
|
|
|
21
|
-
export {
|
|
21
|
+
export { getBoxRenderers, toHTML };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
type AttributeMap = Record<string, string>;
|
|
2
|
-
interface
|
|
2
|
+
interface BoxHTMLNode {
|
|
3
3
|
tagName: string;
|
|
4
4
|
attributes?: AttributeMap;
|
|
5
5
|
isVoid?: boolean;
|
|
6
6
|
innerHTML?: string;
|
|
7
7
|
}
|
|
8
|
-
type
|
|
9
|
-
type
|
|
10
|
-
type BoxRenderers = Record<string,
|
|
8
|
+
type EncodeHTMLEntities = (value: string) => string;
|
|
9
|
+
type RenderBox = (boxValue: AttributeMap, encode: EncodeHTMLEntities) => BoxHTMLNode;
|
|
10
|
+
type BoxRenderers = Record<string, RenderBox>;
|
|
11
11
|
/**
|
|
12
12
|
* Returns the default configuration for rendering various Lake attributes.
|
|
13
13
|
*/
|
|
14
|
-
declare function
|
|
14
|
+
declare function getBoxRenderers(): BoxRenderers;
|
|
15
15
|
/**
|
|
16
16
|
* Main function to convert Lake Markup Language (LML) to standard HTML.
|
|
17
17
|
* It processes custom <lake-box> tags and removes internal anchors.
|
|
18
18
|
*/
|
|
19
|
-
declare function toHTML(value: string,
|
|
19
|
+
declare function toHTML(value: string, renderers?: BoxRenderers): string;
|
|
20
20
|
|
|
21
|
-
export {
|
|
21
|
+
export { getBoxRenderers, toHTML };
|
package/dist/index.js
CHANGED
|
@@ -37,7 +37,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
37
37
|
// src/index.ts
|
|
38
38
|
var index_exports = {};
|
|
39
39
|
__export(index_exports, {
|
|
40
|
-
|
|
40
|
+
getBoxRenderers: () => getBoxRenderers,
|
|
41
41
|
toHTML: () => toHTML
|
|
42
42
|
});
|
|
43
43
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -45,9 +45,15 @@ function extractIdFromUrl(url) {
|
|
|
45
45
|
const result = /[\w\-]+$/.exec(url);
|
|
46
46
|
return result ? result[0] : "";
|
|
47
47
|
}
|
|
48
|
-
function
|
|
48
|
+
function getBoxRenderers() {
|
|
49
49
|
return {
|
|
50
|
-
hr: () =>
|
|
50
|
+
hr: () => ({
|
|
51
|
+
tagName: "div",
|
|
52
|
+
attributes: {
|
|
53
|
+
class: "lake-box-block lake-hr"
|
|
54
|
+
},
|
|
55
|
+
innerHTML: "<hr />"
|
|
56
|
+
}),
|
|
51
57
|
image: (boxValue) => ({
|
|
52
58
|
tagName: "img",
|
|
53
59
|
attributes: __spreadProps(__spreadValues(__spreadValues(__spreadValues({
|
|
@@ -57,6 +63,14 @@ function getDefaultBoxRenderers() {
|
|
|
57
63
|
}),
|
|
58
64
|
isVoid: true
|
|
59
65
|
}),
|
|
66
|
+
media: (boxValue) => ({
|
|
67
|
+
tagName: "video",
|
|
68
|
+
attributes: __spreadProps(__spreadValues(__spreadValues({
|
|
69
|
+
src: boxValue.url
|
|
70
|
+
}, boxValue.width && { width: boxValue.width.replace(/px$/i, "") }), boxValue.height && { height: boxValue.height.replace(/px$/i, "") }), {
|
|
71
|
+
controls: "true"
|
|
72
|
+
})
|
|
73
|
+
}),
|
|
60
74
|
file: (boxValue, encode) => ({
|
|
61
75
|
tagName: "a",
|
|
62
76
|
attributes: {
|
|
@@ -86,15 +100,27 @@ function getDefaultBoxRenderers() {
|
|
|
86
100
|
tagName: "code",
|
|
87
101
|
innerHTML: boxValue.code
|
|
88
102
|
}),
|
|
103
|
+
mention: (boxValue, encode) => {
|
|
104
|
+
var _a;
|
|
105
|
+
return {
|
|
106
|
+
tagName: "a",
|
|
107
|
+
attributes: {
|
|
108
|
+
href: `/${boxValue.name}`,
|
|
109
|
+
target: "_blank"
|
|
110
|
+
},
|
|
111
|
+
innerHTML: encode((_a = boxValue.nickname) != null ? _a : boxValue.name)
|
|
112
|
+
};
|
|
113
|
+
},
|
|
89
114
|
video: (boxValue) => ({
|
|
90
115
|
tagName: "iframe",
|
|
91
116
|
attributes: __spreadProps(__spreadValues({}, boxValue.url && { src: `https://www.youtube.com/embed/${extractIdFromUrl(boxValue.url)}` }), {
|
|
117
|
+
width: boxValue.width ? boxValue.width.replace(/px$/i, "") : "560",
|
|
118
|
+
height: boxValue.height ? boxValue.height.replace(/px$/i, "") : "315",
|
|
92
119
|
title: "YouTube video player",
|
|
93
120
|
frameborder: "0",
|
|
94
121
|
allow: "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share",
|
|
95
122
|
referrerpolicy: "strict-origin-when-cross-origin",
|
|
96
|
-
allowfullscreen: "true"
|
|
97
|
-
style: "width: 560px; height: 315px;"
|
|
123
|
+
allowfullscreen: "true"
|
|
98
124
|
})
|
|
99
125
|
}),
|
|
100
126
|
twitter: (boxValue) => ({
|
|
@@ -148,31 +174,31 @@ function serializeAttributes(attrs) {
|
|
|
148
174
|
}
|
|
149
175
|
return result.join(" ");
|
|
150
176
|
}
|
|
151
|
-
function
|
|
152
|
-
|
|
177
|
+
function toBoxHTML(node) {
|
|
178
|
+
var _a;
|
|
179
|
+
let result = `<${node.tagName}`;
|
|
180
|
+
if (node.attributes) {
|
|
181
|
+
result += ` ${serializeAttributes(node.attributes)}`;
|
|
182
|
+
}
|
|
183
|
+
if (node.isVoid === true) {
|
|
184
|
+
result += " />";
|
|
185
|
+
} else {
|
|
186
|
+
result += `>${(_a = node.innerHTML) != null ? _a : ""}</${node.tagName}>`;
|
|
187
|
+
}
|
|
188
|
+
return result;
|
|
189
|
+
}
|
|
190
|
+
function toHTML(value, renderers) {
|
|
191
|
+
renderers = renderers != null ? renderers : getBoxRenderers();
|
|
153
192
|
const combinedRegex = /(<lake-box[^>]+>)[\s\S]*?(?:<\/lake-box>|$)|(<anchor\s*\/>)|(<focus\s*\/>)/gi;
|
|
154
193
|
return value.replace(combinedRegex, (match, boxOpen) => {
|
|
155
|
-
var _a;
|
|
156
194
|
if (boxOpen) {
|
|
157
195
|
const attributes = parseAttributes(boxOpen);
|
|
158
|
-
const render =
|
|
196
|
+
const render = renderers[attributes.name];
|
|
159
197
|
if (render) {
|
|
160
198
|
try {
|
|
161
|
-
const
|
|
162
|
-
const
|
|
163
|
-
|
|
164
|
-
return result;
|
|
165
|
-
}
|
|
166
|
-
let html = `<${result.tagName}`;
|
|
167
|
-
if (result.attributes) {
|
|
168
|
-
html += ` ${serializeAttributes(result.attributes)}`;
|
|
169
|
-
}
|
|
170
|
-
if (result.isVoid === true) {
|
|
171
|
-
html += " />";
|
|
172
|
-
} else {
|
|
173
|
-
html += `>${(_a = result.innerHTML) != null ? _a : ""}</${result.tagName}>`;
|
|
174
|
-
}
|
|
175
|
-
return html;
|
|
199
|
+
const boxValue = attributes.value ? JSON.parse(decodeBase64(attributes.value)) : {};
|
|
200
|
+
const node = render(boxValue, encodeHTMLEntities);
|
|
201
|
+
return toBoxHTML(node);
|
|
176
202
|
} catch (e) {
|
|
177
203
|
console.error("Failed to parse lake-box value:", e);
|
|
178
204
|
}
|
|
@@ -183,7 +209,7 @@ function toHTML(value, rules) {
|
|
|
183
209
|
}
|
|
184
210
|
// Annotate the CommonJS export names for ESM import in node:
|
|
185
211
|
0 && (module.exports = {
|
|
186
|
-
|
|
212
|
+
getBoxRenderers,
|
|
187
213
|
toHTML
|
|
188
214
|
});
|
|
189
215
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["// Define a generic type for HTML attributes (key-value pairs)\ntype AttributeMap = Record<string, string>;\n\n// Structure representing the output HTML node\ninterface BoxNode {\n tagName: string;\n attributes?: AttributeMap;\n isVoid?: boolean; // True for self-closing tags like <img />, <hr />\n innerHTML?: string;\n}\n\n// Function signature for encoding HTML entities\ntype EntityEncoder = (value: string) => string;\n\n// Function signature for encoding HTML entities\ntype BoxRenderer = (boxValue: AttributeMap, encode: EntityEncoder) => BoxNode | string;\n\n// Registry of renderers for different box types\ntype BoxRenderers = Record<string, BoxRenderer>;\n\n/**\n * Extracts the ID from a URL.\n * Useful for extracting YouTube or Twitter IDs from clean URLs.\n */\nfunction extractIdFromUrl(url: string): string {\n const result = /[\\w\\-]+$/.exec(url);\n return result ? result[0] : '';\n}\n\n/**\n * Returns the default configuration for rendering various Lake attributes.\n */\nexport function getDefaultBoxRenderers(): BoxRenderers {\n return {\n hr: () => '<div class=\"lake-box-block lake-hr\"><hr /></div>',\n\n image: boxValue => ({\n tagName: 'img',\n attributes: {\n src: boxValue.url,\n ...(boxValue.width && { width: boxValue.width }),\n ...(boxValue.height && { height: boxValue.height }),\n ...(boxValue.caption && { alt: boxValue.caption }),\n border: '0',\n },\n isVoid: true,\n }),\n\n file: (boxValue, encode) => ({\n tagName: 'a',\n attributes: {\n href: boxValue.url,\n target: '_blank',\n },\n innerHTML: encode(boxValue.name),\n }),\n\n codeBlock: (boxValue, encode) => ({\n tagName: 'pre',\n attributes: {\n class: `lang-${boxValue.lang}`,\n },\n innerHTML: `<code>${encode(boxValue.code)}</code>`,\n }),\n\n emoji: boxValue => ({\n tagName: 'img',\n attributes: {\n src: boxValue.url,\n width: '32',\n height: '32',\n border: '0',\n },\n isVoid: true,\n }),\n\n equation: boxValue => ({\n tagName: 'code',\n innerHTML: boxValue.code,\n }),\n\n video: boxValue => ({\n tagName: 'iframe',\n attributes: {\n ...(boxValue.url && { src: `https://www.youtube.com/embed/${extractIdFromUrl(boxValue.url)}` }),\n title: 'YouTube video player',\n frameborder: '0',\n allow: 'accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share',\n referrerpolicy: 'strict-origin-when-cross-origin',\n allowfullscreen: 'true',\n style: 'width: 560px; height: 315px;',\n },\n }),\n\n twitter: boxValue => ({\n tagName: 'iframe',\n attributes: {\n ...(boxValue.url && { src: `https://platform.twitter.com/embed/Tweet.html?id=${extractIdFromUrl(boxValue.url)}` }),\n title: 'Twitter tweet',\n scrolling: 'no',\n frameborder: '0',\n allowtransparency: 'true',\n allowfullscreen: 'true',\n style: 'width: 550px; height: 300px;',\n },\n }),\n };\n}\n\n// Map for reserved HTML characters\nconst htmlEntityMap = new Map([\n ['&', '&'],\n ['<', '<'],\n ['>', '>'],\n ['\"', '"'],\n ['\\xA0', ' '],\n]);\n\n/**\n * Escapes reserved HTML characters to prevent XSS and rendering issues.\n */\nfunction encodeHTMLEntities(value: string): string {\n return value.replace(/[&<>\"\\xA0]/g, match => htmlEntityMap.get(match)!);\n}\n\n/**\n * Decodes a Base64 encoded string with UTF-8 support.\n */\nfunction decodeBase64(value: string): string {\n const binaryString = atob(value);\n const byteArray = new Uint8Array(binaryString.length);\n for (let i = 0; i < binaryString.length; i++) {\n byteArray[i] = binaryString.charCodeAt(i);\n }\n const decoder = new TextDecoder();\n return decoder.decode(byteArray);\n}\n\n/**\n * Parses HTML tag attributes from a string into a key-value object.\n */\nfunction parseAttributes(tag: string): AttributeMap {\n const attributes: AttributeMap = {};\n // Regex breakdown:\n // Group 1/2: Key=Value (unquoted)\n // Group 3/4: Key=\"Value\" (double quoted)\n // Group 5/6: Key='Value' (single quoted)\n const reg = /\\s+(?:([\\w\\-:]+)=([^\\s\"'<>]+)|([\\w\\-:\"]+)=\"([^\"]*)\"|([\\w\\-:\"]+)='([^']*)')(?=[\\s/>])/g;\n let match: RegExpExecArray | null;\n while ((match = reg.exec(tag))) {\n const key = (match[1] || match[3] || match[5]).toLowerCase();\n const value = match[1] ? match[2] : (match[3] ? match[4] : match[6]);\n attributes[key] = value;\n }\n return attributes;\n}\n\n/**\n * Serializes an attribute map into an HTML attribute string.\n */\nfunction serializeAttributes(attrs: AttributeMap): string {\n const result: string[] = [];\n for (const key of Object.keys(attrs)) {\n const value = String(attrs[key]);\n result.push(`${key}=\"${encodeHTMLEntities(value)}\"`);\n }\n return result.join(' ');\n}\n\n/**\n * Main function to convert Lake Markup Language (LML) to standard HTML.\n * It processes custom <lake-box> tags and removes internal anchors.\n */\nexport function toHTML(value: string, rules?: BoxRenderers): string {\n const config = rules ?? getDefaultBoxRenderers();\n // Regex to match <lake-box>, <anchor>, and <focus> tags\n const combinedRegex = /(<lake-box[^>]+>)[\\s\\S]*?(?:<\\/lake-box>|$)|(<anchor\\s*\\/>)|(<focus\\s*\\/>)/gi;\n return value.replace(combinedRegex, (match, boxOpen) => {\n // Handle lake-box conversion\n if (boxOpen) {\n const attributes = parseAttributes(boxOpen);\n const render = config[attributes.name];\n if (render) {\n try {\n const decodedValue = attributes.value ? JSON.parse(decodeBase64(attributes.value)) : {};\n const result = render(decodedValue, encodeHTMLEntities);\n // If renderer returns a raw string, return it directly\n if (typeof result === 'string') {\n return result;\n }\n // Otherwise, build the HTML tag from BoxNode\n let html = `<${result.tagName}`;\n if (result.attributes) {\n html += ` ${serializeAttributes(result.attributes)}`;\n }\n if (result.isVoid === true) {\n html += ' />';\n } else {\n html += `>${result.innerHTML ?? ''}</${result.tagName}>`;\n }\n return html;\n } catch (e) {\n console.error('Failed to parse lake-box value:', e);\n }\n }\n }\n // Remove internal selection markers (<anchor /> and <focus />)\n return '';\n });\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["// Define a generic type for HTML attributes (key-value pairs)\ntype AttributeMap = Record<string, string>;\n\n// Structure representing the output HTML node\ninterface BoxHTMLNode {\n tagName: string;\n attributes?: AttributeMap;\n isVoid?: boolean; // True for self-closing tags like <img />, <hr />\n innerHTML?: string;\n}\n\n// Function signature for encoding HTML entities\ntype EncodeHTMLEntities = (value: string) => string;\n\n// Function signature for encoding HTML entities\ntype RenderBox = (boxValue: AttributeMap, encode: EncodeHTMLEntities) => BoxHTMLNode;\n\n// Registry of renderers for different box types\ntype BoxRenderers = Record<string, RenderBox>;\n\n/**\n * Extracts the ID from a URL.\n * Useful for extracting YouTube or Twitter IDs from clean URLs.\n */\nfunction extractIdFromUrl(url: string): string {\n const result = /[\\w\\-]+$/.exec(url);\n return result ? result[0] : '';\n}\n\n/**\n * Returns the default configuration for rendering various Lake attributes.\n */\nexport function getBoxRenderers(): BoxRenderers {\n return {\n hr: () => ({\n tagName: 'div',\n attributes: {\n class: 'lake-box-block lake-hr',\n },\n innerHTML: '<hr />',\n }),\n\n image: boxValue => ({\n tagName: 'img',\n attributes: {\n src: boxValue.url,\n ...(boxValue.width && { width: boxValue.width }),\n ...(boxValue.height && { height: boxValue.height }),\n ...(boxValue.caption && { alt: boxValue.caption }),\n border: '0',\n },\n isVoid: true,\n }),\n\n media: boxValue => ({\n tagName: 'video',\n attributes: {\n src: boxValue.url,\n ...(boxValue.width && { width: boxValue.width.replace(/px$/i, '') }),\n ...(boxValue.height && { height: boxValue.height.replace(/px$/i, '') }),\n controls: 'true',\n },\n }),\n\n file: (boxValue, encode) => ({\n tagName: 'a',\n attributes: {\n href: boxValue.url,\n target: '_blank',\n },\n innerHTML: encode(boxValue.name),\n }),\n\n codeBlock: (boxValue, encode) => ({\n tagName: 'pre',\n attributes: {\n class: `lang-${boxValue.lang}`,\n },\n innerHTML: `<code>${encode(boxValue.code)}</code>`,\n }),\n\n emoji: boxValue => ({\n tagName: 'img',\n attributes: {\n src: boxValue.url,\n width: '32',\n height: '32',\n border: '0',\n },\n isVoid: true,\n }),\n\n equation: boxValue => ({\n tagName: 'code',\n innerHTML: boxValue.code,\n }),\n\n mention: (boxValue, encode) => ({\n tagName: 'a',\n attributes: {\n href: `/${boxValue.name}`,\n target: '_blank',\n },\n innerHTML: encode(boxValue.nickname ?? boxValue.name),\n }),\n\n video: boxValue => ({\n tagName: 'iframe',\n attributes: {\n ...(boxValue.url && { src: `https://www.youtube.com/embed/${extractIdFromUrl(boxValue.url)}` }),\n width: boxValue.width ? boxValue.width.replace(/px$/i, '') : '560',\n height: boxValue.height ? boxValue.height.replace(/px$/i, '') : '315',\n title: 'YouTube video player',\n frameborder: '0',\n allow: 'accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share',\n referrerpolicy: 'strict-origin-when-cross-origin',\n allowfullscreen: 'true',\n },\n }),\n\n twitter: boxValue => ({\n tagName: 'iframe',\n attributes: {\n ...(boxValue.url && { src: `https://platform.twitter.com/embed/Tweet.html?id=${extractIdFromUrl(boxValue.url)}` }),\n title: 'Twitter tweet',\n scrolling: 'no',\n frameborder: '0',\n allowtransparency: 'true',\n allowfullscreen: 'true',\n style: 'width: 550px; height: 300px;',\n },\n }),\n };\n}\n\n// Map for reserved HTML characters\nconst htmlEntityMap = new Map([\n ['&', '&'],\n ['<', '<'],\n ['>', '>'],\n ['\"', '"'],\n ['\\xA0', ' '],\n]);\n\n/**\n * Escapes reserved HTML characters to prevent XSS and rendering issues.\n */\nfunction encodeHTMLEntities(value: string): string {\n return value.replace(/[&<>\"\\xA0]/g, match => htmlEntityMap.get(match)!);\n}\n\n/**\n * Decodes a Base64 encoded string with UTF-8 support.\n */\nfunction decodeBase64(value: string): string {\n const binaryString = atob(value);\n const byteArray = new Uint8Array(binaryString.length);\n for (let i = 0; i < binaryString.length; i++) {\n byteArray[i] = binaryString.charCodeAt(i);\n }\n const decoder = new TextDecoder();\n return decoder.decode(byteArray);\n}\n\n/**\n * Parses HTML tag attributes from a string into a key-value object.\n */\nfunction parseAttributes(tag: string): AttributeMap {\n const attributes: AttributeMap = {};\n // Regex breakdown:\n // Group 1/2: Key=Value (unquoted)\n // Group 3/4: Key=\"Value\" (double quoted)\n // Group 5/6: Key='Value' (single quoted)\n const reg = /\\s+(?:([\\w\\-:]+)=([^\\s\"'<>]+)|([\\w\\-:\"]+)=\"([^\"]*)\"|([\\w\\-:\"]+)='([^']*)')(?=[\\s/>])/g;\n let match: RegExpExecArray | null;\n while ((match = reg.exec(tag))) {\n const key = (match[1] || match[3] || match[5]).toLowerCase();\n const value = match[1] ? match[2] : (match[3] ? match[4] : match[6]);\n attributes[key] = value;\n }\n return attributes;\n}\n\n/**\n * Serializes an attribute map into an HTML attribute string.\n */\nfunction serializeAttributes(attrs: AttributeMap): string {\n const result: string[] = [];\n for (const key of Object.keys(attrs)) {\n const value = String(attrs[key]);\n result.push(`${key}=\"${encodeHTMLEntities(value)}\"`);\n }\n return result.join(' ');\n}\n\n/**\n * Serializes a BoxHTMLNode object into a standard HTML string.\n */\nfunction toBoxHTML(node: BoxHTMLNode): string {\n let result = `<${node.tagName}`;\n if (node.attributes) {\n result += ` ${serializeAttributes(node.attributes)}`;\n }\n if (node.isVoid === true) {\n result += ' />';\n } else {\n result += `>${node.innerHTML ?? ''}</${node.tagName}>`;\n }\n return result;\n}\n\n/**\n * Main function to convert Lake Markup Language (LML) to standard HTML.\n * It processes custom <lake-box> tags and removes internal anchors.\n */\nexport function toHTML(value: string, renderers?: BoxRenderers): string {\n renderers = renderers ?? getBoxRenderers();\n // Regex to match <lake-box>, <anchor>, and <focus> tags\n const combinedRegex = /(<lake-box[^>]+>)[\\s\\S]*?(?:<\\/lake-box>|$)|(<anchor\\s*\\/>)|(<focus\\s*\\/>)/gi;\n return value.replace(combinedRegex, (match, boxOpen) => {\n // Handle lake-box conversion\n if (boxOpen) {\n const attributes = parseAttributes(boxOpen);\n const render = renderers[attributes.name];\n if (render) {\n try {\n const boxValue = attributes.value ? JSON.parse(decodeBase64(attributes.value)) : {};\n const node = render(boxValue, encodeHTMLEntities);\n return toBoxHTML(node);\n } catch (e) {\n console.error('Failed to parse lake-box value:', e);\n }\n }\n }\n // Remove internal selection markers (<anchor /> and <focus />)\n return '';\n });\n}\n"],"mappings":"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","names":[]}
|
package/dist/index.mjs
CHANGED
|
@@ -23,9 +23,15 @@ function extractIdFromUrl(url) {
|
|
|
23
23
|
const result = /[\w\-]+$/.exec(url);
|
|
24
24
|
return result ? result[0] : "";
|
|
25
25
|
}
|
|
26
|
-
function
|
|
26
|
+
function getBoxRenderers() {
|
|
27
27
|
return {
|
|
28
|
-
hr: () =>
|
|
28
|
+
hr: () => ({
|
|
29
|
+
tagName: "div",
|
|
30
|
+
attributes: {
|
|
31
|
+
class: "lake-box-block lake-hr"
|
|
32
|
+
},
|
|
33
|
+
innerHTML: "<hr />"
|
|
34
|
+
}),
|
|
29
35
|
image: (boxValue) => ({
|
|
30
36
|
tagName: "img",
|
|
31
37
|
attributes: __spreadProps(__spreadValues(__spreadValues(__spreadValues({
|
|
@@ -35,6 +41,14 @@ function getDefaultBoxRenderers() {
|
|
|
35
41
|
}),
|
|
36
42
|
isVoid: true
|
|
37
43
|
}),
|
|
44
|
+
media: (boxValue) => ({
|
|
45
|
+
tagName: "video",
|
|
46
|
+
attributes: __spreadProps(__spreadValues(__spreadValues({
|
|
47
|
+
src: boxValue.url
|
|
48
|
+
}, boxValue.width && { width: boxValue.width.replace(/px$/i, "") }), boxValue.height && { height: boxValue.height.replace(/px$/i, "") }), {
|
|
49
|
+
controls: "true"
|
|
50
|
+
})
|
|
51
|
+
}),
|
|
38
52
|
file: (boxValue, encode) => ({
|
|
39
53
|
tagName: "a",
|
|
40
54
|
attributes: {
|
|
@@ -64,15 +78,27 @@ function getDefaultBoxRenderers() {
|
|
|
64
78
|
tagName: "code",
|
|
65
79
|
innerHTML: boxValue.code
|
|
66
80
|
}),
|
|
81
|
+
mention: (boxValue, encode) => {
|
|
82
|
+
var _a;
|
|
83
|
+
return {
|
|
84
|
+
tagName: "a",
|
|
85
|
+
attributes: {
|
|
86
|
+
href: `/${boxValue.name}`,
|
|
87
|
+
target: "_blank"
|
|
88
|
+
},
|
|
89
|
+
innerHTML: encode((_a = boxValue.nickname) != null ? _a : boxValue.name)
|
|
90
|
+
};
|
|
91
|
+
},
|
|
67
92
|
video: (boxValue) => ({
|
|
68
93
|
tagName: "iframe",
|
|
69
94
|
attributes: __spreadProps(__spreadValues({}, boxValue.url && { src: `https://www.youtube.com/embed/${extractIdFromUrl(boxValue.url)}` }), {
|
|
95
|
+
width: boxValue.width ? boxValue.width.replace(/px$/i, "") : "560",
|
|
96
|
+
height: boxValue.height ? boxValue.height.replace(/px$/i, "") : "315",
|
|
70
97
|
title: "YouTube video player",
|
|
71
98
|
frameborder: "0",
|
|
72
99
|
allow: "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share",
|
|
73
100
|
referrerpolicy: "strict-origin-when-cross-origin",
|
|
74
|
-
allowfullscreen: "true"
|
|
75
|
-
style: "width: 560px; height: 315px;"
|
|
101
|
+
allowfullscreen: "true"
|
|
76
102
|
})
|
|
77
103
|
}),
|
|
78
104
|
twitter: (boxValue) => ({
|
|
@@ -126,31 +152,31 @@ function serializeAttributes(attrs) {
|
|
|
126
152
|
}
|
|
127
153
|
return result.join(" ");
|
|
128
154
|
}
|
|
129
|
-
function
|
|
130
|
-
|
|
155
|
+
function toBoxHTML(node) {
|
|
156
|
+
var _a;
|
|
157
|
+
let result = `<${node.tagName}`;
|
|
158
|
+
if (node.attributes) {
|
|
159
|
+
result += ` ${serializeAttributes(node.attributes)}`;
|
|
160
|
+
}
|
|
161
|
+
if (node.isVoid === true) {
|
|
162
|
+
result += " />";
|
|
163
|
+
} else {
|
|
164
|
+
result += `>${(_a = node.innerHTML) != null ? _a : ""}</${node.tagName}>`;
|
|
165
|
+
}
|
|
166
|
+
return result;
|
|
167
|
+
}
|
|
168
|
+
function toHTML(value, renderers) {
|
|
169
|
+
renderers = renderers != null ? renderers : getBoxRenderers();
|
|
131
170
|
const combinedRegex = /(<lake-box[^>]+>)[\s\S]*?(?:<\/lake-box>|$)|(<anchor\s*\/>)|(<focus\s*\/>)/gi;
|
|
132
171
|
return value.replace(combinedRegex, (match, boxOpen) => {
|
|
133
|
-
var _a;
|
|
134
172
|
if (boxOpen) {
|
|
135
173
|
const attributes = parseAttributes(boxOpen);
|
|
136
|
-
const render =
|
|
174
|
+
const render = renderers[attributes.name];
|
|
137
175
|
if (render) {
|
|
138
176
|
try {
|
|
139
|
-
const
|
|
140
|
-
const
|
|
141
|
-
|
|
142
|
-
return result;
|
|
143
|
-
}
|
|
144
|
-
let html = `<${result.tagName}`;
|
|
145
|
-
if (result.attributes) {
|
|
146
|
-
html += ` ${serializeAttributes(result.attributes)}`;
|
|
147
|
-
}
|
|
148
|
-
if (result.isVoid === true) {
|
|
149
|
-
html += " />";
|
|
150
|
-
} else {
|
|
151
|
-
html += `>${(_a = result.innerHTML) != null ? _a : ""}</${result.tagName}>`;
|
|
152
|
-
}
|
|
153
|
-
return html;
|
|
177
|
+
const boxValue = attributes.value ? JSON.parse(decodeBase64(attributes.value)) : {};
|
|
178
|
+
const node = render(boxValue, encodeHTMLEntities);
|
|
179
|
+
return toBoxHTML(node);
|
|
154
180
|
} catch (e) {
|
|
155
181
|
console.error("Failed to parse lake-box value:", e);
|
|
156
182
|
}
|
|
@@ -160,7 +186,7 @@ function toHTML(value, rules) {
|
|
|
160
186
|
});
|
|
161
187
|
}
|
|
162
188
|
export {
|
|
163
|
-
|
|
189
|
+
getBoxRenderers,
|
|
164
190
|
toHTML
|
|
165
191
|
};
|
|
166
192
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["// Define a generic type for HTML attributes (key-value pairs)\ntype AttributeMap = Record<string, string>;\n\n// Structure representing the output HTML node\ninterface BoxNode {\n tagName: string;\n attributes?: AttributeMap;\n isVoid?: boolean; // True for self-closing tags like <img />, <hr />\n innerHTML?: string;\n}\n\n// Function signature for encoding HTML entities\ntype EntityEncoder = (value: string) => string;\n\n// Function signature for encoding HTML entities\ntype BoxRenderer = (boxValue: AttributeMap, encode: EntityEncoder) => BoxNode | string;\n\n// Registry of renderers for different box types\ntype BoxRenderers = Record<string, BoxRenderer>;\n\n/**\n * Extracts the ID from a URL.\n * Useful for extracting YouTube or Twitter IDs from clean URLs.\n */\nfunction extractIdFromUrl(url: string): string {\n const result = /[\\w\\-]+$/.exec(url);\n return result ? result[0] : '';\n}\n\n/**\n * Returns the default configuration for rendering various Lake attributes.\n */\nexport function getDefaultBoxRenderers(): BoxRenderers {\n return {\n hr: () => '<div class=\"lake-box-block lake-hr\"><hr /></div>',\n\n image: boxValue => ({\n tagName: 'img',\n attributes: {\n src: boxValue.url,\n ...(boxValue.width && { width: boxValue.width }),\n ...(boxValue.height && { height: boxValue.height }),\n ...(boxValue.caption && { alt: boxValue.caption }),\n border: '0',\n },\n isVoid: true,\n }),\n\n file: (boxValue, encode) => ({\n tagName: 'a',\n attributes: {\n href: boxValue.url,\n target: '_blank',\n },\n innerHTML: encode(boxValue.name),\n }),\n\n codeBlock: (boxValue, encode) => ({\n tagName: 'pre',\n attributes: {\n class: `lang-${boxValue.lang}`,\n },\n innerHTML: `<code>${encode(boxValue.code)}</code>`,\n }),\n\n emoji: boxValue => ({\n tagName: 'img',\n attributes: {\n src: boxValue.url,\n width: '32',\n height: '32',\n border: '0',\n },\n isVoid: true,\n }),\n\n equation: boxValue => ({\n tagName: 'code',\n innerHTML: boxValue.code,\n }),\n\n video: boxValue => ({\n tagName: 'iframe',\n attributes: {\n ...(boxValue.url && { src: `https://www.youtube.com/embed/${extractIdFromUrl(boxValue.url)}` }),\n title: 'YouTube video player',\n frameborder: '0',\n allow: 'accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share',\n referrerpolicy: 'strict-origin-when-cross-origin',\n allowfullscreen: 'true',\n style: 'width: 560px; height: 315px;',\n },\n }),\n\n twitter: boxValue => ({\n tagName: 'iframe',\n attributes: {\n ...(boxValue.url && { src: `https://platform.twitter.com/embed/Tweet.html?id=${extractIdFromUrl(boxValue.url)}` }),\n title: 'Twitter tweet',\n scrolling: 'no',\n frameborder: '0',\n allowtransparency: 'true',\n allowfullscreen: 'true',\n style: 'width: 550px; height: 300px;',\n },\n }),\n };\n}\n\n// Map for reserved HTML characters\nconst htmlEntityMap = new Map([\n ['&', '&'],\n ['<', '<'],\n ['>', '>'],\n ['\"', '"'],\n ['\\xA0', ' '],\n]);\n\n/**\n * Escapes reserved HTML characters to prevent XSS and rendering issues.\n */\nfunction encodeHTMLEntities(value: string): string {\n return value.replace(/[&<>\"\\xA0]/g, match => htmlEntityMap.get(match)!);\n}\n\n/**\n * Decodes a Base64 encoded string with UTF-8 support.\n */\nfunction decodeBase64(value: string): string {\n const binaryString = atob(value);\n const byteArray = new Uint8Array(binaryString.length);\n for (let i = 0; i < binaryString.length; i++) {\n byteArray[i] = binaryString.charCodeAt(i);\n }\n const decoder = new TextDecoder();\n return decoder.decode(byteArray);\n}\n\n/**\n * Parses HTML tag attributes from a string into a key-value object.\n */\nfunction parseAttributes(tag: string): AttributeMap {\n const attributes: AttributeMap = {};\n // Regex breakdown:\n // Group 1/2: Key=Value (unquoted)\n // Group 3/4: Key=\"Value\" (double quoted)\n // Group 5/6: Key='Value' (single quoted)\n const reg = /\\s+(?:([\\w\\-:]+)=([^\\s\"'<>]+)|([\\w\\-:\"]+)=\"([^\"]*)\"|([\\w\\-:\"]+)='([^']*)')(?=[\\s/>])/g;\n let match: RegExpExecArray | null;\n while ((match = reg.exec(tag))) {\n const key = (match[1] || match[3] || match[5]).toLowerCase();\n const value = match[1] ? match[2] : (match[3] ? match[4] : match[6]);\n attributes[key] = value;\n }\n return attributes;\n}\n\n/**\n * Serializes an attribute map into an HTML attribute string.\n */\nfunction serializeAttributes(attrs: AttributeMap): string {\n const result: string[] = [];\n for (const key of Object.keys(attrs)) {\n const value = String(attrs[key]);\n result.push(`${key}=\"${encodeHTMLEntities(value)}\"`);\n }\n return result.join(' ');\n}\n\n/**\n * Main function to convert Lake Markup Language (LML) to standard HTML.\n * It processes custom <lake-box> tags and removes internal anchors.\n */\nexport function toHTML(value: string, rules?: BoxRenderers): string {\n const config = rules ?? getDefaultBoxRenderers();\n // Regex to match <lake-box>, <anchor>, and <focus> tags\n const combinedRegex = /(<lake-box[^>]+>)[\\s\\S]*?(?:<\\/lake-box>|$)|(<anchor\\s*\\/>)|(<focus\\s*\\/>)/gi;\n return value.replace(combinedRegex, (match, boxOpen) => {\n // Handle lake-box conversion\n if (boxOpen) {\n const attributes = parseAttributes(boxOpen);\n const render = config[attributes.name];\n if (render) {\n try {\n const decodedValue = attributes.value ? JSON.parse(decodeBase64(attributes.value)) : {};\n const result = render(decodedValue, encodeHTMLEntities);\n // If renderer returns a raw string, return it directly\n if (typeof result === 'string') {\n return result;\n }\n // Otherwise, build the HTML tag from BoxNode\n let html = `<${result.tagName}`;\n if (result.attributes) {\n html += ` ${serializeAttributes(result.attributes)}`;\n }\n if (result.isVoid === true) {\n html += ' />';\n } else {\n html += `>${result.innerHTML ?? ''}</${result.tagName}>`;\n }\n return html;\n } catch (e) {\n console.error('Failed to parse lake-box value:', e);\n }\n }\n }\n // Remove internal selection markers (<anchor /> and <focus />)\n return '';\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAwBA,SAAS,iBAAiB,KAAqB;AAC7C,QAAM,SAAS,WAAW,KAAK,GAAG;AAClC,SAAO,SAAS,OAAO,CAAC,IAAI;AAC9B;AAKO,SAAS,yBAAuC;AACrD,SAAO;AAAA,IACL,IAAI,MAAM;AAAA,IAEV,OAAO,eAAa;AAAA,MAClB,SAAS;AAAA,MACT,YAAY;AAAA,QACV,KAAK,SAAS;AAAA,SACV,SAAS,SAAS,EAAE,OAAO,SAAS,MAAM,IAC1C,SAAS,UAAU,EAAE,QAAQ,SAAS,OAAO,IAC7C,SAAS,WAAW,EAAE,KAAK,SAAS,QAAQ,IAJtC;AAAA,QAKV,QAAQ;AAAA,MACV;AAAA,MACA,QAAQ;AAAA,IACV;AAAA,IAEA,MAAM,CAAC,UAAU,YAAY;AAAA,MAC3B,SAAS;AAAA,MACT,YAAY;AAAA,QACV,MAAM,SAAS;AAAA,QACf,QAAQ;AAAA,MACV;AAAA,MACA,WAAW,OAAO,SAAS,IAAI;AAAA,IACjC;AAAA,IAEA,WAAW,CAAC,UAAU,YAAY;AAAA,MAChC,SAAS;AAAA,MACT,YAAY;AAAA,QACV,OAAO,QAAQ,SAAS,IAAI;AAAA,MAC9B;AAAA,MACA,WAAW,SAAS,OAAO,SAAS,IAAI,CAAC;AAAA,IAC3C;AAAA,IAEA,OAAO,eAAa;AAAA,MAClB,SAAS;AAAA,MACT,YAAY;AAAA,QACV,KAAK,SAAS;AAAA,QACd,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,QAAQ;AAAA,MACV;AAAA,MACA,QAAQ;AAAA,IACV;AAAA,IAEA,UAAU,eAAa;AAAA,MACrB,SAAS;AAAA,MACT,WAAW,SAAS;AAAA,IACtB;AAAA,IAEA,OAAO,eAAa;AAAA,MAClB,SAAS;AAAA,MACT,YAAY,iCACN,SAAS,OAAO,EAAE,KAAK,iCAAiC,iBAAiB,SAAS,GAAG,CAAC,GAAG,IADnF;AAAA,QAEV,OAAO;AAAA,QACP,aAAa;AAAA,QACb,OAAO;AAAA,QACP,gBAAgB;AAAA,QAChB,iBAAiB;AAAA,QACjB,OAAO;AAAA,MACT;AAAA,IACF;AAAA,IAEA,SAAS,eAAa;AAAA,MACpB,SAAS;AAAA,MACT,YAAY,iCACN,SAAS,OAAO,EAAE,KAAK,oDAAoD,iBAAiB,SAAS,GAAG,CAAC,GAAG,IADtG;AAAA,QAEV,OAAO;AAAA,QACP,WAAW;AAAA,QACX,aAAa;AAAA,QACb,mBAAmB;AAAA,QACnB,iBAAiB;AAAA,QACjB,OAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF;AACF;AAGA,IAAM,gBAAgB,oBAAI,IAAI;AAAA,EAC5B,CAAC,KAAK,OAAO;AAAA,EACb,CAAC,KAAK,MAAM;AAAA,EACZ,CAAC,KAAK,MAAM;AAAA,EACZ,CAAC,KAAK,QAAQ;AAAA,EACd,CAAC,QAAQ,QAAQ;AACnB,CAAC;AAKD,SAAS,mBAAmB,OAAuB;AACjD,SAAO,MAAM,QAAQ,eAAe,WAAS,cAAc,IAAI,KAAK,CAAE;AACxE;AAKA,SAAS,aAAa,OAAuB;AAC3C,QAAM,eAAe,KAAK,KAAK;AAC/B,QAAM,YAAY,IAAI,WAAW,aAAa,MAAM;AACpD,WAAS,IAAI,GAAG,IAAI,aAAa,QAAQ,KAAK;AAC5C,cAAU,CAAC,IAAI,aAAa,WAAW,CAAC;AAAA,EAC1C;AACA,QAAM,UAAU,IAAI,YAAY;AAChC,SAAO,QAAQ,OAAO,SAAS;AACjC;AAKA,SAAS,gBAAgB,KAA2B;AAClD,QAAM,aAA2B,CAAC;AAKlC,QAAM,MAAM;AACZ,MAAI;AACJ,SAAQ,QAAQ,IAAI,KAAK,GAAG,GAAI;AAC9B,UAAM,OAAO,MAAM,CAAC,KAAK,MAAM,CAAC,KAAK,MAAM,CAAC,GAAG,YAAY;AAC3D,UAAM,QAAQ,MAAM,CAAC,IAAI,MAAM,CAAC,IAAK,MAAM,CAAC,IAAI,MAAM,CAAC,IAAI,MAAM,CAAC;AAClE,eAAW,GAAG,IAAI;AAAA,EACpB;AACA,SAAO;AACT;AAKA,SAAS,oBAAoB,OAA6B;AACxD,QAAM,SAAmB,CAAC;AAC1B,aAAW,OAAO,OAAO,KAAK,KAAK,GAAG;AACpC,UAAM,QAAQ,OAAO,MAAM,GAAG,CAAC;AAC/B,WAAO,KAAK,GAAG,GAAG,KAAK,mBAAmB,KAAK,CAAC,GAAG;AAAA,EACrD;AACA,SAAO,OAAO,KAAK,GAAG;AACxB;AAMO,SAAS,OAAO,OAAe,OAA8B;AAClE,QAAM,SAAS,wBAAS,uBAAuB;AAE/C,QAAM,gBAAgB;AACtB,SAAO,MAAM,QAAQ,eAAe,CAAC,OAAO,YAAY;AAjL1D;AAmLI,QAAI,SAAS;AACX,YAAM,aAAa,gBAAgB,OAAO;AAC1C,YAAM,SAAS,OAAO,WAAW,IAAI;AACrC,UAAI,QAAQ;AACV,YAAI;AACF,gBAAM,eAAe,WAAW,QAAQ,KAAK,MAAM,aAAa,WAAW,KAAK,CAAC,IAAI,CAAC;AACtF,gBAAM,SAAS,OAAO,cAAc,kBAAkB;AAEtD,cAAI,OAAO,WAAW,UAAU;AAC9B,mBAAO;AAAA,UACT;AAEA,cAAI,OAAO,IAAI,OAAO,OAAO;AAC7B,cAAI,OAAO,YAAY;AACrB,oBAAQ,IAAI,oBAAoB,OAAO,UAAU,CAAC;AAAA,UACpD;AACA,cAAI,OAAO,WAAW,MAAM;AAC1B,oBAAQ;AAAA,UACV,OAAO;AACL,oBAAQ,KAAI,YAAO,cAAP,YAAoB,EAAE,KAAK,OAAO,OAAO;AAAA,UACvD;AACA,iBAAO;AAAA,QACT,SAAS,GAAG;AACV,kBAAQ,MAAM,mCAAmC,CAAC;AAAA,QACpD;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,EACT,CAAC;AACH;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["// Define a generic type for HTML attributes (key-value pairs)\ntype AttributeMap = Record<string, string>;\n\n// Structure representing the output HTML node\ninterface BoxHTMLNode {\n tagName: string;\n attributes?: AttributeMap;\n isVoid?: boolean; // True for self-closing tags like <img />, <hr />\n innerHTML?: string;\n}\n\n// Function signature for encoding HTML entities\ntype EncodeHTMLEntities = (value: string) => string;\n\n// Function signature for encoding HTML entities\ntype RenderBox = (boxValue: AttributeMap, encode: EncodeHTMLEntities) => BoxHTMLNode;\n\n// Registry of renderers for different box types\ntype BoxRenderers = Record<string, RenderBox>;\n\n/**\n * Extracts the ID from a URL.\n * Useful for extracting YouTube or Twitter IDs from clean URLs.\n */\nfunction extractIdFromUrl(url: string): string {\n const result = /[\\w\\-]+$/.exec(url);\n return result ? result[0] : '';\n}\n\n/**\n * Returns the default configuration for rendering various Lake attributes.\n */\nexport function getBoxRenderers(): BoxRenderers {\n return {\n hr: () => ({\n tagName: 'div',\n attributes: {\n class: 'lake-box-block lake-hr',\n },\n innerHTML: '<hr />',\n }),\n\n image: boxValue => ({\n tagName: 'img',\n attributes: {\n src: boxValue.url,\n ...(boxValue.width && { width: boxValue.width }),\n ...(boxValue.height && { height: boxValue.height }),\n ...(boxValue.caption && { alt: boxValue.caption }),\n border: '0',\n },\n isVoid: true,\n }),\n\n media: boxValue => ({\n tagName: 'video',\n attributes: {\n src: boxValue.url,\n ...(boxValue.width && { width: boxValue.width.replace(/px$/i, '') }),\n ...(boxValue.height && { height: boxValue.height.replace(/px$/i, '') }),\n controls: 'true',\n },\n }),\n\n file: (boxValue, encode) => ({\n tagName: 'a',\n attributes: {\n href: boxValue.url,\n target: '_blank',\n },\n innerHTML: encode(boxValue.name),\n }),\n\n codeBlock: (boxValue, encode) => ({\n tagName: 'pre',\n attributes: {\n class: `lang-${boxValue.lang}`,\n },\n innerHTML: `<code>${encode(boxValue.code)}</code>`,\n }),\n\n emoji: boxValue => ({\n tagName: 'img',\n attributes: {\n src: boxValue.url,\n width: '32',\n height: '32',\n border: '0',\n },\n isVoid: true,\n }),\n\n equation: boxValue => ({\n tagName: 'code',\n innerHTML: boxValue.code,\n }),\n\n mention: (boxValue, encode) => ({\n tagName: 'a',\n attributes: {\n href: `/${boxValue.name}`,\n target: '_blank',\n },\n innerHTML: encode(boxValue.nickname ?? boxValue.name),\n }),\n\n video: boxValue => ({\n tagName: 'iframe',\n attributes: {\n ...(boxValue.url && { src: `https://www.youtube.com/embed/${extractIdFromUrl(boxValue.url)}` }),\n width: boxValue.width ? boxValue.width.replace(/px$/i, '') : '560',\n height: boxValue.height ? boxValue.height.replace(/px$/i, '') : '315',\n title: 'YouTube video player',\n frameborder: '0',\n allow: 'accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share',\n referrerpolicy: 'strict-origin-when-cross-origin',\n allowfullscreen: 'true',\n },\n }),\n\n twitter: boxValue => ({\n tagName: 'iframe',\n attributes: {\n ...(boxValue.url && { src: `https://platform.twitter.com/embed/Tweet.html?id=${extractIdFromUrl(boxValue.url)}` }),\n title: 'Twitter tweet',\n scrolling: 'no',\n frameborder: '0',\n allowtransparency: 'true',\n allowfullscreen: 'true',\n style: 'width: 550px; height: 300px;',\n },\n }),\n };\n}\n\n// Map for reserved HTML characters\nconst htmlEntityMap = new Map([\n ['&', '&'],\n ['<', '<'],\n ['>', '>'],\n ['\"', '"'],\n ['\\xA0', ' '],\n]);\n\n/**\n * Escapes reserved HTML characters to prevent XSS and rendering issues.\n */\nfunction encodeHTMLEntities(value: string): string {\n return value.replace(/[&<>\"\\xA0]/g, match => htmlEntityMap.get(match)!);\n}\n\n/**\n * Decodes a Base64 encoded string with UTF-8 support.\n */\nfunction decodeBase64(value: string): string {\n const binaryString = atob(value);\n const byteArray = new Uint8Array(binaryString.length);\n for (let i = 0; i < binaryString.length; i++) {\n byteArray[i] = binaryString.charCodeAt(i);\n }\n const decoder = new TextDecoder();\n return decoder.decode(byteArray);\n}\n\n/**\n * Parses HTML tag attributes from a string into a key-value object.\n */\nfunction parseAttributes(tag: string): AttributeMap {\n const attributes: AttributeMap = {};\n // Regex breakdown:\n // Group 1/2: Key=Value (unquoted)\n // Group 3/4: Key=\"Value\" (double quoted)\n // Group 5/6: Key='Value' (single quoted)\n const reg = /\\s+(?:([\\w\\-:]+)=([^\\s\"'<>]+)|([\\w\\-:\"]+)=\"([^\"]*)\"|([\\w\\-:\"]+)='([^']*)')(?=[\\s/>])/g;\n let match: RegExpExecArray | null;\n while ((match = reg.exec(tag))) {\n const key = (match[1] || match[3] || match[5]).toLowerCase();\n const value = match[1] ? match[2] : (match[3] ? match[4] : match[6]);\n attributes[key] = value;\n }\n return attributes;\n}\n\n/**\n * Serializes an attribute map into an HTML attribute string.\n */\nfunction serializeAttributes(attrs: AttributeMap): string {\n const result: string[] = [];\n for (const key of Object.keys(attrs)) {\n const value = String(attrs[key]);\n result.push(`${key}=\"${encodeHTMLEntities(value)}\"`);\n }\n return result.join(' ');\n}\n\n/**\n * Serializes a BoxHTMLNode object into a standard HTML string.\n */\nfunction toBoxHTML(node: BoxHTMLNode): string {\n let result = `<${node.tagName}`;\n if (node.attributes) {\n result += ` ${serializeAttributes(node.attributes)}`;\n }\n if (node.isVoid === true) {\n result += ' />';\n } else {\n result += `>${node.innerHTML ?? ''}</${node.tagName}>`;\n }\n return result;\n}\n\n/**\n * Main function to convert Lake Markup Language (LML) to standard HTML.\n * It processes custom <lake-box> tags and removes internal anchors.\n */\nexport function toHTML(value: string, renderers?: BoxRenderers): string {\n renderers = renderers ?? getBoxRenderers();\n // Regex to match <lake-box>, <anchor>, and <focus> tags\n const combinedRegex = /(<lake-box[^>]+>)[\\s\\S]*?(?:<\\/lake-box>|$)|(<anchor\\s*\\/>)|(<focus\\s*\\/>)/gi;\n return value.replace(combinedRegex, (match, boxOpen) => {\n // Handle lake-box conversion\n if (boxOpen) {\n const attributes = parseAttributes(boxOpen);\n const render = renderers[attributes.name];\n if (render) {\n try {\n const boxValue = attributes.value ? JSON.parse(decodeBase64(attributes.value)) : {};\n const node = render(boxValue, encodeHTMLEntities);\n return toBoxHTML(node);\n } catch (e) {\n console.error('Failed to parse lake-box value:', e);\n }\n }\n }\n // Remove internal selection markers (<anchor /> and <focus />)\n return '';\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAwBA,SAAS,iBAAiB,KAAqB;AAC7C,QAAM,SAAS,WAAW,KAAK,GAAG;AAClC,SAAO,SAAS,OAAO,CAAC,IAAI;AAC9B;AAKO,SAAS,kBAAgC;AAC9C,SAAO;AAAA,IACL,IAAI,OAAO;AAAA,MACT,SAAS;AAAA,MACT,YAAY;AAAA,QACV,OAAO;AAAA,MACT;AAAA,MACA,WAAW;AAAA,IACb;AAAA,IAEA,OAAO,eAAa;AAAA,MAClB,SAAS;AAAA,MACT,YAAY;AAAA,QACV,KAAK,SAAS;AAAA,SACV,SAAS,SAAS,EAAE,OAAO,SAAS,MAAM,IAC1C,SAAS,UAAU,EAAE,QAAQ,SAAS,OAAO,IAC7C,SAAS,WAAW,EAAE,KAAK,SAAS,QAAQ,IAJtC;AAAA,QAKV,QAAQ;AAAA,MACV;AAAA,MACA,QAAQ;AAAA,IACV;AAAA,IAEA,OAAO,eAAa;AAAA,MAClB,SAAS;AAAA,MACT,YAAY;AAAA,QACV,KAAK,SAAS;AAAA,SACV,SAAS,SAAS,EAAE,OAAO,SAAS,MAAM,QAAQ,QAAQ,EAAE,EAAE,IAC9D,SAAS,UAAU,EAAE,QAAQ,SAAS,OAAO,QAAQ,QAAQ,EAAE,EAAE,IAH3D;AAAA,QAIV,UAAU;AAAA,MACZ;AAAA,IACF;AAAA,IAEA,MAAM,CAAC,UAAU,YAAY;AAAA,MAC3B,SAAS;AAAA,MACT,YAAY;AAAA,QACV,MAAM,SAAS;AAAA,QACf,QAAQ;AAAA,MACV;AAAA,MACA,WAAW,OAAO,SAAS,IAAI;AAAA,IACjC;AAAA,IAEA,WAAW,CAAC,UAAU,YAAY;AAAA,MAChC,SAAS;AAAA,MACT,YAAY;AAAA,QACV,OAAO,QAAQ,SAAS,IAAI;AAAA,MAC9B;AAAA,MACA,WAAW,SAAS,OAAO,SAAS,IAAI,CAAC;AAAA,IAC3C;AAAA,IAEA,OAAO,eAAa;AAAA,MAClB,SAAS;AAAA,MACT,YAAY;AAAA,QACV,KAAK,SAAS;AAAA,QACd,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,QAAQ;AAAA,MACV;AAAA,MACA,QAAQ;AAAA,IACV;AAAA,IAEA,UAAU,eAAa;AAAA,MACrB,SAAS;AAAA,MACT,WAAW,SAAS;AAAA,IACtB;AAAA,IAEA,SAAS,CAAC,UAAU,WAAQ;AAjGhC;AAiGoC;AAAA,QAC9B,SAAS;AAAA,QACT,YAAY;AAAA,UACV,MAAM,IAAI,SAAS,IAAI;AAAA,UACvB,QAAQ;AAAA,QACV;AAAA,QACA,WAAW,QAAO,cAAS,aAAT,YAAqB,SAAS,IAAI;AAAA,MACtD;AAAA;AAAA,IAEA,OAAO,eAAa;AAAA,MAClB,SAAS;AAAA,MACT,YAAY,iCACN,SAAS,OAAO,EAAE,KAAK,iCAAiC,iBAAiB,SAAS,GAAG,CAAC,GAAG,IADnF;AAAA,QAEV,OAAO,SAAS,QAAQ,SAAS,MAAM,QAAQ,QAAQ,EAAE,IAAI;AAAA,QAC7D,QAAQ,SAAS,SAAS,SAAS,OAAO,QAAQ,QAAQ,EAAE,IAAI;AAAA,QAChE,OAAO;AAAA,QACP,aAAa;AAAA,QACb,OAAO;AAAA,QACP,gBAAgB;AAAA,QAChB,iBAAiB;AAAA,MACnB;AAAA,IACF;AAAA,IAEA,SAAS,eAAa;AAAA,MACpB,SAAS;AAAA,MACT,YAAY,iCACN,SAAS,OAAO,EAAE,KAAK,oDAAoD,iBAAiB,SAAS,GAAG,CAAC,GAAG,IADtG;AAAA,QAEV,OAAO;AAAA,QACP,WAAW;AAAA,QACX,aAAa;AAAA,QACb,mBAAmB;AAAA,QACnB,iBAAiB;AAAA,QACjB,OAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF;AACF;AAGA,IAAM,gBAAgB,oBAAI,IAAI;AAAA,EAC5B,CAAC,KAAK,OAAO;AAAA,EACb,CAAC,KAAK,MAAM;AAAA,EACZ,CAAC,KAAK,MAAM;AAAA,EACZ,CAAC,KAAK,QAAQ;AAAA,EACd,CAAC,QAAQ,QAAQ;AACnB,CAAC;AAKD,SAAS,mBAAmB,OAAuB;AACjD,SAAO,MAAM,QAAQ,eAAe,WAAS,cAAc,IAAI,KAAK,CAAE;AACxE;AAKA,SAAS,aAAa,OAAuB;AAC3C,QAAM,eAAe,KAAK,KAAK;AAC/B,QAAM,YAAY,IAAI,WAAW,aAAa,MAAM;AACpD,WAAS,IAAI,GAAG,IAAI,aAAa,QAAQ,KAAK;AAC5C,cAAU,CAAC,IAAI,aAAa,WAAW,CAAC;AAAA,EAC1C;AACA,QAAM,UAAU,IAAI,YAAY;AAChC,SAAO,QAAQ,OAAO,SAAS;AACjC;AAKA,SAAS,gBAAgB,KAA2B;AAClD,QAAM,aAA2B,CAAC;AAKlC,QAAM,MAAM;AACZ,MAAI;AACJ,SAAQ,QAAQ,IAAI,KAAK,GAAG,GAAI;AAC9B,UAAM,OAAO,MAAM,CAAC,KAAK,MAAM,CAAC,KAAK,MAAM,CAAC,GAAG,YAAY;AAC3D,UAAM,QAAQ,MAAM,CAAC,IAAI,MAAM,CAAC,IAAK,MAAM,CAAC,IAAI,MAAM,CAAC,IAAI,MAAM,CAAC;AAClE,eAAW,GAAG,IAAI;AAAA,EACpB;AACA,SAAO;AACT;AAKA,SAAS,oBAAoB,OAA6B;AACxD,QAAM,SAAmB,CAAC;AAC1B,aAAW,OAAO,OAAO,KAAK,KAAK,GAAG;AACpC,UAAM,QAAQ,OAAO,MAAM,GAAG,CAAC;AAC/B,WAAO,KAAK,GAAG,GAAG,KAAK,mBAAmB,KAAK,CAAC,GAAG;AAAA,EACrD;AACA,SAAO,OAAO,KAAK,GAAG;AACxB;AAKA,SAAS,UAAU,MAA2B;AAtM9C;AAuME,MAAI,SAAS,IAAI,KAAK,OAAO;AAC7B,MAAI,KAAK,YAAY;AACnB,cAAU,IAAI,oBAAoB,KAAK,UAAU,CAAC;AAAA,EACpD;AACA,MAAI,KAAK,WAAW,MAAM;AACxB,cAAU;AAAA,EACZ,OAAO;AACL,cAAU,KAAI,UAAK,cAAL,YAAkB,EAAE,KAAK,KAAK,OAAO;AAAA,EACrD;AACA,SAAO;AACT;AAMO,SAAS,OAAO,OAAe,WAAkC;AACtE,cAAY,gCAAa,gBAAgB;AAEzC,QAAM,gBAAgB;AACtB,SAAO,MAAM,QAAQ,eAAe,CAAC,OAAO,YAAY;AAEtD,QAAI,SAAS;AACX,YAAM,aAAa,gBAAgB,OAAO;AAC1C,YAAM,SAAS,UAAU,WAAW,IAAI;AACxC,UAAI,QAAQ;AACV,YAAI;AACF,gBAAM,WAAW,WAAW,QAAQ,KAAK,MAAM,aAAa,WAAW,KAAK,CAAC,IAAI,CAAC;AAClF,gBAAM,OAAO,OAAO,UAAU,kBAAkB;AAChD,iBAAO,UAAU,IAAI;AAAA,QACvB,SAAS,GAAG;AACV,kBAAQ,MAAM,mCAAmC,CAAC;AAAA,QACpD;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,EACT,CAAC;AACH;","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lake-html",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "A lightweight utility to convert Lake Markup Language (LML) to HTML",
|
|
5
5
|
"author": "Luo Longhao <luolonghao@gmail.com>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
],
|
|
33
33
|
"devDependencies": {
|
|
34
34
|
"@antfu/eslint-config": "^7.2.0",
|
|
35
|
-
"@vitest/coverage-v8": "4.0.
|
|
35
|
+
"@vitest/coverage-v8": "^4.0.18",
|
|
36
36
|
"conventional-changelog-cli": "^5.0.0",
|
|
37
37
|
"eslint": "^9.39.2",
|
|
38
38
|
"execa": "^9.6.1",
|