@reckona/mreact-router 0.0.211 → 0.0.212
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/link.d.ts.map +1 -1
- package/dist/link.js +12 -1
- package/dist/link.js.map +1 -1
- package/package.json +11 -11
- package/src/link.ts +15 -1
package/dist/link.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"link.d.ts","sourceRoot":"","sources":["../src/link.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0CAA0C,CAAC;AACzE,OAAO,KAAK,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"link.d.ts","sourceRoot":"","sources":["../src/link.ts"],"names":[],"mappings":"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"}
|
package/dist/link.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { escapeHtmlAttribute, escapeHtmlText } from "@reckona/mreact-shared/html-escape";
|
|
2
|
+
import { bindProp } from "@reckona/mreact-reactive-dom";
|
|
2
3
|
import { safeUrlAttributeValue } from "@reckona/mreact-shared/url-safety";
|
|
3
4
|
const TRUSTED_LINK_HTML = Symbol.for("modular.react.router.trusted_link_html");
|
|
4
5
|
const VALID_LINK_ATTRIBUTE_NAME = /^[A-Za-z_][\w.\-:]*$/;
|
|
@@ -60,10 +61,20 @@ function renderLink(props) {
|
|
|
60
61
|
...linkProps({ href, prefetch, reload, scroll, transition }),
|
|
61
62
|
};
|
|
62
63
|
if (typeof document !== "undefined" && typeof document.createElement === "function") {
|
|
63
|
-
|
|
64
|
+
const anchor = createAnchorElement(propsWithLinkAttrs);
|
|
65
|
+
// Destructuring above reads a compiler-emitted reactive `href` getter once.
|
|
66
|
+
// Re-read it through a prop binding so the same anchor follows later updates
|
|
67
|
+
// instead of freezing the URL captured during the first render.
|
|
68
|
+
if (hasReactiveLinkHref(props)) {
|
|
69
|
+
bindProp(anchor, "href", () => props.href);
|
|
70
|
+
}
|
|
71
|
+
return anchor;
|
|
64
72
|
}
|
|
65
73
|
return renderAnchorString(propsWithLinkAttrs);
|
|
66
74
|
}
|
|
75
|
+
function hasReactiveLinkHref(props) {
|
|
76
|
+
return Object.getOwnPropertyDescriptor(props, "href")?.get !== undefined;
|
|
77
|
+
}
|
|
67
78
|
function renderLinkString(props) {
|
|
68
79
|
const { href, prefetch, reload, scroll, transition, ...rest } = props;
|
|
69
80
|
const propsWithLinkAttrs = {
|
package/dist/link.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"link.js","sourceRoot":"","sources":["../src/link.ts"],"names":[],"mappings":"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","sourcesContent":["import { escapeHtmlAttribute, escapeHtmlText } from \"@reckona/mreact-shared/html-escape\";\nimport type { HtmlSink } from \"@reckona/mreact-shared/compiler-contract\";\nimport type { ReactCompatElement, ReactCompatNode } from \"@reckona/mreact-compat\";\nimport { safeUrlAttributeValue } from \"@reckona/mreact-shared/url-safety\";\nimport type { AppRouteLinkHref } from \"./typed-routes.js\";\n/** Re-exports typed route href helper types used by Link. */\nexport type {\n AppRouteLinkHref,\n AppRouteLinkHrefSuffix,\n AppRouteLinkPathname,\n AppRouteLinkSegment,\n AppRouteLinkSegments,\n} from \"./typed-routes.js\";\n\nconst TRUSTED_LINK_HTML = Symbol.for(\"modular.react.router.trusted_link_html\");\nconst VALID_LINK_ATTRIBUTE_NAME = /^[A-Za-z_][\\w.\\-:]*$/;\n\n/**\n * Selects when the app router should prefetch a linked route.\n */\nexport type LinkPrefetch = \"intent\" | \"viewport\" | \"none\" | false;\n/**\n * Controls scroll restoration behavior after client navigation.\n */\nexport type LinkScroll = \"top\" | \"preserve\";\n/**\n * Controls whether client navigation participates in view transitions.\n */\nexport type LinkTransition = \"auto\" | \"none\" | false;\n/**\n * Wraps pre-escaped HTML that can be used as trusted link children.\n */\nexport type TrustedLinkHtml = { readonly [TRUSTED_LINK_HTML]: string };\n/**\n * Represents children accepted by the app-router Link renderer.\n */\nexport type LinkChild = ReactCompatNode | Node | TrustedLinkHtml | readonly LinkChild[];\n/**\n * Allows applications to augment statically registered app route paths through `@reckona/mreact-router/link`.\n */\nexport interface AppRouteDeclarations {}\n/**\n * Extracts registered route paths from `AppRouteDeclarations`.\n */\nexport type RegisteredAppRoutePath = AppRouteDeclarations extends { readonly path: infer Path }\n ? Extract<Path, `/${string}`>\n : never;\n/**\n * Resolves the accepted `href` type for app-router links.\n */\nexport type LinkHref = [RegisteredAppRoutePath] extends [never]\n ? string\n : AppRouteLinkHref<RegisteredAppRoutePath>;\n\n/**\n * Configures client navigation behavior for a router link.\n */\nexport interface LinkOptions<Href extends string = LinkHref> {\n href: Href;\n prefetch?: LinkPrefetch | undefined;\n reload?: boolean | undefined;\n scroll?: LinkScroll | undefined;\n transition?: LinkTransition | undefined;\n}\n\n/**\n * Combines router link options with anchor attributes and children.\n */\nexport interface LinkProps<Href extends string = LinkHref> extends LinkOptions<Href> {\n children?: LinkChild;\n [attribute: string]: unknown;\n}\n\n/** Represents attributes that can be serialized when Link writes to an HtmlSink. */\nexport type LinkSerializableAttribute = boolean | number | string | null | undefined;\n\n/** Represents child values that an HtmlSink Link can serialize without a browser DOM. */\nexport type LinkSinkChild =\n | boolean\n | number\n | string\n | null\n | undefined\n | TrustedLinkHtml\n | readonly LinkSinkChild[];\n\n/** Configures an HtmlSink Link without browser-only event handlers or refs. */\nexport interface LinkSinkProps extends LinkOptions<string> {\n children?: LinkSinkChild;\n class?: string | undefined;\n className?: string | undefined;\n download?: string | boolean | undefined;\n id?: string | undefined;\n name?: string | undefined;\n rel?: string | undefined;\n role?: string | undefined;\n style?: Readonly<Record<string, boolean | number | string | null | undefined>> | undefined;\n tabIndex?: number | undefined;\n target?: string | undefined;\n title?: string | undefined;\n [ariaAttribute: `aria-${string}`]: LinkSerializableAttribute;\n [dataAttribute: `data-${string}`]: LinkSerializableAttribute;\n}\n\n/**\n * Converts router link options into anchor attributes consumed by the client navigation runtime.\n *\n * Use this when rendering a custom anchor component that should still opt into mreact prefetch, scroll, reload, or transition behavior.\n */\nexport function linkProps(options: LinkOptions<string>): Record<string, string> {\n return {\n href: options.href,\n ...(options.prefetch === undefined || options.prefetch === \"intent\"\n ? {}\n : { \"data-mreact-prefetch\": options.prefetch === false ? \"none\" : options.prefetch }),\n ...(options.reload === true ? { \"data-mreact-reload\": \"true\" } : {}),\n ...(options.scroll === undefined || options.scroll === \"top\"\n ? {}\n : { \"data-mreact-scroll\": options.scroll }),\n ...(options.transition === undefined ||\n options.transition === false ||\n options.transition === \"none\"\n ? {}\n : { \"data-mreact-transition\": options.transition }),\n };\n}\n\n/**\n * Produces a compile-time error shape when a typed Link receives an unresolved route pattern.\n */\nexport type ConcreteLinkHrefGuard<Href extends string> = [RegisteredAppRoutePath] extends [never]\n ? unknown\n : Href extends Extract<RegisteredAppRoutePath, `${string}:${string}`>\n ? { readonly __mreactRoutePatternHrefError__: never }\n : unknown;\n\n/**\n * Renders an app-router anchor with typed `href` support and navigation runtime attributes.\n *\n * In JSX it returns an anchor element compatible with the mreact runtime; during server streaming it can also write directly to an `HtmlSink`. Unsafe URL attribute values are dropped during rendering.\n */\nexport function Link<const Href extends LinkHref>(\n props: LinkProps<Href> & ConcreteLinkHrefGuard<Href>,\n): ReactCompatElement;\nexport function Link(sink: HtmlSink, props: LinkSinkProps): void;\nexport function Link(\n sinkOrProps: HtmlSink | LinkProps<string>,\n maybeProps?: LinkProps<string> | LinkSinkProps,\n): ReactCompatElement | string | HTMLAnchorElement | void {\n if (maybeProps !== undefined) {\n reportUnsupportedSinkProps(maybeProps);\n (sinkOrProps as HtmlSink).append(renderLinkString(maybeProps as LinkSinkProps));\n return;\n }\n\n return renderLink(sinkOrProps as LinkProps);\n}\n\nfunction reportUnsupportedSinkProps(props: LinkProps<string> | LinkSinkProps): void {\n const nodeEnv = (\n globalThis as typeof globalThis & {\n process?: { env?: { NODE_ENV?: string | undefined } | undefined } | undefined;\n }\n ).process?.env?.NODE_ENV;\n\n if (nodeEnv === \"production\") {\n return;\n }\n\n const unsupported = Object.entries(props)\n .filter(\n ([name, value]) =>\n name === \"ref\" ||\n typeof value === \"function\" ||\n typeof value === \"symbol\" ||\n isLinkEventAttributeName(name) ||\n (name === \"children\" && !isSerializableSinkChild(value)) ||\n (name !== \"children\" && name !== \"style\" && typeof value === \"object\" && value !== null) ||\n (name !== \"children\" && !isSafeLinkAttributeName(attributeName(name))),\n )\n .map(([name]) => name);\n\n if (unsupported.length > 0) {\n console.warn(\n `[MR_LINK_SINK_UNSUPPORTED_PROP] HtmlSink Link cannot serialize browser-only props: ${unsupported.join(\", \")}. Render Link through JSX for event handlers and refs.`,\n );\n }\n}\n\n(Link as typeof Link & { trustedHtml(html: string): TrustedLinkHtml }).trustedHtml = (\n html: string,\n): TrustedLinkHtml => ({\n [TRUSTED_LINK_HTML]: html,\n});\n\nfunction renderLink(props: LinkProps<string>): string | HTMLAnchorElement {\n const { href, prefetch, reload, scroll, transition, ...rest } = props;\n const propsWithLinkAttrs = {\n ...rest,\n ...linkProps({ href, prefetch, reload, scroll, transition }),\n };\n\n if (typeof document !== \"undefined\" && typeof document.createElement === \"function\") {\n return createAnchorElement(propsWithLinkAttrs);\n }\n\n return renderAnchorString(propsWithLinkAttrs);\n}\n\nfunction renderLinkString(props: LinkSinkProps): string {\n const { href, prefetch, reload, scroll, transition, ...rest } = props;\n const propsWithLinkAttrs = {\n ...rest,\n ...linkProps({ href, prefetch, reload, scroll, transition }),\n };\n\n return `<a${renderAnchorAttributes(propsWithLinkAttrs)}>${renderSinkChildren(props.children)}</a>`;\n}\n\nfunction createAnchorElement(props: Record<string, unknown>): HTMLAnchorElement {\n const anchor = document.createElement(\"a\");\n\n for (const [name, value] of Object.entries(props)) {\n if (name === \"children\") {\n appendLinkChild(anchor, value as LinkChild);\n continue;\n }\n\n if (name === \"ref\") {\n if (typeof value === \"function\") {\n (value as (element: HTMLAnchorElement) => void)(anchor);\n } else if (typeof value === \"object\" && value !== null && \"current\" in value) {\n (value as { current: HTMLAnchorElement | null }).current = anchor;\n }\n continue;\n }\n\n if (/^on[A-Z]/.test(name) && typeof value === \"function\") {\n const capture = name.endsWith(\"Capture\");\n const eventName = name.slice(2, capture ? -\"Capture\".length : undefined).toLowerCase();\n anchor.addEventListener(eventName, value as EventListener, capture);\n continue;\n }\n\n if (isLinkEventAttributeName(name)) {\n reportRejectedBrowserEventProp(name);\n continue;\n }\n\n if (name === \"style\" && typeof value === \"object\" && value !== null) {\n for (const [property, styleValue] of Object.entries(value as Record<string, unknown>)) {\n const cssProperty = linkStylePropertyName(property);\n const cssValue = linkStyleValue(styleValue);\n if (cssProperty !== undefined && cssValue !== undefined) {\n anchor.style.setProperty(cssProperty, cssValue);\n }\n }\n continue;\n }\n\n if (!shouldSetAttribute(name, value)) {\n continue;\n }\n\n const attrName = attributeName(name);\n if (!isSafeLinkAttributeName(attrName)) {\n continue;\n }\n const safeValue = safeUrlAttributeValue(attrName, String(value));\n\n if (safeValue === undefined) {\n continue;\n }\n\n anchor.setAttribute(attrName, value === true ? \"\" : safeValue);\n }\n\n return anchor;\n}\n\nfunction appendLinkChild(parent: Node, child: LinkChild): void {\n if (child === null || child === undefined || typeof child === \"boolean\") {\n return;\n }\n\n if (Array.isArray(child)) {\n for (const item of child) {\n appendLinkChild(parent, item);\n }\n return;\n }\n\n if (child instanceof Node) {\n parent.appendChild(child);\n return;\n }\n\n parent.appendChild(document.createTextNode(String(child)));\n}\n\nfunction renderAnchorString(props: Record<string, unknown>): string {\n return `<a${renderAnchorAttributes(props)}>${renderChildren(props.children as LinkChild)}</a>`;\n}\n\nfunction renderAnchorAttributes(props: Record<string, unknown>): string {\n const attrs: string[] = [];\n\n for (const [name, value] of Object.entries(props)) {\n if (name === \"children\" || isLinkEventAttributeName(name) || !shouldSetAttribute(name, value)) {\n continue;\n }\n\n if (name !== \"style\" && typeof value === \"object\" && value !== null) {\n continue;\n }\n\n const attrName = attributeName(name);\n if (!isSafeLinkAttributeName(attrName)) {\n continue;\n }\n if (name === \"style\" && typeof value === \"object\" && value !== null) {\n const style = Object.entries(value as Record<string, unknown>)\n .flatMap(([property, styleValue]) => {\n const cssProperty = linkStylePropertyName(property);\n const cssValue = linkStyleValue(styleValue);\n return cssProperty === undefined || cssValue === undefined\n ? []\n : [`${cssProperty}:${cssValue}`];\n })\n .join(\";\");\n if (style !== \"\") {\n attrs.push(`${escapeHtmlAttribute(attrName)}=\"${escapeHtmlAttribute(style)}\"`);\n }\n continue;\n }\n const attrValue = String(value);\n const safeValue = safeUrlAttributeValue(attrName, attrValue);\n\n if (safeValue === undefined) {\n continue;\n }\n\n attrs.push(`${escapeHtmlAttribute(attrName)}=\"${escapeHtmlAttribute(safeValue)}\"`);\n }\n\n return attrs.length === 0 ? \"\" : ` ${attrs.join(\" \")}`;\n}\n\nfunction shouldSetAttribute(name: string, value: unknown): boolean {\n return (\n name !== \"key\" &&\n name !== \"ref\" &&\n value !== null &&\n value !== undefined &&\n value !== false &&\n typeof value !== \"function\" &&\n typeof value !== \"symbol\"\n );\n}\n\nfunction attributeName(name: string): string {\n return name === \"className\" ? \"class\" : name;\n}\n\nfunction isSafeLinkAttributeName(name: string): boolean {\n return VALID_LINK_ATTRIBUTE_NAME.test(name);\n}\n\nfunction isLinkEventAttributeName(name: string): boolean {\n return /^on/i.test(name);\n}\n\nfunction reportRejectedBrowserEventProp(name: string): void {\n const nodeEnv = (\n globalThis as typeof globalThis & {\n process?: { env?: { NODE_ENV?: string | undefined } | undefined } | undefined;\n }\n ).process?.env?.NODE_ENV;\n\n if (nodeEnv !== \"production\") {\n console.warn(\n `[MR_LINK_UNSAFE_EVENT_PROP] Link rejected event-like prop ${JSON.stringify(name)}. Pass a supported camel-cased function handler such as onClick instead.`,\n );\n }\n}\n\nfunction linkStylePropertyName(property: string): string | undefined {\n const cssProperty = property.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`);\n return /^(?:--[a-zA-Z0-9_-]+|[a-zA-Z][a-zA-Z0-9-]*)$/.test(cssProperty) ? cssProperty : undefined;\n}\n\nfunction linkStyleValue(value: unknown): string | undefined {\n if (value === null || value === undefined || value === false) {\n return undefined;\n }\n\n const cssValue = String(value);\n return /[;{}]/.test(cssValue) ? undefined : cssValue;\n}\n\nfunction renderChildren(child: LinkChild): string {\n if (child === null || child === undefined || typeof child === \"boolean\") {\n return \"\";\n }\n\n if (Array.isArray(child)) {\n return child.map(renderChildren).join(\"\");\n }\n\n if (isTrustedLinkHtml(child)) {\n return child[TRUSTED_LINK_HTML];\n }\n\n return escapeHtmlText(child);\n}\n\nfunction renderSinkChildren(child: LinkSinkChild): string {\n if (child === null || child === undefined || typeof child === \"boolean\") {\n return \"\";\n }\n\n if (Array.isArray(child)) {\n return child.map(renderSinkChildren).join(\"\");\n }\n\n if (isTrustedLinkHtml(child)) {\n return child[TRUSTED_LINK_HTML];\n }\n\n if (typeof child === \"object\") {\n return \"\";\n }\n\n return escapeHtmlText(String(child));\n}\n\nfunction isSerializableSinkChild(value: unknown): value is LinkSinkChild {\n if (\n value === null ||\n value === undefined ||\n typeof value === \"boolean\" ||\n typeof value === \"number\" ||\n typeof value === \"string\" ||\n isTrustedLinkHtml(value)\n ) {\n return true;\n }\n\n return Array.isArray(value) && value.every(isSerializableSinkChild);\n}\n\nfunction isTrustedLinkHtml(value: unknown): value is TrustedLinkHtml {\n return (\n typeof value === \"object\" &&\n value !== null &&\n TRUSTED_LINK_HTML in value &&\n typeof (value as TrustedLinkHtml)[TRUSTED_LINK_HTML] === \"string\"\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"link.js","sourceRoot":"","sources":["../src/link.ts"],"names":[],"mappings":"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","sourcesContent":["import { escapeHtmlAttribute, escapeHtmlText } from \"@reckona/mreact-shared/html-escape\";\nimport type { HtmlSink } from \"@reckona/mreact-shared/compiler-contract\";\nimport type { ReactCompatElement, ReactCompatNode } from \"@reckona/mreact-compat\";\nimport { bindProp } from \"@reckona/mreact-reactive-dom\";\nimport { safeUrlAttributeValue } from \"@reckona/mreact-shared/url-safety\";\nimport type { AppRouteLinkHref } from \"./typed-routes.js\";\n/** Re-exports typed route href helper types used by Link. */\nexport type {\n AppRouteLinkHref,\n AppRouteLinkHrefSuffix,\n AppRouteLinkPathname,\n AppRouteLinkSegment,\n AppRouteLinkSegments,\n} from \"./typed-routes.js\";\n\nconst TRUSTED_LINK_HTML = Symbol.for(\"modular.react.router.trusted_link_html\");\nconst VALID_LINK_ATTRIBUTE_NAME = /^[A-Za-z_][\\w.\\-:]*$/;\n\n/**\n * Selects when the app router should prefetch a linked route.\n */\nexport type LinkPrefetch = \"intent\" | \"viewport\" | \"none\" | false;\n/**\n * Controls scroll restoration behavior after client navigation.\n */\nexport type LinkScroll = \"top\" | \"preserve\";\n/**\n * Controls whether client navigation participates in view transitions.\n */\nexport type LinkTransition = \"auto\" | \"none\" | false;\n/**\n * Wraps pre-escaped HTML that can be used as trusted link children.\n */\nexport type TrustedLinkHtml = { readonly [TRUSTED_LINK_HTML]: string };\n/**\n * Represents children accepted by the app-router Link renderer.\n */\nexport type LinkChild = ReactCompatNode | Node | TrustedLinkHtml | readonly LinkChild[];\n/**\n * Allows applications to augment statically registered app route paths through `@reckona/mreact-router/link`.\n */\nexport interface AppRouteDeclarations {}\n/**\n * Extracts registered route paths from `AppRouteDeclarations`.\n */\nexport type RegisteredAppRoutePath = AppRouteDeclarations extends { readonly path: infer Path }\n ? Extract<Path, `/${string}`>\n : never;\n/**\n * Resolves the accepted `href` type for app-router links.\n */\nexport type LinkHref = [RegisteredAppRoutePath] extends [never]\n ? string\n : AppRouteLinkHref<RegisteredAppRoutePath>;\n\n/**\n * Configures client navigation behavior for a router link.\n */\nexport interface LinkOptions<Href extends string = LinkHref> {\n href: Href;\n prefetch?: LinkPrefetch | undefined;\n reload?: boolean | undefined;\n scroll?: LinkScroll | undefined;\n transition?: LinkTransition | undefined;\n}\n\n/**\n * Combines router link options with anchor attributes and children.\n */\nexport interface LinkProps<Href extends string = LinkHref> extends LinkOptions<Href> {\n children?: LinkChild;\n [attribute: string]: unknown;\n}\n\n/** Represents attributes that can be serialized when Link writes to an HtmlSink. */\nexport type LinkSerializableAttribute = boolean | number | string | null | undefined;\n\n/** Represents child values that an HtmlSink Link can serialize without a browser DOM. */\nexport type LinkSinkChild =\n | boolean\n | number\n | string\n | null\n | undefined\n | TrustedLinkHtml\n | readonly LinkSinkChild[];\n\n/** Configures an HtmlSink Link without browser-only event handlers or refs. */\nexport interface LinkSinkProps extends LinkOptions<string> {\n children?: LinkSinkChild;\n class?: string | undefined;\n className?: string | undefined;\n download?: string | boolean | undefined;\n id?: string | undefined;\n name?: string | undefined;\n rel?: string | undefined;\n role?: string | undefined;\n style?: Readonly<Record<string, boolean | number | string | null | undefined>> | undefined;\n tabIndex?: number | undefined;\n target?: string | undefined;\n title?: string | undefined;\n [ariaAttribute: `aria-${string}`]: LinkSerializableAttribute;\n [dataAttribute: `data-${string}`]: LinkSerializableAttribute;\n}\n\n/**\n * Converts router link options into anchor attributes consumed by the client navigation runtime.\n *\n * Use this when rendering a custom anchor component that should still opt into mreact prefetch, scroll, reload, or transition behavior.\n */\nexport function linkProps(options: LinkOptions<string>): Record<string, string> {\n return {\n href: options.href,\n ...(options.prefetch === undefined || options.prefetch === \"intent\"\n ? {}\n : { \"data-mreact-prefetch\": options.prefetch === false ? \"none\" : options.prefetch }),\n ...(options.reload === true ? { \"data-mreact-reload\": \"true\" } : {}),\n ...(options.scroll === undefined || options.scroll === \"top\"\n ? {}\n : { \"data-mreact-scroll\": options.scroll }),\n ...(options.transition === undefined ||\n options.transition === false ||\n options.transition === \"none\"\n ? {}\n : { \"data-mreact-transition\": options.transition }),\n };\n}\n\n/**\n * Produces a compile-time error shape when a typed Link receives an unresolved route pattern.\n */\nexport type ConcreteLinkHrefGuard<Href extends string> = [RegisteredAppRoutePath] extends [never]\n ? unknown\n : Href extends Extract<RegisteredAppRoutePath, `${string}:${string}`>\n ? { readonly __mreactRoutePatternHrefError__: never }\n : unknown;\n\n/**\n * Renders an app-router anchor with typed `href` support and navigation runtime attributes.\n *\n * In JSX it returns an anchor element compatible with the mreact runtime; during server streaming it can also write directly to an `HtmlSink`. Unsafe URL attribute values are dropped during rendering.\n */\nexport function Link<const Href extends LinkHref>(\n props: LinkProps<Href> & ConcreteLinkHrefGuard<Href>,\n): ReactCompatElement;\nexport function Link(sink: HtmlSink, props: LinkSinkProps): void;\nexport function Link(\n sinkOrProps: HtmlSink | LinkProps<string>,\n maybeProps?: LinkProps<string> | LinkSinkProps,\n): ReactCompatElement | string | HTMLAnchorElement | void {\n if (maybeProps !== undefined) {\n reportUnsupportedSinkProps(maybeProps);\n (sinkOrProps as HtmlSink).append(renderLinkString(maybeProps as LinkSinkProps));\n return;\n }\n\n return renderLink(sinkOrProps as LinkProps);\n}\n\nfunction reportUnsupportedSinkProps(props: LinkProps<string> | LinkSinkProps): void {\n const nodeEnv = (\n globalThis as typeof globalThis & {\n process?: { env?: { NODE_ENV?: string | undefined } | undefined } | undefined;\n }\n ).process?.env?.NODE_ENV;\n\n if (nodeEnv === \"production\") {\n return;\n }\n\n const unsupported = Object.entries(props)\n .filter(\n ([name, value]) =>\n name === \"ref\" ||\n typeof value === \"function\" ||\n typeof value === \"symbol\" ||\n isLinkEventAttributeName(name) ||\n (name === \"children\" && !isSerializableSinkChild(value)) ||\n (name !== \"children\" && name !== \"style\" && typeof value === \"object\" && value !== null) ||\n (name !== \"children\" && !isSafeLinkAttributeName(attributeName(name))),\n )\n .map(([name]) => name);\n\n if (unsupported.length > 0) {\n console.warn(\n `[MR_LINK_SINK_UNSUPPORTED_PROP] HtmlSink Link cannot serialize browser-only props: ${unsupported.join(\", \")}. Render Link through JSX for event handlers and refs.`,\n );\n }\n}\n\n(Link as typeof Link & { trustedHtml(html: string): TrustedLinkHtml }).trustedHtml = (\n html: string,\n): TrustedLinkHtml => ({\n [TRUSTED_LINK_HTML]: html,\n});\n\nfunction renderLink(props: LinkProps<string>): string | HTMLAnchorElement {\n const { href, prefetch, reload, scroll, transition, ...rest } = props;\n const propsWithLinkAttrs = {\n ...rest,\n ...linkProps({ href, prefetch, reload, scroll, transition }),\n };\n\n if (typeof document !== \"undefined\" && typeof document.createElement === \"function\") {\n const anchor = createAnchorElement(propsWithLinkAttrs);\n\n // Destructuring above reads a compiler-emitted reactive `href` getter once.\n // Re-read it through a prop binding so the same anchor follows later updates\n // instead of freezing the URL captured during the first render.\n if (hasReactiveLinkHref(props)) {\n bindProp(anchor, \"href\", () => props.href);\n }\n\n return anchor;\n }\n\n return renderAnchorString(propsWithLinkAttrs);\n}\n\nfunction hasReactiveLinkHref(props: LinkProps<string>): boolean {\n return Object.getOwnPropertyDescriptor(props, \"href\")?.get !== undefined;\n}\n\nfunction renderLinkString(props: LinkSinkProps): string {\n const { href, prefetch, reload, scroll, transition, ...rest } = props;\n const propsWithLinkAttrs = {\n ...rest,\n ...linkProps({ href, prefetch, reload, scroll, transition }),\n };\n\n return `<a${renderAnchorAttributes(propsWithLinkAttrs)}>${renderSinkChildren(props.children)}</a>`;\n}\n\nfunction createAnchorElement(props: Record<string, unknown>): HTMLAnchorElement {\n const anchor = document.createElement(\"a\");\n\n for (const [name, value] of Object.entries(props)) {\n if (name === \"children\") {\n appendLinkChild(anchor, value as LinkChild);\n continue;\n }\n\n if (name === \"ref\") {\n if (typeof value === \"function\") {\n (value as (element: HTMLAnchorElement) => void)(anchor);\n } else if (typeof value === \"object\" && value !== null && \"current\" in value) {\n (value as { current: HTMLAnchorElement | null }).current = anchor;\n }\n continue;\n }\n\n if (/^on[A-Z]/.test(name) && typeof value === \"function\") {\n const capture = name.endsWith(\"Capture\");\n const eventName = name.slice(2, capture ? -\"Capture\".length : undefined).toLowerCase();\n anchor.addEventListener(eventName, value as EventListener, capture);\n continue;\n }\n\n if (isLinkEventAttributeName(name)) {\n reportRejectedBrowserEventProp(name);\n continue;\n }\n\n if (name === \"style\" && typeof value === \"object\" && value !== null) {\n for (const [property, styleValue] of Object.entries(value as Record<string, unknown>)) {\n const cssProperty = linkStylePropertyName(property);\n const cssValue = linkStyleValue(styleValue);\n if (cssProperty !== undefined && cssValue !== undefined) {\n anchor.style.setProperty(cssProperty, cssValue);\n }\n }\n continue;\n }\n\n if (!shouldSetAttribute(name, value)) {\n continue;\n }\n\n const attrName = attributeName(name);\n if (!isSafeLinkAttributeName(attrName)) {\n continue;\n }\n const safeValue = safeUrlAttributeValue(attrName, String(value));\n\n if (safeValue === undefined) {\n continue;\n }\n\n anchor.setAttribute(attrName, value === true ? \"\" : safeValue);\n }\n\n return anchor;\n}\n\nfunction appendLinkChild(parent: Node, child: LinkChild): void {\n if (child === null || child === undefined || typeof child === \"boolean\") {\n return;\n }\n\n if (Array.isArray(child)) {\n for (const item of child) {\n appendLinkChild(parent, item);\n }\n return;\n }\n\n if (child instanceof Node) {\n parent.appendChild(child);\n return;\n }\n\n parent.appendChild(document.createTextNode(String(child)));\n}\n\nfunction renderAnchorString(props: Record<string, unknown>): string {\n return `<a${renderAnchorAttributes(props)}>${renderChildren(props.children as LinkChild)}</a>`;\n}\n\nfunction renderAnchorAttributes(props: Record<string, unknown>): string {\n const attrs: string[] = [];\n\n for (const [name, value] of Object.entries(props)) {\n if (name === \"children\" || isLinkEventAttributeName(name) || !shouldSetAttribute(name, value)) {\n continue;\n }\n\n if (name !== \"style\" && typeof value === \"object\" && value !== null) {\n continue;\n }\n\n const attrName = attributeName(name);\n if (!isSafeLinkAttributeName(attrName)) {\n continue;\n }\n if (name === \"style\" && typeof value === \"object\" && value !== null) {\n const style = Object.entries(value as Record<string, unknown>)\n .flatMap(([property, styleValue]) => {\n const cssProperty = linkStylePropertyName(property);\n const cssValue = linkStyleValue(styleValue);\n return cssProperty === undefined || cssValue === undefined\n ? []\n : [`${cssProperty}:${cssValue}`];\n })\n .join(\";\");\n if (style !== \"\") {\n attrs.push(`${escapeHtmlAttribute(attrName)}=\"${escapeHtmlAttribute(style)}\"`);\n }\n continue;\n }\n const attrValue = String(value);\n const safeValue = safeUrlAttributeValue(attrName, attrValue);\n\n if (safeValue === undefined) {\n continue;\n }\n\n attrs.push(`${escapeHtmlAttribute(attrName)}=\"${escapeHtmlAttribute(safeValue)}\"`);\n }\n\n return attrs.length === 0 ? \"\" : ` ${attrs.join(\" \")}`;\n}\n\nfunction shouldSetAttribute(name: string, value: unknown): boolean {\n return (\n name !== \"key\" &&\n name !== \"ref\" &&\n value !== null &&\n value !== undefined &&\n value !== false &&\n typeof value !== \"function\" &&\n typeof value !== \"symbol\"\n );\n}\n\nfunction attributeName(name: string): string {\n return name === \"className\" ? \"class\" : name;\n}\n\nfunction isSafeLinkAttributeName(name: string): boolean {\n return VALID_LINK_ATTRIBUTE_NAME.test(name);\n}\n\nfunction isLinkEventAttributeName(name: string): boolean {\n return /^on/i.test(name);\n}\n\nfunction reportRejectedBrowserEventProp(name: string): void {\n const nodeEnv = (\n globalThis as typeof globalThis & {\n process?: { env?: { NODE_ENV?: string | undefined } | undefined } | undefined;\n }\n ).process?.env?.NODE_ENV;\n\n if (nodeEnv !== \"production\") {\n console.warn(\n `[MR_LINK_UNSAFE_EVENT_PROP] Link rejected event-like prop ${JSON.stringify(name)}. Pass a supported camel-cased function handler such as onClick instead.`,\n );\n }\n}\n\nfunction linkStylePropertyName(property: string): string | undefined {\n const cssProperty = property.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`);\n return /^(?:--[a-zA-Z0-9_-]+|[a-zA-Z][a-zA-Z0-9-]*)$/.test(cssProperty) ? cssProperty : undefined;\n}\n\nfunction linkStyleValue(value: unknown): string | undefined {\n if (value === null || value === undefined || value === false) {\n return undefined;\n }\n\n const cssValue = String(value);\n return /[;{}]/.test(cssValue) ? undefined : cssValue;\n}\n\nfunction renderChildren(child: LinkChild): string {\n if (child === null || child === undefined || typeof child === \"boolean\") {\n return \"\";\n }\n\n if (Array.isArray(child)) {\n return child.map(renderChildren).join(\"\");\n }\n\n if (isTrustedLinkHtml(child)) {\n return child[TRUSTED_LINK_HTML];\n }\n\n return escapeHtmlText(child);\n}\n\nfunction renderSinkChildren(child: LinkSinkChild): string {\n if (child === null || child === undefined || typeof child === \"boolean\") {\n return \"\";\n }\n\n if (Array.isArray(child)) {\n return child.map(renderSinkChildren).join(\"\");\n }\n\n if (isTrustedLinkHtml(child)) {\n return child[TRUSTED_LINK_HTML];\n }\n\n if (typeof child === \"object\") {\n return \"\";\n }\n\n return escapeHtmlText(String(child));\n}\n\nfunction isSerializableSinkChild(value: unknown): value is LinkSinkChild {\n if (\n value === null ||\n value === undefined ||\n typeof value === \"boolean\" ||\n typeof value === \"number\" ||\n typeof value === \"string\" ||\n isTrustedLinkHtml(value)\n ) {\n return true;\n }\n\n return Array.isArray(value) && value.every(isSerializableSinkChild);\n}\n\nfunction isTrustedLinkHtml(value: unknown): value is TrustedLinkHtml {\n return (\n typeof value === \"object\" &&\n value !== null &&\n TRUSTED_LINK_HTML in value &&\n typeof (value as TrustedLinkHtml)[TRUSTED_LINK_HTML] === \"string\"\n );\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reckona/mreact-router",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.212",
|
|
4
4
|
"description": "File-system app router, SSR, actions, and deployment adapters for mreact.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"jsx",
|
|
@@ -111,20 +111,20 @@
|
|
|
111
111
|
"dependencies": {
|
|
112
112
|
"@typescript/typescript6": "^6.0.2",
|
|
113
113
|
"esbuild": ">=0.28.1 <0.29",
|
|
114
|
-
"@reckona/mreact": "0.0.
|
|
115
|
-
"@reckona/mreact-
|
|
116
|
-
"@reckona/mreact-
|
|
117
|
-
"@reckona/mreact-
|
|
118
|
-
"@reckona/mreact-
|
|
119
|
-
"@reckona/mreact-
|
|
120
|
-
"@reckona/mreact-
|
|
121
|
-
"@reckona/mreact-
|
|
122
|
-
"@reckona/mreact-
|
|
114
|
+
"@reckona/mreact": "0.0.212",
|
|
115
|
+
"@reckona/mreact-compiler": "0.0.212",
|
|
116
|
+
"@reckona/mreact-compat": "0.0.212",
|
|
117
|
+
"@reckona/mreact-query": "0.0.212",
|
|
118
|
+
"@reckona/mreact-reactive-core": "0.0.212",
|
|
119
|
+
"@reckona/mreact-devtools": "0.0.212",
|
|
120
|
+
"@reckona/mreact-reactive-dom": "0.0.212",
|
|
121
|
+
"@reckona/mreact-server": "0.0.212",
|
|
122
|
+
"@reckona/mreact-shared": "0.0.212"
|
|
123
123
|
},
|
|
124
124
|
"peerDependencies": {
|
|
125
125
|
"vite": ">=8.1.4 <9"
|
|
126
126
|
},
|
|
127
127
|
"optionalDependencies": {
|
|
128
|
-
"@reckona/mreact-router-native": "0.0.
|
|
128
|
+
"@reckona/mreact-router-native": "0.0.212"
|
|
129
129
|
}
|
|
130
130
|
}
|
package/src/link.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { escapeHtmlAttribute, escapeHtmlText } from "@reckona/mreact-shared/html-escape";
|
|
2
2
|
import type { HtmlSink } from "@reckona/mreact-shared/compiler-contract";
|
|
3
3
|
import type { ReactCompatElement, ReactCompatNode } from "@reckona/mreact-compat";
|
|
4
|
+
import { bindProp } from "@reckona/mreact-reactive-dom";
|
|
4
5
|
import { safeUrlAttributeValue } from "@reckona/mreact-shared/url-safety";
|
|
5
6
|
import type { AppRouteLinkHref } from "./typed-routes.js";
|
|
6
7
|
/** Re-exports typed route href helper types used by Link. */
|
|
@@ -201,12 +202,25 @@ function renderLink(props: LinkProps<string>): string | HTMLAnchorElement {
|
|
|
201
202
|
};
|
|
202
203
|
|
|
203
204
|
if (typeof document !== "undefined" && typeof document.createElement === "function") {
|
|
204
|
-
|
|
205
|
+
const anchor = createAnchorElement(propsWithLinkAttrs);
|
|
206
|
+
|
|
207
|
+
// Destructuring above reads a compiler-emitted reactive `href` getter once.
|
|
208
|
+
// Re-read it through a prop binding so the same anchor follows later updates
|
|
209
|
+
// instead of freezing the URL captured during the first render.
|
|
210
|
+
if (hasReactiveLinkHref(props)) {
|
|
211
|
+
bindProp(anchor, "href", () => props.href);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
return anchor;
|
|
205
215
|
}
|
|
206
216
|
|
|
207
217
|
return renderAnchorString(propsWithLinkAttrs);
|
|
208
218
|
}
|
|
209
219
|
|
|
220
|
+
function hasReactiveLinkHref(props: LinkProps<string>): boolean {
|
|
221
|
+
return Object.getOwnPropertyDescriptor(props, "href")?.get !== undefined;
|
|
222
|
+
}
|
|
223
|
+
|
|
210
224
|
function renderLinkString(props: LinkSinkProps): string {
|
|
211
225
|
const { href, prefetch, reload, scroll, transition, ...rest } = props;
|
|
212
226
|
const propsWithLinkAttrs = {
|