create-atsdc-stack 1.0.1 → 1.2.0

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 (48) hide show
  1. package/.claude/settings.local.json +3 -1
  2. package/CLAUDE.md +236 -0
  3. package/CONTRIBUTING.md +342 -342
  4. package/INSTALLATION.md +359 -359
  5. package/LICENSE +201 -201
  6. package/README.md +405 -405
  7. package/app/.env.example +17 -17
  8. package/app/.github/labeler.yml +61 -0
  9. package/app/.github/workflows/browser-tests.yml +101 -0
  10. package/app/.github/workflows/check.yml +24 -0
  11. package/app/.github/workflows/greetings.yml +16 -0
  12. package/app/.github/workflows/label.yml +22 -0
  13. package/app/.github/workflows/stale.yml +27 -0
  14. package/app/.github/workflows/summary.yml +34 -0
  15. package/app/.stylelintrc.json +8 -0
  16. package/app/README.md +251 -251
  17. package/app/astro.config.mjs +83 -83
  18. package/app/drizzle.config.ts +16 -16
  19. package/app/package.json +66 -52
  20. package/app/playwright.config.ts +27 -0
  21. package/app/public/manifest.webmanifest +36 -36
  22. package/app/pwa-assets.config.ts +8 -0
  23. package/app/src/components/Card.astro +36 -36
  24. package/app/src/db/initialize.ts +107 -107
  25. package/app/src/db/schema.ts +72 -72
  26. package/app/src/db/validations.ts +158 -158
  27. package/app/src/layouts/Layout.astro +63 -63
  28. package/app/src/lib/config.ts +36 -36
  29. package/app/src/lib/content-converter.ts +141 -141
  30. package/app/src/lib/dom-utils.ts +230 -230
  31. package/app/src/lib/exa-search.ts +269 -269
  32. package/app/src/pages/api/chat.ts +91 -91
  33. package/app/src/pages/api/posts.ts +350 -350
  34. package/app/src/pages/index.astro +87 -87
  35. package/app/src/styles/components/button.scss +152 -152
  36. package/app/src/styles/components/card.scss +180 -180
  37. package/app/src/styles/components/form.scss +240 -240
  38. package/app/src/styles/global.scss +141 -141
  39. package/app/src/styles/pages/index.scss +80 -80
  40. package/app/src/styles/reset.scss +83 -83
  41. package/app/src/styles/variables/globals.scss +96 -96
  42. package/app/src/styles/variables/mixins.scss +238 -238
  43. package/app/tests/browser.test.nopause.ts +10 -0
  44. package/app/tests/browser.test.ts +13 -0
  45. package/bin/cli.js +1151 -1138
  46. package/package.json +8 -6
  47. package/app/.astro/settings.json +0 -5
  48. package/app/.astro/types.d.ts +0 -1
