Skip to content

lancher-dev/jaamd

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

38 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

JAAMD

Just Another Astro Markdown — remark plugins, client-side enhancements and styles as a single Astro integration.


Table of Contents


Installation

npm install jaamd
# or
npx astro add jaamd

Setup

Add the integration to your Astro config:

// astro.config.mjs
import { defineConfig } from "astro/config";
import jaamd from "jaamd";

export default defineConfig({
  integrations: [jaamd()],
});

Wrap your markdown content with the MarkdownContent component in your layout:

---
// src/layouts/BlogPost.astro
import { MarkdownContent } from "jaamd/components";
---
<MarkdownContent>
  <slot />
</MarkdownContent>

The integration registers all remark plugins and injects the stylesheet automatically. No other configuration is required.

View Transitions (FOUC fix)

If you are using Astro's ClientRouter (View Transitions), you may notice a flash of unstyled content when navigating between pages. This happens because the integration injects the stylesheet via injectScript("page", ...), a JS module that runs after the new page content has already been swapped into the DOM.

To fix it, import the stylesheet statically in your layout's frontmatter alongside your other CSS. Astro will bundle it as a <link> in <head>, which persists across navigations and is applied before any render:

---
//  In any layout that uses MarkdownContent
import "jaamd/default.css"; 
import "jaamd/styles.css";
---

The duplicate import from injectScript is automatically deduplicated by the browser. No extra weight, no side effects.

Integration Options

jaamd({
  selector:   ".jaamd-content", // CSS selector for the JS enhancements (see below)
  theme:      "",               // Shiki theme (default "github-light")
  noDefault:  false,            // set true to skip injecting jaamd/default variable fallbacks
  plugins: {
    codeTabs:  true,            // :::code-tabs directive blocks
    alerts:    true,            // > [!NOTE] / [!WARNING] blockquote alerts
    directive: true,            // remark-directive (prerequisite for codeTabs)
  },
})

About selector

selector only controls which element the client-side JS enhancements target at runtime. It does not affect the CSS file, which always uses .jaamd-content.

  • When using <MarkdownContent> leave selector at its default. The component always adds jaamd-content to the wrapper, the CSS targets it, and so does the JS.
  • When doing manual usage, if you write a completely custom wrapper (e.g. <div data-md>), set selector to match it. You will also need to provide your own CSS, since the bundled stylesheet is hardcoded to .jaamd-content.

MarkdownContent Component

MarkdownContent is a polymorphic component. It renders as <div> by default and accepts any valid HTML tag via the as prop.

import { MarkdownContent } from "jaamd/components";

Props

Prop Type Default Description
as HTMLTag "div" The HTML element to render as.
class string Extra CSS classes appended to the wrapper.
...rest All standard HTML attributes for the chosen as element (e.g. id, data-*, aria-*).

The jaamd-content class is always present on the wrapper element. It is the selector used by the JS enhancements and must not be removed.

Examples

---
import { MarkdownContent } from "jaamd/components";
---

<!-- Default: renders as <div class="jaamd-content"> -->
<MarkdownContent>
  <slot />
</MarkdownContent>

<!-- Custom tag: renders as <article class="jaamd-content"> -->
<MarkdownContent as="article">
  <slot />
</MarkdownContent>

<!-- Extra classes: renders as <article class="jaamd-content prose mx-auto"> -->
<MarkdownContent as="article" class="prose mx-auto">
  <slot />
</MarkdownContent>

Theming

All styles are driven by CSS custom properties. By default, jaamd/default is automatically injected before the main stylesheet so every variable has a sensible fallback value.

Override any variable on :root or .jaamd-content in your own stylesheet:

:root {
  /* core colors */
  --jaamd-color-fg:            #334155;
  --jaamd-color-fg-bright:     #0f172a;
  --jaamd-color-primary:       #6366f1;
  --jaamd-color-primary-light: #818cf8;

  /* typography */
  --jaamd-font-sans: ui-sans-serif, system-ui, sans-serif;
  --jaamd-font-mono: ui-monospace, monospace;
  --jaamd-font-size: 1rem;
}

For the complete list of every available variable with its default value, see src/styles/variables.css.

Skipping the defaults

If you supply your own full variable set and don't want jaamd to inject its defaults, set noDefault: true:

jaamd({ noDefault: true })

Manual / Advanced Usage

Import plugins and styles directly, bypassing the integration:

// astro.config.mjs
import { remarkCodeTabs, remarkAlert, remarkDirective } from "jaamd";

export default defineConfig({
  markdown: {
    remarkPlugins: [remarkAlert, remarkDirective, remarkCodeTabs],
  },
});
---
import "jaamd/default";  // variable fallbacks — omit if you provide your own
import "jaamd/styles";
---
<div class="jaamd-content">
  <slot />
</div>
<script>
  import { initMarkdownEnhancements } from "jaamd/client";
  function run() { initMarkdownEnhancements(".jaamd-content"); }
  run();
  document.addEventListener("astro:page-load", run);
</script>

You can also import the CSS files directly from .css files or frameworks that prefer bare CSS imports:

@import "jaamd/default.css";
@import "jaamd/styles.css";