@p-buddy/parkdown 0.0.4 → 0.0.6
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 +342 -97
- package/dist/cli.js +1 -1
- package/dist/index.d.ts +0 -2
- package/dist/index.js +358 -269
- package/dist/index.umd.cjs +12 -14
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
|
-
# parkdown (p
|
|
1
|
+
# parkdown (p↓)
|
|
2
2
|
|
|
3
3
|
`parkdown` allows you to include other file's content within your markdown using a link with no text (i.e. `[](<url>)`), where `<url>` corresponds to either:
|
|
4
4
|
- a local file, e.g. `[](./other.md)` or `[](../root.ts)`
|
|
5
5
|
- **_COMING SOON_**: An external link
|
|
6
6
|
|
|
7
|
-
Markdown renderers shouldn't display these links, but [parkdown]() can process and populate them. Also, your editor hopefully makes these links easy to navigate to, improving productivity.
|
|
7
|
+
Markdown renderers shouldn't display these links, but [parkdown](https://www.npmjs.com/package/@p-buddy/parkdown) can process and populate them. Also, your editor hopefully makes these links easy to navigate to, improving productivity.
|
|
8
8
|
|
|
9
|
-
Collectively, [parkdown]() enables your documentation to behave a little more like code, and for your code to have a rightful place in your documentation.
|
|
9
|
+
Collectively, [parkdown](https://www.npmjs.com/package/@p-buddy/parkdown) enables your documentation to behave a little more like code, and for your code to have a rightful place in your documentation.
|
|
10
10
|
|
|
11
11
|
[](./.assets/invocation.md)
|
|
12
|
-
<!-- p
|
|
12
|
+
<!-- p↓ BEGIN -->
|
|
13
|
+
<!-- p↓ length lines: 29 chars: 796 -->
|
|
13
14
|
## Invocation
|
|
14
15
|
|
|
15
16
|
Invoke [parkdown's]() functionality with either the [cli](#cli-inclusions) or via the `processMarkdownIncludes` [export](#populateMarkdownIncludes-export):
|
|
@@ -18,28 +19,32 @@ Invoke [parkdown's]() functionality with either the [cli](#cli-inclusions) or vi
|
|
|
18
19
|
|
|
19
20
|
The following commands are all equivalent:
|
|
20
21
|
```bash
|
|
21
|
-
npx parkdown --file ./README.md
|
|
22
|
-
npx parkdown -f README.md
|
|
23
|
-
npx parkdown # defaults to processing inclusions in the 'README.md' file of the current working directory
|
|
22
|
+
npx @p-buddy/parkdown --file ./README.md
|
|
23
|
+
npx @p-buddy/parkdown -f README.md
|
|
24
|
+
npx @p-buddy/parkdown # defaults to processing inclusions in the 'README.md' file of the current working directory
|
|
24
25
|
```
|
|
25
26
|
|
|
26
27
|
### `populateMarkdownIncludes` export
|
|
27
28
|
|
|
28
|
-
[](.assets/code/inclusions.ts?region=replace(pkg,'''
|
|
29
|
-
<!-- p
|
|
29
|
+
[](.assets/code/inclusions.ts?region=replace(pkg,'''@p-buddy_slash_parkdown''',_))
|
|
30
|
+
<!-- p↓ BEGIN -->
|
|
31
|
+
<!-- p↓ length lines: 10 chars: 172 -->
|
|
32
|
+
|
|
30
33
|
```ts
|
|
31
|
-
import { populateMarkdownInclusions } from "parkdown";
|
|
34
|
+
import { populateMarkdownInclusions } from "@p-buddy/parkdown";
|
|
32
35
|
|
|
33
36
|
const file = "README.md";
|
|
34
37
|
const writeFile = true;
|
|
35
38
|
|
|
36
39
|
populateMarkdownInclusions(file, writeFile);
|
|
37
40
|
```
|
|
38
|
-
|
|
39
|
-
<!-- p
|
|
41
|
+
|
|
42
|
+
<!-- p↓ END -->
|
|
43
|
+
<!-- p↓ END -->
|
|
40
44
|
|
|
41
45
|
[](./.assets/authoring.md)
|
|
42
|
-
<!-- p
|
|
46
|
+
<!-- p↓ BEGIN -->
|
|
47
|
+
<!-- p↓ length lines: 572 chars: 17752 -->
|
|
43
48
|
## Authoring
|
|
44
49
|
|
|
45
50
|
You author inclusions in your markdown files using a link with no text i.e. `[](<url>)`, where `<url>` points to some local or remote text resource (e.g.`./other.md`, `https://example.com/remote.md`).
|
|
@@ -57,84 +62,110 @@ There are two equivalent ways to author inline inclusions, [single-line](#single
|
|
|
57
62
|
What you write:
|
|
58
63
|
|
|
59
64
|
[](.assets/unpopulated/inline.single.md?wrap=code)
|
|
60
|
-
<!-- p
|
|
65
|
+
<!-- p↓ BEGIN -->
|
|
66
|
+
<!-- p↓ length lines: 5 chars: 40 -->
|
|
67
|
+
|
|
61
68
|
```md
|
|
62
69
|
Before... [](<url>) ...After
|
|
63
70
|
```
|
|
64
|
-
<!-- p▼ END -->
|
|
65
71
|
|
|
66
|
-
|
|
72
|
+
<!-- p↓ END -->
|
|
73
|
+
|
|
74
|
+
<details>
|
|
75
|
+
<summary>See rendering and processing output</summary>
|
|
76
|
+
|
|
77
|
+
What is rendered (**_before_** processing, same as [Multi-line](#multi-line)):
|
|
67
78
|
|
|
68
79
|
[](.assets/unpopulated/inline.single.md?wrap=quote&inline)
|
|
69
|
-
<!-- p
|
|
80
|
+
<!-- p↓ BEGIN -->
|
|
81
|
+
<!-- p↓ length lines: 1 chars: 30 -->
|
|
70
82
|
> Before... [](<url>) ...After
|
|
71
|
-
<!-- p
|
|
83
|
+
<!-- p↓ END -->
|
|
72
84
|
|
|
73
85
|
What your markdown file contains (**_after_** processing):
|
|
74
86
|
|
|
75
87
|
[](.assets/populated/inline.single.md?wrap=code)
|
|
76
|
-
<!-- p
|
|
88
|
+
<!-- p↓ BEGIN -->
|
|
89
|
+
<!-- p↓ length lines: 7 chars: 120 -->
|
|
90
|
+
|
|
77
91
|
```md
|
|
78
|
-
Before... [](<url>) <!-- p
|
|
92
|
+
Before... [](<url>) <!-- p↓ Begin -->
|
|
79
93
|
...Included Content...
|
|
80
|
-
...Included Content... <!-- p
|
|
94
|
+
...Included Content... <!-- p↓ End --> ...After
|
|
81
95
|
```
|
|
82
|
-
<!-- p▼ END -->
|
|
83
96
|
|
|
84
|
-
|
|
97
|
+
<!-- p↓ END -->
|
|
98
|
+
|
|
99
|
+
What is rendered (**_after_** processing, same as [Multi-line](#multi-line)):
|
|
85
100
|
|
|
86
101
|
[](.assets/populated/inline.single.md?wrap=quote&inline)
|
|
87
|
-
<!-- p
|
|
88
|
-
|
|
102
|
+
<!-- p↓ BEGIN -->
|
|
103
|
+
<!-- p↓ length lines: 3 chars: 110 -->
|
|
104
|
+
> Before... [](<url>) <!-- p↓ Begin -->
|
|
89
105
|
...Included Content...
|
|
90
|
-
...Included Content... <!-- p
|
|
91
|
-
<!-- p
|
|
106
|
+
...Included Content... <!-- p↓ End --> ...After
|
|
107
|
+
<!-- p↓ END -->
|
|
108
|
+
|
|
109
|
+
</details>
|
|
92
110
|
|
|
93
111
|
#### Multi-line
|
|
94
112
|
|
|
95
113
|
What you write:
|
|
96
114
|
|
|
97
115
|
[](.assets/unpopulated/inline.multi.md?wrap=code)
|
|
98
|
-
<!-- p
|
|
116
|
+
<!-- p↓ BEGIN -->
|
|
117
|
+
<!-- p↓ length lines: 7 chars: 41 -->
|
|
118
|
+
|
|
99
119
|
```md
|
|
100
120
|
Before...
|
|
101
121
|
[](<url>)
|
|
102
122
|
...After
|
|
103
123
|
```
|
|
104
|
-
<!-- p▼ END -->
|
|
105
124
|
|
|
106
|
-
|
|
125
|
+
<!-- p↓ END -->
|
|
126
|
+
|
|
127
|
+
<details>
|
|
128
|
+
<summary>See rendering and processing output</summary>
|
|
129
|
+
|
|
130
|
+
What is rendered (**_before_** processing, same as [Single-line](#single-line)):
|
|
107
131
|
|
|
108
132
|
[](.assets/unpopulated/inline.multi.md?wrap=quote&inline)
|
|
109
|
-
<!-- p
|
|
133
|
+
<!-- p↓ BEGIN -->
|
|
134
|
+
<!-- p↓ length lines: 3 chars: 31 -->
|
|
110
135
|
> Before...
|
|
111
136
|
[](<url>)
|
|
112
137
|
...After
|
|
113
|
-
<!-- p
|
|
138
|
+
<!-- p↓ END -->
|
|
114
139
|
|
|
115
140
|
What your markdown file contains (**_after_** processing):
|
|
116
141
|
|
|
117
142
|
[](.assets/populated/inline.multi.md?wrap=code)
|
|
118
|
-
<!-- p
|
|
143
|
+
<!-- p↓ BEGIN -->
|
|
144
|
+
<!-- p↓ length lines: 9 chars: 122 -->
|
|
145
|
+
|
|
119
146
|
```md
|
|
120
147
|
Before...
|
|
121
|
-
[](<url>) <!-- p
|
|
148
|
+
[](<url>) <!-- p↓ Begin -->
|
|
122
149
|
...Included Content...
|
|
123
|
-
...Included Content... <!-- p
|
|
150
|
+
...Included Content... <!-- p↓ End -->
|
|
124
151
|
...After
|
|
125
152
|
```
|
|
126
|
-
<!-- p▼ END -->
|
|
127
153
|
|
|
128
|
-
|
|
154
|
+
<!-- p↓ END -->
|
|
155
|
+
|
|
156
|
+
What is rendered (**_after_** processing, same as [Single-line](#single-line)):
|
|
129
157
|
|
|
130
158
|
[](.assets/populated/inline.multi.md?wrap=quote&inline)
|
|
131
|
-
<!-- p
|
|
159
|
+
<!-- p↓ BEGIN -->
|
|
160
|
+
<!-- p↓ length lines: 5 chars: 112 -->
|
|
132
161
|
> Before...
|
|
133
|
-
[](<url>) <!-- p
|
|
162
|
+
[](<url>) <!-- p↓ Begin -->
|
|
134
163
|
...Included Content...
|
|
135
|
-
...Included Content... <!-- p
|
|
164
|
+
...Included Content... <!-- p↓ End -->
|
|
136
165
|
...After
|
|
137
|
-
<!-- p
|
|
166
|
+
<!-- p↓ END -->
|
|
167
|
+
|
|
168
|
+
</details>
|
|
138
169
|
|
|
139
170
|
### Block
|
|
140
171
|
|
|
@@ -143,7 +174,9 @@ Block inclusions occur when your "empty" link is the **only** node in a [paragra
|
|
|
143
174
|
What you write:
|
|
144
175
|
|
|
145
176
|
[](.assets/unpopulated/block.md?wrap=code)
|
|
146
|
-
<!-- p
|
|
177
|
+
<!-- p↓ BEGIN -->
|
|
178
|
+
<!-- p↓ length lines: 9 chars: 42 -->
|
|
179
|
+
|
|
147
180
|
```md
|
|
148
181
|
Before...
|
|
149
182
|
|
|
@@ -151,12 +184,18 @@ Before...
|
|
|
151
184
|
|
|
152
185
|
...After
|
|
153
186
|
```
|
|
154
|
-
|
|
187
|
+
|
|
188
|
+
<!-- p↓ END -->
|
|
189
|
+
|
|
190
|
+
<details>
|
|
191
|
+
<summary>See rendering and processing output</summary>
|
|
155
192
|
|
|
156
193
|
What is rendered (**_before_** processing):
|
|
157
194
|
|
|
158
195
|
[](.assets/unpopulated/block.md?wrap=quote)
|
|
159
|
-
<!-- p
|
|
196
|
+
<!-- p↓ BEGIN -->
|
|
197
|
+
<!-- p↓ length lines: 11 chars: 61 -->
|
|
198
|
+
|
|
160
199
|
<blockquote>
|
|
161
200
|
|
|
162
201
|
Before...
|
|
@@ -167,47 +206,55 @@ Before...
|
|
|
167
206
|
|
|
168
207
|
</blockquote>
|
|
169
208
|
|
|
170
|
-
<!-- p
|
|
209
|
+
<!-- p↓ END -->
|
|
171
210
|
|
|
172
211
|
What your markdown file contains (**_after_** processing):
|
|
173
212
|
|
|
174
213
|
[](.assets/populated/block.md?wrap=code)
|
|
175
|
-
<!-- p
|
|
214
|
+
<!-- p↓ BEGIN -->
|
|
215
|
+
<!-- p↓ length lines: 13 chars: 124 -->
|
|
216
|
+
|
|
176
217
|
```md
|
|
177
218
|
Before...
|
|
178
219
|
|
|
179
220
|
[](<url>)
|
|
180
|
-
<!-- p
|
|
221
|
+
<!-- p↓ Begin -->
|
|
181
222
|
...Included Content...
|
|
182
223
|
...Included Content...
|
|
183
|
-
<!-- p
|
|
224
|
+
<!-- p↓ End -->
|
|
184
225
|
|
|
185
226
|
...After
|
|
186
227
|
```
|
|
187
|
-
|
|
228
|
+
|
|
229
|
+
<!-- p↓ END -->
|
|
188
230
|
|
|
189
231
|
What is rendered (**_after_** processing):
|
|
190
232
|
|
|
191
233
|
[](.assets/populated/block.md?wrap=quote)
|
|
192
|
-
<!-- p
|
|
234
|
+
<!-- p↓ BEGIN -->
|
|
235
|
+
<!-- p↓ length lines: 15 chars: 143 -->
|
|
236
|
+
|
|
193
237
|
<blockquote>
|
|
194
238
|
|
|
195
239
|
Before...
|
|
196
240
|
|
|
197
241
|
[](<url>)
|
|
198
|
-
<!-- p
|
|
242
|
+
<!-- p↓ Begin -->
|
|
199
243
|
...Included Content...
|
|
200
244
|
...Included Content...
|
|
201
|
-
<!-- p
|
|
245
|
+
<!-- p↓ End -->
|
|
202
246
|
|
|
203
247
|
...After
|
|
204
248
|
|
|
205
249
|
</blockquote>
|
|
206
250
|
|
|
207
|
-
<!-- p
|
|
251
|
+
<!-- p↓ END -->
|
|
252
|
+
|
|
253
|
+
</details>
|
|
208
254
|
|
|
209
255
|
[](.assets/query.md?heading=-1)
|
|
210
|
-
<!-- p
|
|
256
|
+
<!-- p↓ BEGIN -->
|
|
257
|
+
<!-- p↓ length lines: 361 chars: 13249 -->
|
|
211
258
|
### Query parameters
|
|
212
259
|
|
|
213
260
|
You can pass query parameters to your inclusion links to control how their content is processed and included within your markdown.
|
|
@@ -215,7 +262,9 @@ You can pass query parameters to your inclusion links to control how their conte
|
|
|
215
262
|
#### Processing Order
|
|
216
263
|
|
|
217
264
|
[](src/include.ts?®ion=extract(query))
|
|
218
|
-
<!-- p
|
|
265
|
+
<!-- p↓ BEGIN -->
|
|
266
|
+
<!-- p↓ length lines: 10 chars: 322 -->
|
|
267
|
+
|
|
219
268
|
```ts
|
|
220
269
|
const params = new URLSearchParams(query);
|
|
221
270
|
const regions = params.get("region")?.split(COMMA_NOT_IN_PARENTHESIS);
|
|
@@ -224,7 +273,8 @@ const headingModfiier = params.get("heading") ?? 0;
|
|
|
224
273
|
const inlineOverride = params.has("inline");
|
|
225
274
|
const wraps = params.get("wrap")?.split(COMMA_NOT_IN_PARENTHESIS);
|
|
226
275
|
```
|
|
227
|
-
|
|
276
|
+
|
|
277
|
+
<!-- p↓ END -->
|
|
228
278
|
|
|
229
279
|
#### `region`
|
|
230
280
|
|
|
@@ -238,14 +288,18 @@ Specifiers will be searched for within the file's comments, and are expected to
|
|
|
238
288
|
/** some-specifier */
|
|
239
289
|
```
|
|
240
290
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
291
|
+
Below is the currently supported API for the `region` query parameter, where each defined method signature can be _invoked_ as a value for the `region` parameter, for example:
|
|
292
|
+
|
|
293
|
+
- `[](<url>?region=extract(some-specifier))`
|
|
294
|
+
- `[](<url>?region=remove(some-specifier))`
|
|
295
|
+
- `[](<url>?region=replace(some-specifier,replacement-content))`
|
|
244
296
|
|
|
245
|
-
|
|
297
|
+
If no value(s) are included (e.g. `[](<url>?region)`), then simply all comments that contain `parkdown:` or `p↓:` will be stripped (as is done as a post-processing step for all other `region` functionality).
|
|
246
298
|
|
|
247
299
|
[](.assets/api-note.md?wrap=quote)
|
|
248
|
-
<!-- p
|
|
300
|
+
<!-- p↓ BEGIN -->
|
|
301
|
+
<!-- p↓ length lines: 9 chars: 352 -->
|
|
302
|
+
|
|
249
303
|
<blockquote>
|
|
250
304
|
|
|
251
305
|
**_NOTE ON API USAGE:_** As you can see from the included examples, each _invocation_ of an API method looks like a less strict (more quirky) version of a typical javascript function invocation.
|
|
@@ -254,40 +308,78 @@ Please see the [full explanation](#query-parameters-with-function-like-apis) to
|
|
|
254
308
|
|
|
255
309
|
</blockquote>
|
|
256
310
|
|
|
257
|
-
<!-- p
|
|
311
|
+
<!-- p↓ END -->
|
|
258
312
|
|
|
259
313
|
[](src/region.ts?region=extract(definition))
|
|
260
|
-
<!-- p
|
|
314
|
+
<!-- p↓ BEGIN -->
|
|
315
|
+
<!-- p↓ length lines: 36 chars: 1651 -->
|
|
316
|
+
|
|
261
317
|
```ts
|
|
262
318
|
const definitions = [
|
|
319
|
+
/**
|
|
320
|
+
* Extract regions from the retrieved content between comments that INCLUDE the specified ids.
|
|
321
|
+
* @param id The id of the comment to extract.
|
|
322
|
+
* @param 0 An optional additional id to extract.
|
|
323
|
+
* @param 1 An optional additional id to extract.
|
|
324
|
+
* @param 2 An optional additional id to extract.
|
|
325
|
+
* @example [](<url>?region=extract(specifier))
|
|
326
|
+
* @example [](<url>?region=extract(specifier,other-specifier,some-other-specifier))
|
|
327
|
+
*/
|
|
263
328
|
"extract(id: string, 0?: string, 1?: string, 2?: string)",
|
|
329
|
+
/**
|
|
330
|
+
* Remove regions from the retrieved content between comments that INCLUDE the specified ids.
|
|
331
|
+
* @param id The id of the comment to remove.
|
|
332
|
+
* @param 0 An optional additional id to remove.
|
|
333
|
+
* @param 1 An optional additional id to remove.
|
|
334
|
+
* @param 2 An optional additional id to remove.
|
|
335
|
+
* @example [](<url>?region=remove(specifier))
|
|
336
|
+
* @example [](<url>?region=remove(specifier,other-specifier,some-other-specifier))
|
|
337
|
+
*/
|
|
264
338
|
"remove(id: string, 0?: string, 1?: string, 2?: string)",
|
|
339
|
+
/**
|
|
340
|
+
* Replace regions from the retrieved content between comments that INCLUDE the specified ids.
|
|
341
|
+
* @param id The id of the comment to replace.
|
|
342
|
+
* @param with The replacement content (if ommitted, the content of the detected comment will be used).
|
|
343
|
+
* @param space The space character to use between words in the replacement content (defaults to `-`).
|
|
344
|
+
* @example [](<url>?region=replace(specifier))
|
|
345
|
+
* @example [](<url>?region=replace(specifier,new-content))
|
|
346
|
+
* @example [](<url>?region=replace(specifier,new_content,_)
|
|
347
|
+
*/
|
|
265
348
|
"replace(id: string, with?: string, space?: string)",
|
|
266
349
|
]
|
|
267
350
|
```
|
|
268
|
-
|
|
351
|
+
|
|
352
|
+
<!-- p↓ END -->
|
|
269
353
|
|
|
270
354
|
#### `skip`
|
|
271
355
|
|
|
272
356
|
Skip the default processing behavior for the given type of file.
|
|
273
357
|
|
|
274
358
|
[](src/include.ts?wrap=dropdown(See-default-processing-behavior.)®ion=extract(Default-Behavior),replace(...))
|
|
275
|
-
<!-- p
|
|
359
|
+
<!-- p↓ BEGIN -->
|
|
360
|
+
<!-- p↓ length lines: 21 chars: 525 -->
|
|
276
361
|
|
|
277
362
|
<details>
|
|
278
|
-
<summary>
|
|
363
|
+
<summary>
|
|
364
|
+
See default processing behavior.
|
|
365
|
+
</summary>
|
|
279
366
|
|
|
280
367
|
```ts
|
|
281
368
|
if (extension === "md") {
|
|
282
|
-
|
|
283
|
-
|
|
369
|
+
|
|
370
|
+
const getContent = extendGetRelativePathContent(getRelativePathContent, target);
|
|
371
|
+
const relative = basePath ? join(basePath, dir) : dir;
|
|
372
|
+
const depth = clampHeadingSum(headingDepth, Number(headingModfiier));
|
|
373
|
+
|
|
374
|
+
content = recursivelyPopulateInclusions(content, depth, getContent, path, relative);
|
|
284
375
|
}
|
|
285
376
|
else if (/^(js|ts)x?|svelte$/i.test(extension))
|
|
286
|
-
content = wrap(content, "code",
|
|
377
|
+
content = wrap(content, "code", { extension, inline });
|
|
287
378
|
```
|
|
379
|
+
|
|
288
380
|
</details>
|
|
289
381
|
|
|
290
|
-
<!-- p
|
|
382
|
+
<!-- p↓ END -->
|
|
291
383
|
|
|
292
384
|
```md
|
|
293
385
|
[](<url>?skip)
|
|
@@ -295,36 +387,74 @@ else if (/^(js|ts)x?|svelte$/i.test(extension))
|
|
|
295
387
|
|
|
296
388
|
#### `heading`
|
|
297
389
|
|
|
298
|
-
Modify the heading depth applied to included content. By default, the headings of the included content are adjusted to be one-level below their parent heading.
|
|
390
|
+
Modify the heading depth applied to included content. By default, the headings of the included content are adjusted to be one-level below their parent heading (i.e. the heading the included content falls under).
|
|
391
|
+
|
|
392
|
+
You might commonly see `[](<url>?heading=-1)` used to ensure that the included content's heading level is the same as it's parent heading.
|
|
299
393
|
|
|
300
|
-
|
|
394
|
+
<details>
|
|
395
|
+
<summary>
|
|
396
|
+
See example usage:
|
|
397
|
+
</summary>
|
|
398
|
+
Assuming you have the following markdown files:
|
|
301
399
|
|
|
302
400
|
```md
|
|
303
|
-
|
|
401
|
+
<!-- to-be-included.md -->
|
|
402
|
+
# Included Heading
|
|
403
|
+
```
|
|
304
404
|
|
|
305
|
-
|
|
405
|
+
```md
|
|
406
|
+
<!-- README.md -->
|
|
407
|
+
# Heading
|
|
408
|
+
|
|
409
|
+
[](./to-be-included.md)
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
When `README.md` is processed, it will be transformed into the following:
|
|
413
|
+
|
|
414
|
+
```md
|
|
415
|
+
# Heading
|
|
416
|
+
|
|
417
|
+
## Included Heading
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
Where the included content's heading has been modified to be one-level below the parent heading (i.e. it is converted from an `h1` / `#` heading to a `h2` / `##` heading — `h1 + 1 = h2`).
|
|
421
|
+
|
|
422
|
+
If we instead wanted the included heading to remain a `h1` / `#` heading, we'd make use of the `heading` query parameter with a value of `-1` (since `h1 + 1 - 1 = h1`), like so:
|
|
423
|
+
|
|
424
|
+
```md
|
|
425
|
+
<!-- README.md -->
|
|
426
|
+
# Heading
|
|
427
|
+
|
|
428
|
+
[](./to-be-included.md?heading=-1)
|
|
306
429
|
```
|
|
307
430
|
|
|
308
|
-
|
|
431
|
+
which would result in the following:
|
|
309
432
|
|
|
310
433
|
```md
|
|
311
|
-
|
|
434
|
+
# Heading
|
|
312
435
|
|
|
313
|
-
|
|
436
|
+
# Included Heading
|
|
314
437
|
```
|
|
315
438
|
|
|
316
|
-
|
|
439
|
+
</details>
|
|
317
440
|
|
|
318
441
|
#### `inline` (Advanced)
|
|
319
442
|
|
|
443
|
+
Force a replacement target to be treated as [inline](#inline) content.
|
|
444
|
+
|
|
320
445
|
#### `wrap`
|
|
321
446
|
|
|
322
447
|
Wrap the content of the included file in a specific kind of element.
|
|
323
448
|
|
|
324
|
-
Below is the currently supported API for the `wrap` query parameter, where each defined method signature can be _invoked_ as a value for the `wrap` parameter
|
|
449
|
+
Below is the currently supported API for the `wrap` query parameter, where each defined method signature can be _invoked_ as a value for the `wrap` parameter, for example:
|
|
450
|
+
|
|
451
|
+
- `[](<url>?wrap=code)`
|
|
452
|
+
- `[](<url>?wrap=dropdown(hello-world))`
|
|
325
453
|
|
|
326
454
|
[](.assets/api-note.md?wrap=quote)
|
|
327
|
-
<!-- p
|
|
455
|
+
<!-- p↓ BEGIN -->
|
|
456
|
+
<!-- p↓ length lines: 9 chars: 352 -->
|
|
457
|
+
|
|
328
458
|
<blockquote>
|
|
329
459
|
|
|
330
460
|
**_NOTE ON API USAGE:_** As you can see from the included examples, each _invocation_ of an API method looks like a less strict (more quirky) version of a typical javascript function invocation.
|
|
@@ -333,10 +463,12 @@ Please see the [full explanation](#query-parameters-with-function-like-apis) to
|
|
|
333
463
|
|
|
334
464
|
</blockquote>
|
|
335
465
|
|
|
336
|
-
<!-- p
|
|
466
|
+
<!-- p↓ END -->
|
|
337
467
|
|
|
338
468
|
[](src/wrap.ts?region=extract(definition))
|
|
339
|
-
<!-- p
|
|
469
|
+
<!-- p↓ BEGIN -->
|
|
470
|
+
<!-- p↓ length lines: 38 chars: 1384 -->
|
|
471
|
+
|
|
340
472
|
```ts
|
|
341
473
|
const definitions = [
|
|
342
474
|
/**
|
|
@@ -373,13 +505,123 @@ const definitions = [
|
|
|
373
505
|
|
|
374
506
|
]
|
|
375
507
|
```
|
|
376
|
-
<!-- p▼ END -->
|
|
377
508
|
|
|
378
|
-
<!-- p
|
|
379
|
-
|
|
509
|
+
<!-- p↓ END -->
|
|
510
|
+
|
|
511
|
+
[](.assets/api.md?heading=-1)
|
|
512
|
+
<!-- p↓ BEGIN -->
|
|
513
|
+
<!-- p↓ length lines: 104 chars: 4973 -->
|
|
514
|
+
#### Query Parameters with Function-like APIs
|
|
515
|
+
|
|
516
|
+
Some query parameters have more complex APIs, which are defined by a collection of typescript function singatures (limited to only `string`, `boolean`, and `number` arguments), like:
|
|
517
|
+
|
|
518
|
+
```ts
|
|
519
|
+
const definitions = [
|
|
520
|
+
"method(arg1: string, arg2: boolean, arg3?: number)",
|
|
521
|
+
"otherMethod(arg1: string, arg2?: boolean, arg3?: number)"
|
|
522
|
+
]
|
|
523
|
+
```
|
|
524
|
+
|
|
525
|
+
These APIs are utilized when setting the value of the specific query parameter with a _function-like_ invocation syntax, such as:
|
|
526
|
+
|
|
527
|
+
```md
|
|
528
|
+
[](<url>?example=method(hello-world,true))
|
|
529
|
+
```
|
|
530
|
+
|
|
531
|
+
As you can see from the example above, we're relaxing some constraints on typical function invocations (like the need to wrap string arguments in quotes), while also imposing some additional constraints (like not using _any_ spaces) to ensure the links are valid markdown and the URLs are [safe](https://support.exactonline.com/community/s/knowledge-base?language=en_GB#All-All-DNO-Content-urlcharacters).
|
|
532
|
+
|
|
533
|
+
The goal is to make it as painless as possible to author links that are valid markdown, valid URLs, and easy to read and write.
|
|
534
|
+
|
|
535
|
+
Please note the following:
|
|
536
|
+
|
|
537
|
+
- Methods that take no arguments can be invoked without parentheses (e.g. `[](<url>?example=method)`).
|
|
538
|
+
- String arguments do not need to be wrapped in quotes (e.g. `[](<url>?example=method(some-string))`), and they **CANNOT** be wrapped in double quotes (see more below).
|
|
539
|
+
- You cannot use spaces within a string argument or anywhere else in the query (as this would violate the markdown link syntax). For arguments that reasonably could include spaces, there should be an optional `space` argument that defaults to `-`, so that any usage of the space character will be converted to a space (e.g. `hello-world` becomes `hello world`).
|
|
540
|
+
- Characters that are reserved or unsafe in URLs can be included by using the below remapping, where you'll write the corresponding key wrapped in the applicable `space` character (see the above bullet point, defaults to `-`). For example, if you want to use a `/`, you'd instead write `-slash-` (or with whatever you specify as your space character instead of `-`).
|
|
541
|
+
|
|
542
|
+
[](src/utils.ts?region=extract(url))
|
|
543
|
+
<!-- p↓ BEGIN -->
|
|
544
|
+
<!-- p↓ length lines: 31 chars: 498 -->
|
|
545
|
+
|
|
546
|
+
```ts
|
|
547
|
+
const urlCharacters = {
|
|
548
|
+
reserved: {
|
|
549
|
+
["semi"]: ";",
|
|
550
|
+
["slash"]: "/",
|
|
551
|
+
["question"]: "?",
|
|
552
|
+
["colon"]: ":",
|
|
553
|
+
["at"]: "@",
|
|
554
|
+
["equal"]: "=",
|
|
555
|
+
["and"]: "&",
|
|
556
|
+
},
|
|
557
|
+
unsafe: {
|
|
558
|
+
["quote"]: "\"",
|
|
559
|
+
["angle"]: "<",
|
|
560
|
+
["unangle"]: ">",
|
|
561
|
+
["hash"]: "#",
|
|
562
|
+
["percent"]: "%",
|
|
563
|
+
["curly"]: "{",
|
|
564
|
+
["uncurly"]: "}",
|
|
565
|
+
["pipe"]: "|",
|
|
566
|
+
["back"]: "\\",
|
|
567
|
+
["carrot"]: "^",
|
|
568
|
+
["tilde"]: "~",
|
|
569
|
+
["square"]: "[",
|
|
570
|
+
["unsquare"]: "]",
|
|
571
|
+
["tick"]: "`",
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
```
|
|
575
|
+
|
|
576
|
+
<!-- p↓ END -->
|
|
577
|
+
|
|
578
|
+
- If a method takes a string argument, and you want to include a comma within that argument, you must wrap it in one or more single quotes (e.g.`hello,-world` should be specified as `'hello,-world'`).
|
|
579
|
+
- String arguments wrapped in a single set of single quotes will automatically have the quotes removed when the query is parsed (e.g. the argument included in `[](<url>?example=method('hello,world'))` will parse to `hello,world`).
|
|
580
|
+
- If you want single quotes preserved in the parsed output, use two single quotes in a row (e.g. `[](<url>?example=method(''single-quoted''))`).
|
|
581
|
+
- You cannot use double quotes within a string argument (as they are not a [URL safe character](https://support.exactonline.com/community/s/knowledge-base#All-All-DNO-Content-urlcharacters)). To include a double-quote in the parsed output, use three single quotes in a row (e.g. `[](<url>?example=method('''double-quoted'''))`). Or use the remapping described above, like `[](<url>?example=method(-quote-double-quoted-quote-))`.
|
|
582
|
+
- Optional arguments can be completely ommitted (for example if a `method` took 3 optional arguments, and you only wanted to provide the third, you could do the following: `[](<url>?example=method(,,your-third-argument))`).
|
|
583
|
+
- Overall, text meant to be displayed will be _sanitized_ in the following manner (unless otherwise noted):
|
|
584
|
+
|
|
585
|
+
[](src/utils.ts?region=extract(sanitize))
|
|
586
|
+
<!-- p↓ BEGIN -->
|
|
587
|
+
<!-- p↓ length lines: 29 chars: 771 -->
|
|
588
|
+
|
|
589
|
+
```ts
|
|
590
|
+
type Replacement = [from: RegExp | string, to: string];
|
|
591
|
+
|
|
592
|
+
const replacements: Record<string, Replacement[]> = {
|
|
593
|
+
static: [
|
|
594
|
+
[`'''`, `"`],
|
|
595
|
+
[`''`, `'`],
|
|
596
|
+
[/parkdown:\s+/g, ``],
|
|
597
|
+
[/p↓:\s+/g, ``],
|
|
598
|
+
],
|
|
599
|
+
url: [
|
|
600
|
+
...(Object.entries(urlCharacters.unsafe)),
|
|
601
|
+
...(Object.entries(urlCharacters.reserved))
|
|
602
|
+
]
|
|
603
|
+
};
|
|
604
|
+
|
|
605
|
+
const applyReplacement = (accumulator: string, [from, to]: Replacement) =>
|
|
606
|
+
accumulator.replaceAll(from, to);
|
|
607
|
+
|
|
608
|
+
export const sanitize = (content: string, space: string = DEFAULT_SPACE) => {
|
|
609
|
+
const sanitized = replacements.static.reduce(applyReplacement, content)
|
|
610
|
+
return replacements.url
|
|
611
|
+
.map(([key, to]) => ([space + key + space, to] satisfies Replacement))
|
|
612
|
+
.reduce(applyReplacement, sanitized)
|
|
613
|
+
.replaceAll(space, " ");
|
|
614
|
+
}
|
|
615
|
+
```
|
|
616
|
+
|
|
617
|
+
<!-- p↓ END -->
|
|
618
|
+
<!-- p↓ END -->
|
|
619
|
+
<!-- p↓ END -->
|
|
620
|
+
<!-- p↓ END -->
|
|
380
621
|
|
|
381
622
|
[](./.assets/depopulated.md)
|
|
382
|
-
<!-- p
|
|
623
|
+
<!-- p↓ BEGIN -->
|
|
624
|
+
<!-- p↓ length lines: 38 chars: 1473 -->
|
|
383
625
|
## Removing populated inclusions
|
|
384
626
|
|
|
385
627
|
Sometimes you may want to remove populated inclusions from your markdown file, since they can make things more difficult to read during authoring. You can do this either using the [cli](#cli-removing-populated-inclusions) or via the `removePopulatedInclusions` [export](#depopulateMarkdownIncludes-export):
|
|
@@ -389,30 +631,33 @@ Sometimes you may want to remove populated inclusions from your markdown file, s
|
|
|
389
631
|
The following commands are all equivalent:
|
|
390
632
|
|
|
391
633
|
```bash
|
|
392
|
-
npx parkdown --file ./README.md --depopulate --no-inclusions
|
|
393
|
-
npx parkdown -f README.md -d --ni # Notice the double-dash (--) on 'ni'
|
|
394
|
-
npx parkdown -d --ni # defaults to processing the 'README.md' file of the current working directory
|
|
634
|
+
npx @p-buddy/parkdown --file ./README.md --depopulate --no-inclusions
|
|
635
|
+
npx @p-buddy/parkdown -f README.md -d --ni # Notice the double-dash (--) on 'ni'
|
|
636
|
+
npx @p-buddy/parkdown -d --ni # defaults to processing the 'README.md' file of the current working directory
|
|
395
637
|
```
|
|
396
638
|
|
|
397
639
|
The following commands will lead to the same result, but since `--no-inclusions` (`--ni`) is not specified, there will be some wasted work as inclusions will be processed and then removed.
|
|
398
640
|
|
|
399
641
|
```bash
|
|
400
|
-
npx parkdown --file ./README.md --depopulate
|
|
401
|
-
npx parkdown -f README.md -d
|
|
402
|
-
npx parkdown -d # defaults to processing the 'README.md' file of the current working directory
|
|
642
|
+
npx @p-buddy/parkdown --file ./README.md --depopulate
|
|
643
|
+
npx @p-buddy/parkdown -f README.md -d
|
|
644
|
+
npx @p-buddy/parkdown -d # defaults to processing the 'README.md' file of the current working directory
|
|
403
645
|
```
|
|
404
646
|
|
|
405
647
|
### `depopulateMarkdownIncludes` export
|
|
406
648
|
|
|
407
|
-
[](.assets/code/depopulate.ts?region=replace(pkg,'''
|
|
408
|
-
<!-- p
|
|
649
|
+
[](.assets/code/depopulate.ts?region=replace(pkg,'''@p-buddy_slash_parkdown''',_))
|
|
650
|
+
<!-- p↓ BEGIN -->
|
|
651
|
+
<!-- p↓ length lines: 10 chars: 176 -->
|
|
652
|
+
|
|
409
653
|
```ts
|
|
410
|
-
import { depopulateMarkdownInclusions } from "parkdown";
|
|
654
|
+
import { depopulateMarkdownInclusions } from "@p-buddy/parkdown";
|
|
411
655
|
|
|
412
656
|
const file = "README.md";
|
|
413
657
|
const writeFile = true;
|
|
414
658
|
|
|
415
659
|
depopulateMarkdownInclusions(file, writeFile);
|
|
416
660
|
```
|
|
417
|
-
|
|
418
|
-
<!-- p
|
|
661
|
+
|
|
662
|
+
<!-- p↓ END -->
|
|
663
|
+
<!-- p↓ END -->
|