overtype 1.2.4 → 1.2.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/README.md +4 -4
- package/dist/overtype.cjs +104 -19
- package/dist/overtype.cjs.map +2 -2
- package/dist/overtype.esm.js +104 -19
- package/dist/overtype.esm.js.map +2 -2
- package/dist/overtype.js +104 -19
- package/dist/overtype.js.map +2 -2
- package/dist/overtype.min.js +49 -49
- package/package.json +3 -2
- package/src/parser.js +145 -32
package/dist/overtype.esm.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* OverType v1.2.
|
|
2
|
+
* OverType v1.2.5
|
|
3
3
|
* A lightweight markdown editor library with perfect WYSIWYG alignment
|
|
4
4
|
* @license MIT
|
|
5
5
|
* @author Demo User
|
|
@@ -128,7 +128,7 @@ var MarkdownParser = class {
|
|
|
128
128
|
*/
|
|
129
129
|
static parseItalic(html) {
|
|
130
130
|
html = html.replace(new RegExp("(?<!\\*)\\*(?!\\*)(.+?)(?<!\\*)\\*(?!\\*)", "g"), '<em><span class="syntax-marker">*</span>$1<span class="syntax-marker">*</span></em>');
|
|
131
|
-
html = html.replace(new RegExp("(
|
|
131
|
+
html = html.replace(new RegExp("(?<=^|\\s)_(?!_)(.+?)(?<!_)_(?!_)(?=\\s|$)", "g"), '<em><span class="syntax-marker">_</span>$1<span class="syntax-marker">_</span></em>');
|
|
132
132
|
return html;
|
|
133
133
|
}
|
|
134
134
|
/**
|
|
@@ -185,31 +185,116 @@ var MarkdownParser = class {
|
|
|
185
185
|
});
|
|
186
186
|
}
|
|
187
187
|
/**
|
|
188
|
-
*
|
|
189
|
-
* @param {string} text - Text with potential
|
|
190
|
-
* @returns {
|
|
188
|
+
* Identify and protect sanctuaries (code and links) before parsing
|
|
189
|
+
* @param {string} text - Text with potential markdown
|
|
190
|
+
* @returns {Object} Object with protected text and sanctuary map
|
|
191
191
|
*/
|
|
192
|
-
static
|
|
193
|
-
let html = text;
|
|
194
|
-
html = this.parseInlineCode(html);
|
|
192
|
+
static identifyAndProtectSanctuaries(text) {
|
|
195
193
|
const sanctuaries = /* @__PURE__ */ new Map();
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
194
|
+
let sanctuaryCounter = 0;
|
|
195
|
+
let protectedText = text;
|
|
196
|
+
const protectedRegions = [];
|
|
197
|
+
const linkRegex = /\[([^\]]+)\]\(([^)]+)\)/g;
|
|
198
|
+
let linkMatch;
|
|
199
|
+
while ((linkMatch = linkRegex.exec(text)) !== null) {
|
|
200
|
+
const bracketPos = linkMatch.index + linkMatch[0].indexOf("](");
|
|
201
|
+
const urlStart = bracketPos + 2;
|
|
202
|
+
const urlEnd = urlStart + linkMatch[2].length;
|
|
203
|
+
protectedRegions.push({ start: urlStart, end: urlEnd });
|
|
204
|
+
}
|
|
205
|
+
const codeRegex = new RegExp("(?<!`)(`+)(?!`)((?:(?!\\1).)+?)(\\1)(?!`)", "g");
|
|
206
|
+
let codeMatch;
|
|
207
|
+
const codeMatches = [];
|
|
208
|
+
while ((codeMatch = codeRegex.exec(text)) !== null) {
|
|
209
|
+
const codeStart = codeMatch.index;
|
|
210
|
+
const codeEnd = codeMatch.index + codeMatch[0].length;
|
|
211
|
+
const inProtectedRegion = protectedRegions.some(
|
|
212
|
+
(region) => codeStart >= region.start && codeEnd <= region.end
|
|
213
|
+
);
|
|
214
|
+
if (!inProtectedRegion) {
|
|
215
|
+
codeMatches.push({
|
|
216
|
+
match: codeMatch[0],
|
|
217
|
+
index: codeMatch.index,
|
|
218
|
+
openTicks: codeMatch[1],
|
|
219
|
+
content: codeMatch[2],
|
|
220
|
+
closeTicks: codeMatch[3]
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
codeMatches.sort((a, b) => b.index - a.index);
|
|
225
|
+
codeMatches.forEach((codeInfo) => {
|
|
226
|
+
const placeholder = `\uE000${sanctuaryCounter++}\uE001`;
|
|
227
|
+
sanctuaries.set(placeholder, {
|
|
228
|
+
type: "code",
|
|
229
|
+
original: codeInfo.match,
|
|
230
|
+
openTicks: codeInfo.openTicks,
|
|
231
|
+
content: codeInfo.content,
|
|
232
|
+
closeTicks: codeInfo.closeTicks
|
|
233
|
+
});
|
|
234
|
+
protectedText = protectedText.substring(0, codeInfo.index) + placeholder + protectedText.substring(codeInfo.index + codeInfo.match.length);
|
|
200
235
|
});
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
236
|
+
protectedText = protectedText.replace(/\[([^\]]+)\]\(([^)]+)\)/g, (match, linkText, url) => {
|
|
237
|
+
const placeholder = `\uE000${sanctuaryCounter++}\uE001`;
|
|
238
|
+
sanctuaries.set(placeholder, {
|
|
239
|
+
type: "link",
|
|
240
|
+
original: match,
|
|
241
|
+
linkText,
|
|
242
|
+
url
|
|
243
|
+
});
|
|
205
244
|
return placeholder;
|
|
206
245
|
});
|
|
246
|
+
return { protectedText, sanctuaries };
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Restore and transform sanctuaries back to HTML
|
|
250
|
+
* @param {string} html - HTML with sanctuary placeholders
|
|
251
|
+
* @param {Map} sanctuaries - Map of sanctuaries to restore
|
|
252
|
+
* @returns {string} HTML with sanctuaries restored and transformed
|
|
253
|
+
*/
|
|
254
|
+
static restoreAndTransformSanctuaries(html, sanctuaries) {
|
|
255
|
+
const placeholders = Array.from(sanctuaries.keys()).sort((a, b) => {
|
|
256
|
+
const indexA = html.indexOf(a);
|
|
257
|
+
const indexB = html.indexOf(b);
|
|
258
|
+
return indexA - indexB;
|
|
259
|
+
});
|
|
260
|
+
placeholders.forEach((placeholder) => {
|
|
261
|
+
const sanctuary = sanctuaries.get(placeholder);
|
|
262
|
+
let replacement;
|
|
263
|
+
if (sanctuary.type === "code") {
|
|
264
|
+
replacement = `<code><span class="syntax-marker">${sanctuary.openTicks}</span>${this.escapeHtml(sanctuary.content)}<span class="syntax-marker">${sanctuary.closeTicks}</span></code>`;
|
|
265
|
+
} else if (sanctuary.type === "link") {
|
|
266
|
+
let processedLinkText = sanctuary.linkText;
|
|
267
|
+
sanctuaries.forEach((innerSanctuary, innerPlaceholder) => {
|
|
268
|
+
if (processedLinkText.includes(innerPlaceholder)) {
|
|
269
|
+
if (innerSanctuary.type === "code") {
|
|
270
|
+
const codeHtml = `<code><span class="syntax-marker">${innerSanctuary.openTicks}</span>${this.escapeHtml(innerSanctuary.content)}<span class="syntax-marker">${innerSanctuary.closeTicks}</span></code>`;
|
|
271
|
+
processedLinkText = processedLinkText.replace(innerPlaceholder, codeHtml);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
});
|
|
275
|
+
processedLinkText = this.parseStrikethrough(processedLinkText);
|
|
276
|
+
processedLinkText = this.parseBold(processedLinkText);
|
|
277
|
+
processedLinkText = this.parseItalic(processedLinkText);
|
|
278
|
+
const anchorName = `--link-${this.linkIndex++}`;
|
|
279
|
+
const safeUrl = this.sanitizeUrl(sanctuary.url);
|
|
280
|
+
replacement = `<a href="${safeUrl}" style="anchor-name: ${anchorName}"><span class="syntax-marker">[</span>${processedLinkText}<span class="syntax-marker url-part">](${this.escapeHtml(sanctuary.url)})</span></a>`;
|
|
281
|
+
}
|
|
282
|
+
html = html.replace(placeholder, replacement);
|
|
283
|
+
});
|
|
284
|
+
return html;
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* Parse all inline elements in correct order
|
|
288
|
+
* @param {string} text - Text with potential inline markdown
|
|
289
|
+
* @returns {string} HTML with all inline styling
|
|
290
|
+
*/
|
|
291
|
+
static parseInlineElements(text) {
|
|
292
|
+
const { protectedText, sanctuaries } = this.identifyAndProtectSanctuaries(text);
|
|
293
|
+
let html = protectedText;
|
|
207
294
|
html = this.parseStrikethrough(html);
|
|
208
295
|
html = this.parseBold(html);
|
|
209
296
|
html = this.parseItalic(html);
|
|
210
|
-
|
|
211
|
-
html = html.replace(placeholder, content);
|
|
212
|
-
});
|
|
297
|
+
html = this.restoreAndTransformSanctuaries(html, sanctuaries);
|
|
213
298
|
return html;
|
|
214
299
|
}
|
|
215
300
|
/**
|