pantsdown 2.2.3 → 2.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/src/utils.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { type Lexer } from "./lexer.ts";
2
- import { type HTMLAttrs, type SourceMap, type Tokens } from "./types.ts";
2
+ import { PantsdownConfig, type HTMLAttrs, type SourceMap, type Tokens } from "./types.ts";
3
3
 
4
4
  /**
5
5
  * Helpers
@@ -9,158 +9,195 @@ const escapeReplace = new RegExp(escapeTest.source, "g");
9
9
  const escapeTestNoEncode = /[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/;
10
10
  const escapeReplaceNoEncode = new RegExp(escapeTestNoEncode.source, "g");
11
11
  const escapeReplacements: Record<string, string> = {
12
- "&": "&amp;",
13
- "<": "&lt;",
14
- ">": "&gt;",
15
- '"': "&quot;",
16
- "'": "&#39;",
12
+ "&": "&amp;",
13
+ "<": "&lt;",
14
+ ">": "&gt;",
15
+ '"': "&quot;",
16
+ "'": "&#39;",
17
17
  };
18
18
  const getEscapeReplacement = (ch: string) => escapeReplacements[ch]!;
19
19
 
20
20
  // look into using Bun's Bun.escapeHTML()
21
21
  // https://bun.sh/docs/api/utils#bun-escapehtml
22
22
  export function escape(html: string, encode?: boolean) {
23
- if (encode) {
24
- if (escapeTest.test(html)) {
25
- return html.replace(escapeReplace, getEscapeReplacement);
26
- }
27
- } else {
28
- if (escapeTestNoEncode.test(html)) {
29
- return html.replace(escapeReplaceNoEncode, getEscapeReplacement);
30
- }
31
- }
32
-
33
- return html;
23
+ if (encode) {
24
+ if (escapeTest.test(html)) {
25
+ return html.replace(escapeReplace, getEscapeReplacement);
26
+ }
27
+ } else {
28
+ if (escapeTestNoEncode.test(html)) {
29
+ return html.replace(escapeReplaceNoEncode, getEscapeReplacement);
30
+ }
31
+ }
32
+
33
+ return html;
34
34
  }
35
35
 
36
36
  export function getHtmlElementText(html: string) {
37
- try {
38
- const parser = new DOMParser();
39
- const doc = parser.parseFromString(html, "text/html");
40
- // eslint-disable-next-line
41
- if (!doc.body) throw Error("Invalid HTML");
42
- const element = doc.body.firstChild as HTMLElement;
43
- // eslint-disable-next-line
44
- if (!element) throw Error("No valid element found");
45
- return element.textContent ?? html;
46
- } catch (_) {
47
- return html;
48
- }
37
+ try {
38
+ const parser = new DOMParser();
39
+ const doc = parser.parseFromString(html, "text/html");
40
+ // eslint-disable-next-line
41
+ if (!doc.body) throw Error("Invalid HTML");
42
+ const element = doc.body.firstChild as HTMLElement;
43
+ // eslint-disable-next-line
44
+ if (!element) throw Error("No valid element found");
45
+ return element.textContent || html;
46
+ } catch (_) {
47
+ return html;
48
+ }
49
49
  }
50
50
 
51
51
  export function injectHtmlAttributes(html: string, attrs: HTMLAttrs, sourceMap?: SourceMap) {
52
- if (sourceMap) {
53
- attrs.push(["line-start", String(sourceMap[0])]);
54
- attrs.push(["line-end", String(sourceMap[1])]);
55
- }
56
-
57
- if (!attrs.length) return html;
58
-
59
- const closingBracket = /[a-zA-Z0-9\/"]>/;
60
- const match = closingBracket.exec(html);
61
- if (match) {
62
- let htmlAttrs = "";
63
- attrs.forEach((atrr) => (htmlAttrs += ` ${atrr[0]}="${atrr[1]}"`));
64
- const sliceIdx = match.index + (match[0] === "/>" ? -1 : 1);
65
- return html.slice(0, sliceIdx) + htmlAttrs + html.slice(sliceIdx);
66
- }
67
- return html;
52
+ if (sourceMap) {
53
+ attrs.push(["line-start", String(sourceMap[0])]);
54
+ attrs.push(["line-end", String(sourceMap[1])]);
55
+ }
56
+
57
+ if (!attrs.length) return html;
58
+
59
+ const closingBracket = /[a-zA-Z0-9\/"]>/;
60
+ const match = closingBracket.exec(html);
61
+ if (match) {
62
+ let htmlAttrs = "";
63
+ attrs.forEach((atrr) => (htmlAttrs += ` ${atrr[0]}="${atrr[1]}"`));
64
+ const sliceIdx = match.index + (match[0] === "/>" ? -1 : 1);
65
+ return html.slice(0, sliceIdx) + htmlAttrs + html.slice(sliceIdx);
66
+ }
67
+ return html;
68
68
  }
69
69
 
70
- export function fixHtmlLocalImageHref(
71
- html: string,
72
- relativeImageUrlPrefix: string | undefined,
73
- ): string {
74
- return relativeImageUrlPrefix
75
- ? html.replace(
76
- /<img\s+([^>]*?)src\s*=\s*(["'])([^>'"]+?)\2([^>]*)>/gm,
77
- (_m, g1, _g2, g3: string, g4) => {
78
- const href = fixLocalImageHref(g3, relativeImageUrlPrefix);
79
- return `<img ${g1}src="${href}"${g4}>`;
80
- },
81
- )
82
- : html;
70
+ export function fixHtmlLocalImageHref(html: string, config: PantsdownConfig): string {
71
+ return config.renderer.relativeImageUrlPrefix
72
+ ? html.replace(
73
+ /<img\s+([^>]*?)src\s*=\s*(["'])([^>'"]+?)\2([^>]*)>/gm,
74
+ (_m, g1, _g2, g3: string, g4) => {
75
+ const href = fixLocalImageHref(g3, config);
76
+ return `<img ${g1}src="${href}"${g4}>`;
77
+ },
78
+ )
79
+ : html;
83
80
  }
84
81
 
85
- export function fixLocalImageHref(
86
- href: string,
87
- relativeImageUrlPrefix: string | undefined,
88
- ): string {
89
- if (!relativeImageUrlPrefix) return href;
90
-
91
- const reIsAbsolute = /^[\w+]+:\/\//;
92
- const dummyUrl = "http://__dummy__";
93
- const dummyBaseUrl = new URL(relativeImageUrlPrefix, dummyUrl);
94
- const dummyUrlLength = dummyUrl.length + (relativeImageUrlPrefix.startsWith("/") ? 0 : 1);
95
-
96
- if (reIsAbsolute.test(href)) {
97
- // the URL is absolute, do not touch it
98
- return href;
99
- }
100
-
101
- if (href.startsWith("/")) {
102
- // the URL is from root
103
- return relativeImageUrlPrefix + href.slice(1);
104
- }
105
-
106
- try {
107
- const temp = new URL(href, dummyBaseUrl).href;
108
- return temp.slice(dummyUrlLength);
109
- } catch (_) {
110
- return href;
111
- }
82
+ /**
83
+ * Add GitHub-style inline styles to images with dimension attributes.
84
+ * - If `height` or `width` is specified: adds `max-width: 100%`
85
+ * - If `height` is specified: also adds `height: auto; max-height: {height}`
86
+ */
87
+ export function addGithubImageStyles(html: string): string {
88
+ return html.replace(/<img\s+([^>]*)>/gi, (_match, attrs: string) => {
89
+ const heightMatch = /height\s*=\s*["']?(\d+(?:px)?)["']?/i.exec(attrs);
90
+ const widthMatch = /width\s*=\s*["']?(\d+(?:px)?)["']?/i.exec(attrs);
91
+
92
+ if (!heightMatch && !widthMatch) return _match;
93
+
94
+ // Build style string matching GitHub's behavior
95
+ const styles: string[] = ["max-width: 100%"];
96
+ if (heightMatch?.[1]) {
97
+ const value = heightMatch[1].endsWith("px") ? heightMatch[1] : `${heightMatch[1]}px`;
98
+ styles.push("height: auto", `max-height: ${value}`);
99
+ }
100
+
101
+ // Check for existing style attribute
102
+ const styleMatch = /style\s*=\s*["']([^"']*)["']/i.exec(attrs);
103
+ let newAttrs = attrs;
104
+
105
+ if (styleMatch?.[1]) {
106
+ // Append to existing style
107
+ const existingStyle = styleMatch[1].trim();
108
+ const separator = existingStyle.endsWith(";") ? " " : "; ";
109
+ const newStyle = existingStyle + separator + styles.join("; ");
110
+ newAttrs = attrs.replace(styleMatch[0], `style="${newStyle}"`);
111
+ } else {
112
+ // Add new style attribute
113
+ newAttrs = attrs + ` style="${styles.join("; ")}"`;
114
+ }
115
+
116
+ return `<img ${newAttrs}>`;
117
+ });
118
+ }
119
+
120
+ export function fixLocalImageHref(href: string, config: PantsdownConfig): string {
121
+ if (!config.renderer.relativeImageUrlPrefix) return href;
122
+
123
+ // http://something
124
+ const refIsExternal = /^[\w+]+:\/\//;
125
+ const dummyUrl = "http://__dummy__";
126
+ const dummyBaseUrl = new URL(config.renderer.relativeImageUrlPrefix, dummyUrl);
127
+ const dummyUrlLength =
128
+ dummyUrl.length + (config.renderer.relativeImageUrlPrefix.startsWith("/") ? 0 : 1);
129
+
130
+ if (refIsExternal.test(href)) {
131
+ // the URL is external, do not touch it
132
+ return href;
133
+ }
134
+
135
+ if (href.startsWith("/")) {
136
+ // the URL is from root
137
+ return (
138
+ (config.renderer.absoluteImageUrlPrefix ?? config.renderer.relativeImageUrlPrefix) +
139
+ href.slice(1)
140
+ );
141
+ }
142
+
143
+ try {
144
+ const temp = new URL(href, dummyBaseUrl).href;
145
+ return temp.slice(dummyUrlLength);
146
+ } catch (_) {
147
+ return href;
148
+ }
112
149
  }
113
150
 
114
151
  export function cleanUrl(href: string) {
115
- try {
116
- href = encodeURI(href).replace(/%25/g, "%");
117
- } catch (_) {
118
- return null;
119
- }
120
- return href;
152
+ try {
153
+ href = encodeURI(href).replace(/%25/g, "%");
154
+ } catch (_) {
155
+ return null;
156
+ }
157
+ return href;
121
158
  }
122
159
 
123
160
  export const noopTest = { exec: () => null };
124
161
 
125
162
  export function splitCells(tableRow: string, count?: number) {
126
- // ensure that every cell-delimiting pipe has a space
127
- // before it to distinguish it from an escaped pipe
128
- const row = tableRow.replace(/\|/g, (_match, offset: number, str: string) => {
129
- let escaped = false;
130
- let curr = offset;
131
- while (--curr >= 0 && str[curr] === "\\") escaped = !escaped;
132
- if (escaped) {
133
- // odd number of slashes means | is escaped
134
- // so we leave it alone
135
- return "|";
136
- } else {
137
- // add space before unescaped |
138
- return " |";
139
- }
140
- }),
141
- cells = row.split(/ \|/);
142
-
143
- // First/last cell in a row cannot be empty if it has no leading/trailing pipe
144
- if (!cells[0]?.trim()) {
145
- cells.shift();
146
- }
147
- if (cells.length > 0 && !cells[cells.length - 1]?.trim()) {
148
- cells.pop();
149
- }
150
-
151
- if (count) {
152
- if (cells.length > count) {
153
- cells.splice(count);
154
- } else {
155
- while (cells.length < count) cells.push("");
156
- }
157
- }
158
-
159
- for (let i = 0, len = cells.length; i < len; i++) {
160
- // leading or trailing whitespace is ignored per the gfm spec
161
- cells[i] = cells[i]!.trim().replace(/\\\|/g, "|");
162
- }
163
- return cells;
163
+ // ensure that every cell-delimiting pipe has a space
164
+ // before it to distinguish it from an escaped pipe
165
+ const row = tableRow.replace(/\|/g, (_match, offset: number, str: string) => {
166
+ let escaped = false;
167
+ let curr = offset;
168
+ while (--curr >= 0 && str[curr] === "\\") escaped = !escaped;
169
+ if (escaped) {
170
+ // odd number of slashes means | is escaped
171
+ // so we leave it alone
172
+ return "|";
173
+ } else {
174
+ // add space before unescaped |
175
+ return " |";
176
+ }
177
+ }),
178
+ cells = row.split(/ \|/);
179
+
180
+ // First/last cell in a row cannot be empty if it has no leading/trailing pipe
181
+ if (!cells[0]?.trim()) {
182
+ cells.shift();
183
+ }
184
+ if (cells.length > 0 && !cells[cells.length - 1]?.trim()) {
185
+ cells.pop();
186
+ }
187
+
188
+ if (count) {
189
+ if (cells.length > count) {
190
+ cells.splice(count);
191
+ } else {
192
+ while (cells.length < count) cells.push("");
193
+ }
194
+ }
195
+
196
+ for (let i = 0, len = cells.length; i < len; i++) {
197
+ // leading or trailing whitespace is ignored per the gfm spec
198
+ cells[i] = cells[i]!.trim().replace(/\\\|/g, "|");
199
+ }
200
+ return cells;
164
201
  }
165
202
 
166
203
  /**
@@ -172,138 +209,138 @@ export function splitCells(tableRow: string, count?: number) {
172
209
  * @param invert Remove suffix of non-c chars instead. Default falsey.
173
210
  */
174
211
  export function rtrim(str: string, c: string, invert?: boolean) {
175
- const l = str.length;
176
- if (l === 0) {
177
- return "";
178
- }
179
-
180
- // Length of suffix matching the invert condition.
181
- let suffLen = 0;
182
-
183
- // Step left until we fail to match the invert condition.
184
- while (suffLen < l) {
185
- const currChar = str.charAt(l - suffLen - 1);
186
- if (currChar === c && !invert) {
187
- suffLen++;
188
- } else if (currChar !== c && invert) {
189
- suffLen++;
190
- } else {
191
- break;
192
- }
193
- }
194
-
195
- return str.slice(0, l - suffLen);
212
+ const l = str.length;
213
+ if (l === 0) {
214
+ return "";
215
+ }
216
+
217
+ // Length of suffix matching the invert condition.
218
+ let suffLen = 0;
219
+
220
+ // Step left until we fail to match the invert condition.
221
+ while (suffLen < l) {
222
+ const currChar = str.charAt(l - suffLen - 1);
223
+ if (currChar === c && !invert) {
224
+ suffLen++;
225
+ } else if (currChar !== c && invert) {
226
+ suffLen++;
227
+ } else {
228
+ break;
229
+ }
230
+ }
231
+
232
+ return str.slice(0, l - suffLen);
196
233
  }
197
234
 
198
235
  export function findClosingBracket(str: string, b: string) {
199
- if (!b[1] || !str.includes(b[1])) {
200
- return -1;
201
- }
202
-
203
- let level = 0;
204
- for (let i = 0, len = str.length; i < len; i++) {
205
- if (str[i] === "\\") {
206
- i++;
207
- } else if (str[i] === b[0]) {
208
- level++;
209
- } else if (str[i] === b[1]) {
210
- level--;
211
- if (level < 0) {
212
- return i;
213
- }
214
- }
215
- }
216
- return -1;
236
+ if (!b[1] || !str.includes(b[1])) {
237
+ return -1;
238
+ }
239
+
240
+ let level = 0;
241
+ for (let i = 0, len = str.length; i < len; i++) {
242
+ if (str[i] === "\\") {
243
+ i++;
244
+ } else if (str[i] === b[0]) {
245
+ level++;
246
+ } else if (str[i] === b[1]) {
247
+ level--;
248
+ if (level < 0) {
249
+ return i;
250
+ }
251
+ }
252
+ }
253
+ return -1;
217
254
  }
218
255
 
219
256
  export function outputLink(
220
- cap: string[],
221
- link: Pick<Tokens["Link"], "href" | "title">,
222
- raw: string,
223
- lexer: Lexer,
257
+ cap: string[],
258
+ link: Pick<Tokens["Link"], "href" | "title">,
259
+ raw: string,
260
+ lexer: Lexer,
224
261
  ): Tokens["Link"] | Tokens["Image"] {
225
- const href = link.href;
226
- const title = link.title ? escape(link.title) : null;
227
- const text = cap[1]?.replace(/\\([\[\]])/g, "$1") ?? "";
228
-
229
- if (cap[0]?.charAt(0) !== "!") {
230
- lexer.state.inLink = true;
231
- const token: Tokens["Link"] = {
232
- type: "link",
233
- raw,
234
- href,
235
- title,
236
- text,
237
- tokens: lexer.inlineTokens(text),
238
- };
239
- lexer.state.inLink = false;
240
- return token;
241
- }
242
- return {
243
- type: "image",
244
- raw,
245
- href,
246
- title,
247
- text: escape(text),
248
- };
262
+ const href = link.href;
263
+ const title = link.title ? escape(link.title) : null;
264
+ const text = cap[1]?.replace(/\\([\[\]])/g, "$1") ?? "";
265
+
266
+ if (cap[0]?.charAt(0) !== "!") {
267
+ lexer.state.inLink = true;
268
+ const token: Tokens["Link"] = {
269
+ type: "link",
270
+ raw,
271
+ href,
272
+ title,
273
+ text,
274
+ tokens: lexer.inlineTokens(text),
275
+ };
276
+ lexer.state.inLink = false;
277
+ return token;
278
+ }
279
+ return {
280
+ type: "image",
281
+ raw,
282
+ href,
283
+ title,
284
+ text: escape(text),
285
+ };
249
286
  }
250
287
 
251
288
  export function indentCodeCompensation(raw: string, text: string) {
252
- const matchIndentToCode = /^(\s+)(?:```)/.exec(raw);
289
+ const matchIndentToCode = /^(\s+)(?:```)/.exec(raw);
253
290
 
254
- if (matchIndentToCode === null) {
255
- return text;
256
- }
291
+ if (matchIndentToCode === null) {
292
+ return text;
293
+ }
257
294
 
258
- const indentToCode = matchIndentToCode[1];
295
+ const indentToCode = matchIndentToCode[1];
259
296
 
260
- return text
261
- .split("\n")
262
- .map((node) => {
263
- const matchIndentInNode = /^\s+/.exec(node);
264
- if (matchIndentInNode === null) {
265
- return node;
266
- }
297
+ return text
298
+ .split("\n")
299
+ .map((node) => {
300
+ const matchIndentInNode = /^\s+/.exec(node);
301
+ if (matchIndentInNode === null) {
302
+ return node;
303
+ }
267
304
 
268
- const [indentInNode] = matchIndentInNode;
305
+ const [indentInNode] = matchIndentInNode;
269
306
 
270
- if (indentToCode && indentInNode.length >= indentToCode.length) {
271
- return node.slice(indentToCode.length);
272
- }
307
+ if (indentToCode && indentInNode.length >= indentToCode.length) {
308
+ return node.slice(indentToCode.length);
309
+ }
273
310
 
274
- return node;
275
- })
276
- .join("\n");
311
+ return node;
312
+ })
313
+ .join("\n");
277
314
  }
278
315
 
279
316
  function makeAlertRegex(type: string) {
280
- return new RegExp(`^(?:\\[\\!${type.toUpperCase()}\\]|[\\*]{2}${type}[\\*]{2})[\s]*?\n?`);
317
+ return new RegExp(`^(?:\\[\\!${type.toUpperCase()}\\]|[\\*]{2}${type}[\\*]{2})[\s]*?\n?`);
281
318
  }
282
319
 
283
320
  export const ALERTS = [
284
- {
285
- variant: "Note",
286
- regex: makeAlertRegex("Note"),
287
- icon: '<svg class="octicon octicon-info" style="margin-right: 0.5rem;" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8Zm8-6.5a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13ZM6.5 7.75A.75.75 0 0 1 7.25 7h1a.75.75 0 0 1 .75.75v2.75h.25a.75.75 0 0 1 0 1.5h-2a.75.75 0 0 1 0-1.5h.25v-2h-.25a.75.75 0 0 1-.75-.75ZM8 6a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z"></path></svg>',
288
- },
289
- {
290
- variant: "Important",
291
- regex: makeAlertRegex("Important"),
292
- icon: '<svg class="octicon octicon-report" style="margin-right: 0.5rem;" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="M0 1.75C0 .784.784 0 1.75 0h12.5C15.216 0 16 .784 16 1.75v9.5A1.75 1.75 0 0 1 14.25 13H8.06l-2.573 2.573A1.458 1.458 0 0 1 3 14.543V13H1.75A1.75 1.75 0 0 1 0 11.25Zm1.75-.25a.25.25 0 0 0-.25.25v9.5c0 .138.112.25.25.25h2a.75.75 0 0 1 .75.75v2.19l2.72-2.72a.749.749 0 0 1 .53-.22h6.5a.25.25 0 0 0 .25-.25v-9.5a.25.25 0 0 0-.25-.25Zm7 2.25v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 9a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"></path></svg>',
293
- },
294
- {
295
- variant: "Warning",
296
- regex: makeAlertRegex("Warning"),
297
- icon: '<svg class="octicon octicon-alert" style="margin-right: 0.5rem;" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"></path></svg>',
298
- },
299
- {
300
- variant: "Tip",
301
- regex: makeAlertRegex("Tip"),
302
- icon: '<svg class="octicon octicon-alert" style="margin-right: 0.5rem;" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="M8 1.5c-2.363 0-4 1.69-4 3.75 0 .984.424 1.625.984 2.304l.214.253c.223.264.47.556.673.848.284.411.537.896.621 1.49a.75.75 0 0 1-1.484.211c-.04-.282-.163-.547-.37-.847a8.456 8.456 0 0 0-.542-.68c-.084-.1-.173-.205-.268-.32C3.201 7.75 2.5 6.766 2.5 5.25 2.5 2.31 4.863 0 8 0s5.5 2.31 5.5 5.25c0 1.516-.701 2.5-1.328 3.259-.095.115-.184.22-.268.319-.207.245-.383.453-.541.681-.208.3-.33.565-.37.847a.751.751 0 0 1-1.485-.212c.084-.593.337-1.078.621-1.489.203-.292.45-.584.673-.848.075-.088.147-.173.213-.253.561-.679.985-1.32.985-2.304 0-2.06-1.637-3.75-4-3.75ZM5.75 12h4.5a.75.75 0 0 1 0 1.5h-4.5a.75.75 0 0 1 0-1.5ZM6 15.25a.75.75 0 0 1 .75-.75h2.5a.75.75 0 0 1 0 1.5h-2.5a.75.75 0 0 1-.75-.75Z"/></svg>',
303
- },
304
- {
305
- variant: "Caution",
306
- regex: makeAlertRegex("Caution"),
307
- icon: '<svg class="octicon octicon-alert" style="margin-right: 0.5rem;" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="M4.47.22A.749.749 0 0 1 5 0h6c.199 0 .389.079.53.22l4.25 4.25c.141.14.22.331.22.53v6a.749.749 0 0 1-.22.53l-4.25 4.25A.749.749 0 0 1 11 16H5a.749.749 0 0 1-.53-.22L.22 11.53A.749.749 0 0 1 0 11V5c0-.199.079-.389.22-.53Zm.84 1.28L1.5 5.31v5.38l3.81 3.81h5.38l3.81-3.81V5.31L10.69 1.5ZM8 4a.75.75 0 0 1 .75.75v3.5a.75.75 0 0 1-1.5 0v-3.5A.75.75 0 0 1 8 4Zm0 8a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z"/></svg>',
308
- },
321
+ {
322
+ variant: "Note",
323
+ regex: makeAlertRegex("Note"),
324
+ icon: '<svg class="octicon octicon-info" style="margin-right: 0.5rem;" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8Zm8-6.5a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13ZM6.5 7.75A.75.75 0 0 1 7.25 7h1a.75.75 0 0 1 .75.75v2.75h.25a.75.75 0 0 1 0 1.5h-2a.75.75 0 0 1 0-1.5h.25v-2h-.25a.75.75 0 0 1-.75-.75ZM8 6a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z"></path></svg>',
325
+ },
326
+ {
327
+ variant: "Important",
328
+ regex: makeAlertRegex("Important"),
329
+ icon: '<svg class="octicon octicon-report" style="margin-right: 0.5rem;" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="M0 1.75C0 .784.784 0 1.75 0h12.5C15.216 0 16 .784 16 1.75v9.5A1.75 1.75 0 0 1 14.25 13H8.06l-2.573 2.573A1.458 1.458 0 0 1 3 14.543V13H1.75A1.75 1.75 0 0 1 0 11.25Zm1.75-.25a.25.25 0 0 0-.25.25v9.5c0 .138.112.25.25.25h2a.75.75 0 0 1 .75.75v2.19l2.72-2.72a.749.749 0 0 1 .53-.22h6.5a.25.25 0 0 0 .25-.25v-9.5a.25.25 0 0 0-.25-.25Zm7 2.25v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 9a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"></path></svg>',
330
+ },
331
+ {
332
+ variant: "Warning",
333
+ regex: makeAlertRegex("Warning"),
334
+ icon: '<svg class="octicon octicon-alert" style="margin-right: 0.5rem;" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"></path></svg>',
335
+ },
336
+ {
337
+ variant: "Tip",
338
+ regex: makeAlertRegex("Tip"),
339
+ icon: '<svg class="octicon octicon-alert" style="margin-right: 0.5rem;" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="M8 1.5c-2.363 0-4 1.69-4 3.75 0 .984.424 1.625.984 2.304l.214.253c.223.264.47.556.673.848.284.411.537.896.621 1.49a.75.75 0 0 1-1.484.211c-.04-.282-.163-.547-.37-.847a8.456 8.456 0 0 0-.542-.68c-.084-.1-.173-.205-.268-.32C3.201 7.75 2.5 6.766 2.5 5.25 2.5 2.31 4.863 0 8 0s5.5 2.31 5.5 5.25c0 1.516-.701 2.5-1.328 3.259-.095.115-.184.22-.268.319-.207.245-.383.453-.541.681-.208.3-.33.565-.37.847a.751.751 0 0 1-1.485-.212c.084-.593.337-1.078.621-1.489.203-.292.45-.584.673-.848.075-.088.147-.173.213-.253.561-.679.985-1.32.985-2.304 0-2.06-1.637-3.75-4-3.75ZM5.75 12h4.5a.75.75 0 0 1 0 1.5h-4.5a.75.75 0 0 1 0-1.5ZM6 15.25a.75.75 0 0 1 .75-.75h2.5a.75.75 0 0 1 0 1.5h-2.5a.75.75 0 0 1-.75-.75Z"/></svg>',
340
+ },
341
+ {
342
+ variant: "Caution",
343
+ regex: makeAlertRegex("Caution"),
344
+ icon: '<svg class="octicon octicon-alert" style="margin-right: 0.5rem;" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="M4.47.22A.749.749 0 0 1 5 0h6c.199 0 .389.079.53.22l4.25 4.25c.141.14.22.331.22.53v6a.749.749 0 0 1-.22.53l-4.25 4.25A.749.749 0 0 1 11 16H5a.749.749 0 0 1-.53-.22L.22 11.53A.749.749 0 0 1 0 11V5c0-.199.079-.389.22-.53Zm.84 1.28L1.5 5.31v5.38l3.81 3.81h5.38l3.81-3.81V5.31L10.69 1.5ZM8 4a.75.75 0 0 1 .75.75v3.5a.75.75 0 0 1-1.5 0v-3.5A.75.75 0 0 1 8 4Zm0 8a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z"/></svg>',
345
+ },
309
346
  ];
package/tsconfig.json CHANGED
@@ -1,15 +1,16 @@
1
1
  {
2
+ "$schema": "https://json.schemastore.org/tsconfig",
2
3
  "compilerOptions": {
3
4
  "lib": ["ESNext"],
4
5
  "module": "ESNext",
5
6
  "target": "ESNext",
7
+ "types": ["bun"],
6
8
  "moduleResolution": "Bundler",
7
9
  "moduleDetection": "force",
8
10
  "allowImportingTsExtensions": true,
9
11
  "noEmit": true,
10
12
  "composite": true,
11
13
  "strict": true,
12
- "downlevelIteration": true,
13
14
  "skipLibCheck": true,
14
15
  "allowSyntheticDefaultImports": true,
15
16
  "forceConsistentCasingInFileNames": true,
package/.prettierignore DELETED
@@ -1 +0,0 @@
1
- .github/dependabot.yml
@@ -1,4 +0,0 @@
1
- // TODO: I'm not so sure about this, come back to this
2
- // once Bun has official css loader
3
- const styles: string;
4
- export default styles;