fencen 0.0.1 → 0.1.0
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 +85 -0
- package/lib.d.ts +31 -0
- package/lib.js +23 -0
- package/package.json +1 -1
- package/index.d.ts +0 -6
- package/index.js +0 -1
- package/readme.md +0 -1
- /package/{license.txt → LICENSE} +0 -0
package/README.md
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# fencen
|
|
2
|
+
|
|
3
|
+
Safe and simple utilities for wrapping code in Markdown-style fences.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
import fencen, {blockFences, inlineFences, pickFence} from 'fencen'
|
|
9
|
+
|
|
10
|
+
fencen('hello')
|
|
11
|
+
// ```
|
|
12
|
+
// hello
|
|
13
|
+
// ```
|
|
14
|
+
|
|
15
|
+
const fence = pickFence('hello')
|
|
16
|
+
fence.opener() // '```\n'
|
|
17
|
+
fence.closer() // '\n```'
|
|
18
|
+
|
|
19
|
+
fencen('hello ` world', {inline: true})
|
|
20
|
+
// `` hello ` world ``
|
|
21
|
+
|
|
22
|
+
fencen('const value = 1', {inline: true, language: 'ts'})
|
|
23
|
+
// <code language="ts">const value = 1</code>
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
`pickFence` returns a `Fence` with `opener()` and `closer()` renderers. Block Markdown fences render `language` after the opener. Inline output with a language uses the XML `<code language="…">` fence because Markdown inline-code fences have no language syntax. XML attribute values are escaped.
|
|
27
|
+
|
|
28
|
+
## Trimming
|
|
29
|
+
|
|
30
|
+
`trim` accepts a boolean or object:
|
|
31
|
+
|
|
32
|
+
```ts
|
|
33
|
+
fencen(input, {
|
|
34
|
+
trim: {
|
|
35
|
+
vertical: true,
|
|
36
|
+
lines: true,
|
|
37
|
+
indentation: true,
|
|
38
|
+
},
|
|
39
|
+
})
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
`trim: true` is equivalent to:
|
|
43
|
+
|
|
44
|
+
```ts
|
|
45
|
+
{
|
|
46
|
+
vertical: true,
|
|
47
|
+
lines: false,
|
|
48
|
+
indentation: false,
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
`vertical` removes surrounding blank lines, `lines` trims trailing whitespace from each line and `indentation` removes shared leading indentation. `trim` defaults to `true`.
|
|
53
|
+
|
|
54
|
+
## Fence candidates
|
|
55
|
+
|
|
56
|
+
`blockFences` and `inlineFences` are static arrays. `pickFence` checks them in order and throws a `RangeError` if none is safe.
|
|
57
|
+
|
|
58
|
+
Block candidates are:
|
|
59
|
+
|
|
60
|
+
```text
|
|
61
|
+
```
|
|
62
|
+
````
|
|
63
|
+
`````
|
|
64
|
+
``````
|
|
65
|
+
~~~
|
|
66
|
+
~~~~
|
|
67
|
+
~~~~~
|
|
68
|
+
~~~~~~
|
|
69
|
+
```````
|
|
70
|
+
~~~~~~~
|
|
71
|
+
````````
|
|
72
|
+
<code>
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Inline candidates are:
|
|
76
|
+
|
|
77
|
+
```text
|
|
78
|
+
`
|
|
79
|
+
``
|
|
80
|
+
```
|
|
81
|
+
````
|
|
82
|
+
<code>
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Multi-backtick inline fences include a trailing space in the opener and a leading space in the closer. The single-backtick fence and `<code>` fallback are unspaced.
|
package/lib.d.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
declare const fencen: {
|
|
2
|
+
(input: string, options?: Options): string;
|
|
3
|
+
inline(input: string, options?: Exclude<Options, "inline">): string;
|
|
4
|
+
block(input: string, options?: Exclude<Options, "inline">): string;
|
|
5
|
+
};
|
|
6
|
+
export declare const blockFences: Fence[];
|
|
7
|
+
export declare const inlineFences: Fence[];
|
|
8
|
+
export declare const pickFence: (input: string, inline?: boolean, language?: string) => Fence;
|
|
9
|
+
type Fence = {
|
|
10
|
+
closer: () => string;
|
|
11
|
+
opener: (payload?: FencePayload) => string;
|
|
12
|
+
};
|
|
13
|
+
type FencePayload = {
|
|
14
|
+
language?: string;
|
|
15
|
+
};
|
|
16
|
+
type Options = {
|
|
17
|
+
inline?: "auto" | boolean;
|
|
18
|
+
language?: string;
|
|
19
|
+
trim?: TrimOptions;
|
|
20
|
+
};
|
|
21
|
+
type TrimOptions = {
|
|
22
|
+
indentation?: boolean;
|
|
23
|
+
lines?: boolean;
|
|
24
|
+
vertical?: boolean;
|
|
25
|
+
} | boolean;
|
|
26
|
+
|
|
27
|
+
export {
|
|
28
|
+
fencen as default,
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export {};
|
package/lib.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
var e=(e,n)=>{let t=e.repeat(n)
|
|
2
|
+
return{opener:e=>e?.language?`${t}${e.language}\n`:`${t}\n`,closer:()=>`\n${t}`}},n=[e("`",3),e("`",4),e("`",5),e("`",6),e("~",3),e("~",4),e("~",5),e("~",6),e("`",7),e("~",7),e("`",8),{opener:()=>"<code>\n",closer:()=>"\n</code>"}],t=e=>{let n="`".repeat(e)
|
|
3
|
+
return 1===e?{opener:()=>n,closer:()=>n}:{opener:()=>`${n} `,closer:()=>` ${n}`}},l=[t(1),t(2),t(3),t(4),{opener:e=>e?.language?`<code language="${(e=>e.replaceAll("&","&").replaceAll('"',""").replaceAll("<","<").replaceAll(">",">"))(e.language)}">`:"<code>",closer:()=>"</code>"}],r=/\r\n|[\n\r\u2028\u2029]/u,i=e=>e.opener().trimEnd(),o=e=>"<code>"===i(e),a=e=>!e.includes("<code>")&&!e.includes("</code>"),c=(e,n)=>{if(o(n))return a(e)
|
|
4
|
+
let t=i(n)
|
|
5
|
+
for(let n of e.split(r))if(n.replace(/^ {0,3}/u,"").startsWith(t))return!1
|
|
6
|
+
return!0},u=(e,n)=>o(n)?a(e):!e.includes(i(n)),s=(e,t=!1,r)=>{let i=n
|
|
7
|
+
t&&(i=r?l.slice(-1):l)
|
|
8
|
+
for(let n of i)if(t?u(e,n):c(e,n))return n
|
|
9
|
+
throw RangeError("No safe fence is available.")},g=/\r\n|[\n\r\u2028\u2029]/gu,f=/\r\n|[\n\r\u2028\u2029]/u,p=/^\s*$/u,d=(e,n={})=>{let t=((e,n=!0)=>{let t=((e=!0)=>"boolean"==typeof e?{vertical:e,lines:!1,indentation:!1}:{vertical:e.vertical??!1,lines:e.lines??!1,indentation:e.indentation??!1})(n)
|
|
10
|
+
if(!t.vertical&&!t.lines&&!t.indentation)return e
|
|
11
|
+
let l=(e=>{let n=[],t=0
|
|
12
|
+
for(let l of e.matchAll(g)){let r=l.index
|
|
13
|
+
n.push({content:e.slice(t,r),lineBreak:l[0]}),t=r+l[0].length}return n.push({content:e.slice(t),lineBreak:""}),n})(e)
|
|
14
|
+
if(t.lines)for(let e of l)e.content=e.content.trimEnd()
|
|
15
|
+
if(t.vertical){for(;l.length>0&&p.test(l[0].content);)l.shift()
|
|
16
|
+
for(;l.length>0&&p.test(l.at(-1).content);)l.pop()
|
|
17
|
+
l.length>0&&(l.at(-1).lineBreak="")}if(t.indentation){let e=(e=>{let n=e.filter(e=>!p.test(e.content))
|
|
18
|
+
return 0===n.length?0:Math.min(...n.map(e=>/^\s*/u.exec(e.content)[0].length))})(l)
|
|
19
|
+
if(e>0)for(let n of l)n.content=n.content.slice(e)}return l.map(e=>e.content+e.lineBreak).join("")})(e,n.trim),l=((e,n,t)=>!t&&("auto"===n?!f.test(e):n??!1))(t,n.inline,n.language),r=s(t,l,n.language)
|
|
20
|
+
return`${r.opener({language:n.language})}${t}${r.closer()}`}
|
|
21
|
+
d.inline=(e,n={})=>d(e,{...n,inline:!0}),d.block=(e,n={})=>d(e,{...n,inline:!1})
|
|
22
|
+
var h=d
|
|
23
|
+
export{n as blockFences,h as default,l as inlineFences,s as pickFence}
|
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"
|
|
1
|
+
{"bugs":{"url":"https://github.com/Jaid/fencen/issues"},"description":"safe and simple utilities for wrapping code in Markdown-style fences","homepage":"https://github.com/Jaid/fencen#readme","license":"MIT","name":"fencen","repository":"github:Jaid/fencen","version":"0.1.0","type":"module","exports":{".":{"types":"./lib.d.ts","import":"./lib.js","default":"./lib.js"}},"types":"./lib.d.ts"}
|
package/index.d.ts
DELETED
package/index.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export default () => 'fencen'
|
package/readme.md
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
# fencen
|
/package/{license.txt → LICENSE}
RENAMED
|
File without changes
|