@repobit/dex-system-design 0.23.95 → 0.23.97
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/CHANGELOG.md +15 -0
- package/package.json +4 -4
- package/src/blog/assets/articles/fbi-crypto-scam-1.jpeg +0 -0
- package/src/blog/assets/articles/fbi-crypto-scam-cover.png +0 -0
- package/src/blog/assets/fonts/IBMPlexSans-Bold.woff2 +0 -0
- package/src/blog/assets/fonts/IBMPlexSans-BoldItalic.woff2 +0 -0
- package/src/blog/assets/fonts/IBMPlexSans-Italic.woff2 +0 -0
- package/src/blog/assets/fonts/IBMPlexSans-Light.woff2 +0 -0
- package/src/blog/assets/fonts/IBMPlexSans-LightItalic.woff2 +0 -0
- package/src/blog/assets/fonts/IBMPlexSans-Medium.woff2 +0 -0
- package/src/blog/assets/fonts/IBMPlexSans-MediumItalic.woff2 +0 -0
- package/src/blog/assets/fonts/IBMPlexSans-Regular.woff2 +0 -0
- package/src/blog/assets/fonts/IBMPlexSans-SemiBold.woff2 +0 -0
- package/src/blog/assets/fonts/IBMPlexSans-SemiBoldItalic.woff2 +0 -0
- package/src/blog/assets/fonts/IBMPlexSansCondensed-Bold.woff2 +0 -0
- package/src/blog/assets/fonts/IBMPlexSansCondensed-BoldItalic.woff2 +0 -0
- package/src/blog/assets/fonts/IBMPlexSansCondensed-Italic.woff2 +0 -0
- package/src/blog/assets/fonts/IBMPlexSansCondensed-Light.woff2 +0 -0
- package/src/blog/assets/fonts/IBMPlexSansCondensed-LightItalic.woff2 +0 -0
- package/src/blog/assets/fonts/IBMPlexSansCondensed-Medium.woff2 +0 -0
- package/src/blog/assets/fonts/IBMPlexSansCondensed-MediumItalic.woff2 +0 -0
- package/src/blog/assets/fonts/IBMPlexSansCondensed-Regular.woff2 +0 -0
- package/src/blog/assets/fonts/IBMPlexSansCondensed-SemiBold.woff2 +0 -0
- package/src/blog/assets/fonts/IBMPlexSansCondensed-SemiBoldItalic.woff2 +0 -0
- package/src/blog/assets/global-scam-intelligence-report-2026.png +0 -0
- package/src/blog/assets/psd-4.jpg +0 -0
- package/src/blog/src/articles/FBI warns of crypto investment scam that sends couriers to collect victims' cash-editedAB.docx +0 -0
- package/src/blog/src/articles/FBI-crypto-scam-courier-cash.png +0 -0
- package/src/blog/src/articles/fbi-crypto-scam.js +324 -0
- package/src/blog/src/articles/~$I warns of crypto investment scam that sends couriers to collect victims' cash-editedAB.docx +0 -0
- package/src/blog/src/atoms/blog-abstract.js +51 -0
- package/src/blog/src/atoms/blog-atoms.stories.js +519 -0
- package/src/blog/src/atoms/blog-authors.js +70 -0
- package/src/blog/src/atoms/blog-avatar.js +44 -0
- package/src/blog/src/atoms/blog-blockquote.js +92 -0
- package/src/blog/src/atoms/blog-caption.js +31 -0
- package/src/blog/src/atoms/blog-code-block.js +89 -0
- package/src/blog/src/atoms/blog-dek.js +30 -0
- package/src/blog/src/atoms/blog-featured-image.js +65 -0
- package/src/blog/src/atoms/blog-heading.js +63 -0
- package/src/blog/src/atoms/blog-image.js +50 -0
- package/src/blog/src/atoms/blog-key-takeaways.js +101 -0
- package/src/blog/src/atoms/blog-link.js +68 -0
- package/src/blog/src/atoms/blog-meta.js +87 -0
- package/src/blog/src/atoms/blog-most-popular.js +146 -0
- package/src/blog/src/atoms/blog-newsletter-signup.js +342 -0
- package/src/blog/src/atoms/blog-paragraph.js +61 -0
- package/src/blog/src/atoms/blog-product-upsell.js +168 -0
- package/src/blog/src/atoms/blog-related-articles.js +326 -0
- package/src/blog/src/atoms/blog-related-label.js +30 -0
- package/src/blog/src/atoms/blog-report-promo.js +250 -0
- package/src/blog/src/atoms/blog-standout.js +78 -0
- package/src/blog/src/atoms/blog-subhead.js +32 -0
- package/src/blog/src/atoms/blog-table-of-contents.js +447 -0
- package/src/blog/src/atoms/blog-tag.js +86 -0
- package/src/blog/src/atoms/blog-title.js +31 -0
- package/src/blog/src/base/blog-element.js +10 -0
- package/src/blog/src/breakpoints.js +23 -0
- package/src/blog/src/content/blog-article.js +736 -0
- package/src/blog/src/content/blog-atoms-showcase.js +401 -0
- package/src/blog/src/content/blog-page-layout.js +73 -0
- package/src/blog/src/content/blog-pages.stories.js +101 -0
- package/src/blog/src/content/render-inline-content.js +18 -0
- package/src/blog/src/data/popular-articles.js +43 -0
- package/src/blog/src/data/related-articles.js +58 -0
- package/src/blog/src/index.js +104 -0
- package/src/blog/src/lib/article-toc.js +206 -0
- package/src/blog/src/lib/load-prism.js +23 -0
- package/src/blog/src/shell/blog-shell.js +31 -0
- package/src/blog/src/styles/prism-theme.js +65 -0
- package/src/blog/src/tokens/blog.js +406 -0
- package/src/blog/src/tokens/core.js +811 -0
- package/src/blog/src/tokens/fonts.css +241 -0
- package/src/blog/src/tokens/index.js +27 -0
- package/src/blog/src/tokens/legacy.js +58 -0
- package/src/blog/tokens/blog.js +406 -0
- package/src/blog/tokens/core.js +811 -0
- package/src/blog/tokens/fonts.css +241 -0
- package/src/blog/tokens/index.js +27 -0
- package/src/blog/tokens/legacy.js +58 -0
- package/src/blog/tokens.css +1512 -0
- package/src/blog/tokens.js +1 -0
- package/src/blog/vendor/prism/prism.css +120 -0
- package/src/blog/vendor/prism/prism.js +300 -0
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import './shell/blog-shell.js';
|
|
2
|
+
|
|
3
|
+
import './atoms/blog-tag.js';
|
|
4
|
+
|
|
5
|
+
import './atoms/blog-avatar.js';
|
|
6
|
+
|
|
7
|
+
import './atoms/blog-meta.js';
|
|
8
|
+
|
|
9
|
+
import './atoms/blog-title.js';
|
|
10
|
+
|
|
11
|
+
import './atoms/blog-authors.js';
|
|
12
|
+
|
|
13
|
+
import './atoms/blog-abstract.js';
|
|
14
|
+
|
|
15
|
+
import './atoms/blog-product-upsell.js';
|
|
16
|
+
|
|
17
|
+
import './atoms/blog-dek.js';
|
|
18
|
+
|
|
19
|
+
import './atoms/blog-paragraph.js';
|
|
20
|
+
|
|
21
|
+
import './atoms/blog-heading.js';
|
|
22
|
+
import './atoms/blog-subhead.js';
|
|
23
|
+
import './atoms/blog-related-label.js';
|
|
24
|
+
|
|
25
|
+
import './atoms/blog-key-takeaways.js';
|
|
26
|
+
|
|
27
|
+
import './atoms/blog-link.js';
|
|
28
|
+
|
|
29
|
+
import './atoms/blog-featured-image.js';
|
|
30
|
+
|
|
31
|
+
import './atoms/blog-image.js';
|
|
32
|
+
|
|
33
|
+
import './atoms/blog-caption.js';
|
|
34
|
+
|
|
35
|
+
import './atoms/blog-blockquote.js';
|
|
36
|
+
import './atoms/blog-code-block.js';
|
|
37
|
+
import './atoms/blog-standout.js';
|
|
38
|
+
|
|
39
|
+
import './atoms/blog-table-of-contents.js';
|
|
40
|
+
import './atoms/blog-related-articles.js';
|
|
41
|
+
|
|
42
|
+
import './atoms/blog-newsletter-signup.js';
|
|
43
|
+
|
|
44
|
+
import './atoms/blog-report-promo.js';
|
|
45
|
+
|
|
46
|
+
import './content/blog-page-layout.js';
|
|
47
|
+
|
|
48
|
+
import './content/blog-atoms-showcase.js';
|
|
49
|
+
|
|
50
|
+
import './content/blog-article.js';
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
export { BlogElement } from './base/blog-element.js';
|
|
55
|
+
|
|
56
|
+
export { BlogTag } from './atoms/blog-tag.js';
|
|
57
|
+
|
|
58
|
+
export { BlogAvatar } from './atoms/blog-avatar.js';
|
|
59
|
+
|
|
60
|
+
export { BlogMeta } from './atoms/blog-meta.js';
|
|
61
|
+
|
|
62
|
+
export { BlogTitle } from './atoms/blog-title.js';
|
|
63
|
+
|
|
64
|
+
export { BlogAuthors } from './atoms/blog-authors.js';
|
|
65
|
+
|
|
66
|
+
export { BlogAbstract } from './atoms/blog-abstract.js';
|
|
67
|
+
export { BlogProductUpsell } from './atoms/blog-product-upsell.js';
|
|
68
|
+
export { BlogDek } from './atoms/blog-dek.js';
|
|
69
|
+
|
|
70
|
+
export { BlogParagraph } from './atoms/blog-paragraph.js';
|
|
71
|
+
|
|
72
|
+
export { BlogHeading } from './atoms/blog-heading.js';
|
|
73
|
+
export { BlogSubhead } from './atoms/blog-subhead.js';
|
|
74
|
+
export { BlogRelatedLabel } from './atoms/blog-related-label.js';
|
|
75
|
+
|
|
76
|
+
export { BlogKeyTakeaways } from './atoms/blog-key-takeaways.js';
|
|
77
|
+
|
|
78
|
+
export { BlogLink } from './atoms/blog-link.js';
|
|
79
|
+
|
|
80
|
+
export { BlogFeaturedImage } from './atoms/blog-featured-image.js';
|
|
81
|
+
|
|
82
|
+
export { BlogImage } from './atoms/blog-image.js';
|
|
83
|
+
|
|
84
|
+
export { BlogCaption } from './atoms/blog-caption.js';
|
|
85
|
+
|
|
86
|
+
export { BlogBlockquote } from './atoms/blog-blockquote.js';
|
|
87
|
+
export { BlogCodeBlock } from './atoms/blog-code-block.js';
|
|
88
|
+
export { BlogStandout } from './atoms/blog-standout.js';
|
|
89
|
+
export { BlogTableOfContents } from './atoms/blog-table-of-contents.js';
|
|
90
|
+
export { BlogRelatedArticles } from './atoms/blog-related-articles.js';
|
|
91
|
+
|
|
92
|
+
export { BlogReportPromo } from './atoms/blog-report-promo.js';
|
|
93
|
+
|
|
94
|
+
export { BlogNewsletterSignup } from './atoms/blog-newsletter-signup.js';
|
|
95
|
+
|
|
96
|
+
export { BlogShell } from './shell/blog-shell.js';
|
|
97
|
+
|
|
98
|
+
export { BlogAtomsShowcase } from './content/blog-atoms-showcase.js';
|
|
99
|
+
|
|
100
|
+
export { BlogArticle } from './content/blog-article.js';
|
|
101
|
+
export { BlogPageLayout } from './content/blog-page-layout.js';
|
|
102
|
+
|
|
103
|
+
export { breakpoints, minWidth, matchesBreakpoint } from './breakpoints.js';
|
|
104
|
+
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
/** @param {string} text */
|
|
2
|
+
export function slugify(text) {
|
|
3
|
+
return text
|
|
4
|
+
.toLowerCase()
|
|
5
|
+
.trim()
|
|
6
|
+
.replace(/[^\w\s-]/g, '')
|
|
7
|
+
.replace(/\s+/g, '-')
|
|
8
|
+
.replace(/-+/g, '-');
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/** @param {Array<Record<string, unknown>>} blocks */
|
|
12
|
+
export function assignSubheadAnchors(blocks) {
|
|
13
|
+
const seen = new Map();
|
|
14
|
+
|
|
15
|
+
return blocks.map((block) => {
|
|
16
|
+
if (block.type !== 'subhead' || typeof block.text !== 'string') {
|
|
17
|
+
return block;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
let id = slugify(block.text);
|
|
21
|
+
const count = seen.get(id) ?? 0;
|
|
22
|
+
seen.set(id, count + 1);
|
|
23
|
+
|
|
24
|
+
if (count > 0) {
|
|
25
|
+
id = `${id}-${count + 1}`;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return { ...block, anchorId: id };
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** @param {Array<Record<string, unknown>>} blocks */
|
|
33
|
+
export function buildTocItems(blocks) {
|
|
34
|
+
return blocks
|
|
35
|
+
.filter((block) => block.type === 'subhead' && typeof block.text === 'string')
|
|
36
|
+
.map((block) => ({
|
|
37
|
+
id: block.anchorId ?? slugify(block.text),
|
|
38
|
+
label: block.text,
|
|
39
|
+
}));
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Scroll so a heading sits below the top offset (matches scroll-margin behavior).
|
|
44
|
+
*
|
|
45
|
+
* @param {Element} el
|
|
46
|
+
* @param {number} offsetPx
|
|
47
|
+
* @param {ScrollBehavior} [behavior]
|
|
48
|
+
*/
|
|
49
|
+
export function scrollToHeading(el, offsetPx, behavior = 'smooth') {
|
|
50
|
+
window.scrollTo({
|
|
51
|
+
top: getHeadingDocumentTop(el) - offsetPx,
|
|
52
|
+
behavior,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Document Y position of the scroll-spy reading line.
|
|
58
|
+
*
|
|
59
|
+
* @param {number} offsetPx distance from viewport top
|
|
60
|
+
*/
|
|
61
|
+
export function getTocReadingLine(offsetPx) {
|
|
62
|
+
return window.scrollY + offsetPx;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Absolute document Y for a heading element.
|
|
67
|
+
*
|
|
68
|
+
* @param {Element} el
|
|
69
|
+
*/
|
|
70
|
+
export function getHeadingDocumentTop(el) {
|
|
71
|
+
return el.getBoundingClientRect().top + window.scrollY;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Which TOC item is active.
|
|
76
|
+
*
|
|
77
|
+
* Prefers the section heading visible in the upper viewport (what the reader
|
|
78
|
+
* sees as the current chapter), then falls back to a document reading line.
|
|
79
|
+
*
|
|
80
|
+
* @param {Array<{ id: string, el: Element }>} headings
|
|
81
|
+
* @param {number} readingLineOffsetPx
|
|
82
|
+
*/
|
|
83
|
+
export function resolveActiveTocId(headings, readingLineOffsetPx) {
|
|
84
|
+
if (!headings.length) {
|
|
85
|
+
return '';
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const titleZoneMax = Math.max(
|
|
89
|
+
readingLineOffsetPx,
|
|
90
|
+
window.innerHeight * 0.3,
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
let titleZoneActive = '';
|
|
94
|
+
|
|
95
|
+
for (const { id, el } of headings) {
|
|
96
|
+
const rectTop = el.getBoundingClientRect().top;
|
|
97
|
+
|
|
98
|
+
if (rectTop >= -16 && rectTop <= titleZoneMax) {
|
|
99
|
+
titleZoneActive = id;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (titleZoneActive) {
|
|
104
|
+
return titleZoneActive;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const readingLine = getTocReadingLine(readingLineOffsetPx);
|
|
108
|
+
const tops = headings.map(({ el }) => getHeadingDocumentTop(el));
|
|
109
|
+
|
|
110
|
+
if (readingLine < tops[0]) {
|
|
111
|
+
return headings[0].id;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
for (let i = 0; i < headings.length; i++) {
|
|
115
|
+
const start = tops[i];
|
|
116
|
+
const end = i + 1 < tops.length ? tops[i + 1] : Number.POSITIVE_INFINITY;
|
|
117
|
+
|
|
118
|
+
if (readingLine >= start && readingLine < end) {
|
|
119
|
+
return headings[i].id;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return headings[headings.length - 1].id;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/** @param {string} id */
|
|
127
|
+
export function findArticleSubhead(id) {
|
|
128
|
+
const article = document.querySelector('blog-article');
|
|
129
|
+
|
|
130
|
+
if (!article?.shadowRoot) {
|
|
131
|
+
return null;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return (
|
|
135
|
+
article.shadowRoot.getElementById(id) ??
|
|
136
|
+
article.shadowRoot.querySelector(`blog-subhead[id="${CSS.escape(id)}"]`)
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const TOC_SCROLL_LOCK = 'data-toc-scroll-lock';
|
|
141
|
+
|
|
142
|
+
/** @param {string} id */
|
|
143
|
+
export function setTocScrollLock(id) {
|
|
144
|
+
document.documentElement.setAttribute(TOC_SCROLL_LOCK, id);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export function clearTocScrollLock() {
|
|
148
|
+
document.documentElement.removeAttribute(TOC_SCROLL_LOCK);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export function getTocScrollLock() {
|
|
152
|
+
return document.documentElement.getAttribute(TOC_SCROLL_LOCK);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/** @param {() => void} onEnd */
|
|
156
|
+
export function watchTocScrollEnd(onEnd) {
|
|
157
|
+
const lockedId = getTocScrollLock();
|
|
158
|
+
|
|
159
|
+
const finish = () => {
|
|
160
|
+
clearTocScrollLock();
|
|
161
|
+
onEnd(lockedId);
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
if ('onscrollend' in window) {
|
|
165
|
+
window.addEventListener('scrollend', finish, { once: true });
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
window.setTimeout(finish, 600);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Split body blocks so the TOC can sit after Key Takeaways on narrow viewports.
|
|
174
|
+
*
|
|
175
|
+
* @param {Array<Record<string, unknown>>} blocks
|
|
176
|
+
*/
|
|
177
|
+
export function splitBlocksForTocPlacement(blocks) {
|
|
178
|
+
const takeawaysIndex = blocks.findIndex((block) => block.type === 'takeaways');
|
|
179
|
+
|
|
180
|
+
if (takeawaysIndex === -1) {
|
|
181
|
+
return { leading: [], trailing: blocks };
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
return {
|
|
185
|
+
leading: blocks.slice(0, takeawaysIndex + 1),
|
|
186
|
+
trailing: blocks.slice(takeawaysIndex + 1),
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Split body at the first subhead — preamble (intro, takeaways) vs sections (TOC anchor).
|
|
192
|
+
*
|
|
193
|
+
* @param {Array<Record<string, unknown>>} blocks
|
|
194
|
+
*/
|
|
195
|
+
export function splitBodyAtFirstSubhead(blocks) {
|
|
196
|
+
const subheadIndex = blocks.findIndex((block) => block.type === 'subhead');
|
|
197
|
+
|
|
198
|
+
if (subheadIndex === -1) {
|
|
199
|
+
return { preamble: blocks, sections: [] };
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
return {
|
|
203
|
+
preamble: blocks.slice(0, subheadIndex),
|
|
204
|
+
sections: blocks.slice(subheadIndex),
|
|
205
|
+
};
|
|
206
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/** Load PrismJS (vendor bundle, manual highlight mode). */
|
|
2
|
+
let loadPromise;
|
|
3
|
+
|
|
4
|
+
/** @returns {Promise<typeof Prism>} */
|
|
5
|
+
export function loadPrism() {
|
|
6
|
+
if (globalThis.Prism) {
|
|
7
|
+
return Promise.resolve(globalThis.Prism);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
if (!loadPromise) {
|
|
11
|
+
loadPromise = new Promise((resolve, reject) => {
|
|
12
|
+
const script = document.createElement('script');
|
|
13
|
+
script.src = '/vendor/prism/prism.js';
|
|
14
|
+
script.dataset.manual = '';
|
|
15
|
+
script.onload = () => resolve(globalThis.Prism);
|
|
16
|
+
script.onerror = () =>
|
|
17
|
+
reject(new Error('Failed to load Prism from /vendor/prism/prism.js'));
|
|
18
|
+
document.head.appendChild(script);
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return loadPromise;
|
|
23
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { css, html } from 'lit';
|
|
2
|
+
import { LitElement } from 'lit';
|
|
3
|
+
import { tokens, blogTokens, legacyTokens } from '../../tokens/index.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Root page shell — sets base typography and exposes tokens on :host.
|
|
7
|
+
* Load tokens.css globally as well for non-component markup.
|
|
8
|
+
*/
|
|
9
|
+
export class BlogShell extends LitElement {
|
|
10
|
+
static styles = [
|
|
11
|
+
tokens,
|
|
12
|
+
blogTokens,
|
|
13
|
+
legacyTokens,
|
|
14
|
+
css`
|
|
15
|
+
:host {
|
|
16
|
+
display: block;
|
|
17
|
+
font-family: var(--typography-fontFamily-sans);
|
|
18
|
+
font-size: var(--typography-body-regular-fontSize);
|
|
19
|
+
line-height: var(--typography-body-regular-lineHeight);
|
|
20
|
+
color: var(--color-text-primary);
|
|
21
|
+
background: var(--color-surface);
|
|
22
|
+
}
|
|
23
|
+
`,
|
|
24
|
+
];
|
|
25
|
+
|
|
26
|
+
render() {
|
|
27
|
+
return html`<slot></slot>`;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
customElements.define('blog-shell', BlogShell);
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { css } from 'lit';
|
|
2
|
+
|
|
3
|
+
/** Prism token styles scoped to blog-code-block — mirrors vendor monochrome theme via tokens. */
|
|
4
|
+
export const prismTheme = css`
|
|
5
|
+
pre[class*='language-'],
|
|
6
|
+
code[class*='language-'] {
|
|
7
|
+
color: var(--blog-code-block-color);
|
|
8
|
+
background: none;
|
|
9
|
+
text-shadow: none;
|
|
10
|
+
font-family: var(--blog-code-block-fontFamily);
|
|
11
|
+
font-size: var(--blog-code-block-fontSize);
|
|
12
|
+
font-weight: var(--blog-code-block-fontWeight);
|
|
13
|
+
line-height: var(--blog-code-block-lineHeight);
|
|
14
|
+
text-align: left;
|
|
15
|
+
white-space: pre;
|
|
16
|
+
word-spacing: normal;
|
|
17
|
+
word-break: normal;
|
|
18
|
+
tab-size: 4;
|
|
19
|
+
hyphens: none;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
pre[class*='language-'] {
|
|
23
|
+
margin: 0;
|
|
24
|
+
padding: var(--blog-code-block-padding);
|
|
25
|
+
overflow: auto;
|
|
26
|
+
border-radius: var(--blog-code-block-borderRadius);
|
|
27
|
+
background: var(--blog-code-block-background);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
code[class*='language-'] ::selection,
|
|
31
|
+
pre[class*='language-'] ::selection {
|
|
32
|
+
background: var(--blog-code-block-selection-background);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
:is(.token.comment, .token.prolog, .token.doctype, .token.cdata, .token.punctuation,
|
|
36
|
+
.token.namespace, .token.property, .token.tag, .token.boolean, .token.number,
|
|
37
|
+
.token.constant, .token.symbol, .token.deleted, .token.selector, .token.attr-name,
|
|
38
|
+
.token.string, .token.char, .token.builtin, .token.inserted, .token.operator,
|
|
39
|
+
.token.entity, .token.url, .token.atrule, .token.attr-value, .token.keyword,
|
|
40
|
+
.token.class-name, .token.function, .token.variable, .token.regex,
|
|
41
|
+
.token.important) {
|
|
42
|
+
color: var(--blog-code-block-color);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.token.entity {
|
|
46
|
+
cursor: help;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.token.bold,
|
|
50
|
+
.token.important {
|
|
51
|
+
font-weight: var(--typography-fontWeight-bold);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.token.italic {
|
|
55
|
+
font-style: italic;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.token.entity,
|
|
59
|
+
.token.operator,
|
|
60
|
+
.token.url,
|
|
61
|
+
.language-css .token.string,
|
|
62
|
+
.style .token.string {
|
|
63
|
+
background: none;
|
|
64
|
+
}
|
|
65
|
+
`;
|