@astrojs/markdown-remark 0.8.3 → 0.9.3

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/CHANGELOG.md CHANGED
@@ -1,5 +1,39 @@
1
1
  # @astrojs/markdown-remark
2
2
 
3
+ ## 0.9.3
4
+
5
+ ### Patch Changes
6
+
7
+ - [#3234](https://github.com/withastro/astro/pull/3234) [`de123b28`](https://github.com/withastro/astro/commit/de123b28b3ff398b800cb598f20326ca85a0fb60) Thanks [@JuanM04](https://github.com/JuanM04)! - Removed `rehype-slug` in favor of our own implementation. The behavior of the slugging should remain the same
8
+
9
+ * [#3234](https://github.com/withastro/astro/pull/3234) [`de123b28`](https://github.com/withastro/astro/commit/de123b28b3ff398b800cb598f20326ca85a0fb60) Thanks [@JuanM04](https://github.com/JuanM04)! - Moved some type from `astro` to `@astrojs/markdown-remark`
10
+
11
+ ## 0.9.2
12
+
13
+ ### Patch Changes
14
+
15
+ - [#3152](https://github.com/withastro/astro/pull/3152) [`9ba1f4f8`](https://github.com/withastro/astro/commit/9ba1f4f8251155b69398a8af22d6ab8587b96120) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Fix JSX expression inconsistencies within markdown files
16
+
17
+ ## 0.9.1
18
+
19
+ ### Patch Changes
20
+
21
+ - [#3108](https://github.com/withastro/astro/pull/3108) [`ef198ff8`](https://github.com/withastro/astro/commit/ef198ff8351ac8fbc868e209f9cd410dc8b6f265) Thanks [@FredKSchott](https://github.com/FredKSchott)! - shiki: Add `diff` symbol handling to disable `user-select` on `+`/`-` symbols.
22
+
23
+ ## 0.9.0
24
+
25
+ ### Minor Changes
26
+
27
+ - [`53162534`](https://github.com/withastro/astro/commit/53162534450e160f65b95e7ef1523a106347ca28) Thanks [@FredKSchott](https://github.com/FredKSchott)! - - Removed `renderMarkdownWithFrontmatter` because it wasn't being used
28
+ - All options of `renderMarkdown` are now required — see the exported interface `AstroMarkdownOptions`
29
+ - New types: RemarkPlugin, RehypePlugin and ShikiConfig
30
+
31
+ ## 0.8.2
32
+
33
+ ### Patch Changes
34
+
35
+ - [#2970](https://github.com/withastro/astro/pull/2970) [`b835e285`](https://github.com/withastro/astro/commit/b835e285defb4f31fc5ac1039c7f607c07f3c00b) Thanks [@JuanM04](https://github.com/JuanM04)! - Improved type checking
36
+
3
37
  ## 0.8.1
4
38
 
5
39
  ### Patch Changes
package/dist/index.d.ts CHANGED
@@ -1,26 +1,6 @@
1
- import type { AstroMarkdownOptions, MarkdownRenderingOptions, ShikiConfig, Plugin } from './types';
2
- export { AstroMarkdownOptions, MarkdownRenderingOptions, ShikiConfig, Plugin };
3
- /** Internal utility for rendering a full markdown file and extracting Frontmatter data */
4
- export declare function renderMarkdownWithFrontmatter(contents: string, opts?: MarkdownRenderingOptions | null): Promise<{
5
- frontmatter: {
6
- [key: string]: any;
7
- };
8
- metadata: {
9
- headers: any[];
10
- source: string;
11
- html: string;
12
- };
13
- code: string;
14
- }>;
1
+ import type { MarkdownRenderingOptions, MarkdownRenderingResult } from './types';
2
+ export * from './types.js';
15
3
  export declare const DEFAULT_REMARK_PLUGINS: string[];
16
- export declare const DEFAULT_REHYPE_PLUGINS: string[];
4
+ export declare const DEFAULT_REHYPE_PLUGINS: never[];
17
5
  /** Shared utility for rendering markdown */
18
- export declare function renderMarkdown(content: string, opts?: MarkdownRenderingOptions | null): Promise<{
19
- metadata: {
20
- headers: any[];
21
- source: string;
22
- html: string;
23
- };
24
- code: string;
25
- }>;
26
- export default renderMarkdownWithFrontmatter;
6
+ export declare function renderMarkdown(content: string, opts: MarkdownRenderingOptions): Promise<MarkdownRenderingResult>;
package/dist/index.js CHANGED
@@ -1,22 +1,3 @@
1
- var __defProp = Object.defineProperty;
2
- var __defProps = Object.defineProperties;
3
- var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
4
- var __getOwnPropSymbols = Object.getOwnPropertySymbols;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __propIsEnum = Object.prototype.propertyIsEnumerable;
7
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
8
- var __spreadValues = (a, b) => {
9
- for (var prop in b || (b = {}))
10
- if (__hasOwnProp.call(b, prop))
11
- __defNormalProp(a, prop, b[prop]);
12
- if (__getOwnPropSymbols)
13
- for (var prop of __getOwnPropSymbols(b)) {
14
- if (__propIsEnum.call(b, prop))
15
- __defNormalProp(a, prop, b[prop]);
16
- }
17
- return a;
18
- };
19
- var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
20
1
  import createCollectHeaders from "./rehype-collect-headers.js";
21
2
  import scopedStyles from "./remark-scoped-styles.js";
22
3
  import { remarkExpressions, loadRemarkExpressions } from "./remark-expressions.js";
@@ -34,21 +15,13 @@ import markdown from "remark-parse";
34
15
  import markdownToHtml from "remark-rehype";
35
16
  import rehypeStringify from "rehype-stringify";
36
17
  import rehypeRaw from "rehype-raw";
37
- import matter from "gray-matter";
38
- async function renderMarkdownWithFrontmatter(contents, opts) {
39
- const { data: frontmatter, content } = matter(contents);
40
- const value = await renderMarkdown(content, opts);
41
- return __spreadProps(__spreadValues({}, value), { frontmatter });
42
- }
18
+ export * from "./types.js";
43
19
  const DEFAULT_REMARK_PLUGINS = ["remark-gfm", "remark-smartypants"];
44
- const DEFAULT_REHYPE_PLUGINS = ["rehype-slug"];
20
+ const DEFAULT_REHYPE_PLUGINS = [];
45
21
  async function renderMarkdown(content, opts) {
46
22
  var _a;
47
- let { remarkPlugins = [], rehypePlugins = [] } = opts ?? {};
48
- const scopedClassName = (_a = opts == null ? void 0 : opts.$) == null ? void 0 : _a.scopedClassName;
49
- const mode = (opts == null ? void 0 : opts.mode) ?? "mdx";
50
- const syntaxHighlight = (opts == null ? void 0 : opts.syntaxHighlight) ?? "shiki";
51
- const shikiConfig = (opts == null ? void 0 : opts.shikiConfig) ?? {};
23
+ let { mode, syntaxHighlight, shikiConfig, remarkPlugins, rehypePlugins } = opts;
24
+ const scopedClassName = (_a = opts.$) == null ? void 0 : _a.scopedClassName;
52
25
  const isMDX = mode === "mdx";
53
26
  const { headers, rehypeCollectHeaders } = createCollectHeaders();
54
27
  await Promise.all([loadRemarkExpressions(), loadRemarkJsx()]);
@@ -96,11 +69,8 @@ async function renderMarkdown(content, opts) {
96
69
  code: result.toString()
97
70
  };
98
71
  }
99
- var src_default = renderMarkdownWithFrontmatter;
100
72
  export {
101
73
  DEFAULT_REHYPE_PLUGINS,
102
74
  DEFAULT_REMARK_PLUGINS,
103
- src_default as default,
104
- renderMarkdown,
105
- renderMarkdownWithFrontmatter
75
+ renderMarkdown
106
76
  };
@@ -1,3 +1,2 @@
1
1
  import * as unified from 'unified';
2
- import type { Plugin } from './types';
3
- export declare function loadPlugins(items: Plugin[]): Promise<[unified.Plugin, any?]>[];
2
+ export declare function loadPlugins(items: (string | [string, any] | unified.Plugin<any[], any> | [unified.Plugin<any[], any>, any])[]): Promise<[unified.Plugin, any?]>[];
@@ -1,5 +1,5 @@
1
- /** */
1
+ import type { MarkdownHeader, RehypePlugin } from './types.js';
2
2
  export default function createCollectHeaders(): {
3
- headers: any[];
4
- rehypeCollectHeaders: () => (tree: any) => void;
3
+ headers: MarkdownHeader[];
4
+ rehypeCollectHeaders: () => ReturnType<RehypePlugin>;
5
5
  };
@@ -1,11 +1,11 @@
1
1
  import { visit } from "unist-util-visit";
2
- import slugger from "github-slugger";
2
+ import Slugger from "github-slugger";
3
3
  function createCollectHeaders() {
4
4
  const headers = [];
5
+ const slugger = new Slugger();
5
6
  function rehypeCollectHeaders() {
6
7
  return function(tree) {
7
8
  visit(tree, (node) => {
8
- var _a;
9
9
  if (node.type !== "element")
10
10
  return;
11
11
  const { tagName } = node;
@@ -19,10 +19,11 @@ function createCollectHeaders() {
19
19
  visit(node, "text", (child) => {
20
20
  text += child.value;
21
21
  });
22
- let slug = ((_a = node == null ? void 0 : node.properties) == null ? void 0 : _a.id) || slugger.slug(text);
23
22
  node.properties = node.properties || {};
24
- node.properties.id = slug;
25
- headers.push({ depth, slug, text });
23
+ if (typeof node.properties.id !== "string") {
24
+ node.properties.id = slugger.slug(text);
25
+ }
26
+ headers.push({ depth, slug: node.properties.id, text });
26
27
  });
27
28
  };
28
29
  }
File without changes
File without changes
File without changes
@@ -22,7 +22,7 @@ const visit = _visit;
22
22
  function rehypeIslands() {
23
23
  return function(node) {
24
24
  return visit(node, "element", (el) => {
25
- if (el.tagName == "astro-root") {
25
+ if (el.tagName == "astro-island") {
26
26
  visit(el, "text", (child, index, parent) => {
27
27
  if (child.type === "text") {
28
28
  if (parent && child.value.indexOf("<!--") > -1 && index != null) {
File without changes
File without changes
@@ -1,10 +1,8 @@
1
- let mdxExpression;
2
1
  let mdxExpressionFromMarkdown;
3
2
  let mdxExpressionToMarkdown;
4
3
  function remarkExpressions(options) {
5
4
  let settings = options || {};
6
5
  let data = this.data();
7
- add("micromarkExtensions", mdxExpression({}));
8
6
  add("fromMarkdownExtensions", mdxExpressionFromMarkdown);
9
7
  add("toMarkdownExtensions", mdxExpressionToMarkdown);
10
8
  function add(field, value) {
@@ -15,10 +13,6 @@ function remarkExpressions(options) {
15
13
  }
16
14
  }
17
15
  async function loadRemarkExpressions() {
18
- if (!mdxExpression) {
19
- const micromarkMdxExpression = await import("micromark-extension-mdx-expression");
20
- mdxExpression = micromarkMdxExpression.mdxExpression;
21
- }
22
16
  if (!mdxExpressionFromMarkdown || !mdxExpressionToMarkdown) {
23
17
  const mdastUtilMdxExpression = await import("mdast-util-mdx-expression");
24
18
  mdxExpressionFromMarkdown = mdastUtilMdxExpression.mdxExpressionFromMarkdown;
File without changes
File without changes
File without changes
@@ -1,30 +1,3 @@
1
- import type * as shiki from 'shiki';
2
- export interface ShikiConfig {
3
- /**
4
- * The languages loaded to Shiki.
5
- * Supports all languages listed here: https://github.com/shikijs/shiki/blob/main/docs/languages.md#all-languages
6
- * Instructions for loading a custom language: https://github.com/shikijs/shiki/blob/main/docs/languages.md#supporting-your-own-languages-with-shiki
7
- *
8
- * @default []
9
- */
10
- langs?: shiki.ILanguageRegistration[];
11
- /**
12
- * The styling theme.
13
- * Supports all themes listed here: https://github.com/shikijs/shiki/blob/main/docs/themes.md#all-themes
14
- * Instructions for loading a custom theme: https://github.com/shikijs/shiki/blob/main/docs/themes.md#loading-theme
15
- *
16
- * @default "github-dark"
17
- */
18
- theme?: shiki.IThemeRegistration;
19
- /**
20
- * Enable word wrapping.
21
- * - true: enabled.
22
- * - false: enabled.
23
- * - null: All overflow styling removed. Code will overflow the element by default.
24
- *
25
- * @default false
26
- */
27
- wrap?: boolean | null;
28
- }
1
+ import type { ShikiConfig } from './types.js';
29
2
  declare const remarkShiki: ({ langs, theme, wrap }: ShikiConfig, scopedClassName?: string | null | undefined) => Promise<() => (tree: any) => void>;
30
3
  export default remarkShiki;
@@ -1,7 +1,7 @@
1
1
  import { getHighlighter } from "shiki";
2
2
  import { visit } from "unist-util-visit";
3
3
  const highlighterCacheAsync = /* @__PURE__ */ new Map();
4
- const remarkShiki = async ({ langs = [], theme = "github-dark", wrap = false }, scopedClassName) => {
4
+ const remarkShiki = async ({ langs, theme, wrap }, scopedClassName) => {
5
5
  const cacheID = typeof theme === "string" ? theme : theme.name;
6
6
  let highlighterAsync = highlighterCacheAsync.get(cacheID);
7
7
  if (!highlighterAsync) {
@@ -17,6 +17,9 @@ const remarkShiki = async ({ langs = [], theme = "github-dark", wrap = false },
17
17
  let html = highlighter.codeToHtml(node.value, { lang: node.lang ?? "plaintext" });
18
18
  html = html.replace('<pre class="shiki"', `<pre is:raw class="astro-code${scopedClassName ? " " + scopedClassName : ""}"`);
19
19
  html = html.replace(/style="(background-)?color: var\(--shiki-/g, 'style="$1color: var(--astro-code-');
20
+ if (node.lang === "diff") {
21
+ html = html.replace(/<span class="line"><span style="(.*?)">([\+|\-])/g, '<span class="line"><span style="$1"><span style="user-select: none;">$2</span>');
22
+ }
20
23
  if (wrap === false) {
21
24
  html = html.replace(/style="(.*?)"/, 'style="$1; overflow-x: auto;"');
22
25
  } else if (wrap === true) {
File without changes
@@ -7,10 +7,10 @@ function remarkUnwrap() {
7
7
  insideAstroRoot = false;
8
8
  astroRootNodes.clear();
9
9
  visit(tree, "html", (node) => {
10
- if (node.value.indexOf("<astro-root") > -1 && !insideAstroRoot) {
10
+ if (node.value.indexOf("<astro-island") > -1 && !insideAstroRoot) {
11
11
  insideAstroRoot = true;
12
12
  }
13
- if (node.value.indexOf("</astro-root") > -1 && insideAstroRoot) {
13
+ if (node.value.indexOf("</astro-island") > -1 && insideAstroRoot) {
14
14
  insideAstroRoot = false;
15
15
  }
16
16
  astroRootNodes.add(node);
package/dist/types.d.ts CHANGED
@@ -1,17 +1,42 @@
1
1
  import type * as unified from 'unified';
2
- import type { ShikiConfig } from './remark-shiki';
3
- export { ShikiConfig };
4
- export declare type Plugin = string | [string, any] | unified.Plugin | [unified.Plugin, any];
2
+ import type * as mdast from 'mdast';
3
+ import type * as hast from 'hast';
4
+ import type { ILanguageRegistration, IThemeRegistration, Theme } from 'shiki';
5
+ export type { Node } from 'unist';
6
+ export declare type RemarkPlugin<PluginParameters extends any[] = any[]> = unified.Plugin<PluginParameters, mdast.Root>;
7
+ export declare type RemarkPlugins = (string | [string, any] | RemarkPlugin | [RemarkPlugin, any])[];
8
+ export declare type RehypePlugin<PluginParameters extends any[] = any[]> = unified.Plugin<PluginParameters, hast.Root>;
9
+ export declare type RehypePlugins = (string | [string, any] | RehypePlugin | [RehypePlugin, any])[];
10
+ export interface ShikiConfig {
11
+ langs: ILanguageRegistration[];
12
+ theme: Theme | IThemeRegistration;
13
+ wrap: boolean | null;
14
+ }
5
15
  export interface AstroMarkdownOptions {
6
- mode?: 'md' | 'mdx';
7
- syntaxHighlight?: 'shiki' | 'prism' | false;
8
- shikiConfig?: ShikiConfig;
9
- remarkPlugins?: Plugin[];
10
- rehypePlugins?: Plugin[];
16
+ mode: 'md' | 'mdx';
17
+ drafts: boolean;
18
+ syntaxHighlight: 'shiki' | 'prism' | false;
19
+ shikiConfig: ShikiConfig;
20
+ remarkPlugins: RemarkPlugins;
21
+ rehypePlugins: RehypePlugins;
11
22
  }
12
- export interface MarkdownRenderingOptions extends Partial<AstroMarkdownOptions> {
23
+ export interface MarkdownRenderingOptions extends AstroMarkdownOptions {
13
24
  /** @internal */
14
25
  $?: {
15
26
  scopedClassName: string | null;
16
27
  };
17
28
  }
29
+ export interface MarkdownHeader {
30
+ depth: number;
31
+ slug: string;
32
+ text: string;
33
+ }
34
+ export interface MarkdownMetadata {
35
+ headers: MarkdownHeader[];
36
+ source: string;
37
+ html: string;
38
+ }
39
+ export interface MarkdownRenderingResult {
40
+ metadata: MarkdownMetadata;
41
+ code: string;
42
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@astrojs/markdown-remark",
3
- "version": "0.8.3",
3
+ "version": "0.9.3",
4
4
  "type": "module",
5
5
  "author": "withastro",
6
6
  "license": "MIT",
@@ -26,15 +26,12 @@
26
26
  "@astrojs/prism": "^0.4.1",
27
27
  "assert": "^2.0.0",
28
28
  "github-slugger": "^1.4.0",
29
- "gray-matter": "^4.0.3",
30
29
  "mdast-util-mdx-expression": "^1.2.0",
31
30
  "mdast-util-mdx-jsx": "^1.2.0",
32
31
  "mdast-util-to-string": "^3.1.0",
33
- "micromark-extension-mdx-expression": "^1.0.3",
34
32
  "micromark-extension-mdx-jsx": "^1.0.3",
35
- "prismjs": "^1.27.0",
33
+ "prismjs": "^1.28.0",
36
34
  "rehype-raw": "^6.1.1",
37
- "rehype-slug": "^5.0.1",
38
35
  "rehype-stringify": "^9.0.3",
39
36
  "remark-gfm": "^3.0.1",
40
37
  "remark-parse": "^10.0.1",
@@ -47,7 +44,10 @@
47
44
  },
48
45
  "devDependencies": {
49
46
  "@types/github-slugger": "^1.3.0",
47
+ "@types/hast": "^2.3.4",
48
+ "@types/mdast": "^3.0.10",
50
49
  "@types/prismjs": "^1.26.0",
50
+ "@types/unist": "^2.0.6",
51
51
  "astro-scripts": "workspace:*"
52
52
  }
53
53
  }
package/src/index.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { AstroMarkdownOptions, MarkdownRenderingOptions, ShikiConfig, Plugin } from './types';
1
+ import type { MarkdownRenderingOptions, MarkdownRenderingResult } from './types';
2
2
 
3
3
  import createCollectHeaders from './rehype-collect-headers.js';
4
4
  import scopedStyles from './remark-scoped-styles.js';
@@ -18,31 +18,19 @@ import markdown from 'remark-parse';
18
18
  import markdownToHtml from 'remark-rehype';
19
19
  import rehypeStringify from 'rehype-stringify';
20
20
  import rehypeRaw from 'rehype-raw';
21
- import matter from 'gray-matter';
22
-
23
- export { AstroMarkdownOptions, MarkdownRenderingOptions, ShikiConfig, Plugin };
24
-
25
- /** Internal utility for rendering a full markdown file and extracting Frontmatter data */
26
- export async function renderMarkdownWithFrontmatter(
27
- contents: string,
28
- opts?: MarkdownRenderingOptions | null
29
- ) {
30
- const { data: frontmatter, content } = matter(contents);
31
- const value = await renderMarkdown(content, opts);
32
- return { ...value, frontmatter };
33
- }
34
21
 
35
- export const DEFAULT_REMARK_PLUGINS = ['remark-gfm', 'remark-smartypants'];
22
+ export * from './types.js';
36
23
 
37
- export const DEFAULT_REHYPE_PLUGINS = ['rehype-slug'];
24
+ export const DEFAULT_REMARK_PLUGINS = ['remark-gfm', 'remark-smartypants'];
25
+ export const DEFAULT_REHYPE_PLUGINS = [];
38
26
 
39
27
  /** Shared utility for rendering markdown */
40
- export async function renderMarkdown(content: string, opts?: MarkdownRenderingOptions | null) {
41
- let { remarkPlugins = [], rehypePlugins = [] } = opts ?? {};
42
- const scopedClassName = opts?.$?.scopedClassName;
43
- const mode = opts?.mode ?? 'mdx';
44
- const syntaxHighlight = opts?.syntaxHighlight ?? 'shiki';
45
- const shikiConfig = opts?.shikiConfig ?? {};
28
+ export async function renderMarkdown(
29
+ content: string,
30
+ opts: MarkdownRenderingOptions
31
+ ): Promise<MarkdownRenderingResult> {
32
+ let { mode, syntaxHighlight, shikiConfig, remarkPlugins, rehypePlugins } = opts;
33
+ const scopedClassName = opts.$?.scopedClassName;
46
34
  const isMDX = mode === 'mdx';
47
35
  const { headers, rehypeCollectHeaders } = createCollectHeaders();
48
36
 
@@ -111,5 +99,3 @@ export async function renderMarkdown(content: string, opts?: MarkdownRenderingOp
111
99
  code: result.toString(),
112
100
  };
113
101
  }
114
-
115
- export default renderMarkdownWithFrontmatter;
@@ -1,5 +1,4 @@
1
1
  import * as unified from 'unified';
2
- import type { Plugin } from './types';
3
2
 
4
3
  async function importPlugin(p: string | unified.Plugin): Promise<unified.Plugin> {
5
4
  if (typeof p === 'string') {
@@ -10,7 +9,9 @@ async function importPlugin(p: string | unified.Plugin): Promise<unified.Plugin>
10
9
  return p;
11
10
  }
12
11
 
13
- export function loadPlugins(items: Plugin[]): Promise<[unified.Plugin, any?]>[] {
12
+ export function loadPlugins(
13
+ items: (string | [string, any] | unified.Plugin<any[], any> | [unified.Plugin<any[], any>, any])[]
14
+ ): Promise<[unified.Plugin, any?]>[] {
14
15
  return items.map((p) => {
15
16
  return new Promise((resolve, reject) => {
16
17
  if (Array.isArray(p)) {
@@ -1,12 +1,14 @@
1
1
  import { visit } from 'unist-util-visit';
2
- import slugger from 'github-slugger';
2
+ import Slugger from 'github-slugger';
3
+
4
+ import type { MarkdownHeader, RehypePlugin } from './types.js';
3
5
 
4
- /** */
5
6
  export default function createCollectHeaders() {
6
- const headers: any[] = [];
7
+ const headers: MarkdownHeader[] = [];
8
+ const slugger = new Slugger();
7
9
 
8
- function rehypeCollectHeaders() {
9
- return function (tree: any) {
10
+ function rehypeCollectHeaders(): ReturnType<RehypePlugin> {
11
+ return function (tree) {
10
12
  visit(tree, (node) => {
11
13
  if (node.type !== 'element') return;
12
14
  const { tagName } = node;
@@ -21,11 +23,12 @@ export default function createCollectHeaders() {
21
23
  text += child.value;
22
24
  });
23
25
 
24
- let slug = node?.properties?.id || slugger.slug(text);
25
-
26
26
  node.properties = node.properties || {};
27
- node.properties.id = slug;
28
- headers.push({ depth, slug, text });
27
+ if (typeof node.properties.id !== 'string') {
28
+ node.properties.id = slugger.slug(text);
29
+ }
30
+
31
+ headers.push({ depth, slug: node.properties.id, text });
29
32
  });
30
33
  };
31
34
  }
@@ -9,14 +9,14 @@ const visit = _visit as (
9
9
  ) => any;
10
10
 
11
11
  // This fixes some confusing bugs coming from somewhere inside of our Markdown pipeline.
12
- // `unist`/`remark`/`rehype` (not sure) often generate malformed HTML inside of <astro-root>
12
+ // `unist`/`remark`/`rehype` (not sure) often generate malformed HTML inside of <astro-island>
13
13
  // For hydration to work properly, frameworks need the DOM to be the exact same on server/client.
14
14
  // This reverts some "helpful corrections" that are applied to our perfectly valid HTML!
15
15
  export default function rehypeIslands(): any {
16
16
  return function (node: any): any {
17
17
  return visit(node, 'element', (el) => {
18
- // Bugs only happen inside of <astro-root> islands
19
- if (el.tagName == 'astro-root') {
18
+ // Bugs only happen inside of <astro-island> islands
19
+ if (el.tagName == 'astro-island') {
20
20
  visit(el, 'text', (child, index, parent) => {
21
21
  if (child.type === 'text') {
22
22
  // Sometimes comments can be trapped as text, which causes them to be escaped
@@ -1,5 +1,4 @@
1
1
  // Vite bug: dynamically import() modules needed for CJS. Cache in memory to keep side effects
2
- let mdxExpression: any;
3
2
  let mdxExpressionFromMarkdown: any;
4
3
  let mdxExpressionToMarkdown: any;
5
4
 
@@ -7,7 +6,6 @@ export function remarkExpressions(this: any, options: any) {
7
6
  let settings = options || {};
8
7
  let data = this.data();
9
8
 
10
- add('micromarkExtensions', mdxExpression({}));
11
9
  add('fromMarkdownExtensions', mdxExpressionFromMarkdown);
12
10
  add('toMarkdownExtensions', mdxExpressionToMarkdown);
13
11
 
@@ -19,10 +17,6 @@ export function remarkExpressions(this: any, options: any) {
19
17
  }
20
18
 
21
19
  export async function loadRemarkExpressions() {
22
- if (!mdxExpression) {
23
- const micromarkMdxExpression = await import('micromark-extension-mdx-expression');
24
- mdxExpression = micromarkMdxExpression.mdxExpression;
25
- }
26
20
  if (!mdxExpressionFromMarkdown || !mdxExpressionToMarkdown) {
27
21
  const mdastUtilMdxExpression = await import('mdast-util-mdx-expression');
28
22
  mdxExpressionFromMarkdown = mdastUtilMdxExpression.mdxExpressionFromMarkdown;
@@ -1,34 +1,7 @@
1
1
  import type * as shiki from 'shiki';
2
2
  import { getHighlighter } from 'shiki';
3
3
  import { visit } from 'unist-util-visit';
4
-
5
- export interface ShikiConfig {
6
- /**
7
- * The languages loaded to Shiki.
8
- * Supports all languages listed here: https://github.com/shikijs/shiki/blob/main/docs/languages.md#all-languages
9
- * Instructions for loading a custom language: https://github.com/shikijs/shiki/blob/main/docs/languages.md#supporting-your-own-languages-with-shiki
10
- *
11
- * @default []
12
- */
13
- langs?: shiki.ILanguageRegistration[];
14
- /**
15
- * The styling theme.
16
- * Supports all themes listed here: https://github.com/shikijs/shiki/blob/main/docs/themes.md#all-themes
17
- * Instructions for loading a custom theme: https://github.com/shikijs/shiki/blob/main/docs/themes.md#loading-theme
18
- *
19
- * @default "github-dark"
20
- */
21
- theme?: shiki.IThemeRegistration;
22
- /**
23
- * Enable word wrapping.
24
- * - true: enabled.
25
- * - false: enabled.
26
- * - null: All overflow styling removed. Code will overflow the element by default.
27
- *
28
- * @default false
29
- */
30
- wrap?: boolean | null;
31
- }
4
+ import type { ShikiConfig } from './types.js';
32
5
 
33
6
  /**
34
7
  * getHighlighter() is the most expensive step of Shiki. Instead of calling it on every page,
@@ -38,7 +11,7 @@ export interface ShikiConfig {
38
11
  const highlighterCacheAsync = new Map<string, Promise<shiki.Highlighter>>();
39
12
 
40
13
  const remarkShiki = async (
41
- { langs = [], theme = 'github-dark', wrap = false }: ShikiConfig,
14
+ { langs, theme, wrap }: ShikiConfig,
42
15
  scopedClassName?: string | null
43
16
  ) => {
44
17
  const cacheID: string = typeof theme === 'string' ? theme : theme.name;
@@ -75,6 +48,13 @@ const remarkShiki = async (
75
48
  /style="(background-)?color: var\(--shiki-/g,
76
49
  'style="$1color: var(--astro-code-'
77
50
  );
51
+ // Add "user-select: none;" for "+"/"-" diff symbols
52
+ if (node.lang === 'diff') {
53
+ html = html.replace(
54
+ /<span class="line"><span style="(.*?)">([\+|\-])/g,
55
+ '<span class="line"><span style="$1"><span style="user-select: none;">$2</span>'
56
+ );
57
+ }
78
58
  // Handle code wrapping
79
59
  // if wrap=null, do nothing.
80
60
  if (wrap === false) {
@@ -8,7 +8,7 @@ const visit = _visit as (
8
8
  callback?: (node: any, index: number, parent: any) => any
9
9
  ) => any;
10
10
 
11
- // Remove the wrapping paragraph for <astro-root> islands
11
+ // Remove the wrapping paragraph for <astro-island> islands
12
12
  export default function remarkUnwrap() {
13
13
  const astroRootNodes = new Set();
14
14
  let insideAstroRoot = false;
@@ -19,10 +19,10 @@ export default function remarkUnwrap() {
19
19
  astroRootNodes.clear();
20
20
 
21
21
  visit(tree, 'html', (node) => {
22
- if (node.value.indexOf('<astro-root') > -1 && !insideAstroRoot) {
22
+ if (node.value.indexOf('<astro-island') > -1 && !insideAstroRoot) {
23
23
  insideAstroRoot = true;
24
24
  }
25
- if (node.value.indexOf('</astro-root') > -1 && insideAstroRoot) {
25
+ if (node.value.indexOf('</astro-island') > -1 && insideAstroRoot) {
26
26
  insideAstroRoot = false;
27
27
  }
28
28
  astroRootNodes.add(node);
package/src/types.ts CHANGED
@@ -1,20 +1,59 @@
1
1
  import type * as unified from 'unified';
2
- import type { ShikiConfig } from './remark-shiki';
3
- export { ShikiConfig };
2
+ import type * as mdast from 'mdast';
3
+ import type * as hast from 'hast';
4
+ import type { ILanguageRegistration, IThemeRegistration, Theme } from 'shiki';
4
5
 
5
- export type Plugin = string | [string, any] | unified.Plugin | [unified.Plugin, any];
6
+ export type { Node } from 'unist';
7
+
8
+ export type RemarkPlugin<PluginParameters extends any[] = any[]> = unified.Plugin<
9
+ PluginParameters,
10
+ mdast.Root
11
+ >;
12
+
13
+ export type RemarkPlugins = (string | [string, any] | RemarkPlugin | [RemarkPlugin, any])[];
14
+
15
+ export type RehypePlugin<PluginParameters extends any[] = any[]> = unified.Plugin<
16
+ PluginParameters,
17
+ hast.Root
18
+ >;
19
+
20
+ export type RehypePlugins = (string | [string, any] | RehypePlugin | [RehypePlugin, any])[];
21
+
22
+ export interface ShikiConfig {
23
+ langs: ILanguageRegistration[];
24
+ theme: Theme | IThemeRegistration;
25
+ wrap: boolean | null;
26
+ }
6
27
 
7
28
  export interface AstroMarkdownOptions {
8
- mode?: 'md' | 'mdx';
9
- syntaxHighlight?: 'shiki' | 'prism' | false;
10
- shikiConfig?: ShikiConfig;
11
- remarkPlugins?: Plugin[];
12
- rehypePlugins?: Plugin[];
29
+ mode: 'md' | 'mdx';
30
+ drafts: boolean;
31
+ syntaxHighlight: 'shiki' | 'prism' | false;
32
+ shikiConfig: ShikiConfig;
33
+ remarkPlugins: RemarkPlugins;
34
+ rehypePlugins: RehypePlugins;
13
35
  }
14
36
 
15
- export interface MarkdownRenderingOptions extends Partial<AstroMarkdownOptions> {
37
+ export interface MarkdownRenderingOptions extends AstroMarkdownOptions {
16
38
  /** @internal */
17
39
  $?: {
18
40
  scopedClassName: string | null;
19
41
  };
20
42
  }
43
+
44
+ export interface MarkdownHeader {
45
+ depth: number;
46
+ slug: string;
47
+ text: string;
48
+ }
49
+
50
+ export interface MarkdownMetadata {
51
+ headers: MarkdownHeader[];
52
+ source: string;
53
+ html: string;
54
+ }
55
+
56
+ export interface MarkdownRenderingResult {
57
+ metadata: MarkdownMetadata;
58
+ code: string;
59
+ }
@@ -1,5 +0,0 @@
1
- @astrojs/markdown-remark:build: cache hit, replaying output 5817ab166c77bc86
2
- @astrojs/markdown-remark:build: 
3
- @astrojs/markdown-remark:build: > @astrojs/markdown-remark@0.8.1 build /Users/fks/Code/astro/packages/markdown/remark
4
- @astrojs/markdown-remark:build: > astro-scripts build "src/**/*.ts" && tsc -p tsconfig.json
5
- @astrojs/markdown-remark:build: 
@@ -1,10 +0,0 @@
1
- /**
2
- * @typedef {import('mdast').Root} Root
3
- * @typedef {import('hast').Properties} Properties
4
- */
5
- /**
6
- * Plugin to add anchors headings using GitHub’s algorithm.
7
- *
8
- * @type {import('unified').Plugin<void[], Root>}
9
- */
10
- export default function remarkSlug(): (tree: any) => void;
@@ -1,23 +0,0 @@
1
- import { toString } from "mdast-util-to-string";
2
- import { visit } from "unist-util-visit";
3
- import BananaSlug from "github-slugger";
4
- const slugs = new BananaSlug();
5
- function remarkSlug() {
6
- return (tree) => {
7
- slugs.reset();
8
- visit(tree, (node) => {
9
- console.log(node);
10
- });
11
- visit(tree, "heading", (node) => {
12
- const data = node.data || (node.data = {});
13
- const props = data.hProperties || (data.hProperties = {});
14
- let id = props.id;
15
- id = id ? slugs.slug(String(id), true) : slugs.slug(toString(node));
16
- data.id = id;
17
- props.id = id;
18
- });
19
- };
20
- }
21
- export {
22
- remarkSlug as default
23
- };
@@ -1,32 +0,0 @@
1
- /**
2
- * @typedef {import('mdast').Root} Root
3
- * @typedef {import('hast').Properties} Properties
4
- */
5
-
6
- import { toString } from 'mdast-util-to-string';
7
- import { visit } from 'unist-util-visit';
8
- import BananaSlug from 'github-slugger';
9
-
10
- const slugs = new BananaSlug();
11
-
12
- /**
13
- * Plugin to add anchors headings using GitHub’s algorithm.
14
- *
15
- * @type {import('unified').Plugin<void[], Root>}
16
- */
17
- export default function remarkSlug() {
18
- return (tree: any) => {
19
- slugs.reset();
20
- visit(tree, (node) => {
21
- console.log(node);
22
- });
23
- visit(tree, 'heading', (node) => {
24
- const data = node.data || (node.data = {});
25
- const props = /** @type {Properties} */ data.hProperties || (data.hProperties = {});
26
- let id = props.id;
27
- id = id ? slugs.slug(String(id), true) : slugs.slug(toString(node));
28
- data.id = id;
29
- props.id = id;
30
- });
31
- };
32
- }