astro-directify
v0.0.1-alpha.7
Published
Declarative server-side control-flow directives for Astro templates.
Maintainers
Readme
astro-directify
Declarative server-side control flow for Astro templates.
astro-directify adds template directives such as d:if, d:for, and d:switch to Astro. The directives are transformed at build time into ordinary Astro expressions, so they add no browser runtime and no client JavaScript.
Supported Directives
d:ifd:elseifd:elsed:ford:switchd:cased:default
Compatibility
This release is validated with:
- Astro
7.2.9 @astrojs/compiler4.0.0- Node.js
>=22.12.0
The package peer range supports Astro ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0, but the current local validation target is Astro 7.
Installation
npm install astro-directifyUsage
Enable the integration in astro.config.mjs:
import { defineConfig } from "astro/config";
import directify from "astro-directify";
export default defineConfig({
integrations: [directify()]
});Named import is also supported:
import { directifyIntegration } from "astro-directify";
export default defineConfig({
integrations: [directifyIntegration()]
});Security And Memory Guards
astro-directify uses @astrojs/compiler to parse .astro templates before Astro compiles them. This release adds guardrails for compiler input size and transform-cache memory.
import { defineConfig } from "astro/config";
import directify from "astro-directify";
export default defineConfig({
integrations: [
directify({
maxTemplateCharacters: 5_000_000,
maxCacheEntries: 500,
maxCachedCharacters: 10_000_000
})
]
});Options:
maxTemplateCharacters: Maximum template size passed to the Astro compiler. Defaults to5_000_000. Set to0to disable the guard.maxCacheEntries: Maximum transformed templates retained in memory. Defaults to500. Set to0to disable caching.maxCachedCharacters: Maximum total transformed-output characters retained in memory. Defaults to10_000_000. Set to0to disable caching.
The transform cache stores a source fingerprint and transformed output. It does not retain the original template source text.
TypeScript Setup
To make editors accept d:* attributes in .astro files, add a declaration file such as src/types/directify-directives.d.ts:
/// <reference types="astro-directify/directify-directives.d.ts" />If you prefer to keep the declarations inline, use:
import "astro";
declare module "astro" {
interface AstroBuiltinAttributes {
"d:if"?: any;
"d:elseif"?: any;
"d:else"?: any;
"d:for"?: any;
"d:switch"?: any;
"d:case"?: any;
"d:default"?: any;
}
}Make sure your tsconfig.json includes src or the folder where you place the declaration file.
d:if, d:elseif, And d:else
<button d:if={user}>Logout</button>Compiles to:
{(user) && <button>Logout</button>}Full chain:
<div d:if={role === "admin"}>Admin</div>
<div d:elseif={role === "manager"}>Manager</div>
<div d:else>Guest</div>Compiles roughly to:
{(role === "admin") ? (
<div>Admin</div>
) : (role === "manager") ? (
<div>Manager</div>
) : (
<div>Guest</div>
)}Chains are local to their parent. A d:else or d:elseif in a different container will not attach to a previous d:if.
d:for
<li d:for="user in users">
{user.name}
</li>Compiles to:
{users.map((user) => (
<li>{user.name}</li>
))}With index:
<li d:for="(user, i) in users">
{i + 1}. {user.name}
</li>Compiles to:
{users.map((user, i) => (
<li>{i + 1}. {user.name}</li>
))}The left side can be item or (item, index). The right side should be an expression with a .map() method, usually an array.
d:switch, d:case, And d:default
<div d:switch={role}>
<div d:case="'admin'">Admin panel</div>
<div d:case="'editor'">Editor tools</div>
<div d:default>Viewer mode</div>
</div>Compiles roughly to:
{(role === "admin") ? (
<div>Admin panel</div>
) : (role === "editor") ? (
<div>Editor tools</div>
) : (
<div>Viewer mode</div>
)}Notes:
d:caseexpressions are compared with===to thed:switchexpression.- Only direct children of the switch container are considered.
- Without
d:default, the generated fallback isnull. - Standalone
d:caseord:defaultattributes are stripped and the element remains.
Custom Directives
You can add or override directive handlers:
import { defineConfig } from "astro/config";
import directify, { type ServerDirectiveHandler } from "astro-directify";
const showDirective: ServerDirectiveHandler = ({ attr, removeAttribute }) => {
removeAttribute();
console.log(attr.name);
};
export default defineConfig({
integrations: [
directify({
directives: {
show: showDirective
}
})
]
});Release Notes For 0.0.1-alpha.7
- Validated against Astro
7.2.9and@astrojs/compiler4.0.0. - Broadened Astro template request matching for current Vite/Astro query forms while avoiding virtual script/style/custom subrequests.
Release Notes For 0.0.1-alpha.6
- Validated against Astro
7.1.3and@astrojs/compiler4.0.0. - Added compiler input-size protection with
maxTemplateCharacters. - Added bounded transform-cache controls with
maxCacheEntriesandmaxCachedCharacters. - Avoided retaining original template source strings in memory cache.
- Switched AST traversal from recursive to iterative to reduce stack overflow risk.
- Fixed package ESM output by emitting
.jsrelative import specifiers. - Added a default export for
directify. - Removed direct Vite type coupling from the loader return type.
- Updated Node engine to
>=22.12.0.
License
MIT
