@mathstack/app-kit 1.1.2 → 2.0.3

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.
Files changed (74) hide show
  1. package/.eslintrc.json +34 -0
  2. package/LICENSE +21 -21
  3. package/README.md +36 -31
  4. package/ng-package.json +15 -0
  5. package/package.json +9 -13
  6. package/project.json +76 -0
  7. package/src/lib/assets/assets-resource.ts +18 -0
  8. package/src/lib/assets/assets-service.spec.ts +54 -0
  9. package/src/lib/assets/assets-service.ts +73 -0
  10. package/src/lib/assets/index.ts +2 -0
  11. package/{baseline-styles → src/lib/baseline-styles}/_css-reset.scss +118 -118
  12. package/{baseline-styles → src/lib/baseline-styles}/_grid.scss +4 -4
  13. package/{baseline-styles → src/lib/baseline-styles}/_index.scss +6 -6
  14. package/{baseline-styles → src/lib/baseline-styles}/_sass-utils.scss +23 -23
  15. package/{baseline-styles → src/lib/baseline-styles}/_themes.scss +19 -19
  16. package/{baseline-styles → src/lib/baseline-styles}/_typography.scss +232 -232
  17. package/{baseline-styles → src/lib/baseline-styles}/_webkit-scrollbar.scss +22 -22
  18. package/{baseline-styles → src/lib/baseline-styles}/theming/_colors.scss +46 -46
  19. package/{baseline-styles → src/lib/baseline-styles}/theming/_index.scss +2 -2
  20. package/{baseline-styles → src/lib/baseline-styles}/theming/_typography.scss +32 -32
  21. package/{lib/content-parsing/index.d.ts → src/lib/content-parsing/index.ts} +2 -2
  22. package/src/lib/content-parsing/markdown-parser.ts +197 -0
  23. package/src/lib/content-parsing/shiki-highlighter.ts +219 -0
  24. package/src/lib/core/scss/_colors.scss +37 -0
  25. package/src/lib/core/scss/_functions.scss +4 -0
  26. package/src/lib/core/scss/_placeholders.scss +1 -0
  27. package/src/lib/core/scss/_vars.scss +15 -0
  28. package/src/lib/core/testing/stubs/services/assets.resource.stub.ts +3 -0
  29. package/src/lib/core/testing/stubs/services/main.service.stub.ts +5 -0
  30. package/src/lib/core/utilities/deep-merge.spec.ts +29 -0
  31. package/src/lib/core/utilities/deep-merge.ts +21 -0
  32. package/{lib/core/utilities/index.d.ts → src/lib/core/utilities/index.ts} +2 -2
  33. package/src/lib/core/utilities/safe-assign.spec.ts +41 -0
  34. package/{lib/core/utilities/safe-assign.d.ts → src/lib/core/utilities/safe-assign.ts} +42 -18
  35. package/src/lib/documentation-display/active-heading-tracker.ts +61 -0
  36. package/src/lib/documentation-display/document-index/document-index.component.html +34 -0
  37. package/src/lib/documentation-display/document-index/document-index.component.scss +56 -0
  38. package/src/lib/documentation-display/document-index/document-index.component.spec.ts +0 -0
  39. package/src/lib/documentation-display/document-index/document-index.component.ts +39 -0
  40. package/src/lib/documentation-display/documentation-config-parser.ts +92 -0
  41. package/src/lib/documentation-display/documentation-content-service.ts +118 -0
  42. package/src/lib/documentation-display/documentation-display.component.html +33 -0
  43. package/src/lib/documentation-display/documentation-display.component.scss +142 -0
  44. package/src/lib/documentation-display/documentation-display.component.spec.ts +0 -0
  45. package/src/lib/documentation-display/documentation-display.component.ts +129 -0
  46. package/{lib/documentation-display/index.d.ts → src/lib/documentation-display/index.ts} +6 -6
  47. package/src/lib/documentation-display/navigation-siblings/navigation-siblings.component.html +31 -0
  48. package/src/lib/documentation-display/navigation-siblings/navigation-siblings.component.scss +68 -0
  49. package/src/lib/documentation-display/navigation-siblings/navigation-siblings.component.spec.ts +0 -0
  50. package/src/lib/documentation-display/navigation-siblings/navigation-siblings.component.ts +52 -0
  51. package/{lib/ng-utilities/index.d.ts → src/lib/ng-utilities/index.ts} +2 -2
  52. package/src/lib/ng-utilities/ng-on-changes.spec.ts +117 -0
  53. package/src/lib/ng-utilities/ng-on-changes.ts +50 -0
  54. package/{lib/ng-utilities/run-ng-change-detection-then.d.ts → src/lib/ng-utilities/run-ng-change-detection-then.ts} +40 -22
  55. package/{public-api.d.ts → src/public-api.ts} +6 -6
  56. package/tsconfig.lib.json +16 -0
  57. package/tsconfig.lib.prod.json +11 -0
  58. package/tsconfig.spec.json +10 -0
  59. package/fesm2022/mathstack-app-kit.mjs +0 -846
  60. package/fesm2022/mathstack-app-kit.mjs.map +0 -1
  61. package/index.d.ts +0 -5
  62. package/lib/assets/assets-resource.d.ts +0 -11
  63. package/lib/assets/assets-service.d.ts +0 -35
  64. package/lib/assets/index.d.ts +0 -1
  65. package/lib/content-parsing/markdown-parser.d.ts +0 -54
  66. package/lib/content-parsing/shiki-highlighter.d.ts +0 -77
  67. package/lib/core/utilities/deep-merge.d.ts +0 -1
  68. package/lib/documentation-display/active-heading-tracker.d.ts +0 -14
  69. package/lib/documentation-display/document-index/document-index.component.d.ts +0 -17
  70. package/lib/documentation-display/documentation-config-parser.d.ts +0 -41
  71. package/lib/documentation-display/documentation-content-service.d.ts +0 -50
  72. package/lib/documentation-display/documentation-display.component.d.ts +0 -39
  73. package/lib/documentation-display/navigation-siblings/navigation-siblings.component.d.ts +0 -18
  74. package/lib/ng-utilities/ng-on-changes.d.ts +0 -22
