overtype 1.1.5 → 1.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -1
- package/dist/overtype.esm.js +35 -7
- package/dist/overtype.esm.js.map +2 -2
- package/dist/overtype.js +35 -7
- package/dist/overtype.js.map +2 -2
- package/dist/overtype.min.js +10 -10
- package/package.json +1 -1
- package/src/parser.js +66 -11
package/README.md
CHANGED
|
@@ -483,7 +483,10 @@ OverType uses a unique invisible textarea overlay approach:
|
|
|
483
483
|
## Contributors
|
|
484
484
|
|
|
485
485
|
Special thanks to:
|
|
486
|
-
- [Josh Doman](https://github.com/joshdoman) - Fixed inline code formatting preservation ([#6](https://github.com/panphora/overtype/pull/6))
|
|
486
|
+
- [Josh Doman](https://github.com/joshdoman) - Fixed inline code formatting preservation ([#6](https://github.com/panphora/overtype/pull/6)), improved code fence detection ([#19](https://github.com/panphora/overtype/pull/19))
|
|
487
|
+
- [kbhomes](https://github.com/kbhomes) - Fixed text selection desynchronization during overscroll ([#17](https://github.com/panphora/overtype/pull/17))
|
|
488
|
+
- [merlinz01](https://github.com/merlinz01) - Initial TypeScript definitions implementation ([#20](https://github.com/panphora/overtype/pull/20))
|
|
489
|
+
- [Max Bernstein](https://github.com/tekknolagi) - Fixed typo in website ([#11](https://github.com/panphora/overtype/pull/11))
|
|
487
490
|
|
|
488
491
|
## License
|
|
489
492
|
|
package/dist/overtype.esm.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* OverType v1.1.
|
|
2
|
+
* OverType v1.1.7
|
|
3
3
|
* A lightweight markdown editor library with perfect WYSIWYG alignment
|
|
4
4
|
* @license MIT
|
|
5
5
|
* @author Demo User
|
|
@@ -140,6 +140,28 @@ var MarkdownParser = class {
|
|
|
140
140
|
static parseInlineCode(html) {
|
|
141
141
|
return html.replace(new RegExp("(?<!`)(`+)(?!`)((?:(?!\\1).)+?)(\\1)(?!`)", "g"), '<code><span class="syntax-marker">$1</span>$2<span class="syntax-marker">$3</span></code>');
|
|
142
142
|
}
|
|
143
|
+
/**
|
|
144
|
+
* Sanitize URL to prevent XSS attacks
|
|
145
|
+
* @param {string} url - URL to sanitize
|
|
146
|
+
* @returns {string} Safe URL or '#' if dangerous
|
|
147
|
+
*/
|
|
148
|
+
static sanitizeUrl(url) {
|
|
149
|
+
const trimmed = url.trim();
|
|
150
|
+
const lower = trimmed.toLowerCase();
|
|
151
|
+
const safeProtocols = [
|
|
152
|
+
"http://",
|
|
153
|
+
"https://",
|
|
154
|
+
"mailto:",
|
|
155
|
+
"ftp://",
|
|
156
|
+
"ftps://"
|
|
157
|
+
];
|
|
158
|
+
const hasSafeProtocol = safeProtocols.some((protocol) => lower.startsWith(protocol));
|
|
159
|
+
const isRelative = trimmed.startsWith("/") || trimmed.startsWith("#") || trimmed.startsWith("?") || trimmed.startsWith(".") || !trimmed.includes(":") && !trimmed.includes("//");
|
|
160
|
+
if (hasSafeProtocol || isRelative) {
|
|
161
|
+
return url;
|
|
162
|
+
}
|
|
163
|
+
return "#";
|
|
164
|
+
}
|
|
143
165
|
/**
|
|
144
166
|
* Parse links
|
|
145
167
|
* @param {string} html - HTML with potential link markdown
|
|
@@ -148,7 +170,8 @@ var MarkdownParser = class {
|
|
|
148
170
|
static parseLinks(html) {
|
|
149
171
|
return html.replace(/\[(.+?)\]\((.+?)\)/g, (match, text, url) => {
|
|
150
172
|
const anchorName = `--link-${this.linkIndex++}`;
|
|
151
|
-
|
|
173
|
+
const safeUrl = this.sanitizeUrl(url);
|
|
174
|
+
return `<a href="${safeUrl}" style="anchor-name: ${anchorName}"><span class="syntax-marker">[</span>${text}<span class="syntax-marker">](</span><span class="syntax-marker link-url">${url}</span><span class="syntax-marker">)</span></a>`;
|
|
152
175
|
});
|
|
153
176
|
}
|
|
154
177
|
/**
|
|
@@ -159,17 +182,22 @@ var MarkdownParser = class {
|
|
|
159
182
|
static parseInlineElements(text) {
|
|
160
183
|
let html = text;
|
|
161
184
|
html = this.parseInlineCode(html);
|
|
162
|
-
const
|
|
185
|
+
const sanctuaries = /* @__PURE__ */ new Map();
|
|
163
186
|
html = html.replace(/(<code>.*?<\/code>)/g, (match) => {
|
|
164
|
-
const placeholder = `\uE000${
|
|
165
|
-
|
|
187
|
+
const placeholder = `\uE000${sanctuaries.size}\uE001`;
|
|
188
|
+
sanctuaries.set(placeholder, match);
|
|
166
189
|
return placeholder;
|
|
167
190
|
});
|
|
168
191
|
html = this.parseLinks(html);
|
|
192
|
+
html = html.replace(/(<a[^>]*>.*?<\/a>)/g, (match) => {
|
|
193
|
+
const placeholder = `\uE000${sanctuaries.size}\uE001`;
|
|
194
|
+
sanctuaries.set(placeholder, match);
|
|
195
|
+
return placeholder;
|
|
196
|
+
});
|
|
169
197
|
html = this.parseBold(html);
|
|
170
198
|
html = this.parseItalic(html);
|
|
171
|
-
|
|
172
|
-
html = html.replace(placeholder,
|
|
199
|
+
sanctuaries.forEach((content, placeholder) => {
|
|
200
|
+
html = html.replace(placeholder, content);
|
|
173
201
|
});
|
|
174
202
|
return html;
|
|
175
203
|
}
|