@copepod/unified-plugins 0.0.1
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/LICENSE +21 -0
- package/README.md +193 -0
- package/dist/index.d.ts +56 -0
- package/dist/index.mjs +408 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +57 -0
- package/src/index.ts +2 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Julien Cayzac
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
# `@jcayzac/unified-plugins`
|
|
2
|
+
|
|
3
|
+
> [!WARNING]
|
|
4
|
+
> This package is not (yet?) meant for public use.
|
|
5
|
+
> It doesn't follow semantic versioning. It is part of a larger project and is published for internal use only.
|
|
6
|
+
|
|
7
|
+
## Remark Preset
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
import * as presets from '@jcayzac/unified-plugins'
|
|
11
|
+
|
|
12
|
+
const remarkPlugins = [
|
|
13
|
+
...otherPlugins,
|
|
14
|
+
...presets.remark({
|
|
15
|
+
/* options */
|
|
16
|
+
}),
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
// Use remarkPlugins in your unified processor
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### Linkified headings
|
|
23
|
+
|
|
24
|
+
All headings are automatically given an `id` attribute based on their text content, and their children are wrapped in a link to that id.
|
|
25
|
+
|
|
26
|
+
### Unwrapping of "loner" elements
|
|
27
|
+
|
|
28
|
+
Elements that are the only child of a paragraph are unwrapped from the paragraph is they can be block elements. This includes the following elements:
|
|
29
|
+
|
|
30
|
+
**HTML (or JSX):**
|
|
31
|
+
|
|
32
|
+
* `<img>`.
|
|
33
|
+
* `<figcaption>`
|
|
34
|
+
* `<picture>`
|
|
35
|
+
* `<video>`
|
|
36
|
+
|
|
37
|
+
**Markdown:**
|
|
38
|
+
|
|
39
|
+
* `image` elements.
|
|
40
|
+
* `link` elements that are recognized by a link transform (see below).
|
|
41
|
+
|
|
42
|
+
### Link transforms
|
|
43
|
+
|
|
44
|
+
Lone links whose URL is recognized by a registered link transform can be altered or transformed into other elements.
|
|
45
|
+
|
|
46
|
+
A link transform conforms to the following interface:
|
|
47
|
+
|
|
48
|
+
```ts
|
|
49
|
+
interface LinkTransform {
|
|
50
|
+
// The name of the transform, e.g. `youtube`.
|
|
51
|
+
readonly name: string
|
|
52
|
+
// A regular expression a link's URL must match.
|
|
53
|
+
readonly detect: RegExp
|
|
54
|
+
// Names for captured groups.
|
|
55
|
+
readonly groups?: (string | undefined)[]
|
|
56
|
+
// The transform function.
|
|
57
|
+
readonly transform: (link: Link, ...captured: (string | undefined)[]) => Parent | undefined
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
`transform()` may just add or change properties on the link, or return a completely new element to replace it.
|
|
62
|
+
|
|
63
|
+
If the `baseline.links.componentRoutes` option is set and contains an entry for `name`, or if the `baseline.links.defaultComponent` option is set, the link will be replaced by an MDX component and the `transform()` function ignored.
|
|
64
|
+
|
|
65
|
+
In addition to `url` and `title`, captured groups with a corresponding name in `groups` are also passed as props to the MDX component, as well as an `args` prop containing all captured groups.
|
|
66
|
+
|
|
67
|
+
> [!TIP]
|
|
68
|
+
> In order for an MDX component to be available, in must also be registered in the MDX provider.
|
|
69
|
+
|
|
70
|
+
By default, the following link transforms are registered:
|
|
71
|
+
|
|
72
|
+
* `youtube`: Transforms YouTube video URLs into responsive iframes.
|
|
73
|
+
|
|
74
|
+
You can override the default transforms, or register new ones, by setting the `baseline.links.transforms` option.
|
|
75
|
+
|
|
76
|
+
> [!NOTE]
|
|
77
|
+
> Links often don't have titles. Writing a link like this:
|
|
78
|
+
>
|
|
79
|
+
> ```md
|
|
80
|
+
> [A link](https://example.com)
|
|
81
|
+
> ```
|
|
82
|
+
>
|
|
83
|
+
> is more readable than this:
|
|
84
|
+
>
|
|
85
|
+
> ```md
|
|
86
|
+
> [](https://example.com "A link")
|
|
87
|
+
> ```
|
|
88
|
+
>
|
|
89
|
+
> When the `title` attribute is absent, the preset automatically sets it to the element's text content before passing it to the `transform()` function (or the registered MDX component), so that the first syntax is equivalent to the latter one.
|
|
90
|
+
|
|
91
|
+
### Asides
|
|
92
|
+
|
|
93
|
+
GFM-style asides are supported.
|
|
94
|
+
|
|
95
|
+
```md
|
|
96
|
+
> [!NOTE]
|
|
97
|
+
> Highlights information that users should take into account, even when skimming.
|
|
98
|
+
|
|
99
|
+
> [!TIP]
|
|
100
|
+
> Optional information to help a user be more successful.
|
|
101
|
+
|
|
102
|
+
> [!IMPORTANT]
|
|
103
|
+
> Crucial information necessary for users to succeed.
|
|
104
|
+
|
|
105
|
+
> [!WARNING]
|
|
106
|
+
> Critical content demanding immediate user attention due to potential risks.
|
|
107
|
+
|
|
108
|
+
> [!CAUTION]
|
|
109
|
+
> Negative potential consequences of an action.
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Arbitrary aside types are also supported, for instance:
|
|
113
|
+
|
|
114
|
+
```md
|
|
115
|
+
> [!COOKING_TIP]
|
|
116
|
+
> A tip for cooking.
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Asides are converted to `<aside>` elements in rehype. They have a class list that includes `aside` and `aside-<type>`, where `<type>` is the aside type in lowercase. The mdast elements also have the `type` attribute set so that it can be picked up by any MDX component responsible for rendering asides.
|
|
120
|
+
|
|
121
|
+
A title can be passed as an argument to the aside type:
|
|
122
|
+
|
|
123
|
+
```md
|
|
124
|
+
> [!TIP: I bet you didn't know this!]
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Titles are not inserted into the tree, but are available in the `data` attribute of the mdast node as well as the `data-title` attribute of the rehype node.
|
|
128
|
+
|
|
129
|
+
### _"Double blockquotes"_ `>>` syntax for figure captions
|
|
130
|
+
|
|
131
|
+
```md
|
|
132
|
+

|
|
133
|
+
>> Image caption.
|
|
134
|
+
>>
|
|
135
|
+
>> Another paragraph in the caption.
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
The outter blockquote is converted to a `<figcaption>` in rehype. The inner one is removed, and its children attached to the outter one instead.
|
|
139
|
+
|
|
140
|
+
### Captioning of block elements
|
|
141
|
+
|
|
142
|
+
Block elements followed by a caption are wrapped in a `<figure>` element with a `<figcaption>` child.
|
|
143
|
+
|
|
144
|
+
The caption element must be at the same level as the block element, and must be a block element itself. It can be a raw `<figcaption>` or any element marked to be converted to a `<figcaption>` in rehype.
|
|
145
|
+
|
|
146
|
+
````md
|
|
147
|
+
```js
|
|
148
|
+
console.log('Hello, world!')
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
<figcaption>This is a code block.</figcaption>
|
|
152
|
+
````
|
|
153
|
+
|
|
154
|
+
````md
|
|
155
|
+
```js
|
|
156
|
+
console.log('Hello, world!')
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
>>This is a code block.
|
|
160
|
+
````
|
|
161
|
+
|
|
162
|
+
```md
|
|
163
|
+
[A video about pandas](https://youtu.be/dqT-UlYlg1s?si=90AKHyMJG_6TLV9p)
|
|
164
|
+
>> A video about pandas.
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### Math
|
|
168
|
+
|
|
169
|
+
[`remark-math`](https://github.com/remarkjs/remark-math) is included in the preset.
|
|
170
|
+
|
|
171
|
+
## Rehype Preset
|
|
172
|
+
|
|
173
|
+
```ts
|
|
174
|
+
import * as presets from '@jcayzac/unified-plugins'
|
|
175
|
+
|
|
176
|
+
const rehypePlugins = [
|
|
177
|
+
...otherPlugins,
|
|
178
|
+
...presets.rehype({
|
|
179
|
+
/* options */
|
|
180
|
+
}),
|
|
181
|
+
]
|
|
182
|
+
|
|
183
|
+
// Use rehypePlugins in your unified processor
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### Whitespace Cleaning
|
|
187
|
+
|
|
188
|
+
* Paragraphs are trimmed.
|
|
189
|
+
* Empty paragraphs are removed.
|
|
190
|
+
|
|
191
|
+
### Math Typesetting
|
|
192
|
+
|
|
193
|
+
[`rehype-katex`](https://github.com/remarkjs/remark-math/tree/main/packages/rehype-katex#rehype-katex) is included in the preset.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { Root } from 'hast';
|
|
2
|
+
import { Options as Options$2 } from 'rehype-katex';
|
|
3
|
+
import { Link, Parent, Root as Root$1 } from 'mdast';
|
|
4
|
+
import { Options as Options$3 } from 'remark-math';
|
|
5
|
+
|
|
6
|
+
interface BaselineOptions$1 {
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
interface PresetOptions$1 {
|
|
10
|
+
baseline?: BaselineOptions$1 | undefined;
|
|
11
|
+
katex?: Options$2 | undefined;
|
|
12
|
+
}
|
|
13
|
+
interface Options$1 {
|
|
14
|
+
[key: string]: any;
|
|
15
|
+
}
|
|
16
|
+
type Factory$1 = (options: Options$1) => (root: Root) => void;
|
|
17
|
+
declare function plugins$1(options?: PresetOptions$1): [Factory$1, Options$1][];
|
|
18
|
+
|
|
19
|
+
declare namespace index$1 {
|
|
20
|
+
export { type PresetOptions$1 as PresetOptions, plugins$1 as plugins };
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
interface LinkTransform {
|
|
24
|
+
readonly name: string;
|
|
25
|
+
readonly detect: RegExp;
|
|
26
|
+
readonly groups?: (string | undefined)[];
|
|
27
|
+
readonly transform: (link: Link, ...captured: (string | undefined)[]) => Parent | undefined;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
interface LinkOptions {
|
|
31
|
+
readonly transforms?: LinkTransform[];
|
|
32
|
+
readonly defaultComponent?: string | undefined;
|
|
33
|
+
readonly componentRoutes?: Record<string, string> | undefined;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
interface BaselineOptions {
|
|
37
|
+
links?: LinkOptions | undefined;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
interface PresetOptions {
|
|
41
|
+
baseline?: BaselineOptions | undefined;
|
|
42
|
+
math?: Options$3 | undefined;
|
|
43
|
+
}
|
|
44
|
+
interface Options {
|
|
45
|
+
[key: string]: any;
|
|
46
|
+
}
|
|
47
|
+
type Factory = (options: Options) => (root: Root$1) => void;
|
|
48
|
+
declare function plugins(options?: PresetOptions): [Factory, Options][];
|
|
49
|
+
|
|
50
|
+
type index_PresetOptions = PresetOptions;
|
|
51
|
+
declare const index_plugins: typeof plugins;
|
|
52
|
+
declare namespace index {
|
|
53
|
+
export { type index_PresetOptions as PresetOptions, index_plugins as plugins };
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export { index$1 as rehype, index as remark };
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,408 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __export = (target, all) => {
|
|
3
|
+
for (var name in all)
|
|
4
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
// src/rehype/index.ts
|
|
8
|
+
var rehype_exports = {};
|
|
9
|
+
__export(rehype_exports, {
|
|
10
|
+
plugins: () => plugins
|
|
11
|
+
});
|
|
12
|
+
import katex from "rehype-katex";
|
|
13
|
+
|
|
14
|
+
// src/rehype/utils.ts
|
|
15
|
+
function nodeToString(node) {
|
|
16
|
+
if (node.type === "text") {
|
|
17
|
+
const literal = node;
|
|
18
|
+
return literal.value.trim();
|
|
19
|
+
}
|
|
20
|
+
if (isParent(node)) {
|
|
21
|
+
return node.children.map(nodeToString).join(" ").replace(/\s+/g, " ");
|
|
22
|
+
}
|
|
23
|
+
return "";
|
|
24
|
+
}
|
|
25
|
+
function onlyParents(nodes) {
|
|
26
|
+
return nodes.filter((node) => isParent(node));
|
|
27
|
+
}
|
|
28
|
+
function isParent(node) {
|
|
29
|
+
return "children" in node && Array.isArray(node.children) && node.children.length > 0;
|
|
30
|
+
}
|
|
31
|
+
function isElement(node, withName = void 0) {
|
|
32
|
+
const element = node;
|
|
33
|
+
const name = element?.type === "element" && element.tagName;
|
|
34
|
+
if (typeof name !== "string") {
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
if (withName instanceof RegExp) {
|
|
38
|
+
return withName.test(name);
|
|
39
|
+
} else if (typeof withName === "string") {
|
|
40
|
+
return name === withName;
|
|
41
|
+
}
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// src/rehype/transforms/paragraphs.ts
|
|
46
|
+
function paragraphs(parent) {
|
|
47
|
+
const children = [];
|
|
48
|
+
for (const child of parent.children) {
|
|
49
|
+
if (isElement(child, "p")) {
|
|
50
|
+
if (child.children.length === 0) {
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
let text = child.children[0];
|
|
54
|
+
if (text.type === "text") {
|
|
55
|
+
text.value = text.value.trimStart();
|
|
56
|
+
}
|
|
57
|
+
text = child.children[child.children.length - 1];
|
|
58
|
+
if (text.type === "text") {
|
|
59
|
+
text.value = text.value.trimEnd();
|
|
60
|
+
}
|
|
61
|
+
const hasNonText = child.children.some((child2) => child2.type !== "text");
|
|
62
|
+
const isEmpty = !hasNonText && nodeToString(child).trim() === "";
|
|
63
|
+
if (isEmpty) {
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
children.push(child);
|
|
68
|
+
}
|
|
69
|
+
parent.children = children;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// src/rehype/baseline.ts
|
|
73
|
+
function baseline(_options = {}) {
|
|
74
|
+
return function plugin(root) {
|
|
75
|
+
const queue = [];
|
|
76
|
+
let parent;
|
|
77
|
+
queue.push(root);
|
|
78
|
+
while (parent = queue.shift()) {
|
|
79
|
+
paragraphs(parent);
|
|
80
|
+
queue.push(...onlyParents(parent.children));
|
|
81
|
+
}
|
|
82
|
+
queue.push(root);
|
|
83
|
+
while (parent = queue.shift()) {
|
|
84
|
+
if (isElement(parent, /^code|pre$/)) {
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
parent.children = parent.children.filter(
|
|
88
|
+
(node) => node.type !== "text" || node.value !== "\n"
|
|
89
|
+
);
|
|
90
|
+
queue.push(...onlyParents(parent.children));
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// src/rehype/index.ts
|
|
96
|
+
function plugins(options = {}) {
|
|
97
|
+
return [
|
|
98
|
+
[katex, options.katex ?? {}],
|
|
99
|
+
[baseline, options.baseline ?? {}]
|
|
100
|
+
];
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// src/remark/index.ts
|
|
104
|
+
var remark_exports = {};
|
|
105
|
+
__export(remark_exports, {
|
|
106
|
+
plugins: () => plugins2
|
|
107
|
+
});
|
|
108
|
+
import math from "remark-math";
|
|
109
|
+
|
|
110
|
+
// src/remark/baseline.ts
|
|
111
|
+
import GithubSlugger from "github-slugger";
|
|
112
|
+
|
|
113
|
+
// src/remark/utils.ts
|
|
114
|
+
function nodeToString2(node) {
|
|
115
|
+
if (node.type === "text") {
|
|
116
|
+
const literal = node;
|
|
117
|
+
return literal.value.trim();
|
|
118
|
+
}
|
|
119
|
+
if (isParent2(node)) {
|
|
120
|
+
return node.children.map(nodeToString2).join(" ").replace(/\s+/g, " ");
|
|
121
|
+
}
|
|
122
|
+
return "";
|
|
123
|
+
}
|
|
124
|
+
function onlyParents2(nodes) {
|
|
125
|
+
return nodes.filter((node) => isParent2(node));
|
|
126
|
+
}
|
|
127
|
+
function isParent2(node) {
|
|
128
|
+
const asParent = node ? node : node;
|
|
129
|
+
return Array.isArray(asParent?.children) && asParent.children[0] !== void 0;
|
|
130
|
+
}
|
|
131
|
+
function isLink(node) {
|
|
132
|
+
return node?.type === "link";
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// src/remark/transforms/asides.ts
|
|
136
|
+
function asides(parent) {
|
|
137
|
+
if (parent.type !== "blockquote" || parent.children[0]?.type !== "paragraph") {
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
const paragraph = parent.children[0];
|
|
141
|
+
if (paragraph.children[0]?.type !== "text") {
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
const text = paragraph.children[0];
|
|
145
|
+
const [full, args] = /^\s*\[!([^\]]+)\]\s*/.exec(text.value) || [];
|
|
146
|
+
if (!full || !args) {
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
text.value = text.value.slice(full.length);
|
|
150
|
+
const match = /^\s*([A-Z][A-Z_]*)(?::\s+([^\]]+))?$/.exec(args);
|
|
151
|
+
if (!match) {
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
const type = match[1].toLowerCase();
|
|
155
|
+
const title = match[2]?.trim() ?? `${match[1][0]}${type.slice(1).replace(/_/g, " ")}`;
|
|
156
|
+
const { data } = parent;
|
|
157
|
+
parent.data = {
|
|
158
|
+
...data,
|
|
159
|
+
hName: "aside",
|
|
160
|
+
hProperties: {
|
|
161
|
+
...data?.hProperties,
|
|
162
|
+
className: ["aside", `aside-${type}`],
|
|
163
|
+
type,
|
|
164
|
+
title,
|
|
165
|
+
dataTitle: title
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// src/remark/transforms/captions.ts
|
|
171
|
+
function captions(parent) {
|
|
172
|
+
if (parent.children[1] || parent.type !== "blockquote" || parent.children[0]?.type !== "blockquote") {
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
parent.data = {
|
|
176
|
+
...parent.data,
|
|
177
|
+
hName: "figcaption"
|
|
178
|
+
};
|
|
179
|
+
parent.children = parent.children[0].children;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// src/remark/transforms/figures.ts
|
|
183
|
+
function figures(parent) {
|
|
184
|
+
const parentJSX = parent;
|
|
185
|
+
let len = parent.children.length;
|
|
186
|
+
for (let i = 0; i < len; i++) {
|
|
187
|
+
const child = parent.children[i];
|
|
188
|
+
if (i > 0 && (child.data?.hName === "figcaption" || child.type === "mdxJsxFlowElement" && child.name === "figcaption") && !(parentJSX.data?.hName === "figure" || parent.type === "mdxJsxFlowElement" && parentJSX.name === "figure")) {
|
|
189
|
+
--len;
|
|
190
|
+
const captioned = parent.children[--i];
|
|
191
|
+
parent.children.splice(i, 2, {
|
|
192
|
+
type: "blockquote",
|
|
193
|
+
data: {
|
|
194
|
+
hName: "figure"
|
|
195
|
+
},
|
|
196
|
+
position: captioned.position,
|
|
197
|
+
children: [captioned, child]
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// src/remark/transforms/headings.ts
|
|
204
|
+
function headings(parent, slugger) {
|
|
205
|
+
if (parent.type !== "heading" || !parent.children[0]) {
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
const slug = slugger.slug(nodeToString2(parent));
|
|
209
|
+
parent.data = {
|
|
210
|
+
...parent.data,
|
|
211
|
+
id: slug
|
|
212
|
+
};
|
|
213
|
+
parent.children = [
|
|
214
|
+
{
|
|
215
|
+
type: "link",
|
|
216
|
+
url: `#${slug}`,
|
|
217
|
+
title: null,
|
|
218
|
+
children: parent.children,
|
|
219
|
+
position: parent.position
|
|
220
|
+
}
|
|
221
|
+
];
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// src/remark/transforms/loners/index.ts
|
|
225
|
+
import "mdast-util-to-hast";
|
|
226
|
+
|
|
227
|
+
// src/remark/transforms/loners/links/youtube.ts
|
|
228
|
+
var youtube = {
|
|
229
|
+
name: "youtube",
|
|
230
|
+
detect: /^https:\/\/(?:youtu\.be\/|(?:.+\.)?youtube\.com\/watch\?(?:[^&]+&)*v=)([^?&/]+)/,
|
|
231
|
+
groups: ["id"],
|
|
232
|
+
transform: function(link, id) {
|
|
233
|
+
const url = new URL(link.url);
|
|
234
|
+
const t = url.searchParams.get("t");
|
|
235
|
+
if (t) {
|
|
236
|
+
url.searchParams.set("start", t);
|
|
237
|
+
url.searchParams.delete("t");
|
|
238
|
+
}
|
|
239
|
+
url.hostname = "www.youtube-nocookie.com";
|
|
240
|
+
url.pathname = `/embed/${id}`;
|
|
241
|
+
const element = {
|
|
242
|
+
type: "image",
|
|
243
|
+
url: url.href,
|
|
244
|
+
title: link.title || "YouTube video player",
|
|
245
|
+
position: link.position,
|
|
246
|
+
children: [],
|
|
247
|
+
data: {
|
|
248
|
+
hName: "iframe",
|
|
249
|
+
hProperties: {
|
|
250
|
+
width: "560",
|
|
251
|
+
height: "315",
|
|
252
|
+
style: "border:0;width:100%;height:auto;aspect-ratio:16/9",
|
|
253
|
+
frameborder: "0",
|
|
254
|
+
allow: "accelerometer; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share",
|
|
255
|
+
referrerpolicy: "strict-origin-when-cross-origin",
|
|
256
|
+
allowfullscreen: true,
|
|
257
|
+
loading: "lazy"
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
};
|
|
261
|
+
return element;
|
|
262
|
+
}
|
|
263
|
+
};
|
|
264
|
+
|
|
265
|
+
// src/remark/transforms/loners/links/index.ts
|
|
266
|
+
var DEFAULT_TRANSFORMS = [
|
|
267
|
+
youtube
|
|
268
|
+
];
|
|
269
|
+
function processLink(link, options) {
|
|
270
|
+
for (const { name, detect, transform, groups } of [
|
|
271
|
+
...DEFAULT_TRANSFORMS,
|
|
272
|
+
...options.transforms ?? []
|
|
273
|
+
]) {
|
|
274
|
+
const match = detect.exec(link.url);
|
|
275
|
+
if (!match) {
|
|
276
|
+
continue;
|
|
277
|
+
}
|
|
278
|
+
const args = match.slice(1);
|
|
279
|
+
if (!link.title) {
|
|
280
|
+
const title = nodeToString2(link).trim();
|
|
281
|
+
if (title) {
|
|
282
|
+
link.title = title;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
const component = options.componentRoutes?.[name] ?? options.defaultComponent;
|
|
286
|
+
if (!component) {
|
|
287
|
+
return transform(link, ...args);
|
|
288
|
+
}
|
|
289
|
+
const mdx = {
|
|
290
|
+
type: "mdxJsxFlowElement",
|
|
291
|
+
name: component,
|
|
292
|
+
children: link.children,
|
|
293
|
+
position: link.position,
|
|
294
|
+
data: { _mdxExplicitJsx: true },
|
|
295
|
+
attributes: [
|
|
296
|
+
{
|
|
297
|
+
type: "mdxJsxAttribute",
|
|
298
|
+
name: "url",
|
|
299
|
+
value: link.url
|
|
300
|
+
},
|
|
301
|
+
{
|
|
302
|
+
type: "mdxJsxAttribute",
|
|
303
|
+
name: "args",
|
|
304
|
+
value: {
|
|
305
|
+
type: "mdxJsxAttributeValueExpression",
|
|
306
|
+
value: `[${args.map((value) => value ? JSON.stringify(value) : "undefined").join(", ")}]`,
|
|
307
|
+
data: {
|
|
308
|
+
estree: {
|
|
309
|
+
type: "Program",
|
|
310
|
+
body: [
|
|
311
|
+
{
|
|
312
|
+
type: "ExpressionStatement",
|
|
313
|
+
expression: {
|
|
314
|
+
type: "ArrayExpression",
|
|
315
|
+
elements: args.map((value) => value ? { type: "Literal", value, raw: JSON.stringify(value) } : { type: "Identifier", name: "undefined" })
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
],
|
|
319
|
+
sourceType: "module"
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
]
|
|
325
|
+
};
|
|
326
|
+
if (link.title) {
|
|
327
|
+
mdx.attributes.push({
|
|
328
|
+
type: "mdxJsxAttribute",
|
|
329
|
+
name: "title",
|
|
330
|
+
value: link.title
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
for (const [index, name2] of groups?.entries() ?? []) {
|
|
334
|
+
const value = args[index];
|
|
335
|
+
if (typeof name2 === "string" && typeof value === "string") {
|
|
336
|
+
mdx.attributes.push({ type: "mdxJsxAttribute", name: name2, value });
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
return mdx;
|
|
340
|
+
}
|
|
341
|
+
return void 0;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// src/remark/transforms/loners/index.ts
|
|
345
|
+
var LONERS_MD = /* @__PURE__ */ new Set(["image"]);
|
|
346
|
+
var LONERS_MDX = /* @__PURE__ */ new Set([
|
|
347
|
+
"img",
|
|
348
|
+
"figcaption",
|
|
349
|
+
"picture",
|
|
350
|
+
"video"
|
|
351
|
+
]);
|
|
352
|
+
function loners(parent, options = {}) {
|
|
353
|
+
for (const [index, child] of parent.children.entries()) {
|
|
354
|
+
if (child.type === "paragraph" && child.children[0] && !child.children[1]) {
|
|
355
|
+
const loner = child.children[0];
|
|
356
|
+
let replacer;
|
|
357
|
+
if (LONERS_MD.has(loner.type)) {
|
|
358
|
+
replacer = loner;
|
|
359
|
+
} else if (/^mdxJsx.+Element$/.test(loner.type) && LONERS_MDX.has(loner.name ?? "")) {
|
|
360
|
+
replacer = {
|
|
361
|
+
...loner,
|
|
362
|
+
type: "mdxJsxFlowElement"
|
|
363
|
+
};
|
|
364
|
+
} else if (isLink(loner)) {
|
|
365
|
+
replacer = processLink(loner, options);
|
|
366
|
+
}
|
|
367
|
+
if (replacer) {
|
|
368
|
+
parent.children[index] = replacer;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
// src/remark/baseline.ts
|
|
375
|
+
var SLUGGER = new GithubSlugger();
|
|
376
|
+
function baseline2(options = {}) {
|
|
377
|
+
return function plugin(root) {
|
|
378
|
+
SLUGGER.reset();
|
|
379
|
+
const queue = [];
|
|
380
|
+
let parent;
|
|
381
|
+
queue.push(root);
|
|
382
|
+
while (parent = queue.shift()) {
|
|
383
|
+
asides(parent);
|
|
384
|
+
captions(parent);
|
|
385
|
+
headings(parent, SLUGGER);
|
|
386
|
+
loners(parent, options.links ?? {});
|
|
387
|
+
queue.push(...onlyParents2(parent.children));
|
|
388
|
+
}
|
|
389
|
+
queue.push(root);
|
|
390
|
+
while (parent = queue.shift()) {
|
|
391
|
+
figures(parent);
|
|
392
|
+
queue.push(...onlyParents2(parent.children));
|
|
393
|
+
}
|
|
394
|
+
};
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
// src/remark/index.ts
|
|
398
|
+
function plugins2(options = {}) {
|
|
399
|
+
return [
|
|
400
|
+
[math, options.math ?? {}],
|
|
401
|
+
[baseline2, options.baseline ?? {}]
|
|
402
|
+
];
|
|
403
|
+
}
|
|
404
|
+
export {
|
|
405
|
+
rehype_exports as rehype,
|
|
406
|
+
remark_exports as remark
|
|
407
|
+
};
|
|
408
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/rehype/index.ts","../src/rehype/utils.ts","../src/rehype/transforms/paragraphs.ts","../src/rehype/baseline.ts","../src/remark/index.ts","../src/remark/baseline.ts","../src/remark/utils.ts","../src/remark/transforms/asides.ts","../src/remark/transforms/captions.ts","../src/remark/transforms/figures.ts","../src/remark/transforms/headings.ts","../src/remark/transforms/loners/index.ts","../src/remark/transforms/loners/links/youtube.ts","../src/remark/transforms/loners/links/index.ts"],"sourcesContent":["import type { Root } from 'hast'\nimport katex from 'rehype-katex'\nimport type { Options as KatexOptions } from 'rehype-katex'\nimport { type BaselineOptions, baseline } from './baseline'\n\nexport interface PresetOptions {\n\tbaseline?: BaselineOptions | undefined\n\tkatex?: KatexOptions | undefined\n}\n\ninterface Options { [key: string]: any }\ntype Factory = (options: Options) => (root: Root) => void\n\nexport function plugins(options: PresetOptions = {}) {\n\treturn [\n\t\t[katex, options.katex ?? {}],\n\t\t[baseline, options.baseline ?? {}],\n\t] as [Factory, Options][]\n}\n","import type * as hast from 'hast'\n\nexport function nodeToString(node: hast.Node): string {\n\tif (node.type === 'text') {\n\t\tconst literal = node as hast.Text\n\t\treturn literal.value.trim()\n\t}\n\n\tif (isParent(node)) {\n\t\treturn node.children.map(nodeToString).join(' ').replace(/\\s+/g, ' ')\n\t}\n\n\treturn ''\n}\n\nexport function onlyParents(nodes: hast.Node[]): hast.Parent[] {\n\treturn nodes.filter(node => isParent(node)) as hast.Parent[]\n}\n\nexport function isParent(node: hast.Node): node is hast.Parent {\n\treturn 'children' in node && Array.isArray(node.children) && node.children.length > 0\n}\n\nexport function isElement(node: hast.Node | undefined, withName: string | RegExp | undefined = undefined): node is hast.Element {\n\tconst element = node as hast.Element\n\tconst name = element?.type === 'element' && element.tagName\n\n\tif (typeof name !== 'string') {\n\t\treturn false\n\t}\n\n\tif (withName instanceof RegExp) {\n\t\treturn withName.test(name)\n\t}\n\telse if (typeof withName === 'string') {\n\t\treturn name === withName\n\t}\n\n\treturn true\n}\n","import type { ElementContent, Node, Parent, Text } from 'hast'\nimport { isElement, nodeToString } from '../utils'\n\nexport function paragraphs(parent: Parent) {\n\tconst children: Node[] = []\n\tfor (const child of parent.children) {\n\t\tif (isElement(child, 'p')) {\n\t\t\t// Skip empty paragraphs\n\t\t\tif (child.children.length === 0) {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// Trim start\n\t\t\tlet text = child.children[0] as Text\n\t\t\tif (text.type === 'text') {\n\t\t\t\ttext.value = text.value.trimStart()\n\t\t\t}\n\n\t\t\t// Trim end\n\t\t\ttext = child.children[child.children.length - 1] as Text\n\t\t\tif (text.type === 'text') {\n\t\t\t\ttext.value = text.value.trimEnd()\n\t\t\t}\n\n\t\t\t// Skip empty text paragraphs\n\t\t\tconst hasNonText = child.children.some(child => child.type !== 'text')\n\t\t\tconst isEmpty = !hasNonText && nodeToString(child).trim() === ''\n\t\t\tif (isEmpty) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t}\n\n\t\t// Accept node\n\t\tchildren.push(child)\n\t}\n\n\tparent.children = children as ElementContent[]\n}\n","import type { Parent, Root, Text } from 'hast'\nimport { isElement, onlyParents } from './utils'\nimport * as transforms from './transforms'\n\nexport interface BaselineOptions {\n}\n\nexport function baseline(_options: BaselineOptions = {}) {\n\treturn function plugin(root: Root) {\n\t\tconst queue: Array<Parent> = []\n\t\tlet parent: Parent | undefined\n\n\t\t// First pass:\n\t\t// 1. Trim paragraphs.\n\t\t// 2. Remove empty paragraphs.\n\t\tqueue.push(root)\n\t\t// eslint-disable-next-line no-cond-assign\n\t\twhile (parent = queue.shift()) {\n\t\t\ttransforms.paragraphs(parent)\n\n\t\t\tqueue.push(...onlyParents(parent.children))\n\t\t}\n\n\t\t// Second pass:\n\t\t// 1. Remove lone newlines from all nodes that aren't inside `<code>` or `<pre>`.\n\t\tqueue.push(root)\n\t\t// eslint-disable-next-line no-cond-assign\n\t\twhile (parent = queue.shift()) {\n\t\t\tif (isElement(parent, /^code|pre$/)) {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tparent.children = parent.children.filter(node =>\n\t\t\t\tnode.type !== 'text' || (node as Text).value !== '\\n',\n\t\t\t)\n\n\t\t\tqueue.push(...onlyParents(parent.children))\n\t\t}\n\t}\n}\n","import type { Root } from 'mdast'\nimport math from 'remark-math'\nimport type { Options as MathOptions } from 'remark-math'\nimport { type BaselineOptions, baseline } from './baseline'\n\nexport interface PresetOptions {\n\tbaseline?: BaselineOptions | undefined\n\tmath?: MathOptions | undefined\n}\n\ninterface Options { [key: string]: any }\ntype Factory = (options: Options) => (root: Root) => void\n\nexport function plugins(options: PresetOptions = {}) {\n\treturn [\n\t\t[math, options.math ?? {}],\n\t\t[baseline, options.baseline ?? {}],\n\t] as [Factory, Options][]\n}\n","import type { Parent, Root } from 'mdast'\nimport GithubSlugger from 'github-slugger'\nimport * as utils from './utils'\nimport * as transforms from './transforms'\nimport type { LinkOptions } from './transforms/loners/links'\n\nconst SLUGGER = new GithubSlugger()\n\nexport interface BaselineOptions {\n\tlinks?: LinkOptions | undefined\n}\n\nexport function baseline(options: BaselineOptions = {}) {\n\treturn function plugin(root: Root) {\n\t\tSLUGGER.reset()\n\n\t\tconst queue: Array<Parent> = []\n\t\tlet parent: Parent | undefined\n\n\t\tqueue.push(root)\n\t\t// eslint-disable-next-line no-cond-assign\n\t\twhile (parent = queue.shift()) {\n\t\t\ttransforms.asides(parent)\n\t\t\ttransforms.captions(parent)\n\t\t\ttransforms.headings(parent, SLUGGER)\n\t\t\ttransforms.loners(parent, options.links ?? {})\n\t\t\tqueue.push(...utils.onlyParents(parent.children))\n\t\t}\n\n\t\tqueue.push(root)\n\t\t// eslint-disable-next-line no-cond-assign\n\t\twhile (parent = queue.shift()) {\n\t\t\ttransforms.figures(parent)\n\t\t\tqueue.push(...utils.onlyParents(parent.children))\n\t\t}\n\t}\n}\n","import type * as mdast from 'mdast'\n\nexport interface AnyData { data?: { [key: string]: any } }\n\nexport function nodeToString(node: mdast.Node): string {\n\tif (node.type === 'text') {\n\t\tconst literal = node as mdast.Text\n\t\treturn literal.value.trim()\n\t}\n\n\tif (isParent(node)) {\n\t\treturn node.children.map(nodeToString).join(' ').replace(/\\s+/g, ' ')\n\t}\n\n\treturn ''\n}\n\nexport function onlyParents(nodes: mdast.Node[]): mdast.Parent[] {\n\treturn nodes.filter(node => isParent(node)) as mdast.Parent[]\n}\n\nexport function isParent(node: mdast.Node | undefined | null): node is mdast.Parent {\n\tconst asParent = node ? node as mdast.Parent : node\n\treturn Array.isArray(asParent?.children) && asParent.children[0] !== undefined\n}\n\nexport function isLink(node: mdast.Node | undefined | null): node is mdast.Link {\n\treturn node?.type === 'link'\n}\n\nexport function isParagraph(node: mdast.Node | undefined | null): node is mdast.Paragraph {\n\treturn node?.type === 'paragraph'\n}\n\nexport function isText(node: mdast.Node | undefined | null): node is mdast.Text {\n\treturn node?.type === 'text'\n}\n","import type { Paragraph, Parent, Text } from 'mdast'\nimport type { AnyData } from '../utils'\n\n/**\n * Support for asides.\n *\n * ```md\n * > [!NOTE: This is a note]\n * > This is the content of the note.\n *\n * > [!WARNING]\n * > This is a warning.\n * ```\n */\nexport function asides(parent: Parent) {\n\tif (parent.type !== 'blockquote' || parent.children[0]?.type !== 'paragraph') {\n\t\treturn\n\t}\n\n\tconst paragraph = parent.children[0] as Paragraph\n\tif (paragraph.children[0]?.type !== 'text') {\n\t\treturn\n\t}\n\n\tconst text = paragraph.children[0] as Text\n\n\t// Extract the inner content of [!…]\n\tconst [full, args] = /^\\s*\\[!([^\\]]+)\\]\\s*/.exec(text.value) || []\n\tif (!full || !args) {\n\t\treturn\n\t}\n\n\t// Remove the [!…] from the text\n\t// Note: This has the effect of trimming the start of the paragraph\n\ttext.value = text.value.slice(full.length)\n\n\t// Parse the type and title\n\t// eslint-disable-next-line regexp/no-super-linear-backtracking\n\tconst match = /^\\s*([A-Z][A-Z_]*)(?::\\s+([^\\]]+))?$/.exec(args)\n\tif (!match) {\n\t\treturn\n\t}\n\tconst type = match[1]!.toLowerCase()\n\tconst title = match[2]?.trim() ?? `${match[1]![0]}${type.slice(1).replace(/_/g, ' ')}`\n\tconst { data } = parent as AnyData\n\tparent.data = {\n\t\t...data,\n\t\thName: 'aside',\n\t\thProperties: {\n\t\t\t...data?.hProperties,\n\t\t\tclassName: ['aside', `aside-${type}`],\n\t\t\ttype,\n\t\t\ttitle,\n\t\t\tdataTitle: title,\n\t\t},\n\t}\n}\n","import type { Parent } from 'mdast'\n\n/**\n * Support for captions, using the \"double blockquote\" `>>` syntax.\n */\nexport function captions(parent: Parent) {\n\tif (parent.children[1] || parent.type !== 'blockquote' || parent.children[0]?.type !== 'blockquote') {\n\t\treturn\n\t}\n\n\tparent.data = {\n\t\t...parent.data,\n\t\thName: 'figcaption',\n\t}\n\tparent.children = parent.children[0].children\n}\n","import type { BlockContent, Blockquote, Parent } from 'mdast'\nimport type { MdxJsxFlowElement } from 'mdast-util-mdx-jsx'\nimport type * as utils from '../utils'\n\nexport function figures(parent: Parent) {\n\tconst parentJSX = parent as MdxJsxFlowElement & utils.AnyData\n\n\tlet len = parent.children.length\n\tfor (let i = 0; i < len; i++) {\n\t\tconst child = parent.children[i] as MdxJsxFlowElement & utils.AnyData\n\n\t\t// Wrap <figcaption> elements and their previous sibling in a <figure>\n\t\tif (i > 0\n\t\t\t&& (child.data?.hName === 'figcaption' || (child.type === 'mdxJsxFlowElement' && child.name === 'figcaption'))\n\t\t\t&& !(parentJSX.data?.hName === 'figure' || (parent.type === 'mdxJsxFlowElement' && parentJSX.name === 'figure'))\n\t\t) {\n\t\t\t--len\n\t\t\tconst captioned = parent.children[--i] as BlockContent\n\t\t\tparent.children.splice(i, 2, {\n\t\t\t\ttype: 'blockquote',\n\t\t\t\tdata: {\n\t\t\t\t\thName: 'figure',\n\t\t\t\t},\n\t\t\t\tposition: captioned.position,\n\t\t\t\tchildren: [captioned, child],\n\t\t\t} satisfies Blockquote)\n\t\t}\n\t}\n}\n","import type { Link, Parent, PhrasingContent } from 'mdast'\nimport { nodeToString } from '../utils'\n\nexport interface Slugger {\n\tslug: (value: string) => string\n}\n\nexport function headings(parent: Parent, slugger: Slugger) {\n\tif (parent.type !== 'heading' || !parent.children[0]) {\n\t\treturn\n\t}\n\n\tconst slug = slugger.slug(nodeToString(parent))\n\tparent.data = {\n\t\t...parent.data,\n\t\tid: slug,\n\t} as Parent['data']\n\tparent.children = [\n\t\t{\n\t\t\ttype: 'link',\n\t\t\turl: `#${slug}`,\n\t\t\ttitle: null,\n\t\t\tchildren: parent.children as PhrasingContent[],\n\t\t\tposition: parent.position,\n\t\t} satisfies Link,\n\t]\n}\n","import type { Parent, PhrasingContent, RootContent } from 'mdast'\nimport 'mdast-util-to-hast'\nimport { isLink } from '../../utils'\nimport { type LinkOptions, type LinkTransform, processLink } from './links'\n\nconst LONERS_MD = new Set(['image'])\nconst LONERS_MDX = new Set([\n\t'img',\n\t'figcaption',\n\t'picture',\n\t'video',\n])\n\nexport type { LinkTransform }\n\nexport function loners(parent: Parent, options: LinkOptions = {}): void {\n\tfor (const [index, child] of parent.children.entries()) {\n\t\tif (child.type === 'paragraph' && child.children[0] && !child.children[1]) {\n\t\t\t// This paragraph has only one child\n\t\t\tconst loner = child.children[0] as PhrasingContent & { name?: string }\n\t\t\tlet replacer: Parent | undefined\n\n\t\t\tif (LONERS_MD.has(loner.type)) {\n\t\t\t\t// Unwrap the loner\n\t\t\t\treplacer = loner as Parent\n\t\t\t}\n\t\t\telse if (/^mdxJsx.+Element$/.test(loner.type) && LONERS_MDX.has(loner.name ?? '')) {\n\t\t\t\t// Unwrap the loner and mark it as a flow element\n\t\t\t\treplacer = {\n\t\t\t\t\t...loner,\n\t\t\t\t\ttype: 'mdxJsxFlowElement',\n\t\t\t\t} as Parent\n\t\t\t}\n\t\t\telse if (isLink(loner)) {\n\t\t\t\treplacer = processLink(loner, options)\n\t\t\t}\n\n\t\t\tif (replacer) {\n\t\t\t\tparent.children[index] = replacer as RootContent\n\t\t\t}\n\t\t}\n\t}\n}\n","import type { Link, Parent } from 'mdast'\nimport type { LinkTransform } from './transform'\n\nexport const youtube: LinkTransform = {\n\tname: 'youtube',\n\tdetect: /^https:\\/\\/(?:youtu\\.be\\/|(?:.+\\.)?youtube\\.com\\/watch\\?(?:[^&]+&)*v=)([^?&/]+)/,\n\tgroups: ['id'],\n\ttransform: function (link: Link, id: string): Parent | undefined {\n\t\tconst url = new URL(link.url)\n\t\tconst t = url.searchParams.get('t')\n\t\tif (t) {\n\t\t\turl.searchParams.set('start', t)\n\t\t\turl.searchParams.delete('t')\n\t\t}\n\t\turl.hostname = 'www.youtube-nocookie.com'\n\t\turl.pathname = `/embed/${id}`\n\n\t\tconst element = {\n\t\t\ttype: 'image',\n\t\t\turl: url.href,\n\t\t\ttitle: link.title || 'YouTube video player',\n\t\t\tposition: link.position,\n\t\t\tchildren: [],\n\t\t\tdata: {\n\t\t\t\thName: 'iframe',\n\t\t\t\thProperties: {\n\t\t\t\t\twidth: '560',\n\t\t\t\t\theight: '315',\n\t\t\t\t\tstyle: 'border:0;width:100%;height:auto;aspect-ratio:16/9',\n\t\t\t\t\tframeborder: '0',\n\t\t\t\t\tallow: 'accelerometer; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share',\n\t\t\t\t\treferrerpolicy: 'strict-origin-when-cross-origin',\n\t\t\t\t\tallowfullscreen: true,\n\t\t\t\t\tloading: 'lazy',\n\t\t\t\t},\n\t\t\t},\n\t\t}\n\n\t\treturn element\n\t} as LinkTransform['transform'],\n}\n","import type { Link } from 'mdast'\nimport type { MdxJsxFlowElement, MdxJsxFlowElementData } from 'mdast-util-mdx-jsx'\nimport { nodeToString } from '../../../utils'\nimport type { LinkTransform } from './transform'\nimport { youtube } from './youtube'\n\nexport * from './transform'\nexport * from './youtube'\n\nconst DEFAULT_TRANSFORMS: LinkTransform[] = [\n\tyoutube,\n]\n\nexport interface LinkOptions {\n\treadonly transforms?: LinkTransform[]\n\treadonly defaultComponent?: string | undefined\n\treadonly componentRoutes?: Record<string, string> | undefined\n}\n\nexport function processLink(link: Link, options: LinkOptions) {\n\tfor (const { name, detect, transform, groups } of [\n\t\t...DEFAULT_TRANSFORMS,\n\t\t...options.transforms ?? [],\n\t]) {\n\t\tconst match = detect.exec(link.url)\n\t\tif (!match) {\n\t\t\tcontinue\n\t\t}\n\n\t\tconst args = match.slice(1) as Array<string | undefined>\n\n\t\t// Links utually don't have a title, only child nodes.\n\t\tif (!link.title) {\n\t\t\tconst title = nodeToString(link).trim()\n\t\t\tif (title) {\n\t\t\t\tlink.title = title\n\t\t\t}\n\t\t}\n\n\t\t// Replace the link with the transformed node\n\t\tconst component = options.componentRoutes?.[name] ?? options.defaultComponent\n\t\tif (!component) {\n\t\t\treturn transform(link, ...args)\n\t\t}\n\n\t\t// Route the loner to an MDX component, passing not only the url and title as props,\n\t\t// but also all the captured groups from the regex.\n\t\tconst mdx = {\n\t\t\ttype: 'mdxJsxFlowElement',\n\t\t\tname: component,\n\t\t\tchildren: link.children,\n\t\t\tposition: link.position,\n\t\t\tdata: { _mdxExplicitJsx: true } as MdxJsxFlowElementData,\n\t\t\tattributes: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'mdxJsxAttribute',\n\t\t\t\t\tname: 'url',\n\t\t\t\t\tvalue: link.url,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'mdxJsxAttribute',\n\t\t\t\t\tname: 'args',\n\t\t\t\t\tvalue: {\n\t\t\t\t\t\ttype: 'mdxJsxAttributeValueExpression',\n\t\t\t\t\t\tvalue: `[${args.map(value => value ? JSON.stringify(value) : 'undefined').join(', ')}]`,\n\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\testree: {\n\t\t\t\t\t\t\t\ttype: 'Program',\n\t\t\t\t\t\t\t\tbody: [\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\ttype: 'ExpressionStatement',\n\t\t\t\t\t\t\t\t\t\texpression: {\n\t\t\t\t\t\t\t\t\t\t\ttype: 'ArrayExpression',\n\t\t\t\t\t\t\t\t\t\t\telements: args.map(value => value ? { type: 'Literal', value, raw: JSON.stringify(value) } : { type: 'Identifier', name: 'undefined' }),\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\tsourceType: 'module',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t],\n\t\t} as MdxJsxFlowElement\n\n\t\tif (link.title) {\n\t\t\tmdx.attributes.push({\n\t\t\t\ttype: 'mdxJsxAttribute',\n\t\t\t\tname: 'title',\n\t\t\t\tvalue: link.title,\n\t\t\t})\n\t\t}\n\n\t\t// If the transform names any group, pass them as props\n\t\tfor (const [index, name] of groups?.entries() ?? []) {\n\t\t\tconst value = args[index]\n\t\t\tif (typeof name === 'string' && typeof value === 'string') {\n\t\t\t\tmdx.attributes.push({ type: 'mdxJsxAttribute', name, value })\n\t\t\t}\n\t\t}\n\n\t\treturn mdx\n\t}\n\n\treturn undefined\n}\n"],"mappings":";;;;;;;AAAA;AAAA;AAAA;AAAA;AACA,OAAO,WAAW;;;ACCX,SAAS,aAAa,MAAyB;AACrD,MAAI,KAAK,SAAS,QAAQ;AACzB,UAAM,UAAU;AAChB,WAAO,QAAQ,MAAM,KAAK;AAAA,EAC3B;AAEA,MAAI,SAAS,IAAI,GAAG;AACnB,WAAO,KAAK,SAAS,IAAI,YAAY,EAAE,KAAK,GAAG,EAAE,QAAQ,QAAQ,GAAG;AAAA,EACrE;AAEA,SAAO;AACR;AAEO,SAAS,YAAY,OAAmC;AAC9D,SAAO,MAAM,OAAO,UAAQ,SAAS,IAAI,CAAC;AAC3C;AAEO,SAAS,SAAS,MAAsC;AAC9D,SAAO,cAAc,QAAQ,MAAM,QAAQ,KAAK,QAAQ,KAAK,KAAK,SAAS,SAAS;AACrF;AAEO,SAAS,UAAU,MAA6B,WAAwC,QAAiC;AAC/H,QAAM,UAAU;AAChB,QAAM,OAAO,SAAS,SAAS,aAAa,QAAQ;AAEpD,MAAI,OAAO,SAAS,UAAU;AAC7B,WAAO;AAAA,EACR;AAEA,MAAI,oBAAoB,QAAQ;AAC/B,WAAO,SAAS,KAAK,IAAI;AAAA,EAC1B,WACS,OAAO,aAAa,UAAU;AACtC,WAAO,SAAS;AAAA,EACjB;AAEA,SAAO;AACR;;;ACpCO,SAAS,WAAW,QAAgB;AAC1C,QAAM,WAAmB,CAAC;AAC1B,aAAW,SAAS,OAAO,UAAU;AACpC,QAAI,UAAU,OAAO,GAAG,GAAG;AAE1B,UAAI,MAAM,SAAS,WAAW,GAAG;AAChC;AAAA,MACD;AAGA,UAAI,OAAO,MAAM,SAAS,CAAC;AAC3B,UAAI,KAAK,SAAS,QAAQ;AACzB,aAAK,QAAQ,KAAK,MAAM,UAAU;AAAA,MACnC;AAGA,aAAO,MAAM,SAAS,MAAM,SAAS,SAAS,CAAC;AAC/C,UAAI,KAAK,SAAS,QAAQ;AACzB,aAAK,QAAQ,KAAK,MAAM,QAAQ;AAAA,MACjC;AAGA,YAAM,aAAa,MAAM,SAAS,KAAK,CAAAA,WAASA,OAAM,SAAS,MAAM;AACrE,YAAM,UAAU,CAAC,cAAc,aAAa,KAAK,EAAE,KAAK,MAAM;AAC9D,UAAI,SAAS;AACZ;AAAA,MACD;AAAA,IACD;AAGA,aAAS,KAAK,KAAK;AAAA,EACpB;AAEA,SAAO,WAAW;AACnB;;;AC9BO,SAAS,SAAS,WAA4B,CAAC,GAAG;AACxD,SAAO,SAAS,OAAO,MAAY;AAClC,UAAM,QAAuB,CAAC;AAC9B,QAAI;AAKJ,UAAM,KAAK,IAAI;AAEf,WAAO,SAAS,MAAM,MAAM,GAAG;AAC9B,MAAW,WAAW,MAAM;AAE5B,YAAM,KAAK,GAAG,YAAY,OAAO,QAAQ,CAAC;AAAA,IAC3C;AAIA,UAAM,KAAK,IAAI;AAEf,WAAO,SAAS,MAAM,MAAM,GAAG;AAC9B,UAAI,UAAU,QAAQ,YAAY,GAAG;AACpC;AAAA,MACD;AAEA,aAAO,WAAW,OAAO,SAAS;AAAA,QAAO,UACxC,KAAK,SAAS,UAAW,KAAc,UAAU;AAAA,MAClD;AAEA,YAAM,KAAK,GAAG,YAAY,OAAO,QAAQ,CAAC;AAAA,IAC3C;AAAA,EACD;AACD;;;AH1BO,SAAS,QAAQ,UAAyB,CAAC,GAAG;AACpD,SAAO;AAAA,IACN,CAAC,OAAO,QAAQ,SAAS,CAAC,CAAC;AAAA,IAC3B,CAAC,UAAU,QAAQ,YAAY,CAAC,CAAC;AAAA,EAClC;AACD;;;AIlBA;AAAA;AAAA,iBAAAC;AAAA;AACA,OAAO,UAAU;;;ACAjB,OAAO,mBAAmB;;;ACGnB,SAASC,cAAa,MAA0B;AACtD,MAAI,KAAK,SAAS,QAAQ;AACzB,UAAM,UAAU;AAChB,WAAO,QAAQ,MAAM,KAAK;AAAA,EAC3B;AAEA,MAAIC,UAAS,IAAI,GAAG;AACnB,WAAO,KAAK,SAAS,IAAID,aAAY,EAAE,KAAK,GAAG,EAAE,QAAQ,QAAQ,GAAG;AAAA,EACrE;AAEA,SAAO;AACR;AAEO,SAASE,aAAY,OAAqC;AAChE,SAAO,MAAM,OAAO,UAAQD,UAAS,IAAI,CAAC;AAC3C;AAEO,SAASA,UAAS,MAA2D;AACnF,QAAM,WAAW,OAAO,OAAuB;AAC/C,SAAO,MAAM,QAAQ,UAAU,QAAQ,KAAK,SAAS,SAAS,CAAC,MAAM;AACtE;AAEO,SAAS,OAAO,MAAyD;AAC/E,SAAO,MAAM,SAAS;AACvB;;;ACdO,SAAS,OAAO,QAAgB;AACtC,MAAI,OAAO,SAAS,gBAAgB,OAAO,SAAS,CAAC,GAAG,SAAS,aAAa;AAC7E;AAAA,EACD;AAEA,QAAM,YAAY,OAAO,SAAS,CAAC;AACnC,MAAI,UAAU,SAAS,CAAC,GAAG,SAAS,QAAQ;AAC3C;AAAA,EACD;AAEA,QAAM,OAAO,UAAU,SAAS,CAAC;AAGjC,QAAM,CAAC,MAAM,IAAI,IAAI,uBAAuB,KAAK,KAAK,KAAK,KAAK,CAAC;AACjE,MAAI,CAAC,QAAQ,CAAC,MAAM;AACnB;AAAA,EACD;AAIA,OAAK,QAAQ,KAAK,MAAM,MAAM,KAAK,MAAM;AAIzC,QAAM,QAAQ,uCAAuC,KAAK,IAAI;AAC9D,MAAI,CAAC,OAAO;AACX;AAAA,EACD;AACA,QAAM,OAAO,MAAM,CAAC,EAAG,YAAY;AACnC,QAAM,QAAQ,MAAM,CAAC,GAAG,KAAK,KAAK,GAAG,MAAM,CAAC,EAAG,CAAC,CAAC,GAAG,KAAK,MAAM,CAAC,EAAE,QAAQ,MAAM,GAAG,CAAC;AACpF,QAAM,EAAE,KAAK,IAAI;AACjB,SAAO,OAAO;AAAA,IACb,GAAG;AAAA,IACH,OAAO;AAAA,IACP,aAAa;AAAA,MACZ,GAAG,MAAM;AAAA,MACT,WAAW,CAAC,SAAS,SAAS,IAAI,EAAE;AAAA,MACpC;AAAA,MACA;AAAA,MACA,WAAW;AAAA,IACZ;AAAA,EACD;AACD;;;ACnDO,SAAS,SAAS,QAAgB;AACxC,MAAI,OAAO,SAAS,CAAC,KAAK,OAAO,SAAS,gBAAgB,OAAO,SAAS,CAAC,GAAG,SAAS,cAAc;AACpG;AAAA,EACD;AAEA,SAAO,OAAO;AAAA,IACb,GAAG,OAAO;AAAA,IACV,OAAO;AAAA,EACR;AACA,SAAO,WAAW,OAAO,SAAS,CAAC,EAAE;AACtC;;;ACXO,SAAS,QAAQ,QAAgB;AACvC,QAAM,YAAY;AAElB,MAAI,MAAM,OAAO,SAAS;AAC1B,WAAS,IAAI,GAAG,IAAI,KAAK,KAAK;AAC7B,UAAM,QAAQ,OAAO,SAAS,CAAC;AAG/B,QAAI,IAAI,MACH,MAAM,MAAM,UAAU,gBAAiB,MAAM,SAAS,uBAAuB,MAAM,SAAS,iBAC7F,EAAE,UAAU,MAAM,UAAU,YAAa,OAAO,SAAS,uBAAuB,UAAU,SAAS,WACrG;AACD,QAAE;AACF,YAAM,YAAY,OAAO,SAAS,EAAE,CAAC;AACrC,aAAO,SAAS,OAAO,GAAG,GAAG;AAAA,QAC5B,MAAM;AAAA,QACN,MAAM;AAAA,UACL,OAAO;AAAA,QACR;AAAA,QACA,UAAU,UAAU;AAAA,QACpB,UAAU,CAAC,WAAW,KAAK;AAAA,MAC5B,CAAsB;AAAA,IACvB;AAAA,EACD;AACD;;;ACrBO,SAAS,SAAS,QAAgB,SAAkB;AAC1D,MAAI,OAAO,SAAS,aAAa,CAAC,OAAO,SAAS,CAAC,GAAG;AACrD;AAAA,EACD;AAEA,QAAM,OAAO,QAAQ,KAAKE,cAAa,MAAM,CAAC;AAC9C,SAAO,OAAO;AAAA,IACb,GAAG,OAAO;AAAA,IACV,IAAI;AAAA,EACL;AACA,SAAO,WAAW;AAAA,IACjB;AAAA,MACC,MAAM;AAAA,MACN,KAAK,IAAI,IAAI;AAAA,MACb,OAAO;AAAA,MACP,UAAU,OAAO;AAAA,MACjB,UAAU,OAAO;AAAA,IAClB;AAAA,EACD;AACD;;;ACzBA,OAAO;;;ACEA,IAAM,UAAyB;AAAA,EACrC,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,QAAQ,CAAC,IAAI;AAAA,EACb,WAAW,SAAU,MAAY,IAAgC;AAChE,UAAM,MAAM,IAAI,IAAI,KAAK,GAAG;AAC5B,UAAM,IAAI,IAAI,aAAa,IAAI,GAAG;AAClC,QAAI,GAAG;AACN,UAAI,aAAa,IAAI,SAAS,CAAC;AAC/B,UAAI,aAAa,OAAO,GAAG;AAAA,IAC5B;AACA,QAAI,WAAW;AACf,QAAI,WAAW,UAAU,EAAE;AAE3B,UAAM,UAAU;AAAA,MACf,MAAM;AAAA,MACN,KAAK,IAAI;AAAA,MACT,OAAO,KAAK,SAAS;AAAA,MACrB,UAAU,KAAK;AAAA,MACf,UAAU,CAAC;AAAA,MACX,MAAM;AAAA,QACL,OAAO;AAAA,QACP,aAAa;AAAA,UACZ,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,OAAO;AAAA,UACP,aAAa;AAAA,UACb,OAAO;AAAA,UACP,gBAAgB;AAAA,UAChB,iBAAiB;AAAA,UACjB,SAAS;AAAA,QACV;AAAA,MACD;AAAA,IACD;AAEA,WAAO;AAAA,EACR;AACD;;;AC/BA,IAAM,qBAAsC;AAAA,EAC3C;AACD;AAQO,SAAS,YAAY,MAAY,SAAsB;AAC7D,aAAW,EAAE,MAAM,QAAQ,WAAW,OAAO,KAAK;AAAA,IACjD,GAAG;AAAA,IACH,GAAG,QAAQ,cAAc,CAAC;AAAA,EAC3B,GAAG;AACF,UAAM,QAAQ,OAAO,KAAK,KAAK,GAAG;AAClC,QAAI,CAAC,OAAO;AACX;AAAA,IACD;AAEA,UAAM,OAAO,MAAM,MAAM,CAAC;AAG1B,QAAI,CAAC,KAAK,OAAO;AAChB,YAAM,QAAQC,cAAa,IAAI,EAAE,KAAK;AACtC,UAAI,OAAO;AACV,aAAK,QAAQ;AAAA,MACd;AAAA,IACD;AAGA,UAAM,YAAY,QAAQ,kBAAkB,IAAI,KAAK,QAAQ;AAC7D,QAAI,CAAC,WAAW;AACf,aAAO,UAAU,MAAM,GAAG,IAAI;AAAA,IAC/B;AAIA,UAAM,MAAM;AAAA,MACX,MAAM;AAAA,MACN,MAAM;AAAA,MACN,UAAU,KAAK;AAAA,MACf,UAAU,KAAK;AAAA,MACf,MAAM,EAAE,iBAAiB,KAAK;AAAA,MAC9B,YAAY;AAAA,QACX;AAAA,UACC,MAAM;AAAA,UACN,MAAM;AAAA,UACN,OAAO,KAAK;AAAA,QACb;AAAA,QACA;AAAA,UACC,MAAM;AAAA,UACN,MAAM;AAAA,UACN,OAAO;AAAA,YACN,MAAM;AAAA,YACN,OAAO,IAAI,KAAK,IAAI,WAAS,QAAQ,KAAK,UAAU,KAAK,IAAI,WAAW,EAAE,KAAK,IAAI,CAAC;AAAA,YACpF,MAAM;AAAA,cACL,QAAQ;AAAA,gBACP,MAAM;AAAA,gBACN,MAAM;AAAA,kBACL;AAAA,oBACC,MAAM;AAAA,oBACN,YAAY;AAAA,sBACX,MAAM;AAAA,sBACN,UAAU,KAAK,IAAI,WAAS,QAAQ,EAAE,MAAM,WAAW,OAAO,KAAK,KAAK,UAAU,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,MAAM,YAAY,CAAC;AAAA,oBACvI;AAAA,kBACD;AAAA,gBACD;AAAA,gBACA,YAAY;AAAA,cACb;AAAA,YACD;AAAA,UACD;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAEA,QAAI,KAAK,OAAO;AACf,UAAI,WAAW,KAAK;AAAA,QACnB,MAAM;AAAA,QACN,MAAM;AAAA,QACN,OAAO,KAAK;AAAA,MACb,CAAC;AAAA,IACF;AAGA,eAAW,CAAC,OAAOC,KAAI,KAAK,QAAQ,QAAQ,KAAK,CAAC,GAAG;AACpD,YAAM,QAAQ,KAAK,KAAK;AACxB,UAAI,OAAOA,UAAS,YAAY,OAAO,UAAU,UAAU;AAC1D,YAAI,WAAW,KAAK,EAAE,MAAM,mBAAmB,MAAAA,OAAM,MAAM,CAAC;AAAA,MAC7D;AAAA,IACD;AAEA,WAAO;AAAA,EACR;AAEA,SAAO;AACR;;;AFpGA,IAAM,YAAY,oBAAI,IAAI,CAAC,OAAO,CAAC;AACnC,IAAM,aAAa,oBAAI,IAAI;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD,CAAC;AAIM,SAAS,OAAO,QAAgB,UAAuB,CAAC,GAAS;AACvE,aAAW,CAAC,OAAO,KAAK,KAAK,OAAO,SAAS,QAAQ,GAAG;AACvD,QAAI,MAAM,SAAS,eAAe,MAAM,SAAS,CAAC,KAAK,CAAC,MAAM,SAAS,CAAC,GAAG;AAE1E,YAAM,QAAQ,MAAM,SAAS,CAAC;AAC9B,UAAI;AAEJ,UAAI,UAAU,IAAI,MAAM,IAAI,GAAG;AAE9B,mBAAW;AAAA,MACZ,WACS,oBAAoB,KAAK,MAAM,IAAI,KAAK,WAAW,IAAI,MAAM,QAAQ,EAAE,GAAG;AAElF,mBAAW;AAAA,UACV,GAAG;AAAA,UACH,MAAM;AAAA,QACP;AAAA,MACD,WACS,OAAO,KAAK,GAAG;AACvB,mBAAW,YAAY,OAAO,OAAO;AAAA,MACtC;AAEA,UAAI,UAAU;AACb,eAAO,SAAS,KAAK,IAAI;AAAA,MAC1B;AAAA,IACD;AAAA,EACD;AACD;;;ANpCA,IAAM,UAAU,IAAI,cAAc;AAM3B,SAASC,UAAS,UAA2B,CAAC,GAAG;AACvD,SAAO,SAAS,OAAO,MAAY;AAClC,YAAQ,MAAM;AAEd,UAAM,QAAuB,CAAC;AAC9B,QAAI;AAEJ,UAAM,KAAK,IAAI;AAEf,WAAO,SAAS,MAAM,MAAM,GAAG;AAC9B,MAAW,OAAO,MAAM;AACxB,MAAW,SAAS,MAAM;AAC1B,MAAW,SAAS,QAAQ,OAAO;AACnC,MAAW,OAAO,QAAQ,QAAQ,SAAS,CAAC,CAAC;AAC7C,YAAM,KAAK,GAASC,aAAY,OAAO,QAAQ,CAAC;AAAA,IACjD;AAEA,UAAM,KAAK,IAAI;AAEf,WAAO,SAAS,MAAM,MAAM,GAAG;AAC9B,MAAW,QAAQ,MAAM;AACzB,YAAM,KAAK,GAASA,aAAY,OAAO,QAAQ,CAAC;AAAA,IACjD;AAAA,EACD;AACD;;;ADvBO,SAASC,SAAQ,UAAyB,CAAC,GAAG;AACpD,SAAO;AAAA,IACN,CAAC,MAAM,QAAQ,QAAQ,CAAC,CAAC;AAAA,IACzB,CAACC,WAAU,QAAQ,YAAY,CAAC,CAAC;AAAA,EAClC;AACD;","names":["child","plugins","nodeToString","isParent","onlyParents","nodeToString","nodeToString","name","baseline","onlyParents","plugins","baseline"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@copepod/unified-plugins",
|
|
3
|
+
"type": "module",
|
|
4
|
+
"version": "0.0.1",
|
|
5
|
+
"description": "A collection of plugins",
|
|
6
|
+
"author": "Julien Cayzac",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"funding": "https://github.com/sponsors/jcayzac",
|
|
9
|
+
"homepage": "https://github.com/jcayzac/copepod-modules/tree/main/packages/unified-plugins#readme",
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "github:jcayzac/copepod-modules",
|
|
13
|
+
"directory": "packages/unified-plugins"
|
|
14
|
+
},
|
|
15
|
+
"bugs": "https://github.com/jcayzac/copepod-modules/issues",
|
|
16
|
+
"keywords": [
|
|
17
|
+
"rehype",
|
|
18
|
+
"rehype-plugin",
|
|
19
|
+
"remark",
|
|
20
|
+
"remark-plugin",
|
|
21
|
+
"unified",
|
|
22
|
+
"unifiedjs"
|
|
23
|
+
],
|
|
24
|
+
"sideEffects": false,
|
|
25
|
+
"publishConfig": {
|
|
26
|
+
"access": "public"
|
|
27
|
+
},
|
|
28
|
+
"main": "./src/index.ts",
|
|
29
|
+
"files": [
|
|
30
|
+
"dist"
|
|
31
|
+
],
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"@types/hast": "^3.0.4",
|
|
34
|
+
"@types/mdast": "^4.0.4",
|
|
35
|
+
"@types/unist": "^3.0.3",
|
|
36
|
+
"github-slugger": "^2.0.0",
|
|
37
|
+
"hast-util-parse-selector": "^4.0.0",
|
|
38
|
+
"mdast-util-mdx-jsx": "^3.1.3",
|
|
39
|
+
"mdast-util-to-hast": "^13.2.0",
|
|
40
|
+
"rehype-katex": "^7.0.1",
|
|
41
|
+
"remark-math": "^6.0.0",
|
|
42
|
+
"unified": "^11.0.5",
|
|
43
|
+
"unist-util-is": "^6.0.0",
|
|
44
|
+
"unist-util-visit-parents": "^6.0.1"
|
|
45
|
+
},
|
|
46
|
+
"scripts": {
|
|
47
|
+
"build": "pnpm exec tsup"
|
|
48
|
+
},
|
|
49
|
+
"exports": {
|
|
50
|
+
".": {
|
|
51
|
+
"types": "./dist/index.d.ts",
|
|
52
|
+
"import": "./dist/index.mjs"
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
"module": "./dist/index.mjs",
|
|
56
|
+
"types": "./dist/index.d.ts"
|
|
57
|
+
}
|
package/src/index.ts
ADDED