diff --git a/docs/EXTENSION_TYPES.md b/docs/EXTENSION_TYPES.md
new file mode 100644
index 0000000000..07f9163d46
--- /dev/null
+++ b/docs/EXTENSION_TYPES.md
@@ -0,0 +1,150 @@
+# Extension Types in Marked.js
+
+This document clarifies the different types of extensions in marked.js to help developers understand the API better.
+
+## Two Types of Extensions
+
+Marked.js has two distinct concepts that are both called "extensions" in the documentation, which can cause confusion:
+
+### 1. MarkedExtensions (Configuration Objects)
+
+**Type**: `MarkedExtension` interface
+**Usage**: Passed to `marked.use()` or `new Marked()`
+**Purpose**: Configuration objects that can contain various options and settings
+
+```javascript
+// MarkedExtension examples
+marked.use({
+ gfm: true,
+ breaks: false,
+ pedantic: false
+});
+
+marked.use({
+ renderer: {
+ heading(text, level) {
+ return `${text}`;
+ }
+ }
+});
+
+marked.use({
+ extensions: [/* SyntaxExtensions go here */]
+});
+```
+
+### 2. SyntaxExtensions (Custom Parsing Logic)
+
+**Type**: `SyntaxExtension` interface
+**Usage**: Objects inside the `extensions` array of a MarkedExtension
+**Purpose**: Define custom tokenizers and renderers for new syntax
+
+```javascript
+// SyntaxExtension example
+const customExtension = {
+ name: 'customBlock',
+ level: 'block',
+ start: (src) => src.match(/:::/)?.index,
+ tokenizer(src) {
+ const match = src.match(/^:::\s*(\w+)\s*\n([\s\S]*?)\n:::/);
+ if (match) {
+ return {
+ type: 'customBlock',
+ raw: match[0],
+ name: match[1],
+ content: match[2]
+ };
+ }
+ },
+ renderer(token) {
+ return `
${token.content}
`;
+ }
+};
+
+// Using the SyntaxExtension
+marked.use({
+ extensions: [customExtension] // This is a MarkedExtension with SyntaxExtensions
+});
+```
+
+## API Signatures Clarified
+
+### 1. `new Marked(extension, extension, extension)`
+- Each `extension` parameter is a **MarkedExtension**
+- Can contain any MarkedExtension options including `extensions` array
+
+### 2. `marked.use(extension)`
+- The `extension` parameter is a **MarkedExtension**
+- Can contain any MarkedExtension options including `extensions` array
+
+### 3. `marked.use({ extensions: [SyntaxExtensions] })`
+- The outer object is a **MarkedExtension**
+- The `extensions` property contains an array of **SyntaxExtensions**
+
+## Clear Terminology
+
+To avoid confusion, we recommend using these prefixes in documentation:
+
+- **MarkedExtension**: Configuration objects for `marked.use()`
+- **SyntaxExtension**: Custom parsing logic objects for the `extensions` array
+- **Extension Options**: The `extensions` property within a MarkedExtension
+
+## Examples of Clear Usage
+
+```javascript
+// MarkedExtension with various options
+const markdownConfig = {
+ gfm: true,
+ breaks: false,
+ renderer: {
+ // custom renderer methods
+ }
+};
+
+// MarkedExtension with SyntaxExtensions
+const customSyntaxConfig = {
+ extensions: [
+ {
+ name: 'alert',
+ level: 'block',
+ start: (src) => src.match(/^!!!\s/)?.index,
+ tokenizer(src) {
+ // custom tokenizer logic
+ },
+ renderer(token) {
+ // custom renderer logic
+ }
+ }
+ ]
+};
+
+// Using both
+marked.use(markdownConfig);
+marked.use(customSyntaxConfig);
+```
+
+## Migration from Previous Versions
+
+When upgrading from older versions of marked.js, you may need to separate your configuration:
+
+```javascript
+// Old way (confusing)
+const config = {
+ gfm: true,
+ extensions: [customExtension1, customExtension2]
+};
+
+// New way (clear separation)
+const markdownOptions = {
+ gfm: true
+};
+
+const customExtensions = {
+ extensions: [customExtension1, customExtension2]
+};
+
+marked.use(markdownOptions);
+marked.use(customExtensions);
+```
+
+This separation makes it clear which parts are general configuration and which are custom parsing extensions.
diff --git a/docs/USING_ADVANCED.md b/docs/USING_ADVANCED.md
index ba758e56f5..37f7aabd9f 100644
--- a/docs/USING_ADVANCED.md
+++ b/docs/USING_ADVANCED.md
@@ -73,9 +73,9 @@ console.log(marked.parse(markdownString));
|smartypants (**removed**)|`boolean` |`false` |v0.2.9 |Removed in v8.0.0 use [`marked-smartypants`](https://www.npmjs.com/package/marked-smartypants) to use "smart" typographic punctuation for things like quotes and dashes.|
|xhtml (**removed**)|`boolean` |`false` |v0.3.2 |Removed in v8.0.0 use [`marked-xhtml`](https://www.npmjs.com/package/marked-xhtml) to emit self-closing HTML tags for void elements (<br/>, <img/>, etc.) with a "/" as required by XHTML.|
-Known Extensions
+Known MarkedExtensions
-Marked can be extended using [custom extensions](/using_pro#extensions). This is a list of extensions that can be used with `marked.use(extension)`.
+Marked can be extended using [custom SyntaxExtensions](/using_pro#extensions). This is a list of **MarkedExtension** packages that can be used with `marked.use(extension)`.
diff --git a/docs/USING_PRO.md b/docs/USING_PRO.md
index 57fcc15e0f..d4efbfee70 100644
--- a/docs/USING_PRO.md
+++ b/docs/USING_PRO.md
@@ -2,9 +2,11 @@
To champion the single-responsibility and open/closed principles, we have tried to make it relatively painless to extend Marked. If you are looking to add custom functionality, this is the place to start.
+> **📖 Extension Types**: Marked.js has two different types of "extensions" that can be confusing. See [Extension Types Documentation](/extension_types) for a clear explanation of **MarkedExtensions** vs **SyntaxExtensions**.
+
marked.use()
-`marked.use(extension)` is the recommended way to extend Marked. The `extension` object can contain any [option](/using_advanced#options) available in Marked:
+`marked.use(extension)` is the recommended way to extend Marked. The `extension` parameter is a **MarkedExtension** object that can contain any [option](/using_advanced#options) available in Marked:
```js
@@ -17,16 +19,16 @@ marked.use({
});
```
-You can also supply multiple `extension` objects at once.
+You can also supply multiple **MarkedExtension** objects at once.
```js
-marked.use(myExtension, extension2, extension3);
+marked.use(myMarkedExtension, markedExtension2, markedExtension3);
\\ EQUIVALENT TO:
-marked.use(myExtension);
-marked.use(extension2);
-marked.use(extension3);
+marked.use(myMarkedExtension);
+marked.use(markedExtension2);
+marked.use(markedExtension3);
```
All options will overwrite those previously set, except for the following options which will be merged with the existing framework and can be used to change or extend the functionality of Marked: `renderer`, `tokenizer`, `hooks`, `walkTokens`, and `extensions`.
@@ -35,7 +37,7 @@ All options will overwrite those previously set, except for the following option
* The `walkTokens` option is a function that will be called to post-process every token before rendering.
-* The `extensions` option is an array of objects that can contain additional custom `renderer` and `tokenizer` steps that will execute before any of the default parsing logic occurs.
+* The `extensions` option is an array of **SyntaxExtension** objects that can contain additional custom `renderer` and `tokenizer` steps that will execute before any of the default parsing logic occurs.
Importantly, ensure that the extensions are only added to `marked` once (ie in the global scope of a regular JavaScript or TypeScript module). If they are added in a function that is called repeatedly, or in the JS for an HTML component in a library such as Svelte, your extensions will be added repeatedly, eventually causing a recursion error. If you cannot prevent the code from being run repeatedly, you should create a [Marked instance](/using_advanced#instance) so that your extensions are stored independently from the global instance Marked provides.
@@ -392,9 +394,54 @@ console.log(marked.parse(`_The formula is $a_ b=c_ d$._`));
***
-Custom Extensions : extensions
+Extension Types Example
+
+Here's a clear example showing the difference between **MarkedExtensions** and **SyntaxExtensions**:
+
+```js
+// 1. MarkedExtension - Configuration object passed to marked.use()
+const markdownConfig = {
+ gfm: true,
+ breaks: false,
+ pedantic: false
+};
+
+// 2. SyntaxExtension - Custom parsing logic
+const customBlockExtension = {
+ name: 'customBlock',
+ level: 'block',
+ start: (src) => src.match(/:::/)?.index,
+ tokenizer(src) {
+ const match = src.match(/^:::\s*(\w+)\s*\n([\s\S]*?)\n:::/);
+ if (match) {
+ return {
+ type: 'customBlock',
+ raw: match[0],
+ name: match[1],
+ content: match[2]
+ };
+ }
+ },
+ renderer(token) {
+ return `${token.content}
`;
+ }
+};
+
+// 3. MarkedExtension containing SyntaxExtensions
+const customSyntaxConfig = {
+ extensions: [customBlockExtension] // SyntaxExtensions go here
+};
+
+// Usage
+marked.use(markdownConfig); // MarkedExtension
+marked.use(customSyntaxConfig); // MarkedExtension with SyntaxExtensions
+```
+
+***
+
+Custom SyntaxExtensions : extensions
-You may supply an `extensions` array to the `options` object. This array can contain any number of `extension` objects, using the following properties:
+You may supply an `extensions` array to the `options` object. This array can contain any number of **SyntaxExtension** objects, using the following properties:
name
diff --git a/docs/_document.html b/docs/_document.html
index b76588947c..a0400d853e 100644
--- a/docs/_document.html
+++ b/docs/_document.html
@@ -57,6 +57,7 @@ Marked Documentation
Walk Tokens
Hooks
Custom Extensions
+ Extension Types
Async Marked
Lexer
Parser
diff --git a/src/MarkedOptions.ts b/src/MarkedOptions.ts
index 6ef3353330..f01a4e9d00 100644
--- a/src/MarkedOptions.ts
+++ b/src/MarkedOptions.ts
@@ -32,7 +32,7 @@ export interface RendererExtension;
}
-export type TokenizerAndRendererExtension = TokenizerExtension | RendererExtension | (TokenizerExtension & RendererExtension);
+export type SyntaxExtension = TokenizerExtension | RendererExtension | (TokenizerExtension & RendererExtension);
type HooksApi = Omit<_Hooks, 'constructor' | 'options' | 'block'>;
type HooksObject = {
@@ -64,7 +64,7 @@ export interface MarkedExtension
* Add tokenizers and renderers to marked
*/
extensions?:
- | TokenizerAndRendererExtension[]
+ | SyntaxExtension[]
| null;
/**
diff --git a/test/types/marked.ts b/test/types/marked.ts
index 43712b6059..af3cc45ed3 100644
--- a/test/types/marked.ts
+++ b/test/types/marked.ts
@@ -4,7 +4,7 @@ import { marked } from 'marked';
// other exports
import { Lexer, Parser, Tokenizer, Renderer, TextRenderer, Marked } from 'marked';
-import type { Tokens, MarkedExtension, TokenizerAndRendererExtension, Token ,TokenizerExtension, MarkedOptions, TokensList, RendererExtension, RendererObject } from 'marked';
+import type { Tokens, MarkedExtension, SyntaxExtension, Token ,TokenizerExtension, MarkedOptions, TokensList, RendererExtension, RendererObject } from 'marked';
const tokenizer = new marked.Tokenizer();
@@ -215,7 +215,7 @@ const rendererExtension: RendererExtension = {
}
};
-const tokenizerAndRendererExtension: TokenizerAndRendererExtension = {
+const syntaxExtension: SyntaxExtension = {
name: 'name',
level: 'block',
tokenizer(src: string) {
@@ -237,7 +237,7 @@ const tokenizerAndRendererExtension: TokenizerAndRendererExtension = {
};
marked.use({
- extensions: [tokenizerExtension, rendererExtension, tokenizerAndRendererExtension]
+ extensions: [tokenizerExtension, rendererExtension, syntaxExtension]
});
const asyncExtension: MarkedExtension = {