@@ -1,46 +1,46 @@
1
- $primary: (
2
- 0: #000000,
3
- 5: #000c38,
4
- 10: #001550,
5
- 15: #001e68,
6
- 20: #002780,
7
- 25: #003099,
8
- 30: #003ab3,
9
- 35: #0043ce,
10
- 40: #1550e1,
11
- 50: #3d6bfb,
12
- 60: #6889ff,
13
- 70: #90a7ff,
14
- 80: #b6c4ff,
15
- 90: #dce1ff,
16
- 95: #eff0ff,
17
- 98: #faf8ff,
18
- 99: #fefbff,
19
- 100: #ffffff,
20
- );
21
-
22
- $muted-primary: (
23
- 0: #000000,
24
- 5: #141821,
25
- 10: #20283c,
26
- 15: #2b3246,
27
- 20: #353c4f,
28
- 25: #404759,
29
- 30: #4c5263,
30
- 35: #575d6e,
31
- 40: #636878,
32
- 50: #7b7f8e,
33
- 60: #9397a4,
34
- 70: #adb0ba,
35
- 80: #c7cad1,
36
- 90: #e1e4e9,
37
- 95: #eff1f5,
38
- 98: #f9f9fb,
39
- 99: #fcfcfd,
40
- 100: #ffffff,
41
- );
42
-
43
- $colors: (
44
- 'primary': $primary,
45
- 'muted-primary': $muted-primary,
46
- );
1
+ $primary: (
2
+ 0: #000000,
3
+ 5: #000c38,
4
+ 10: #001550,
5
+ 15: #001e68,
6
+ 20: #002780,
7
+ 25: #003099,
8
+ 30: #003ab3,
9
+ 35: #0043ce,
10
+ 40: #1550e1,
11
+ 50: #3d6bfb,
12
+ 60: #6889ff,
13
+ 70: #90a7ff,
14
+ 80: #b6c4ff,
15
+ 90: #dce1ff,
16
+ 95: #eff0ff,
17
+ 98: #faf8ff,
18
+ 99: #fefbff,
19
+ 100: #ffffff,
20
+ );
21
+
22
+ $muted-primary: (
23
+ 0: #000000,
24
+ 5: #141821,
25
+ 10: #20283c,
26
+ 15: #2b3246,
27
+ 20: #353c4f,
28
+ 25: #404759,
29
+ 30: #4c5263,
30
+ 35: #575d6e,
31
+ 40: #636878,
32
+ 50: #7b7f8e,
33
+ 60: #9397a4,
34
+ 70: #adb0ba,
35
+ 80: #c7cad1,
36
+ 90: #e1e4e9,
37
+ 95: #eff1f5,
38
+ 98: #f9f9fb,
39
+ 99: #fcfcfd,
40
+ 100: #ffffff,
41
+ );
42
+
43
+ $colors: (
44
+ 'primary': $primary,
45
+ 'muted-primary': $muted-primary,
46
+ );
@@ -1,2 +1,2 @@
1
- @forward 'colors';
2
- @forward 'typography';
1
+ @forward 'colors';
2
+ @forward 'typography';
@@ -1,32 +1,32 @@
1
- @import url('https://fonts.googleapis.com/css2?family=Noto+Sans+Mono:wght@100..900&family=Noto+Sans:ital,wght@0,100..900;1,100..900&family=Noto+Serif:ital,wght@0,100..900;1,100..900&display=swap');
2
-
3
- // Fonts
4
- $font: (
5
- 'sans': (
6
- 'Noto Sans',
7
- sans-serif,
8
- ),
9
- 'serif': (
10
- 'Noto Serif',
11
- serif,
12
- ),
13
- 'mono': (
14
- 'Noto Sans Mono',
15
- monospace,
16
- ),
17
- 'weight': (
18
- 'light': 100,
19
- 'regular': 400,
20
- 'medium': 500,
21
- 'semibold': 600,
22
- 'bold': 700,
23
- ),
24
- 'line-height': (
25
- 0: 1,
26
- 1: 1.125,
27
- 2: 1.25,
28
- 3: 1.5,
29
- 4: 1.75,
30
- 5: 2,
31
- ),
32
- );
1
+ @import url('https://fonts.googleapis.com/css2?family=Noto+Sans+Mono:wght@100..900&family=Noto+Sans:ital,wght@0,100..900;1,100..900&family=Noto+Serif:ital,wght@0,100..900;1,100..900&display=swap');
2
+
3
+ // Fonts
4
+ $font: (
5
+ 'sans': (
6
+ 'Noto Sans',
7
+ sans-serif,
8
+ ),
9
+ 'serif': (
10
+ 'Noto Serif',
11
+ serif,
12
+ ),
13
+ 'mono': (
14
+ 'Noto Sans Mono',
15
+ monospace,
16
+ ),
17
+ 'weight': (
18
+ 'light': 100,
19
+ 'regular': 400,
20
+ 'medium': 500,
21
+ 'semibold': 600,
22
+ 'bold': 700,
23
+ ),
24
+ 'line-height': (
25
+ 0: 1,
26
+ 1: 1.125,
27
+ 2: 1.25,
28
+ 3: 1.5,
29
+ 4: 1.75,
30
+ 5: 2,
31
+ ),
32
+ );
@@ -1,2 +1,2 @@
1
- export * from './markdown-parser';
2
- export * from './shiki-highlighter';
1
+ export * from './markdown-parser';
2
+ export * from './shiki-highlighter';
@@ -0,0 +1,197 @@
1
+ import { inject, Injectable } from '@angular/core';
2
+ import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
3
+ import rehypeAutolinkHeadings from 'rehype-autolink-headings';
4
+ import rehypeRaw from 'rehype-raw';
5
+ import rehypeSlug from 'rehype-slug';
6
+ import rehypeStringify from 'rehype-stringify';
7
+ import remarkGfm from 'remark-gfm';
8
+ import remarkParse from 'remark-parse';
9
+ import remarkRehype from 'remark-rehype';
10
+ import { forkJoin, from, map, mergeMap, Observable, of, switchMap } from 'rxjs';
11
+ import { BundledLanguage } from 'shiki/langs';
12
+ import { BundledTheme } from 'shiki/themes';
13
+ import { HighlighterGeneric } from 'shiki/types.mjs';
14
+ import { unified } from 'unified';
15
+ import { deepMerge } from '../core/utilities/deep-merge';
16
+ import { AdkShikiHighlighter, ShikiTheme } from './shiki-highlighter';
17
+
18
+ export interface AdkParsedContentSection<Content = string> {
19
+ type: string;
20
+ content: Content;
21
+ html?: SafeHtml;
22
+ headers: { id: string; text: string; level: number }[];
23
+ }
24
+
25
+ export interface AdkMarkdownParsingOptions {
26
+ highlighter?: AdkShikiHighlighterOptions;
27
+ gfm?: boolean;
28
+ headingIds?: boolean;
29
+ headingFragmentLinks?: AdkHeadingFragmentLinkOptions;
30
+ }
31
+
32
+ export interface AdkShikiHighlighterOptions {
33
+ highlighter?: HighlighterGeneric<BundledLanguage, BundledTheme>;
34
+ theme?: ShikiTheme;
35
+ type?: 'html' | 'markdown';
36
+ ignoreUnknownLanguage?: boolean;
37
+ }
38
+
39
+ export interface AdkHeadingFragmentLinkOptions {
40
+ createLinks?: boolean;
41
+ behavior?: 'append' | 'prepend' | 'wrap' | 'before' | 'after';
42
+ }
43
+
44
+ const DEFAULT_HIGHLIGHTER_OPTIONS: AdkShikiHighlighterOptions = {
45
+ highlighter: undefined,
46
+ theme: ShikiTheme.GitHubLight,
47
+ type: 'markdown',
48
+ ignoreUnknownLanguage: true,
49
+ };
50
+
51
+ const DEFAULT_PARSING_OPTIONS: AdkMarkdownParsingOptions = {
52
+ gfm: true,
53
+ headingIds: true,
54
+ headingFragmentLinks: { createLinks: false },
55
+ highlighter: DEFAULT_HIGHLIGHTER_OPTIONS,
56
+ };
57
+
58
+ @Injectable()
59
+ export class AdkMarkdownParser {
60
+ parser: typeof unified;
61
+
62
+ private sanitizer = inject(DomSanitizer);
63
+ private shikiHighlighter = inject(AdkShikiHighlighter);
64
+
65
+ constructor() {
66
+ this.parser = unified;
67
+ }
68
+
69
+ parse(
70
+ markdown: string,
71
+ options?: AdkMarkdownParsingOptions
72
+ ): Observable<AdkParsedContentSection[]> {
73
+ const mergedOptions = deepMerge(DEFAULT_PARSING_OPTIONS, options || {});
74
+
75
+ return of(mergedOptions).pipe(
76
+ mergeMap((_options) => {
77
+ if (_options.highlighter && !_options.highlighter.highlighter) {
78
+ return from(this.shikiHighlighter.getHighlighter()).pipe(
79
+ map((highlighter) => ({
80
+ ..._options,
81
+ highlighter: {
82
+ ..._options.highlighter,
83
+ highlighter,
84
+ },
85
+ }))
86
+ );
87
+ } else {
88
+ return of(_options);
89
+ }
90
+ }),
91
+ switchMap((_options) => {
92
+ const sections = this.getSections(markdown);
93
+ const parsedSections$ = sections.map((section) => {
94
+ return this.parseSection(section, _options);
95
+ });
96
+ return forkJoin(parsedSections$);
97
+ })
98
+ );
99
+ }
100
+
101
+ private getSections(markdown: string): AdkParsedContentSection[] {
102
+ const sections: AdkParsedContentSection[] = [];
103
+ let currentMarkdown = '';
104
+
105
+ const lines = markdown.split('\n');
106
+
107
+ for (const line of lines) {
108
+ currentMarkdown += line + '\n';
109
+ }
110
+
111
+ // Add any remaining markdown
112
+ if (currentMarkdown.trim()) {
113
+ sections.push({
114
+ type: 'markdown',
115
+ content: currentMarkdown,
116
+ html: undefined,
117
+ headers: this.getHeaders(currentMarkdown),
118
+ });
119
+ }
120
+
121
+ return sections;
122
+ }
123
+
124
+ private parseSection(
125
+ section: AdkParsedContentSection,
126
+ options: AdkMarkdownParsingOptions
127
+ ): Observable<AdkParsedContentSection> {
128
+ const parsedContent$ = from(
129
+ unified()
130
+ .use(remarkParse)
131
+ .use(options.gfm ? remarkGfm : undefined)
132
+ .use(
133
+ options.highlighter && options.highlighter.type === 'markdown'
134
+ ? this.shikiHighlighter.remarkHighlight
135
+ : undefined,
136
+ options.highlighter
137
+ )
138
+ .use(remarkRehype, { allowDangerousHtml: true })
139
+ .use(rehypeRaw)
140
+ .use(options.headingIds ? rehypeSlug : undefined)
141
+ .use(
142
+ options.headingFragmentLinks ? rehypeAutolinkHeadings : undefined,
143
+ { behavior: options.headingFragmentLinks?.behavior }
144
+ )
145
+ .use(rehypeStringify)
146
+ .process(section.content)
147
+ .then((file) => String(file))
148
+ );
149
+
150
+ return parsedContent$.pipe(
151
+ map((parsedContent) => {
152
+ const toReturn = {
153
+ ...section,
154
+ html: this.sanitizer.bypassSecurityTrustHtml(parsedContent),
155
+ };
156
+ return toReturn;
157
+ })
158
+ );
159
+ }
160
+
161
+ getHeaders(markdown: string): { id: string; text: string; level: number }[] {
162
+ const headerRegex =
163
+ /^(#{1,6})\s*(.+)$|<h([1-6])(?:\s+[^>]*)?>(.*?)<\/h[1-6]>/gm;
164
+ const headers: { id: string; text: string; level: number }[] = [];
165
+ let match;
166
+
167
+ while ((match = headerRegex.exec(markdown)) !== null) {
168
+ let level: number;
169
+ let text: string;
170
+
171
+ if (match[1]) {
172
+ // Markdown header, e.g., ## Heading
173
+ level = match[1].length;
174
+ text = match[2].trim();
175
+ } else {
176
+ // HTML header, e.g., <h2>Heading</h2>
177
+ level = parseInt(match[3], 10);
178
+ text = match[4].trim();
179
+ }
180
+
181
+ const id = text
182
+ .toLowerCase()
183
+ .replace(/\s+/g, '-')
184
+ .replace(/[^\w-]+/g, '');
185
+ headers.push({ id, text, level });
186
+ }
187
+ return headers;
188
+ }
189
+
190
+ parseComponent(content: string): { name: string; pathTo: string } {
191
+ const cleanedLine = content.trim().slice(2, -2).trim();
192
+ const [nameKV, pathToKV] = cleanedLine.split(',');
193
+ const name = nameKV.split(':')[1]?.trim();
194
+ const pathTo = pathToKV.split(':')[1]?.trim();
195
+ return { name, pathTo };
196
+ }
197
+ }
@@ -0,0 +1,219 @@
1
+ import { Injectable } from '@angular/core';
2
+ import { Root } from 'hast';
3
+ import { fromParse5 } from 'hast-util-from-parse5';
4
+ import { parse } from 'parse5';
5
+ import { createHighlighter } from 'shiki/index.mjs';
6
+ import { BundledLanguage } from 'shiki/langs';
7
+ import { BundledTheme } from 'shiki/themes';
8
+ import { HighlighterGeneric } from 'shiki/types.mjs';
9
+ import { visit } from 'unist-util-visit';
10
+ import { AdkShikiHighlighterOptions } from './markdown-parser';
11
+
12
+ export const defaultHighlighterLangs = [
13
+ 'json',
14
+ 'ts',
15
+ 'js',
16
+ 'html',
17
+ 'css',
18
+ 'scss',
19
+ 'yaml',
20
+ 'angular-html',
21
+ 'angular-ts',
22
+ 'mermaid',
23
+ 'bash',
24
+ ];
25
+
26
+ export enum ShikiTheme {
27
+ Andromeeda = 'andromeeda',
28
+ AuroraX = 'aurora-x',
29
+ AyuDark = 'ayu-dark',
30
+ CatppuccinFrappe = 'catppuccin-frappe',
31
+ CatppuccinLatte = 'catppuccin-latte',
32
+ CatppuccinMacchiato = 'catppuccin-macchiato',
33
+ CatppuccinMocha = 'catppuccin-mocha',
34
+ DarkPlus = 'dark-plus',
35
+ DraculaTheme = 'dracula',
36
+ DraculaThemeSoft = 'dracula-soft',
37
+ EverforestDark = 'everforest-dark',
38
+ EverforestLight = 'everforest-light',
39
+ GitHubDark = 'github-dark',
40
+ GitHubDarkDefault = 'github-dark-default',
41
+ GitHubDarkDimmed = 'github-dark-dimmed',
42
+ GitHubDarkHighContrast = 'github-dark-high-contrast',
43
+ GitHubLight = 'github-light',
44
+ GitHubLightDefault = 'github-light-default',
45
+ GitHubLightHighContrast = 'github-light-high-contrast',
46
+ Houston = 'houston',
47
+ LaserWave = 'laserwave',
48
+ LightPlus = 'light-plus',
49
+ MaterialTheme = 'material-theme',
50
+ MaterialThemeDarker = 'material-theme-darker',
51
+ MaterialThemeLighter = 'material-theme-lighter',
52
+ MaterialThemeOcean = 'material-theme-ocean',
53
+ MaterialThemePalenight = 'material-theme-palenight',
54
+ MinDark = 'min-dark',
55
+ MinLight = 'min-light',
56
+ Monokai = 'monokai',
57
+ NightOwl = 'night-owl',
58
+ Nord = 'nord',
59
+ OneDarkPro = 'one-dark-pro',
60
+ OneLight = 'one-light',
61
+ Plastic = 'plastic',
62
+ Poimandres = 'poimandres',
63
+ Red = 'red',
64
+ RosePine = 'rose-pine',
65
+ RosePineDawn = 'rose-pine-dawn',
66
+ RosePineMoon = 'rose-pine-moon',
67
+ SlackDark = 'slack-dark',
68
+ SlackOchin = 'slack-ochin',
69
+ SnazzyLight = 'snazzy-light',
70
+ SolarizedDark = 'solarized-dark',
71
+ SolarizedLight = 'solarized-light',
72
+ Synthwave84 = 'synthwave-84',
73
+ TokyoNight = 'tokyo-night',
74
+ Vesper = 'vesper',
75
+ VitesseBlack = 'vitesse-black',
76
+ VitesseDark = 'vitesse-dark',
77
+ VitesseLight = 'vitesse-light',
78
+ }
79
+
80
+ const MISSING_HIGHLIGHTER = `Please provide a \`shiki\` highlighter instance via \`options\`.`;
81
+
82
+ @Injectable({
83
+ providedIn: 'root',
84
+ })
85
+ export class AdkShikiHighlighter {
86
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
87
+ private highlighterPromise: Promise<
88
+ HighlighterGeneric<BundledLanguage, BundledTheme>
89
+ > | null = null;
90
+
91
+ /**
92
+ * Initialize the highlighter. This should only be called one in an application.
93
+ *
94
+ * @param themes an array of any Shiki themes you may want to use anywhere in the app. You can control which theme for your particular parsing by passing the theme name to the actual parsing function.
95
+ *
96
+ * @returns void
97
+ */
98
+ async initialize(
99
+ themes: ShikiTheme[],
100
+ langs: string[] = defaultHighlighterLangs
101
+ ): Promise<void> {
102
+ if (!this.highlighterPromise) {
103
+ this.highlighterPromise = createHighlighter({
104
+ langs,
105
+ themes: themes.length ? themes : [ShikiTheme.GitHubLight],
106
+ });
107
+ }
108
+ await this.highlighterPromise;
109
+ }
110
+
111
+ async getHighlighter(): Promise<
112
+ HighlighterGeneric<BundledLanguage, BundledTheme>
113
+ > {
114
+ if (!this.highlighterPromise) {
115
+ throw new Error(
116
+ 'Highlighter is not initialized. Please call initialize() once in your application first.'
117
+ );
118
+ }
119
+ return this.highlighterPromise;
120
+ }
121
+
122
+ remarkHighlight(options: AdkShikiHighlighterOptions): (tree: Root) => void {
123
+ const highlighter = options.highlighter;
124
+ if (!options.highlighter) {
125
+ throw new Error(MISSING_HIGHLIGHTER);
126
+ }
127
+ const loadedLanguages = highlighter.getLoadedLanguages();
128
+ const ignoreUnknownLanguage =
129
+ options.ignoreUnknownLanguage === undefined
130
+ ? true
131
+ : options.ignoreUnknownLanguage;
132
+
133
+ const visitor = (node) => {
134
+ if (!loadedLanguages.includes(node.lang)) {
135
+ if (ignoreUnknownLanguage) {
136
+ node.lang = null;
137
+ } else {
138
+ return;
139
+ }
140
+ }
141
+
142
+ const highlighted = highlighter.codeToHtml(node.value, {
143
+ lang: node.lang,
144
+ theme: options.theme,
145
+ });
146
+
147
+ node.type = 'html';
148
+ node.value = highlighted;
149
+ };
150
+
151
+ const transformer = (tree: Root) => {
152
+ visit(tree, 'code', visitor);
153
+ };
154
+
155
+ return transformer;
156
+ }
157
+
158
+ rehypeHighlight(options: AdkShikiHighlighterOptions): (tree: Root) => void {
159
+ const highlighter = options.highlighter;
160
+ if (!options.highlighter) {
161
+ throw new Error(MISSING_HIGHLIGHTER);
162
+ }
163
+
164
+ const visitor = (node, _index, parent) => {
165
+ if (!parent || parent.tagName !== 'pre' || node.tagName !== 'code') {
166
+ return;
167
+ }
168
+
169
+ const [langClass] = node.properties.className;
170
+ const lang = langClass.replace('language-', '');
171
+
172
+ if (highlighter.getLoadedLanguages().includes(lang)) {
173
+ const code = node.children[0]?.value;
174
+ if (!code) {
175
+ return;
176
+ }
177
+ const highlighted = highlighter.codeToHtml(code, {
178
+ lang,
179
+ theme: options.theme,
180
+ });
181
+ const parsed = parse(highlighted);
182
+ const hastTree = fromParse5(parsed);
183
+
184
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
185
+ const content = (hastTree as any).children[0].children[1].children[0]
186
+ .children[0];
187
+
188
+ content.properties.class = ['shiki', 'shiki-' + lang, langClass];
189
+
190
+ node.properties = content.properties;
191
+ node.children = content.children;
192
+ }
193
+ };
194
+
195
+ const transformer = (tree: Root) => {
196
+ visit(tree, 'element', visitor);
197
+ };
198
+
199
+ return transformer;
200
+ }
201
+
202
+ getLanguage(node): string {
203
+ const dataLanguage = node.properties.dataLanguage;
204
+
205
+ if (dataLanguage != null) {
206
+ return dataLanguage;
207
+ }
208
+
209
+ const className = node.properties.className || [];
210
+
211
+ for (const classListItem of className) {
212
+ if (classListItem.slice(0, 9) === 'language-') {
213
+ return classListItem.slice(9).toLowerCase();
214
+ }
215
+ }
216
+
217
+ return null;
218
+ }
219
+ }
@@ -0,0 +1,37 @@
1
+ $primary-0: var(--hsi-adk-color-primary-0);
2
+ $primary-5: var(--hsi-adk-color-primary-5);
3
+ $primary-10: var(--hsi-adk-color-primary-10);
4
+ $primary-15: var(--hsi-adk-color-primary-15);
5
+ $primary-20: var(--hsi-adk-color-primary-20);
6
+ $primary-25: var(--hsi-adk-color-primary-25);
7
+ $primary-30: var(--hsi-adk-color-primary-30);
8
+ $primary-35: var(--hsi-adk-color-primary-35);
9
+ $primary-40: var(--hsi-adk-color-primary-40);
10
+ $primary-50: var(--hsi-adk-color-primary-50);
11
+ $primary-60: var(--hsi-adk-color-primary-60);
12
+ $primary-70: var(--hsi-adk-color-primary-70);
13
+ $primary-80: var(--hsi-adk-color-primary-80);
14
+ $primary-90: var(--hsi-adk-color-primary-90);
15
+ $primary-95: var(--hsi-adk-color-primary-95);
16
+ $primary-98: var(--hsi-adk-color-primary-98);
17
+ $primary-99: var(--hsi-adk-color-primary-99);
18
+ $primary-100: var(--hsi-adk-color-primary-100);
19
+
20
+ $muted-primary-0: var(--hsi-adk-color-muted-primary-0);
21
+ $muted-primary-5: var(--hsi-adk-color-muted-primary-5);
22
+ $muted-primary-10: var(--hsi-adk-color-muted-primary-10);
23
+ $muted-primary-15: var(--hsi-adk-color-muted-primary-15);
24
+ $muted-primary-20: var(--hsi-adk-color-muted-primary-20);
25
+ $muted-primary-25: var(--hsi-adk-color-muted-primary-25);
26
+ $muted-primary-30: var(--hsi-adk-color-muted-primary-30);
27
+ $muted-primary-35: var(--hsi-adk-color-muted-primary-35);
28
+ $muted-primary-40: var(--hsi-adk-color-muted-primary-40);
29
+ $muted-primary-50: var(--hsi-adk-color-muted-primary-50);
30
+ $muted-primary-60: var(--hsi-adk-color-muted-primary-60);
31
+ $muted-primary-70: var(--hsi-adk-color-muted-primary-70);
32
+ $muted-primary-80: var(--hsi-adk-color-muted-primary-80);
33
+ $muted-primary-90: var(--hsi-adk-color-muted-primary-90);
34
+ $muted-primary-95: var(--hsi-adk-color-muted-primary-95);
35
+ $muted-primary-98: var(--hsi-adk-color-muted-primary-98);
36
+ $muted-primary-99: var(--hsi-adk-color-muted-primary-99);
37
+ $muted-primary-100: var(--hsi-adk-color-muted-primary-100);
@@ -0,0 +1,4 @@
1
+ @function grid($number) {
2
+ $grid: 0.25rem;
3
+ @return $number * $grid;
4
+ }
@@ -0,0 +1 @@
1
+ @forward '../../baseline-styles/typography';
@@ -0,0 +1,15 @@
1
+ $font-sans: var(--hsi-adk-font-sans);
2
+ $font-serif: var(--hsi-adk-font-serif);
3
+ $font-mono: var(--hsi-adk-font-mono);
4
+ $font-weight-light: var(--hsi-adk-font-weight-light);
5
+ $font-weight-regular: var(--hsi-adk-font-weight-regular);
6
+ $font-weight-medium: var(--hsi-adk-font-weight-medium);
7
+ $font-weight-semibold: var(--hsi-adk-font-weight-semibold);
8
+ $font-weight-bold: var(--hsi-adk-font-weight-bold);
9
+ $font-weight-black: var(--hsi-adk-font-weight-black);
10
+ $font-line-height-0: var(--hsi-adk-font-line-height-0);
11
+ $font-line-height-1: var(--hsi-adk-font-line-height-1);
12
+ $font-line-height-2: var(--hsi-adk-font-line-height-2);
13
+ $font-line-height-3: var(--hsi-adk-font-line-height-3);
14
+ $font-line-height-4: var(--hsi-adk-font-line-height-4);
15
+ $font-line-height-5: var(--hsi-adk-font-line-height-5);
@@ -0,0 +1,3 @@
1
+ export class AdkAssetsResourceStub {
2
+ getAsset = jasmine.createSpy('getAsset');
3
+ }
@@ -0,0 +1,5 @@
1
+ import { AdkAssetsResourceStub } from './assets.resource.stub';
2
+
3
+ export class MainServiceStub {
4
+ assetsResourceStub = new AdkAssetsResourceStub();
5
+ }
@@ -0,0 +1,29 @@
1
+ import { deepMerge } from './deep-merge';
2
+
3
+ describe('deepMerge', () => {
4
+ it('should merge two objects without the source overwriting undefined properties on the target', () => {
5
+ const target = {
6
+ a: 1,
7
+ b: 2,
8
+ c: {
9
+ d: 3,
10
+ e: 4,
11
+ },
12
+ };
13
+ const source = {
14
+ b: 5,
15
+ c: {
16
+ e: 6,
17
+ },
18
+ };
19
+ const result = deepMerge(target, source as unknown);
20
+ expect(result).toEqual({
21
+ a: 1,
22
+ b: 5,
23
+ c: {
24
+ d: 3,
25
+ e: 6,
26
+ },
27
+ });
28
+ });
29
+ });