@covalent/markdown 0.0.0-COVALENT
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/.browserslistrc +16 -0
- package/.eslintrc.json +36 -0
- package/README.md +103 -0
- package/_markdown-theme.scss +72 -0
- package/jest.config.js +23 -0
- package/ng-package.json +5 -0
- package/package.json +34 -0
- package/project.json +64 -0
- package/src/lib/markdown-loader/markdown-loader.service.spec.ts +101 -0
- package/src/lib/markdown-loader/markdown-loader.service.ts +35 -0
- package/src/lib/markdown-utils/markdown-utils.spec.ts +189 -0
- package/src/lib/markdown-utils/markdown-utils.ts +148 -0
- package/src/lib/markdown.component.html +1 -0
- package/src/lib/markdown.component.scss +664 -0
- package/src/lib/markdown.component.spec.ts +786 -0
- package/src/lib/markdown.component.ts +471 -0
- package/src/lib/markdown.module.ts +23 -0
- package/src/public_api.ts +4 -0
- package/src/test-setup.ts +1 -0
- package/tailwind.config.js +13 -0
- package/tsconfig.json +29 -0
- package/tsconfig.lib.json +12 -0
- package/tsconfig.lib.prod.json +9 -0
- package/tsconfig.spec.json +10 -0
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
export function removeLeadingHash(str: string): string {
|
|
2
|
+
if (str) {
|
|
3
|
+
return str.replace(/^#+/, '');
|
|
4
|
+
}
|
|
5
|
+
return '';
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function removeTrailingHash(str: string | null): string {
|
|
9
|
+
if (str) {
|
|
10
|
+
return str.replace(/#.*/, '');
|
|
11
|
+
}
|
|
12
|
+
return '';
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function genHeadingId(str: string): string {
|
|
16
|
+
if (str) {
|
|
17
|
+
return removeLeadingHash(
|
|
18
|
+
str
|
|
19
|
+
.replace(/(_|-|\s)+/g, '')
|
|
20
|
+
// Remove certain special chars to create heading ids similar to those in github
|
|
21
|
+
// borrowed from showdown
|
|
22
|
+
// https://github.com/showdownjs/showdown/blob/main/src/subParsers/makehtml/headers.js#L94
|
|
23
|
+
.replace(/[&+$,/:;=?@"#{}|^¨~[\]`\\*)(%.!'<>]/g, '')
|
|
24
|
+
).toLowerCase();
|
|
25
|
+
}
|
|
26
|
+
return '';
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function scrollToAnchor(
|
|
30
|
+
scope: HTMLElement,
|
|
31
|
+
anchor: string,
|
|
32
|
+
tryParent: boolean
|
|
33
|
+
): boolean {
|
|
34
|
+
if (scope && anchor) {
|
|
35
|
+
const normalizedAnchor: string = genHeadingId(anchor);
|
|
36
|
+
let headingToJumpTo: Element | null = null;
|
|
37
|
+
const headingWithinComponent = scope.querySelector(
|
|
38
|
+
`[id="${normalizedAnchor}"]`
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
if (headingWithinComponent) {
|
|
42
|
+
headingToJumpTo = headingWithinComponent;
|
|
43
|
+
} else if (tryParent) {
|
|
44
|
+
const parent = scope.parentElement;
|
|
45
|
+
if (parent) {
|
|
46
|
+
headingToJumpTo = parent.querySelector(`[id="${normalizedAnchor}"]`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
if (headingToJumpTo) {
|
|
50
|
+
headingToJumpTo.scrollIntoView({ behavior: 'auto' });
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function isAnchorLink(anchor?: HTMLAnchorElement): boolean {
|
|
58
|
+
if (anchor) {
|
|
59
|
+
const href = anchor.getAttribute('href');
|
|
60
|
+
if (href) {
|
|
61
|
+
return href.startsWith('#');
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export function isFileLink(
|
|
68
|
+
anchor: HTMLAnchorElement,
|
|
69
|
+
fileExtensions: string[] | undefined
|
|
70
|
+
): boolean {
|
|
71
|
+
if (fileExtensions && fileExtensions.length) {
|
|
72
|
+
const href = anchor.getAttribute('href');
|
|
73
|
+
if (href) {
|
|
74
|
+
return fileExtensions.some((fileExtension) =>
|
|
75
|
+
href.endsWith(fileExtension)
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const RAW_GITHUB_HOSTNAME = 'raw.githubusercontent.com';
|
|
83
|
+
|
|
84
|
+
export function rawGithubHref(githubHref?: string): string {
|
|
85
|
+
if (githubHref) {
|
|
86
|
+
try {
|
|
87
|
+
const url: URL = new URL(githubHref);
|
|
88
|
+
if (url.hostname === RAW_GITHUB_HOSTNAME) {
|
|
89
|
+
return url.href;
|
|
90
|
+
} else if (isGithubHref(githubHref)) {
|
|
91
|
+
url.hostname = RAW_GITHUB_HOSTNAME;
|
|
92
|
+
url.pathname = url.pathname.split('/blob', 2).join('');
|
|
93
|
+
return url.href;
|
|
94
|
+
}
|
|
95
|
+
} catch {
|
|
96
|
+
return '';
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return '';
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export function isGithubHref(href?: string): boolean {
|
|
103
|
+
try {
|
|
104
|
+
const temp: URL = new URL(href ?? '');
|
|
105
|
+
return temp.hostname === 'github.com';
|
|
106
|
+
} catch {
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export function isRawGithubHref(href = ''): boolean {
|
|
112
|
+
try {
|
|
113
|
+
const temp: URL = new URL(href);
|
|
114
|
+
return temp.hostname === RAW_GITHUB_HOSTNAME;
|
|
115
|
+
} catch {
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export function renderVideoElements(html: string): string {
|
|
121
|
+
const ytLongEmbed =
|
|
122
|
+
/!\[(?:(?:https?:)?(?:\/\/)?)(?:(?:www)?.)?youtube.(?:.+?)\/(?:(?:embed\/)([\w-]{11})(\?[\w%;-]+(?:=[\w%;-]+)?(?:&[\w%;-]+(?:=[\w%;-]+)?)*)?)]/gi;
|
|
123
|
+
const ytLongWatch =
|
|
124
|
+
/!\[(?:(?:https?:)?(?:\/\/)?)(?:(?:www)?.)?youtube.(?:.+?)\/(?:(?:watch\?v=)([\w-]{11})(&[\w%;-]+(?:=[\w%;-]+)?)*)]/gi;
|
|
125
|
+
const ytShort =
|
|
126
|
+
/!\[(?:(?:https?:)?(?:\/\/)?)?youtu.be\/([\w-]{11})\??([\w%;-]+(?:=[\w%;-]+)?(?:&[\w%;-]+(?:=[\w%;-]+)?)*)?]/gi;
|
|
127
|
+
const ytPlaylist =
|
|
128
|
+
/!\[(?:(?:https?:)?(?:\/\/)?)(?:(?:www)?.)?youtube.(?:.+?)\/(?:(?:playlist\?list=)([\w-]{34})(&[\w%;-]+(?:=[\w%;-]+)?)*)]/gi;
|
|
129
|
+
|
|
130
|
+
function convert(match: string, id: string, flags: string): string {
|
|
131
|
+
if (flags) {
|
|
132
|
+
id += '?' + flags.replace(/&/gi, '&');
|
|
133
|
+
}
|
|
134
|
+
return `<iframe allow="fullscreen" frameborder="0" src="https://www.youtube.com/embed/${id}"></iframe>`;
|
|
135
|
+
}
|
|
136
|
+
function convertPL(match: string, id: string, flags: string): string {
|
|
137
|
+
if (flags) {
|
|
138
|
+
id += flags.replace(/&/gi, '&');
|
|
139
|
+
}
|
|
140
|
+
return `<iframe allow="fullscreen" frameborder="0" src="https://www.youtube.com/embed/videoseries?list=${id}"></iframe>`;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return html
|
|
144
|
+
.replace(ytLongWatch, convert)
|
|
145
|
+
.replace(ytLongEmbed, convert)
|
|
146
|
+
.replace(ytShort, convert)
|
|
147
|
+
.replace(ytPlaylist, convertPL);
|
|
148
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<ng-content></ng-content>
|