@@ -1,141 +1,141 @@
1
- /**
2
- * Content Converter Utilities
3
- * Provides functions for converting between HTML and Markdown using marked and turndown
4
- */
5
-
6
- import { marked } from 'marked';
7
- import TurndownService from 'turndown';
8
-
9
- // Configure marked for markdown to HTML conversion
10
- marked.setOptions({
11
- gfm: true, // GitHub Flavored Markdown
12
- breaks: true, // Convert \n to <br>
13
- headerIds: true, // Add IDs to headings
14
- mangle: false, // Don't escape email addresses
15
- });
16
-
17
- // Configure turndown for HTML to markdown conversion
18
- const turndownService = new TurndownService({
19
- headingStyle: 'atx', // Use # for headings
20
- hr: '---', // Use --- for horizontal rules
21
- bulletListMarker: '-', // Use - for bullet lists
22
- codeBlockStyle: 'fenced', // Use ``` for code blocks
23
- fence: '```', // Code fence marker
24
- emDelimiter: '*', // Use * for emphasis
25
- strongDelimiter: '**', // Use ** for strong
26
- linkStyle: 'inlined', // Use [text](url) for links
27
- });
28
-
29
- /**
30
- * Convert Markdown to HTML
31
- * @param markdown - The markdown string to convert
32
- * @returns HTML string
33
- */
34
- export async function markdownToHtml(markdown: string): Promise<string> {
35
- try {
36
- const html = await marked.parse(markdown);
37
- return html;
38
- } catch (error) {
39
- console.error('Error converting markdown to HTML:', error);
40
- throw new Error('Failed to convert markdown to HTML');
41
- }
42
- }
43
-
44
- /**
45
- * Convert Markdown to HTML synchronously
46
- * @param markdown - The markdown string to convert
47
- * @returns HTML string
48
- */
49
- export function markdownToHtmlSync(markdown: string): string {
50
- try {
51
- const html = marked.parse(markdown) as string;
52
- return html;
53
- } catch (error) {
54
- console.error('Error converting markdown to HTML:', error);
55
- throw new Error('Failed to convert markdown to HTML');
56
- }
57
- }
58
-
59
- /**
60
- * Convert HTML to Markdown
61
- * @param html - The HTML string to convert
62
- * @returns Markdown string
63
- */
64
- export function htmlToMarkdown(html: string): string {
65
- try {
66
- const markdown = turndownService.turndown(html);
67
- return markdown;
68
- } catch (error) {
69
- console.error('Error converting HTML to markdown:', error);
70
- throw new Error('Failed to convert HTML to markdown');
71
- }
72
- }
73
-
74
- /**
75
- * Sanitize and convert Markdown to HTML
76
- * Useful for user-generated content
77
- * @param markdown - The markdown string to convert
78
- * @returns Sanitized HTML string
79
- */
80
- export async function sanitizeMarkdown(markdown: string): Promise<string> {
81
- try {
82
- // Basic sanitization - remove script tags and dangerous attributes
83
- const sanitized = markdown
84
- .replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '')
85
- .replace(/on\w+="[^"]*"/g, '')
86
- .replace(/on\w+='[^']*'/g, '');
87
-
88
- const html = await marked.parse(sanitized);
89
- return html;
90
- } catch (error) {
91
- console.error('Error sanitizing markdown:', error);
92
- throw new Error('Failed to sanitize markdown');
93
- }
94
- }
95
-
96
- /**
97
- * Extract plain text from markdown
98
- * @param markdown - The markdown string
99
- * @returns Plain text string
100
- */
101
- export function markdownToPlainText(markdown: string): string {
102
- try {
103
- const html = marked.parse(markdown) as string;
104
- const text = html
105
- .replace(/<[^>]*>/g, '') // Remove HTML tags
106
- .replace(/&nbsp;/g, ' ') // Replace &nbsp;
107
- .replace(/&amp;/g, '&') // Replace &amp;
108
- .replace(/&lt;/g, '<') // Replace &lt;
109
- .replace(/&gt;/g, '>') // Replace &gt;
110
- .replace(/&quot;/g, '"') // Replace &quot;
111
- .trim();
112
- return text;
113
- } catch (error) {
114
- console.error('Error extracting plain text:', error);
115
- throw new Error('Failed to extract plain text');
116
- }
117
- }
118
-
119
- /**
120
- * Generate excerpt from markdown
121
- * @param markdown - The markdown string
122
- * @param maxLength - Maximum length of the excerpt (default: 200)
123
- * @returns Excerpt string
124
- */
125
- export function generateExcerpt(markdown: string, maxLength: number = 200): string {
126
- const plainText = markdownToPlainText(markdown);
127
-
128
- if (plainText.length <= maxLength) {
129
- return plainText;
130
- }
131
-
132
- // Truncate at word boundary
133
- const truncated = plainText.slice(0, maxLength);
134
- const lastSpace = truncated.lastIndexOf(' ');
135
-
136
- if (lastSpace > 0) {
137
- return truncated.slice(0, lastSpace) + '...';
138
- }
139
-
140
- return truncated + '...';
141
- }
1
+ /**
2
+ * Content Converter Utilities
3
+ * Provides functions for converting between HTML and Markdown using marked and turndown
4
+ */
5
+
6
+ import { marked } from 'marked';
7
+ import TurndownService from 'turndown';
8
+
9
+ // Configure marked for markdown to HTML conversion
10
+ marked.setOptions({
11
+ gfm: true, // GitHub Flavored Markdown
12
+ breaks: true, // Convert \n to <br>
13
+ headerIds: true, // Add IDs to headings
14
+ mangle: false, // Don't escape email addresses
15
+ });
16
+
17
+ // Configure turndown for HTML to markdown conversion
18
+ const turndownService = new TurndownService({
19
+ headingStyle: 'atx', // Use # for headings
20
+ hr: '---', // Use --- for horizontal rules
21
+ bulletListMarker: '-', // Use - for bullet lists
22
+ codeBlockStyle: 'fenced', // Use ``` for code blocks
23
+ fence: '```', // Code fence marker
24
+ emDelimiter: '*', // Use * for emphasis
25
+ strongDelimiter: '**', // Use ** for strong
26
+ linkStyle: 'inlined', // Use [text](url) for links
27
+ });
28
+
29
+ /**
30
+ * Convert Markdown to HTML
31
+ * @param markdown - The markdown string to convert
32
+ * @returns HTML string
33
+ */
34
+ export async function markdownToHtml(markdown: string): Promise<string> {
35
+ try {
36
+ const html = await marked.parse(markdown);
37
+ return html;
38
+ } catch (error) {
39
+ console.error('Error converting markdown to HTML:', error);
40
+ throw new Error('Failed to convert markdown to HTML');
41
+ }
42
+ }
43
+
44
+ /**
45
+ * Convert Markdown to HTML synchronously
46
+ * @param markdown - The markdown string to convert
47
+ * @returns HTML string
48
+ */
49
+ export function markdownToHtmlSync(markdown: string): string {
50
+ try {
51
+ const html = marked.parse(markdown) as string;
52
+ return html;
53
+ } catch (error) {
54
+ console.error('Error converting markdown to HTML:', error);
55
+ throw new Error('Failed to convert markdown to HTML');
56
+ }
57
+ }
58
+
59
+ /**
60
+ * Convert HTML to Markdown
61
+ * @param html - The HTML string to convert
62
+ * @returns Markdown string
63
+ */
64
+ export function htmlToMarkdown(html: string): string {
65
+ try {
66
+ const markdown = turndownService.turndown(html);
67
+ return markdown;
68
+ } catch (error) {
69
+ console.error('Error converting HTML to markdown:', error);
70
+ throw new Error('Failed to convert HTML to markdown');
71
+ }
72
+ }
73
+
74
+ /**
75
+ * Sanitize and convert Markdown to HTML
76
+ * Useful for user-generated content
77
+ * @param markdown - The markdown string to convert
78
+ * @returns Sanitized HTML string
79
+ */
80
+ export async function sanitizeMarkdown(markdown: string): Promise<string> {
81
+ try {
82
+ // Basic sanitization - remove script tags and dangerous attributes
83
+ const sanitized = markdown
84
+ .replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '')
85
+ .replace(/on\w+="[^"]*"/g, '')
86
+ .replace(/on\w+='[^']*'/g, '');
87
+
88
+ const html = await marked.parse(sanitized);
89
+ return html;
90
+ } catch (error) {
91
+ console.error('Error sanitizing markdown:', error);
92
+ throw new Error('Failed to sanitize markdown');
93
+ }
94
+ }
95
+
96
+ /**
97
+ * Extract plain text from markdown
98
+ * @param markdown - The markdown string
99
+ * @returns Plain text string
100
+ */
101
+ export function markdownToPlainText(markdown: string): string {
102
+ try {
103
+ const html = marked.parse(markdown) as string;
104
+ const text = html
105
+ .replace(/<[^>]*>/g, '') // Remove HTML tags
106
+ .replace(/&nbsp;/g, ' ') // Replace &nbsp;
107
+ .replace(/&amp;/g, '&') // Replace &amp;
108
+ .replace(/&lt;/g, '<') // Replace &lt;
109
+ .replace(/&gt;/g, '>') // Replace &gt;
110
+ .replace(/&quot;/g, '"') // Replace &quot;
111
+ .trim();
112
+ return text;
113
+ } catch (error) {
114
+ console.error('Error extracting plain text:', error);
115
+ throw new Error('Failed to extract plain text');
116
+ }
117
+ }
118
+
119
+ /**
120
+ * Generate excerpt from markdown
121
+ * @param markdown - The markdown string
122
+ * @param maxLength - Maximum length of the excerpt (default: 200)
123
+ * @returns Excerpt string
124
+ */
125
+ export function generateExcerpt(markdown: string, maxLength: number = 200): string {
126
+ const plainText = markdownToPlainText(markdown);
127
+
128
+ if (plainText.length <= maxLength) {
129
+ return plainText;
130
+ }
131
+
132
+ // Truncate at word boundary
133
+ const truncated = plainText.slice(0, maxLength);
134
+ const lastSpace = truncated.lastIndexOf(' ');
135
+
136
+ if (lastSpace > 0) {
137
+ return truncated.slice(0, lastSpace) + '...';
138
+ }
139
+
140
+ return truncated + '...';
141
+ }