@stacksjs/stx 0.2.148 → 0.2.150
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/dist/cli.js +516 -516
- package/dist/craft.js +252 -252
- package/dist/dev-server/serve-multi.js +3 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/markdown-view.d.ts +25 -0
- package/dist/markdown-view.js +39 -0
- package/dist/production-server.js +3 -5
- package/dist/render.d.ts +1 -0
- package/dist/render.js +12 -1
- package/dist/ssr.js +2 -4
- package/package.json +5 -5
|
@@ -8,6 +8,7 @@ import { partialsCache } from "../includes.js";
|
|
|
8
8
|
import { stateDir } from "../state-dir.js";
|
|
9
9
|
import { plugin as stxPlugin } from "../plugin.js";
|
|
10
10
|
import { clearComponentCache } from "../utils.js";
|
|
11
|
+
import { bracketPathToRegex } from "stx-router";
|
|
11
12
|
import {
|
|
12
13
|
colors,
|
|
13
14
|
findAvailablePort,
|
|
@@ -275,9 +276,9 @@ export async function serveMultipleStxFiles(filePaths, options = {}) {
|
|
|
275
276
|
if (routePath.endsWith("/index"))
|
|
276
277
|
routePath = routePath.slice(0, -6) || "/";
|
|
277
278
|
if (routePath.includes("[")) {
|
|
278
|
-
const
|
|
279
|
+
const { regex, params: paramNames } = bracketPathToRegex(routePath);
|
|
279
280
|
dynamicRoutes.push({
|
|
280
|
-
pattern:
|
|
281
|
+
pattern: regex,
|
|
281
282
|
paramNames,
|
|
282
283
|
filePath: absolutePath,
|
|
283
284
|
routeTemplate: routePath,
|
package/dist/index.d.ts
CHANGED
|
@@ -228,5 +228,6 @@ export {
|
|
|
228
228
|
validated,
|
|
229
229
|
withDefaults,
|
|
230
230
|
} from './props';
|
|
231
|
+
export { isMarkdownPath, type MarkdownRenderer, type MarkdownView, protectCodeBlocks, renderMarkdownView } from './markdown-view';
|
|
231
232
|
// Default export for the stx module
|
|
232
233
|
export default {};
|
package/dist/index.js
CHANGED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/** Whether a path should be treated as a markdown view. */
|
|
2
|
+
export declare function isMarkdownPath(filePath: string): boolean;
|
|
3
|
+
/**
|
|
4
|
+
* Wrap code blocks so the stx pass leaves their contents alone.
|
|
5
|
+
*
|
|
6
|
+
* Applies to `<pre>` (fenced blocks) and to any `<code>` not already inside
|
|
7
|
+
* one (inline spans). Without this, a page documenting a directive executes it.
|
|
8
|
+
*/
|
|
9
|
+
export declare function protectCodeBlocks(html: string): string;
|
|
10
|
+
/**
|
|
11
|
+
* Turn markdown source into HTML the stx pipeline can process.
|
|
12
|
+
*
|
|
13
|
+
* Frontmatter is returned rather than injected, so the caller decides how it
|
|
14
|
+
* merges with the rest of the render context.
|
|
15
|
+
*/
|
|
16
|
+
export declare function renderMarkdownView(source: string, options?: MarkdownViewOptions): Promise<MarkdownView>;
|
|
17
|
+
export declare interface MarkdownViewOptions {
|
|
18
|
+
renderer?: MarkdownRenderer
|
|
19
|
+
}
|
|
20
|
+
export declare interface MarkdownView {
|
|
21
|
+
html: string
|
|
22
|
+
frontmatter: Record<string, any>
|
|
23
|
+
}
|
|
24
|
+
/** Converts markdown source to HTML. */
|
|
25
|
+
export type MarkdownRenderer = (source: string) => string | Promise<string>;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { parseFrontmatter, parseMarkdown } from "./internal-markdown.js";
|
|
2
|
+
export function isMarkdownPath(filePath) {
|
|
3
|
+
return filePath.endsWith(".md") || filePath.endsWith(".markdown");
|
|
4
|
+
}
|
|
5
|
+
export function protectCodeBlocks(html) {
|
|
6
|
+
const protectedRanges = [];
|
|
7
|
+
collect(/<pre\b[^>]*>[\s\S]*?<\/pre>/gi);
|
|
8
|
+
const preRanges = [...protectedRanges];
|
|
9
|
+
collect(/<code\b[^>]*>[\s\S]*?<\/code>/gi, preRanges);
|
|
10
|
+
function collect(re, skipWithin) {
|
|
11
|
+
let m;
|
|
12
|
+
while ((m = re.exec(html)) !== null) {
|
|
13
|
+
const start = m.index, end = start + m[0].length;
|
|
14
|
+
if (skipWithin?.some((r) => start >= r.start && end <= r.end))
|
|
15
|
+
continue;
|
|
16
|
+
protectedRanges.push({ start, end });
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
if (protectedRanges.length === 0)
|
|
20
|
+
return html;
|
|
21
|
+
protectedRanges.sort((a, b) => a.start - b.start);
|
|
22
|
+
let out = "", cursor = 0;
|
|
23
|
+
for (const range of protectedRanges) {
|
|
24
|
+
if (range.start < cursor)
|
|
25
|
+
continue;
|
|
26
|
+
out += html.slice(cursor, range.start);
|
|
27
|
+
out += `@raw${html.slice(range.start, range.end)}@endraw`;
|
|
28
|
+
cursor = range.end;
|
|
29
|
+
}
|
|
30
|
+
out += html.slice(cursor);
|
|
31
|
+
return out;
|
|
32
|
+
}
|
|
33
|
+
export async function renderMarkdownView(source, options = {}) {
|
|
34
|
+
const { data, content } = parseFrontmatter(source), html = await (options.renderer ?? ((md) => parseMarkdown(md)))(content);
|
|
35
|
+
return {
|
|
36
|
+
html: protectCodeBlocks(html),
|
|
37
|
+
frontmatter: data ?? {}
|
|
38
|
+
};
|
|
39
|
+
}
|
|
@@ -4,6 +4,7 @@ import { serve } from "bun";
|
|
|
4
4
|
import { loadManifest } from "./manifest.js";
|
|
5
5
|
import { hydrateTemplateStream, hydrateFragment } from "./template-hydrator.js";
|
|
6
6
|
import { extractLayoutMetadata } from "./app-shell.js";
|
|
7
|
+
import { patternToRegex } from "stx-router";
|
|
7
8
|
const MIME_TYPES = {
|
|
8
9
|
".js": "application/javascript",
|
|
9
10
|
".mjs": "application/javascript",
|
|
@@ -55,11 +56,8 @@ export async function startProductionServer(options = {}) {
|
|
|
55
56
|
const exactRoutes = new Map, paramRoutes = [];
|
|
56
57
|
for (const route of manifest.routes)
|
|
57
58
|
if (route.hasParams) {
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
return "([^/]+)";
|
|
61
|
-
});
|
|
62
|
-
paramRoutes.push({ regex: new RegExp(`^${regexStr}$`), route, paramNames });
|
|
59
|
+
const { regex, params: paramNames } = patternToRegex(route.pattern);
|
|
60
|
+
paramRoutes.push({ regex, route, paramNames });
|
|
63
61
|
} else
|
|
64
62
|
exactRoutes.set(route.pattern, route);
|
|
65
63
|
const server = serve({
|
package/dist/render.d.ts
CHANGED
|
@@ -42,6 +42,7 @@ export declare function renderTemplateString(content: string, filePath: string,
|
|
|
42
42
|
// Types
|
|
43
43
|
// ============================================================================
|
|
44
44
|
export declare interface RenderOptions {
|
|
45
|
+
markdownRenderer?: (source: string) => string | Promise<string>
|
|
45
46
|
context?: Record<string, unknown>
|
|
46
47
|
options?: Partial<StxOptions>
|
|
47
48
|
processClientScripts?: boolean
|
package/dist/render.js
CHANGED
|
@@ -4,6 +4,7 @@ import { extractVariables } from "./variable-extractor.js";
|
|
|
4
4
|
import { injectRouterScript, processDirectives } from "./process.js";
|
|
5
5
|
import { extractBridgeData, processClientScript } from "./client-script.js";
|
|
6
6
|
import { findSfcTemplateBlock } from "./sfc-template.js";
|
|
7
|
+
import { isMarkdownPath, renderMarkdownView } from "./markdown-view.js";
|
|
7
8
|
function parseTemplate(content) {
|
|
8
9
|
let workingContent = content;
|
|
9
10
|
const templateBlock = findSfcTemplateBlock(content);
|
|
@@ -69,7 +70,17 @@ export async function renderTemplate(filePath, renderOptions = {}) {
|
|
|
69
70
|
const resolvedPath = resolve(filePath), file = Bun.file(resolvedPath);
|
|
70
71
|
if (!await file.exists())
|
|
71
72
|
throw Error(`Template file not found: ${resolvedPath}`);
|
|
72
|
-
|
|
73
|
+
let content = await file.text(), markdownFrontmatter = null;
|
|
74
|
+
if (isMarkdownPath(resolvedPath)) {
|
|
75
|
+
const view = await renderMarkdownView(content, { renderer: renderOptions.markdownRenderer });
|
|
76
|
+
content = view.html;
|
|
77
|
+
markdownFrontmatter = view.frontmatter;
|
|
78
|
+
}
|
|
79
|
+
if (markdownFrontmatter)
|
|
80
|
+
renderOptions = {
|
|
81
|
+
...renderOptions,
|
|
82
|
+
context: { ...markdownFrontmatter, ...renderOptions.context || {} }
|
|
83
|
+
};
|
|
73
84
|
if (renderOptions.layout) {
|
|
74
85
|
const layoutPath = resolve(renderOptions.layout), layoutFile = Bun.file(layoutPath);
|
|
75
86
|
if (!await layoutFile.exists())
|
package/dist/ssr.js
CHANGED
|
@@ -3,6 +3,7 @@ import path from "node:path";
|
|
|
3
3
|
import { errorLogger } from "./error-handling.js";
|
|
4
4
|
import { processDirectives } from "./process.js";
|
|
5
5
|
import { extractVariables } from "./utils.js";
|
|
6
|
+
import { patternToRegex } from "stx-router";
|
|
6
7
|
|
|
7
8
|
export class MemorySessionStore {
|
|
8
9
|
store = new Map;
|
|
@@ -180,10 +181,7 @@ export function createApp(config = {}) {
|
|
|
180
181
|
for (const route of routes) {
|
|
181
182
|
if (route.method !== method && route.method !== "*")
|
|
182
183
|
continue;
|
|
183
|
-
const
|
|
184
|
-
paramNames.push(name);
|
|
185
|
-
return "/([^/]+)";
|
|
186
|
-
}).replace(/\//g, "\\/"), regex = new RegExp(`^${regexPattern}$`), match = pathname.match(regex);
|
|
184
|
+
const { regex, params: paramNames } = patternToRegex(route.pattern), match = pathname.match(regex);
|
|
187
185
|
if (match) {
|
|
188
186
|
const params = {};
|
|
189
187
|
paramNames.forEach((name, i) => {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stacksjs/stx",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.150",
|
|
5
5
|
"description": "A performant UI Framework. Powered by Bun.",
|
|
6
6
|
"author": "Chris Breuer <chris@stacksjs.org>",
|
|
7
7
|
"license": "MIT",
|
|
@@ -117,12 +117,12 @@
|
|
|
117
117
|
"dependencies": {
|
|
118
118
|
"@cwcss/crosswind": "^0.2.14",
|
|
119
119
|
"@stacksjs/clapp": "^0.2.0",
|
|
120
|
-
"@stacksjs/desktop": "0.2.
|
|
121
|
-
"@stacksjs/sanitizer": "0.2.
|
|
120
|
+
"@stacksjs/desktop": "0.2.150",
|
|
121
|
+
"@stacksjs/sanitizer": "0.2.150",
|
|
122
122
|
"@stacksjs/ts-i18n": "^0.1.11",
|
|
123
|
-
"bun-plugin-stx": "0.2.
|
|
123
|
+
"bun-plugin-stx": "0.2.150",
|
|
124
124
|
"bunfig": "^0.15.17",
|
|
125
|
-
"stx-router": "0.2.
|
|
125
|
+
"stx-router": "0.2.150",
|
|
126
126
|
"ts-broadcasting": "^0.0.9",
|
|
127
127
|
"ts-images": "^0.1.9",
|
|
128
128
|
"ts-syntax-highlighter": "^0.2.1"
|