@covalent/markdown 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/README.md ADDED
@@ -0,0 +1,94 @@
1
+ ## TdMarkdownComponent: td-markdown
2
+
3
+ `<td-markdown>` is a component that parses and renders Github flavored markdown. It is based on the [showdown](https://github.com/showdownjs/showdown/) library.
4
+
5
+ **Note:** This module uses the **DomSanitizer** service to sanitize the parsed html from the showdown lib to avoid **XSS** issues.
6
+
7
+ By default, `--dev` build will log the following message in the console to let you know:
8
+
9
+ `WARNING: sanitizing HTML stripped some content (see http://g.co/ng/security#xss).`
10
+
11
+ ## API Summary
12
+
13
+ #### Inputs
14
+
15
+ - content?: string
16
+
17
+ - Markdown format content to be parsed as html markup.
18
+ - Used to load data dynamically. e.g. `README.md` content.
19
+
20
+ - simpleLineBreaks?: string
21
+
22
+ - Sets whether newline characters inside paragraphs and spans are parsed as <br/>.
23
+ - Defaults to false.
24
+
25
+ - hostedUrl?: string
26
+
27
+ - If markdown contains relative paths, this is required to generate correct urls.
28
+
29
+ - anchor?: string
30
+ - Anchor to jump to.
31
+
32
+ #### Events
33
+
34
+ - contentReady: undefined
35
+ - Event emitted after the markdown content rendering is finished.
36
+
37
+ ## Installation
38
+
39
+ This component can be installed as an npm package.
40
+
41
+ ```bash
42
+ npm i -save @covalent/markdown
43
+ ```
44
+
45
+ ## Setup
46
+
47
+ Then, import the **CovalentMarkdownModule** in your NgModule:
48
+
49
+ ```typescript
50
+ import { CovalentMarkdownModule } from '@covalent/markdown';
51
+ @NgModule({
52
+ imports: [
53
+ CovalentMarkdownModule,
54
+ ...
55
+ ],
56
+ ...
57
+ })
58
+ export class MyModule {}
59
+ ```
60
+
61
+ ### Theming
62
+
63
+ This module comes with its own Covalent theme which uses the material theme which is used by importing our theme scss file.
64
+
65
+ ```scss
66
+ @import '~@angular/material/theming';
67
+ @import '~@covalent/markdown/markdown-theme';
68
+
69
+ @include mat-core();
70
+
71
+ $primary: mat-palette($mat-orange, 800);
72
+ $accent: mat-palette($mat-light-blue, 600, A100, A400);
73
+ $warn: mat-palette($mat-red, 600);
74
+
75
+ $theme: mat-light-theme($primary, $accent, $warn);
76
+
77
+ @include covalent-markdown-theme($theme);
78
+ ```
79
+
80
+ ## Example
81
+
82
+ **Html:**
83
+
84
+ ```html
85
+ <td-markdown> # Heading ## Sub Heading (H2) ### Steps (H2) </td-markdown>
86
+ ```
87
+
88
+ **Output:**
89
+
90
+ # Heading
91
+
92
+ ## Sub Heading (H2)
93
+
94
+ ### Steps (H2)
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Generated bundle index. Do not edit.
3
+ */
4
+ /// <amd-module name="@covalent/markdown" />
5
+ export * from './public_api';
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Generated bundle index. Do not edit.
3
+ */
4
+ export * from './public_api';
5
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY292YWxlbnQtbWFya2Rvd24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9saWJzL21hcmtkb3duL3NyYy9jb3ZhbGVudC1tYXJrZG93bi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7R0FFRztBQUVILGNBQWMsY0FBYyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBHZW5lcmF0ZWQgYnVuZGxlIGluZGV4LiBEbyBub3QgZWRpdC5cbiAqL1xuXG5leHBvcnQgKiBmcm9tICcuL3B1YmxpY19hcGknO1xuIl19
@@ -0,0 +1,41 @@
1
+ import { Injectable, SecurityContext } from '@angular/core';
2
+ import { DomSanitizer } from '@angular/platform-browser';
3
+ import { HttpClient } from '@angular/common/http';
4
+ import { isGithubHref, rawGithubHref } from '../markdown-utils/markdown-utils';
5
+ import * as i0 from "@angular/core";
6
+ import * as i1 from "@angular/common/http";
7
+ import * as i2 from "@angular/platform-browser";
8
+ export class TdMarkdownLoaderService {
9
+ constructor(_http, _sanitizer) {
10
+ this._http = _http;
11
+ this._sanitizer = _sanitizer;
12
+ }
13
+ async load(url, httpOptions = {}) {
14
+ const sanitizedUrl = this._sanitizer.sanitize(SecurityContext.URL, url) ?? '';
15
+ let urlToGet = sanitizedUrl;
16
+ if (isGithubHref(sanitizedUrl)) {
17
+ urlToGet = rawGithubHref(sanitizedUrl);
18
+ }
19
+ const response = await this._http
20
+ .get(urlToGet, {
21
+ ...httpOptions,
22
+ responseType: 'text',
23
+ observe: 'response',
24
+ })
25
+ .toPromise();
26
+ const contentType = response?.headers.get('Content-Type') ?? '';
27
+ if (contentType.includes('text/plain') ||
28
+ contentType.includes('text/markdown')) {
29
+ return response?.body ?? '';
30
+ }
31
+ else {
32
+ throw Error(`${contentType} is not a handled content type`);
33
+ }
34
+ }
35
+ }
36
+ TdMarkdownLoaderService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.2", ngImport: i0, type: TdMarkdownLoaderService, deps: [{ token: i1.HttpClient }, { token: i2.DomSanitizer }], target: i0.ɵɵFactoryTarget.Injectable });
37
+ TdMarkdownLoaderService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.2.2", ngImport: i0, type: TdMarkdownLoaderService });
38
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.2", ngImport: i0, type: TdMarkdownLoaderService, decorators: [{
39
+ type: Injectable
40
+ }], ctorParameters: function () { return [{ type: i1.HttpClient }, { type: i2.DomSanitizer }]; } });
41
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFya2Rvd24tbG9hZGVyLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9saWJzL21hcmtkb3duL3NyYy9saWIvbWFya2Rvd24tbG9hZGVyL21hcmtkb3duLWxvYWRlci5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsZUFBZSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzVELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUN6RCxPQUFPLEVBQUUsVUFBVSxFQUFnQixNQUFNLHNCQUFzQixDQUFDO0FBQ2hFLE9BQU8sRUFBRSxZQUFZLEVBQUUsYUFBYSxFQUFFLE1BQU0sa0NBQWtDLENBQUM7Ozs7QUFHL0UsTUFBTSxPQUFPLHVCQUF1QjtJQUNsQyxZQUFvQixLQUFpQixFQUFVLFVBQXdCO1FBQW5ELFVBQUssR0FBTCxLQUFLLENBQVk7UUFBVSxlQUFVLEdBQVYsVUFBVSxDQUFjO0lBQUcsQ0FBQztJQUUzRSxLQUFLLENBQUMsSUFBSSxDQUFDLEdBQVcsRUFBRSxjQUFzQixFQUFFO1FBQzlDLE1BQU0sWUFBWSxHQUNoQixJQUFJLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxlQUFlLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUMzRCxJQUFJLFFBQVEsR0FBVyxZQUFZLENBQUM7UUFDcEMsSUFBSSxZQUFZLENBQUMsWUFBWSxDQUFDLEVBQUU7WUFDOUIsUUFBUSxHQUFHLGFBQWEsQ0FBQyxZQUFZLENBQUMsQ0FBQztTQUN4QztRQUVELE1BQU0sUUFBUSxHQUFxQyxNQUFNLElBQUksQ0FBQyxLQUFLO2FBQ2hFLEdBQUcsQ0FBQyxRQUFRLEVBQUU7WUFDYixHQUFHLFdBQVc7WUFDZCxZQUFZLEVBQUUsTUFBTTtZQUNwQixPQUFPLEVBQUUsVUFBVTtTQUNwQixDQUFDO2FBQ0QsU0FBUyxFQUFFLENBQUM7UUFDZixNQUFNLFdBQVcsR0FBVyxRQUFRLEVBQUUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxjQUFjLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDeEUsSUFDRSxXQUFXLENBQUMsUUFBUSxDQUFDLFlBQVksQ0FBQztZQUNsQyxXQUFXLENBQUMsUUFBUSxDQUFDLGVBQWUsQ0FBQyxFQUNyQztZQUNBLE9BQU8sUUFBUSxFQUFFLElBQUksSUFBSSxFQUFFLENBQUM7U0FDN0I7YUFBTTtZQUNMLE1BQU0sS0FBSyxDQUFDLEdBQUcsV0FBVyxnQ0FBZ0MsQ0FBQyxDQUFDO1NBQzdEO0lBQ0gsQ0FBQzs7b0hBM0JVLHVCQUF1Qjt3SEFBdkIsdUJBQXVCOzJGQUF2Qix1QkFBdUI7a0JBRG5DLFVBQVUiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJbmplY3RhYmxlLCBTZWN1cml0eUNvbnRleHQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IERvbVNhbml0aXplciB9IGZyb20gJ0Bhbmd1bGFyL3BsYXRmb3JtLWJyb3dzZXInO1xuaW1wb3J0IHsgSHR0cENsaWVudCwgSHR0cFJlc3BvbnNlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uL2h0dHAnO1xuaW1wb3J0IHsgaXNHaXRodWJIcmVmLCByYXdHaXRodWJIcmVmIH0gZnJvbSAnLi4vbWFya2Rvd24tdXRpbHMvbWFya2Rvd24tdXRpbHMnO1xuXG5ASW5qZWN0YWJsZSgpXG5leHBvcnQgY2xhc3MgVGRNYXJrZG93bkxvYWRlclNlcnZpY2Uge1xuICBjb25zdHJ1Y3Rvcihwcml2YXRlIF9odHRwOiBIdHRwQ2xpZW50LCBwcml2YXRlIF9zYW5pdGl6ZXI6IERvbVNhbml0aXplcikge31cblxuICBhc3luYyBsb2FkKHVybDogc3RyaW5nLCBodHRwT3B0aW9uczogb2JqZWN0ID0ge30pOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIGNvbnN0IHNhbml0aXplZFVybDogc3RyaW5nID1cbiAgICAgIHRoaXMuX3Nhbml0aXplci5zYW5pdGl6ZShTZWN1cml0eUNvbnRleHQuVVJMLCB1cmwpID8/ICcnO1xuICAgIGxldCB1cmxUb0dldDogc3RyaW5nID0gc2FuaXRpemVkVXJsO1xuICAgIGlmIChpc0dpdGh1YkhyZWYoc2FuaXRpemVkVXJsKSkge1xuICAgICAgdXJsVG9HZXQgPSByYXdHaXRodWJIcmVmKHNhbml0aXplZFVybCk7XG4gICAgfVxuXG4gICAgY29uc3QgcmVzcG9uc2U6IEh0dHBSZXNwb25zZTxzdHJpbmc+IHwgdW5kZWZpbmVkID0gYXdhaXQgdGhpcy5faHR0cFxuICAgICAgLmdldCh1cmxUb0dldCwge1xuICAgICAgICAuLi5odHRwT3B0aW9ucyxcbiAgICAgICAgcmVzcG9uc2VUeXBlOiAndGV4dCcsXG4gICAgICAgIG9ic2VydmU6ICdyZXNwb25zZScsXG4gICAgICB9KVxuICAgICAgLnRvUHJvbWlzZSgpO1xuICAgIGNvbnN0IGNvbnRlbnRUeXBlOiBzdHJpbmcgPSByZXNwb25zZT8uaGVhZGVycy5nZXQoJ0NvbnRlbnQtVHlwZScpID8/ICcnO1xuICAgIGlmIChcbiAgICAgIGNvbnRlbnRUeXBlLmluY2x1ZGVzKCd0ZXh0L3BsYWluJykgfHxcbiAgICAgIGNvbnRlbnRUeXBlLmluY2x1ZGVzKCd0ZXh0L21hcmtkb3duJylcbiAgICApIHtcbiAgICAgIHJldHVybiByZXNwb25zZT8uYm9keSA/PyAnJztcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgRXJyb3IoYCR7Y29udGVudFR5cGV9IGlzIG5vdCBhIGhhbmRsZWQgY29udGVudCB0eXBlYCk7XG4gICAgfVxuICB9XG59XG4iXX0=
@@ -0,0 +1,115 @@
1
+ export function removeLeadingHash(str) {
2
+ if (str) {
3
+ return str.replace(/^#+/, '');
4
+ }
5
+ return '';
6
+ }
7
+ export function removeTrailingHash(str) {
8
+ if (str) {
9
+ return str.replace(/#.*/, '');
10
+ }
11
+ return '';
12
+ }
13
+ export function genHeadingId(str) {
14
+ if (str) {
15
+ return removeLeadingHash(str
16
+ .replace(/(_|-|\s)+/g, '')
17
+ // Remove certain special chars to create heading ids similar to those in github
18
+ // borrowed from showdown
19
+ // https://github.com/showdownjs/showdown/blob/develop/src/subParsers/makehtml/headers.js#L94
20
+ .replace(/[&+$,/:;=?@"#{}|^¨~[\]`\\*)(%.!'<>]/g, '')).toLowerCase();
21
+ }
22
+ return '';
23
+ }
24
+ export function scrollToAnchor(scope, anchor, tryParent) {
25
+ if (scope && anchor) {
26
+ const normalizedAnchor = genHeadingId(anchor);
27
+ let headingToJumpTo = null;
28
+ const headingWithinComponent = scope.querySelector(`[id="${normalizedAnchor}"]`);
29
+ if (headingWithinComponent) {
30
+ headingToJumpTo = headingWithinComponent;
31
+ }
32
+ else if (tryParent) {
33
+ const parent = scope.parentElement;
34
+ if (parent) {
35
+ headingToJumpTo = parent.querySelector(`[id="${normalizedAnchor}"]`);
36
+ }
37
+ }
38
+ if (headingToJumpTo) {
39
+ headingToJumpTo.scrollIntoView({ behavior: 'auto' });
40
+ return true;
41
+ }
42
+ }
43
+ return false;
44
+ }
45
+ export function isAnchorLink(anchor) {
46
+ if (anchor) {
47
+ const href = anchor.getAttribute('href');
48
+ if (href) {
49
+ return href.startsWith('#');
50
+ }
51
+ }
52
+ return false;
53
+ }
54
+ const RAW_GITHUB_HOSTNAME = 'raw.githubusercontent.com';
55
+ export function rawGithubHref(githubHref) {
56
+ if (githubHref) {
57
+ try {
58
+ const url = new URL(githubHref);
59
+ if (url.hostname === RAW_GITHUB_HOSTNAME) {
60
+ return url.href;
61
+ }
62
+ else if (isGithubHref(githubHref)) {
63
+ url.hostname = RAW_GITHUB_HOSTNAME;
64
+ url.pathname = url.pathname.split('/blob', 2).join('');
65
+ return url.href;
66
+ }
67
+ }
68
+ catch {
69
+ return '';
70
+ }
71
+ }
72
+ return '';
73
+ }
74
+ export function isGithubHref(href) {
75
+ try {
76
+ const temp = new URL(href ?? '');
77
+ return temp.hostname === 'github.com';
78
+ }
79
+ catch {
80
+ return false;
81
+ }
82
+ }
83
+ export function isRawGithubHref(href = '') {
84
+ try {
85
+ const temp = new URL(href);
86
+ return temp.hostname === RAW_GITHUB_HOSTNAME;
87
+ }
88
+ catch {
89
+ return false;
90
+ }
91
+ }
92
+ export function renderVideoElements(html) {
93
+ const ytLongEmbed = /!\[(?:(?:https?:)?(?:\/\/)?)(?:(?:www)?.)?youtube.(?:.+?)\/(?:(?:embed\/)([\w-]{11})(\?[\w%;-]+(?:=[\w%;-]+)?(?:&[\w%;-]+(?:=[\w%;-]+)?)*)?)]/gi;
94
+ const ytLongWatch = /!\[(?:(?:https?:)?(?:\/\/)?)(?:(?:www)?.)?youtube.(?:.+?)\/(?:(?:watch\?v=)([\w-]{11})(&[\w%;-]+(?:=[\w%;-]+)?)*)]/gi;
95
+ const ytShort = /!\[(?:(?:https?:)?(?:\/\/)?)?youtu.be\/([\w-]{11})\??([\w%;-]+(?:=[\w%;-]+)?(?:&[\w%;-]+(?:=[\w%;-]+)?)*)?]/gi;
96
+ const ytPlaylist = /!\[(?:(?:https?:)?(?:\/\/)?)(?:(?:www)?.)?youtube.(?:.+?)\/(?:(?:playlist\?list=)([\w-]{34})(&[\w%;-]+(?:=[\w%;-]+)?)*)]/gi;
97
+ function convert(match, id, flags) {
98
+ if (flags) {
99
+ id += '?' + flags.replace(/&amp;/gi, '&');
100
+ }
101
+ return `<iframe allow="fullscreen" frameborder="0" src="https://www.youtube.com/embed/${id}"></iframe>`;
102
+ }
103
+ function convertPL(match, id, flags) {
104
+ if (flags) {
105
+ id += flags.replace(/&amp;/gi, '&');
106
+ }
107
+ return `<iframe allow="fullscreen" frameborder="0" src="https://www.youtube.com/embed/videoseries?list=${id}"></iframe>`;
108
+ }
109
+ return html
110
+ .replace(ytLongWatch, convert)
111
+ .replace(ytLongEmbed, convert)
112
+ .replace(ytShort, convert)
113
+ .replace(ytPlaylist, convertPL);
114
+ }
115
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFya2Rvd24tdXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9saWJzL21hcmtkb3duL3NyYy9saWIvbWFya2Rvd24tdXRpbHMvbWFya2Rvd24tdXRpbHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsTUFBTSxVQUFVLGlCQUFpQixDQUFDLEdBQVc7SUFDM0MsSUFBSSxHQUFHLEVBQUU7UUFDUCxPQUFPLEdBQUcsQ0FBQyxPQUFPLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDO0tBQy9CO0lBQ0QsT0FBTyxFQUFFLENBQUM7QUFDWixDQUFDO0FBRUQsTUFBTSxVQUFVLGtCQUFrQixDQUFDLEdBQWtCO0lBQ25ELElBQUksR0FBRyxFQUFFO1FBQ1AsT0FBTyxHQUFHLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQztLQUMvQjtJQUNELE9BQU8sRUFBRSxDQUFDO0FBQ1osQ0FBQztBQUVELE1BQU0sVUFBVSxZQUFZLENBQUMsR0FBVztJQUN0QyxJQUFJLEdBQUcsRUFBRTtRQUNQLE9BQU8saUJBQWlCLENBQ3RCLEdBQUc7YUFDQSxPQUFPLENBQUMsWUFBWSxFQUFFLEVBQUUsQ0FBQztZQUMxQixnRkFBZ0Y7WUFDaEYseUJBQXlCO1lBQ3pCLDZGQUE2RjthQUM1RixPQUFPLENBQUMsc0NBQXNDLEVBQUUsRUFBRSxDQUFDLENBQ3ZELENBQUMsV0FBVyxFQUFFLENBQUM7S0FDakI7SUFDRCxPQUFPLEVBQUUsQ0FBQztBQUNaLENBQUM7QUFFRCxNQUFNLFVBQVUsY0FBYyxDQUM1QixLQUFrQixFQUNsQixNQUFjLEVBQ2QsU0FBa0I7SUFFbEIsSUFBSSxLQUFLLElBQUksTUFBTSxFQUFFO1FBQ25CLE1BQU0sZ0JBQWdCLEdBQVcsWUFBWSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ3RELElBQUksZUFBZSxHQUFtQixJQUFJLENBQUM7UUFDM0MsTUFBTSxzQkFBc0IsR0FBRyxLQUFL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RUFBRSxHQUFHLENBQUMsQ0FBQztTQUMzQztRQUNELE9BQU8saUZBQWlGLEVBQUUsYUFBYSxDQUFDO0lBQzFHLENBQUM7SUFDRCxTQUFTLFNBQVMsQ0FBQyxLQUFhLEVBQUUsRUFBVSxFQUFFLEtBQWE7UUFDekQsSUFBSSxLQUFLLEVBQUU7WUFDVCxFQUFFLElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxTQUFTLEVBQUUsR0FBRyxDQUFDLENBQUM7U0FDckM7UUFDRCxPQUFPLGtHQUFrRyxFQUFFLGFBQWEsQ0FBQztJQUMzSCxDQUFDO0lBRUQsT0FBTyxJQUFJO1NBQ1IsT0FBTyxDQUFDLFdBQVcsRUFBRSxPQUFPLENBQUM7U0FDN0IsT0FBTyxDQUFDLFdBQVcsRUFBRSxPQUFPLENBQUM7U0FDN0IsT0FBTyxDQUFDLE9BQU8sRUFBRSxPQUFPLENBQUM7U0FDekIsT0FBTyxDQUFDLFVBQVUsRUFBRSxTQUFTLENBQUMsQ0FBQztBQUNwQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0IGZ1bmN0aW9uIHJlbW92ZUxlYWRpbmdIYXNoKHN0cjogc3RyaW5nKTogc3RyaW5nIHtcbiAgaWYgKHN0cikge1xuICAgIHJldHVybiBzdHIucmVwbGFjZSgvXiMrLywgJycpO1xuICB9XG4gIHJldHVybiAnJztcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHJlbW92ZVRyYWlsaW5nSGFzaChzdHI6IHN0cmluZyB8IG51bGwpOiBzdHJpbmcge1xuICBpZiAoc3RyKSB7XG4gICAgcmV0dXJuIHN0ci5yZXBsYWNlKC8jLiovLCAnJyk7XG4gIH1cbiAgcmV0dXJuICcnO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2VuSGVhZGluZ0lkKHN0cjogc3RyaW5nKTogc3RyaW5nIHtcbiAgaWYgKHN0cikge1xuICAgIHJldHVybiByZW1vdmVMZWFkaW5nSGFzaChcbiAgICAgIHN0clxuICAgICAgICAucmVwbGFjZSgvKF98LXxcXHMpKy9nLCAnJylcbiAgICAgICAgLy8gUmVtb3ZlIGNlcnRhaW4gc3BlY2lhbCBjaGFycyB0byBjcmVhdGUgaGVhZGluZyBpZHMgc2ltaWxhciB0byB0aG9zZSBpbiBnaXRodWJcbiAgICAgICAgLy8gYm9ycm93ZWQgZnJvbSBzaG93ZG93blxuICAgICAgICAvLyBodHRwczovL2dpdGh1Yi5jb20vc2hvd2Rvd25qcy9zaG93ZG93bi9ibG9iL2RldmVsb3Avc3JjL3N1YlBhcnNlcnMvbWFrZWh0bWwvaGVhZGVycy5qcyNMOTRcbiAgICAgICAgLnJlcGxhY2UoL1smKyQsLzo7PT9AXCIje318XsKofltcXF1gXFxcXCopKCUuISc8Pl0vZywgJycpXG4gICAgKS50b0xvd2VyQ2FzZSgpO1xuICB9XG4gIHJldHVybiAnJztcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHNjcm9sbFRvQW5jaG9yKFxuICBzY29wZTogSFRNTEVsZW1lbnQsXG4gIGFuY2hvcjogc3RyaW5nLFxuICB0cnlQYXJlbnQ6IGJvb2xlYW5cbik6IGJvb2xlYW4ge1xuICBpZiAoc2NvcGUgJiYgYW5jaG9yKSB7XG4gICAgY29uc3Qgbm9ybWFsaXplZEFuY2hvcjogc3RyaW5nID0gZ2VuSGVhZGluZ0lkKGFuY2hvcik7XG4gICAgbGV0IGhlYWRpbmdUb0p1bXBUbzogRWxlbWVudCB8IG51bGwgPSBudWxsO1xuICAgIGNvbnN0IGhlYWRpbmdXaXRoaW5Db21wb25lbnQgPSBzY29wZS5xdWVyeVNlbGVjdG9yKFxuICAgICAgYFtpZD1cIiR7bm9ybWFsaXplZEFuY2hvcn1cIl1gXG4gICAgKTtcblxuICAgIGlmIChoZWFkaW5nV2l0aGluQ29tcG9uZW50KSB7XG4gICAgICBoZWFkaW5nVG9KdW1wVG8gPSBoZWFkaW5nV2l0aGluQ29tcG9uZW50O1xuICAgIH0gZWxzZSBpZiAodHJ5UGFyZW50KSB7XG4gICAgICBjb25zdCBwYXJlbnQgPSBzY29wZS5wYXJlbnRFbGVtZW50O1xuICAgICAgaWYgKHBhcmVudCkge1xuICAgICAgICBoZWFkaW5nVG9KdW1wVG8gPSBwYXJlbnQucXVlcnlTZWxlY3RvcihgW2lkPVwiJHtub3JtYWxpemVkQW5jaG9yfVwiXWApO1xuICAgICAgfVxuICAgIH1cbiAgICBpZiAoaGVhZGluZ1RvSnVtcFRvKSB7XG4gICAgICBoZWFkaW5nVG9KdW1wVG8uc2Nyb2xsSW50b1ZpZXcoeyBiZWhhdmlvcjogJ2F1dG8nIH0pO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9XG4gIHJldHVybiBmYWxzZTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGlzQW5jaG9yTGluayhhbmNob3I/OiBIVE1MQW5jaG9yRWxlbWVudCk6IGJvb2xlYW4ge1xuICBpZiAoYW5jaG9yKSB7XG4gICAgY29uc3QgaHJlZiA9IGFuY2hvci5nZXRBdHRyaWJ1dGUoJ2hyZWYnKTtcbiAgICBpZiAoaHJlZikge1xuICAgICAgcmV0dXJuIGhyZWYuc3RhcnRzV2l0aCgnIycpO1xuICAgIH1cbiAgfVxuICByZXR1cm4gZmFsc2U7XG59XG5jb25zdCBSQVdfR0lUSFVCX0hPU1ROQU1FID0gJ3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20nO1xuXG5leHBvcnQgZnVuY3Rpb24gcmF3R2l0aHViSHJlZihnaXRodWJIcmVmPzogc3RyaW5nKTogc3RyaW5nIHtcbiAgaWYgKGdpdGh1YkhyZWYpIHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgdXJsOiBVUkwgPSBuZXcgVVJMKGdpdGh1YkhyZWYpO1xuICAgICAgaWYgKHVybC5ob3N0bmFtZSA9PT0gUkFXX0dJVEhVQl9IT1NUTkFNRSkge1xuICAgICAgICByZXR1cm4gdXJsLmhyZWY7XG4gICAgICB9IGVsc2UgaWYgKGlzR2l0aHViSHJlZihnaXRodWJIcmVmKSkge1xuICAgICAgICB1cmwuaG9zdG5hbWUgPSBSQVdfR0lUSFVCX0hPU1ROQU1FO1xuICAgICAgICB1cmwucGF0aG5hbWUgPSB1cmwucGF0aG5hbWUuc3BsaXQoJy9ibG9iJywgMikuam9pbignJyk7XG4gICAgICAgIHJldHVybiB1cmwuaHJlZjtcbiAgICAgIH1cbiAgICB9IGNhdGNoIHtcbiAgICAgIHJldHVybiAnJztcbiAgICB9XG4gIH1cbiAgcmV0dXJuICcnO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaXNHaXRodWJIcmVmKGhyZWY/OiBzdHJpbmcpOiBib29sZWFuIHtcbiAgdHJ5IHtcbiAgICBjb25zdCB0ZW1wOiBVUkwgPSBuZXcgVVJMKGhyZWYgPz8gJycpO1xuICAgIHJldHVybiB0ZW1wLmhvc3RuYW1lID09PSAnZ2l0aHViLmNvbSc7XG4gIH0gY2F0Y2gge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gaXNSYXdHaXRodWJIcmVmKGhyZWY6IHN0cmluZyA9ICcnKTogYm9vbGVhbiB7XG4gIHRyeSB7XG4gICAgY29uc3QgdGVtcDogVVJMID0gbmV3IFVSTChocmVmKTtcbiAgICByZXR1cm4gdGVtcC5ob3N0bmFtZSA9PT0gUkFXX0dJVEhVQl9IT1NUTkFNRTtcbiAgfSBjYXRjaCB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiByZW5kZXJWaWRlb0VsZW1lbnRzKGh0bWw6IHN0cmluZyk6IHN0cmluZyB7XG4gIGNvbnN0IHl0TG9uZ0VtYmVkID1cbiAgICAvIVxcWyg/Oig/Omh0dHBzPzopPyg/OlxcL1xcLyk/KSg/Oig/Ond3dyk/Lik/eW91dHViZS4oPzouKz8pXFwvKD86KD86ZW1iZWRcXC8pKFtcXHctXXsxMX0pKFxcP1tcXHclOy1dKyg/Oj1bXFx3JTstXSspPyg/OiZbXFx3JTstXSsoPzo9W1xcdyU7LV0rKT8pKik/KV0vZ2k7XG4gIGNvbnN0IHl0TG9uZ1dhdGNoID1cbiAgICAvIVxcWyg/Oig/Omh0dHBzPzopPyg/OlxcL1xcLyk/KSg/Oig/Ond3dyk/Lik/eW91dHViZS4oPzouKz8pXFwvKD86KD86d2F0Y2hcXD92PSkoW1xcdy1dezExfSkoJltcXHclOy1dKyg/Oj1bXFx3JTstXSspPykqKV0vZ2k7XG4gIGNvbnN0IHl0U2hvcnQgPVxuICAgIC8hXFxbKD86KD86aHR0cHM/Oik/KD86XFwvXFwvKT8pP3lvdXR1LmJlXFwvKFtcXHctXXsxMX0pXFw/PyhbXFx3JTstXSsoPzo9W1xcdyU7LV0rKT8oPzomW1xcdyU7LV0rKD86PVtcXHclOy1dKyk/KSopP10vZ2k7XG4gIGNvbnN0IHl0UGxheWxpc3QgPVxuICAgIC8hXFxbKD86KD86aHR0cHM/Oik/KD86XFwvXFwvKT8pKD86KD86d3d3KT8uKT95b3V0dWJlLig/Oi4rPylcXC8oPzooPzpwbGF5bGlzdFxcP2xpc3Q9KShbXFx3LV17MzR9KSgmW1xcdyU7LV0rKD86PVtcXHclOy1dKyk/KSopXS9naTtcblxuICBmdW5jdGlvbiBjb252ZXJ0KG1hdGNoOiBzdHJpbmcsIGlkOiBzdHJpbmcsIGZsYWdzOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIGlmIChmbGFncykge1xuICAgICAgaWQgKz0gJz8nICsgZmxhZ3MucmVwbGFjZSgvJmFtcDsvZ2ksICcmJyk7XG4gICAgfVxuICAgIHJldHVybiBgPGlmcmFtZSBhbGxvdz1cImZ1bGxzY3JlZW5cIiBmcmFtZWJvcmRlcj1cIjBcIiBzcmM9XCJodHRwczovL3d3dy55b3V0dWJlLmNvbS9lbWJlZC8ke2lkfVwiPjwvaWZyYW1lPmA7XG4gIH1cbiAgZnVuY3Rpb24gY29udmVydFBMKG1hdGNoOiBzdHJpbmcsIGlkOiBzdHJpbmcsIGZsYWdzOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIGlmIChmbGFncykge1xuICAgICAgaWQgKz0gZmxhZ3MucmVwbGFjZSgvJmFtcDsvZ2ksICcmJyk7XG4gICAgfVxuICAgIHJldHVybiBgPGlmcmFtZSBhbGxvdz1cImZ1bGxzY3JlZW5cIiBmcmFtZWJvcmRlcj1cIjBcIiBzcmM9XCJodHRwczovL3d3dy55b3V0dWJlLmNvbS9lbWJlZC92aWRlb3Nlcmllcz9saXN0PSR7aWR9XCI+PC9pZnJhbWU+YDtcbiAgfVxuXG4gIHJldHVybiBodG1sXG4gICAgLnJlcGxhY2UoeXRMb25nV2F0Y2gsIGNvbnZlcnQpXG4gICAgLnJlcGxhY2UoeXRMb25nRW1iZWQsIGNvbnZlcnQpXG4gICAgLnJlcGxhY2UoeXRTaG9ydCwgY29udmVydClcbiAgICAucmVwbGFjZSh5dFBsYXlsaXN0LCBjb252ZXJ0UEwpO1xufVxuIl19