doc-fetch-cli 2.0.4 → 2.0.6

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 (44) hide show
  1. package/README.md +2 -0
  2. package/bin/doc-fetch_darwin_amd64 +0 -0
  3. package/bin/doc-fetch_windows_amd64.exe +0 -0
  4. package/doc-fetch +0 -0
  5. package/doc-fetch_darwin_amd64 +0 -0
  6. package/doc-fetch_darwin_arm64 +0 -0
  7. package/doc-fetch_linux_amd64 +0 -0
  8. package/doc-fetch_windows_amd64.exe +0 -0
  9. package/package.json +1 -1
  10. package/website/BLOG-SETUP-SUMMARY.md +385 -0
  11. package/website/DEPLOYMENT.md +189 -0
  12. package/website/LAUNCH-CHECKLIST.md +134 -0
  13. package/website/README.md +75 -0
  14. package/website/SEO-STRATEGY.md +347 -0
  15. package/website/URL-STRUCTURE.md +334 -0
  16. package/website/WEBSITE-SUMMARY.md +246 -0
  17. package/website/package-lock.json +1628 -0
  18. package/website/package.json +39 -0
  19. package/website/pnpm-lock.yaml +1061 -0
  20. package/website/src/app.d.ts +13 -0
  21. package/website/src/app.html +11 -0
  22. package/website/src/lib/actions/addCopyButtons.ts +73 -0
  23. package/website/src/lib/assets/favicon.svg +1 -0
  24. package/website/src/lib/components/CopyCodeButton.svelte +97 -0
  25. package/website/src/lib/components/DarkModeToggle.svelte +140 -0
  26. package/website/src/lib/components/ReadingProgress.svelte +36 -0
  27. package/website/src/lib/components/RelatedPosts.svelte +151 -0
  28. package/website/src/lib/components/TableOfContents.svelte +184 -0
  29. package/website/src/lib/index.ts +1 -0
  30. package/website/src/lib/posts/convert-docs-to-markdown.md +506 -0
  31. package/website/src/routes/+layout.svelte +59 -0
  32. package/website/src/routes/+page.svelte +1033 -0
  33. package/website/src/routes/about/+page.svelte +607 -0
  34. package/website/src/routes/blog/+page.svelte +486 -0
  35. package/website/src/routes/blog/[slug]/+page.svelte +988 -0
  36. package/website/src/routes/blog/[slug]/+page.ts +53 -0
  37. package/website/src/routes/sitemap.xml/+server.ts +62 -0
  38. package/website/static/favicon.svg +10 -0
  39. package/website/static/og.png +2 -0
  40. package/website/static/og.svg +26 -0
  41. package/website/static/robots.txt +43 -0
  42. package/website/svelte.config.js +13 -0
  43. package/website/tsconfig.json +20 -0
  44. package/website/vite.config.ts +6 -0
