Add landing pages library with comprehensive components and demos

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
skyai_dev
2025-09-06 13:52:41 +10:00
parent 5346d6d0c9
commit 246c62fd49
113 changed files with 13015 additions and 165 deletions

View File

@@ -83,7 +83,7 @@
overflow-x: auto;
font-family: inherit;
font-size: inherit;
line-height: $base-typography-line-height-relaxed;
line-height: 1.5;
display: flex;
&--with-line-numbers {
@@ -116,7 +116,7 @@
.code-block__line-number {
color: var(--code-line-number, #{$semantic-color-text-tertiary});
font-size: inherit;
line-height: inherit;
line-height: 1.5;
padding: 0 $semantic-spacing-component-xs;
&--highlighted {
@@ -134,7 +134,7 @@
color: var(--code-text, #{$semantic-color-text-primary});
font-family: inherit;
font-size: inherit;
line-height: inherit;
line-height: 1.5;
white-space: pre;
overflow: visible;
flex: 1;

View File

@@ -31,11 +31,11 @@ export type CodeBlockVariant = 'default' | 'minimal' | 'bordered';
@if (showLineNumbers && lineCount() > 1) {
<div class="code-block__line-numbers" [attr.aria-hidden]="true">
@for (lineNum of lineNumbers(); track lineNum) {
<span
<div
class="code-block__line-number"
[class.code-block__line-number--highlighted]="isLineHighlighted(lineNum)">
{{ lineNum }}
</span>
</div>
}
</div>
}
@@ -95,7 +95,14 @@ export class CodeBlockComponent implements OnInit, OnChanges {
}
readonly lineCount = computed(() => {
return this.code ? this.code.split('\n').length : 0;
if (!this.code) return 0;
const lines = this.code.split('\n');
// Remove the last empty line if the code ends with a newline
if (lines.length > 1 && lines[lines.length - 1] === '') {
return lines.length - 1;
}
return lines.length;
});
readonly lineNumbers = computed(() => {

View File

@@ -154,7 +154,7 @@
overflow: visible;
font-family: inherit;
font-size: inherit;
line-height: $base-typography-line-height-relaxed;
line-height: 1.5;
display: flex;
&--with-line-numbers {

View File

@@ -62,13 +62,13 @@ export class SyntaxHighlighterService {
}
// Load Prism core
const prismModule = await import(/* @vite-ignore */ 'prismjs');
const prismModule = await import('prismjs');
const Prism = prismModule.default || prismModule;
// Ensure global availability
(window as any).Prism = Prism;
this.prismLoaded = true;
this.prismLoaded = true;
resolve(Prism);
} catch (error) {
console.warn('Failed to load Prism:', error);
@@ -90,29 +90,14 @@ export class SyntaxHighlighterService {
return;
}
try {
// Map of language identifiers to their import paths
const languageMap: Record<string, string> = {
'typescript': 'prismjs/components/prism-typescript',
'javascript': 'prismjs/components/prism-javascript',
'css': 'prismjs/components/prism-css',
'scss': 'prismjs/components/prism-scss',
'json': 'prismjs/components/prism-json',
'markup': 'prismjs/components/prism-markup',
'html': 'prismjs/components/prism-markup',
'bash': 'prismjs/components/prism-bash',
'python': 'prismjs/components/prism-python',
'java': 'prismjs/components/prism-java',
'csharp': 'prismjs/components/prism-csharp'
};
const importPath = languageMap[language];
if (importPath) {
await import(/* @vite-ignore */ importPath);
}
} catch (error) {
console.warn(`Failed to load language ${language}:`, error);
// Skip loading for unsupported languages or use fallback
if (!this.isLanguageSupported(language)) {
return;
}
// For now, just use the built-in languages or fallback gracefully
// This avoids the import issues while still providing basic highlighting
console.warn(`Language '${language}' not preloaded, using fallback`);
}
isLanguageSupported(language: string): boolean {