-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhtml2md.ts
73 lines (64 loc) · 2.22 KB
/
html2md.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
type Tag = 'h1' | 'h2' | 'h3' | 'p' | 'b' | 'i' | 'img' | 'a'
type ImgTagToMd<Attribs extends string> =
Attribs extends `src="${infer Src}" alt="${infer Alt}"` ?
Src extends string ?
Alt extends string ? `` : never
: never
: never
type AToMd<
Attribs extends string,
Content extends string
> = Attribs extends `href="${infer Href}"` ?
Href extends string ? `[${Content}](${Href})` : never
: never
type HTMLTagToMd<
T extends Tag,
Content extends string,
Attribs extends string
> = T extends 'h1' ? `# ${Content}` :
T extends 'h2' ? `## ${Content}` :
T extends 'h3' ? `### ${Content}` :
T extends 'p' ? `${Content}` :
T extends 'b' ? `**${Content}**` :
T extends 'i' ? `___${Content}___` :
T extends 'img' ? ImgTagToMd<Attribs> :
T extends 'a' ? AToMd<Attribs, Content>
: never
type TransformNode<
Head extends string,
OpenTag extends Tag,
InnerContent extends string,
Attribs extends string,
Tail extends string
> = `${Head extends '' ? '' : HTMLNode<Head>}${HTMLTagToMd<OpenTag, HTMLNode<InnerContent>, Attribs>}${Tail extends '' ? '' : HTMLNode<Tail>}`
type HTMLNode<T extends string> =
T extends `${infer Head}<${`${infer OpenTag} ${infer Attribs}` | `${infer OpenTag}`}>${infer Rest}` ?
Rest extends `${infer InnerContent}</${OpenTag}>${infer Tail}` ?
OpenTag extends Tag ?
TransformNode<Head, OpenTag, InnerContent, Attribs, Tail>
: never
: never
: `${T}`
type Join<Items> =
Items extends [infer FirstItem, ...infer Rest] ?
FirstItem extends string ?
Rest extends string[] ? `${FirstItem}\n${Join<Rest>}` : FirstItem
: never
: Items extends string ? Items : '\n'
type Split<
Str,
Delim extends string
> = Str extends `${infer Head}${Delim}${infer Rest}` ?
[Head, ...Split<Rest, Delim>]
: Str extends string ?
Str extends '' ? never : [Str]
: never
type MapToMarkdown<Items> =
Items extends [infer FirstItem, ...infer Rest] ?
FirstItem extends string ?
Rest extends string[] ?
[HTMLNode<FirstItem>, ...MapToMarkdown<Rest>]
: FirstItem
: never
: Items extends string ? Items : []
export type Parse<Input extends string> = Join<MapToMarkdown<Split<Input, '\n'>>>