@@ -0,0 +1,13 @@
1
+ // See https://svelte.dev/docs/kit/types#app.d.ts
2
+ // for information about these interfaces
3
+ declare global {
4
+ namespace App {
5
+ // interface Error {}
6
+ // interface Locals {}
7
+ // interface PageData {}
8
+ // interface PageState {}
9
+ // interface Platform {}
10
+ }
11
+ }
12
+
13
+ export {};
@@ -0,0 +1,11 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
6
+ %sveltekit.head%
7
+ </head>
8
+ <body data-sveltekit-preload-data="hover">
9
+ <div style="display: contents">%sveltekit.body%</div>
10
+ </body>
11
+ </html>
@@ -0,0 +1,73 @@
1
+ // Svelte action to automatically add copy buttons to all code blocks
2
+ export function addCopyButtons(node: HTMLElement) {
3
+ const observer = new MutationObserver(() => {
4
+ addButtonsToCodeBlocks(node);
5
+ });
6
+
7
+ // Initial setup
8
+ addButtonsToCodeBlocks(node);
9
+
10
+ // Watch for dynamically added content
11
+ observer.observe(node, {
12
+ childList: true,
13
+ subtree: true
14
+ });
15
+
16
+ return {
17
+ destroy() {
18
+ observer.disconnect();
19
+ }
20
+ };
21
+ }
22
+
23
+ function addButtonsToCodeBlocks(container: HTMLElement) {
24
+ const pres = container.querySelectorAll('pre');
25
+
26
+ pres.forEach((pre) => {
27
+ // Skip if already has a copy button
28
+ if (pre.querySelector('.copy-btn')) return;
29
+
30
+ const code = pre.querySelector('code');
31
+ if (!code) return;
32
+
33
+ // Create copy button
34
+ const button = document.createElement('button');
35
+ button.className = 'copy-code-button';
36
+ button.setAttribute('aria-label', 'Copy code');
37
+ button.innerHTML = `
38
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
39
+ <rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
40
+ <path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
41
+ </svg>
42
+ <span class="tooltip">Copy</span>
43
+ `;
44
+
45
+ button.addEventListener('click', async () => {
46
+ try {
47
+ await navigator.clipboard.writeText(code.textContent || '');
48
+ button.classList.add('copied');
49
+ button.innerHTML = `
50
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
51
+ <polyline points="20 6 9 17 4 12"></polyline>
52
+ </svg>
53
+ <span class="tooltip">Copied!</span>
54
+ `;
55
+
56
+ setTimeout(() => {
57
+ button.classList.remove('copied');
58
+ button.innerHTML = `
59
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
60
+ <rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
61
+ <path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
62
+ </svg>
63
+ <span class="tooltip">Copy</span>
64
+ `;
65
+ }, 2000);
66
+ } catch (err) {
67
+ console.error('Failed to copy:', err);
68
+ }
69
+ });
70
+
71
+ pre.appendChild(button);
72
+ });
73
+ }
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="107" height="128" viewBox="0 0 107 128"><title>svelte-logo</title><path d="M94.157 22.819c-10.4-14.885-30.94-19.297-45.792-9.835L22.282 29.608A29.92 29.92 0 0 0 8.764 49.65a31.5 31.5 0 0 0 3.108 20.231 30 30 0 0 0-4.477 11.183 31.9 31.9 0 0 0 5.448 24.116c10.402 14.887 30.942 19.297 45.791 9.835l26.083-16.624A29.92 29.92 0 0 0 98.235 78.35a31.53 31.53 0 0 0-3.105-20.232 30 30 0 0 0 4.474-11.182 31.88 31.88 0 0 0-5.447-24.116" style="fill:#ff3e00"/><path d="M45.817 106.582a20.72 20.72 0 0 1-22.237-8.243 19.17 19.17 0 0 1-3.277-14.503 18 18 0 0 1 .624-2.435l.49-1.498 1.337.981a33.6 33.6 0 0 0 10.203 5.098l.97.294-.09.968a5.85 5.85 0 0 0 1.052 3.878 6.24 6.24 0 0 0 6.695 2.485 5.8 5.8 0 0 0 1.603-.704L69.27 76.28a5.43 5.43 0 0 0 2.45-3.631 5.8 5.8 0 0 0-.987-4.371 6.24 6.24 0 0 0-6.698-2.487 5.7 5.7 0 0 0-1.6.704l-9.953 6.345a19 19 0 0 1-5.296 2.326 20.72 20.72 0 0 1-22.237-8.243 19.17 19.17 0 0 1-3.277-14.502 17.99 17.99 0 0 1 8.13-12.052l26.081-16.623a19 19 0 0 1 5.3-2.329 20.72 20.72 0 0 1 22.237 8.243 19.17 19.17 0 0 1 3.277 14.503 18 18 0 0 1-.624 2.435l-.49 1.498-1.337-.98a33.6 33.6 0 0 0-10.203-5.1l-.97-.294.09-.968a5.86 5.86 0 0 0-1.052-3.878 6.24 6.24 0 0 0-6.696-2.485 5.8 5.8 0 0 0-1.602.704L37.73 51.72a5.42 5.42 0 0 0-2.449 3.63 5.79 5.79 0 0 0 .986 4.372 6.24 6.24 0 0 0 6.698 2.486 5.8 5.8 0 0 0 1.602-.704l9.952-6.342a19 19 0 0 1 5.295-2.328 20.72 20.72 0 0 1 22.237 8.242 19.17 19.17 0 0 1 3.277 14.503 18 18 0 0 1-8.13 12.053l-26.081 16.622a19 19 0 0 1-5.3 2.328" style="fill:#fff"/></svg>
@@ -0,0 +1,97 @@
1
+ <script lang="ts">
2
+ import { onMount } from 'svelte';
3
+
4
+ export let codeElement: HTMLElement | null = null;
5
+ let copied = false;
6
+ let showTooltip = false;
7
+
8
+ onMount(() => {
9
+ if (codeElement) {
10
+ const pre = codeElement.parentElement;
11
+ if (pre) {
12
+ pre.style.position = 'relative';
13
+ }
14
+ }
15
+ });
16
+
17
+ async function copyCode() {
18
+ if (!codeElement) return;
19
+
20
+ try {
21
+ await navigator.clipboard.writeText(codeElement.textContent || '');
22
+ copied = true;
23
+ showTooltip = true;
24
+
25
+ setTimeout(() => {
26
+ copied = false;
27
+ showTooltip = false;
28
+ }, 2000);
29
+ } catch (err) {
30
+ console.error('Failed to copy:', err);
31
+ }
32
+ }
33
+ </script>
34
+
35
+ <button class="copy-btn" class:visible={copied || showTooltip} on:click={copyCode} aria-label="Copy code">
36
+ {#if copied}
37
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
38
+ <polyline points="20 6 9 17 4 12"></polyline>
39
+ </svg>
40
+ <span class="tooltip">Copied!</span>
41
+ {:else}
42
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
43
+ <rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
44
+ <path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
45
+ </svg>
46
+ <span class="tooltip">Copy</span>
47
+ {/if}
48
+ </button>
49
+
50
+ <style>
51
+ .copy-btn {
52
+ position: absolute;
53
+ top: 0.75rem;
54
+ right: 0.75rem;
55
+ background: rgba(255, 255, 255, 0.1);
56
+ border: none;
57
+ border-radius: 4px;
58
+ padding: 0.5rem;
59
+ cursor: pointer;
60
+ color: #d4d4d4;
61
+ transition: all 0.2s;
62
+ opacity: 0;
63
+ z-index: 10;
64
+ display: flex;
65
+ align-items: center;
66
+ gap: 0.5rem;
67
+ font-size: 0.875rem;
68
+ }
69
+
70
+ .copy-btn:hover,
71
+ .copy-btn.visible {
72
+ opacity: 1;
73
+ background: rgba(255, 255, 255, 0.15);
74
+ }
75
+
76
+ .copy-btn:active {
77
+ transform: scale(0.95);
78
+ }
79
+
80
+ .copy-btn svg {
81
+ display: block;
82
+ }
83
+
84
+ .tooltip {
85
+ background: rgba(0, 0, 0, 0.8);
86
+ color: white;
87
+ padding: 0.25rem 0.5rem;
88
+ border-radius: 4px;
89
+ font-size: 0.75rem;
90
+ white-space: nowrap;
91
+ pointer-events: none;
92
+ }
93
+
94
+ pre:hover .copy-btn {
95
+ opacity: 1;
96
+ }
97
+ </style>
@@ -0,0 +1,140 @@
1
+ <script lang="ts">
2
+ import { onMount } from 'svelte';
3
+
4
+ let isDark = false;
5
+ let initialized = false;
6
+
7
+ onMount(() => {
8
+ // Check localStorage first
9
+ const stored = localStorage.getItem('theme');
10
+ if (stored) {
11
+ isDark = stored === 'dark';
12
+ } else {
13
+ // Fall back to system preference
14
+ isDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
15
+ }
16
+
17
+ applyTheme(isDark);
18
+ initialized = true;
19
+
20
+ // Listen for system theme changes
21
+ const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
22
+ const handleChange = (e: MediaQueryListEvent) => {
23
+ if (!localStorage.getItem('theme')) {
24
+ isDark = e.matches;
25
+ applyTheme(isDark);
26
+ }
27
+ };
28
+
29
+ mediaQuery.addEventListener('change', handleChange);
30
+
31
+ return () => {
32
+ mediaQuery.removeEventListener('change', handleChange);
33
+ };
34
+ });
35
+
36
+ function toggle() {
37
+ isDark = !isDark;
38
+ applyTheme(isDark);
39
+ localStorage.setItem('theme', isDark ? 'dark' : 'light');
40
+ }
41
+
42
+ function applyTheme(dark: boolean) {
43
+ if (dark) {
44
+ document.documentElement.classList.add('dark');
45
+ document.documentElement.style.colorScheme = 'dark';
46
+ } else {
47
+ document.documentElement.classList.remove('dark');
48
+ document.documentElement.style.colorScheme = 'light';
49
+ }
50
+ }
51
+ </script>
52
+
53
+ <button class="theme-toggle" on:click={toggle} aria-label="Toggle dark mode" title={isDark ? 'Switch to light mode' : 'Switch to dark mode'}>
54
+ {#if isDark}
55
+ <!-- Sun icon -->
56
+ <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
57
+ <circle cx="12" cy="12" r="5"></circle>
58
+ <line x1="12" y1="1" x2="12" y2="3"></line>
59
+ <line x1="12" y1="21" x2="12" y2="23"></line>
60
+ <line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
61
+ <line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
62
+ <line x1="1" y1="12" x2="3" y2="12"></line>
63
+ <line x1="21" y1="12" x2="23" y2="12"></line>
64
+ <line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
65
+ <line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
66
+ </svg>
67
+ {:else}
68
+ <!-- Moon icon -->
69
+ <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
70
+ <path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path>
71
+ </svg>
72
+ {/if}
73
+ </button>
74
+
75
+ <style>
76
+ .theme-toggle {
77
+ background: transparent;
78
+ border: 1px solid var(--border);
79
+ border-radius: 6px;
80
+ padding: 0.5rem;
81
+ cursor: pointer;
82
+ color: var(--text-secondary);
83
+ transition: all 0.2s;
84
+ display: flex;
85
+ align-items: center;
86
+ justify-content: center;
87
+ }
88
+
89
+ .theme-toggle:hover {
90
+ background: var(--bg-secondary);
91
+ color: var(--accent);
92
+ border-color: var(--accent);
93
+ }
94
+
95
+ .theme-toggle:active {
96
+ transform: scale(0.95);
97
+ }
98
+
99
+ :global(.dark) {
100
+ --bg-primary: #0d1117;
101
+ --bg-secondary: #161b22;
102
+ --text-primary: #f0f6fc;
103
+ --text-secondary: #8b949e;
104
+ --text-muted: #6e7681;
105
+ --border: #30363d;
106
+ --accent: #58a6ff;
107
+ --accent-hover: #79c0ff;
108
+ }
109
+
110
+ :global(.dark) .copy-code-button {
111
+ background: rgba(255, 255, 255, 0.05);
112
+ }
113
+
114
+ :global(.dark) .copy-code-button:hover {
115
+ background: rgba(255, 255, 255, 0.1);
116
+ }
117
+
118
+ :global(.dark) pre {
119
+ background: #161b22;
120
+ }
121
+
122
+ :global(.dark) .toc {
123
+ background: var(--bg-secondary);
124
+ border-color: var(--border);
125
+ }
126
+
127
+ :global(.dark) .install-card {
128
+ background: var(--bg-secondary);
129
+ }
130
+
131
+ :global(.dark) .feature-card,
132
+ :global(.dark) .example-card,
133
+ :global(.dark) .related-card {
134
+ background: var(--bg-secondary);
135
+ }
136
+
137
+ :global(.dark) .cta-box {
138
+ background: var(--bg-secondary);
139
+ }
140
+ </style>
@@ -0,0 +1,36 @@
1
+ <script lang="ts">
2
+ import { onMount, onDestroy } from 'svelte';
3
+
4
+ let progress = 0;
5
+ let animationFrame: number;
6
+
7
+ onMount(() => {
8
+ const updateProgress = () => {
9
+ const scrollTop = window.scrollY;
10
+ const docHeight = document.documentElement.scrollHeight - window.innerHeight;
11
+ progress = docHeight > 0 ? (scrollTop / docHeight) * 100 : 0;
12
+ animationFrame = requestAnimationFrame(updateProgress);
13
+ };
14
+
15
+ updateProgress();
16
+
17
+ return () => {
18
+ cancelAnimationFrame(animationFrame);
19
+ };
20
+ });
21
+ </script>
22
+
23
+ <div class="progress-bar" style="--progress: {progress}%"></div>
24
+
25
+ <style>
26
+ .progress-bar {
27
+ position: fixed;
28
+ top: 0;
29
+ left: 0;
30
+ width: var(--progress);
31
+ height: 3px;
32
+ background: linear-gradient(90deg, var(--accent), var(--accent-hover));
33
+ z-index: 9999;
34
+ transition: width 0.1s ease-out;
35
+ }
36
+ </style>
@@ -0,0 +1,151 @@
1
+ <script lang="ts">
2
+ export let posts: Array<{
3
+ slug: string;
4
+ title: string;
5
+ excerpt: string;
6
+ readTime?: string;
7
+ }> = [];
8
+
9
+ // Generate placeholder OG images (in production, these would be real images)
10
+ function getThumbnailUrl(slug: string): string {
11
+ // Using gradient placeholders with text overlay
12
+ const colors = [
13
+ 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
14
+ 'linear-gradient(135deg, #f093fb 0%, #f5576c 100%)',
15
+ 'linear-gradient(135deg, #4facfe 0%, #00f2fe 100%)',
16
+ 'linear-gradient(135deg, #43e97b 0%, #38f9d7 100%)',
17
+ 'linear-gradient(135deg, #fa709a 0%, #fee140 100%)'
18
+ ];
19
+
20
+ const index = slug.length % colors.length;
21
+ return colors[index];
22
+ }
23
+
24
+ function getInitials(title: string): string {
25
+ return title
26
+ .split(' ')
27
+ .filter(word => word.length > 0)
28
+ .slice(0, 2)
29
+ .map(word => word[0].toUpperCase())
30
+ .join('');
31
+ }
32
+ </script>
33
+
34
+ {#if posts.length > 0}
35
+ <section class="related-posts-component">
36
+ <h3>Related Articles</h3>
37
+ <div class="related-grid-with-thumbs">
38
+ {#each posts as post}
39
+ <article class="related-card-with-thumb">
40
+ <a href={`/blog/${post.slug}`} class="related-thumbnail" style="background: {getThumbnailUrl(post.slug)}">
41
+ <span class="thumbnail-initials">{getInitials(post.title)}</span>
42
+ </a>
43
+ <div class="related-content">
44
+ <h4>
45
+ <a href={`/blog/${post.slug}`}>{post.title}</a>
46
+ </h4>
47
+ <p class="related-excerpt">{post.excerpt}</p>
48
+ {#if post.readTime}
49
+ <span class="related-read-time">{post.readTime}</span>
50
+ {/if}
51
+ </div>
52
+ </article>
53
+ {/each}
54
+ </div>
55
+ </section>
56
+ {/if}
57
+
58
+ <style>
59
+ .related-posts-component {
60
+ margin-bottom: 3rem;
61
+ padding-bottom: 2rem;
62
+ border-bottom: 1px solid var(--border);
63
+ }
64
+
65
+ .related-posts-component h3 {
66
+ font-size: 1.4rem;
67
+ margin-bottom: 1.5rem;
68
+ }
69
+
70
+ .related-grid-with-thumbs {
71
+ display: grid;
72
+ grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
73
+ gap: 2rem;
74
+ }
75
+
76
+ .related-card-with-thumb {
77
+ background: var(--bg-secondary);
78
+ border-radius: 8px;
79
+ overflow: hidden;
80
+ transition: transform 0.2s, box-shadow 0.2s;
81
+ display: flex;
82
+ flex-direction: column;
83
+ }
84
+
85
+ .related-card-with-thumb:hover {
86
+ transform: translateY(-4px);
87
+ box-shadow: 0 8px 16px rgba(0, 0, 0, 0.08);
88
+ }
89
+
90
+ .related-thumbnail {
91
+ display: flex;
92
+ align-items: center;
93
+ justify-content: center;
94
+ height: 180px;
95
+ text-decoration: none;
96
+ position: relative;
97
+ overflow: hidden;
98
+ }
99
+
100
+ .thumbnail-initials {
101
+ font-size: 3rem;
102
+ font-weight: 800;
103
+ color: rgba(255, 255, 255, 0.9);
104
+ text-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
105
+ }
106
+
107
+ .related-content {
108
+ padding: 1.5rem;
109
+ flex: 1;
110
+ display: flex;
111
+ flex-direction: column;
112
+ }
113
+
114
+ .related-content h4 {
115
+ margin: 0 0 0.75rem;
116
+ font-size: 1.1rem;
117
+ line-height: 1.4;
118
+ }
119
+
120
+ .related-content h4 a {
121
+ color: var(--text-primary);
122
+ text-decoration: none;
123
+ }
124
+
125
+ .related-content h4 a:hover {
126
+ color: var(--accent);
127
+ }
128
+
129
+ .related-excerpt {
130
+ color: var(--text-secondary);
131
+ font-size: 0.9rem;
132
+ line-height: 1.6;
133
+ margin: 0 0 1rem;
134
+ flex: 1;
135
+ }
136
+
137
+ .related-read-time {
138
+ font-size: 0.8rem;
139
+ color: var(--text-muted);
140
+ font-weight: 500;
141
+ display: inline-flex;
142
+ align-items: center;
143
+ gap: 0.25rem;
144
+ }
145
+
146
+ @media (max-width: 768px) {
147
+ .related-grid-with-thumbs {
148
+ grid-template-columns: 1fr;
149
+ }
150
+ }
151
+ </style>