-
-
Notifications
You must be signed in to change notification settings - Fork 23
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add heading anchor link plugin (#31)
- Loading branch information
Showing
19 changed files
with
481 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
--- | ||
section: Plugins | ||
title: Anchor | ||
--- | ||
|
||
<script> | ||
import Code from '$lib/components/code/Code.svelte'; | ||
</script> | ||
|
||
This plugin adds `id` attributes and permalinks to headings. | ||
|
||
## Installation | ||
|
||
<Code> | ||
|
||
``` | ||
npm i @cartamd/plugin-anchor | ||
``` | ||
|
||
</Code> | ||
|
||
## Setup | ||
|
||
### Styles | ||
|
||
Import the default theme, or create you own: | ||
|
||
<Code> | ||
|
||
```ts | ||
import '@cartamd/plugin-anchor/default.css'; | ||
``` | ||
|
||
</Code> | ||
|
||
### Extension | ||
|
||
<Code> | ||
|
||
```svelte | ||
<script> | ||
import { Carta, CartaEditor } from 'carta-md'; | ||
import { anchor } from '@cartamd/plugin-anchor'; | ||
const carta = new Carta({ | ||
extensions: [anchor()] | ||
}); | ||
</script> | ||
<CartaEditor {carta} /> | ||
``` | ||
|
||
</Code> | ||
|
||
## Options | ||
|
||
Here are the options you can pass to `anchor()`: | ||
|
||
```ts | ||
export interface AnchorExtensionOptions { | ||
/** | ||
* Maximum depth of headers to generate anchors for. Defaults to 6. | ||
*/ | ||
maxDepth?: number; | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
.DS_Store | ||
node_modules | ||
/build | ||
/dist | ||
/.svelte-kit | ||
/package | ||
.env | ||
.env.* | ||
!.env.example | ||
vite.config.js.timestamp-* | ||
vite.config.ts.timestamp-* |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
# Carta Anchor Plugin | ||
|
||
This plugin adds `id` attributes and permalinks to headings. Install it using: | ||
|
||
``` | ||
npm i @cartamd/plugin-anchor | ||
``` | ||
|
||
## Setup | ||
|
||
### Styles | ||
|
||
Import the default theme, or create you own: | ||
|
||
```ts | ||
import '@cartamd/plugin-anchor/default.css'; | ||
``` | ||
|
||
### Extension | ||
|
||
```svelte | ||
<script> | ||
import { Carta, CartaEditor } from 'carta-md'; | ||
import { anchor } from '@cartamd/plugin-anchor'; | ||
const carta = new Carta({ | ||
extensions: [anchor()] | ||
}); | ||
</script> | ||
<CartaEditor {carta} /> | ||
``` | ||
|
||
## Documentation | ||
|
||
Checkout the [docs](https://beartocode.github.io/carta/plugins/anchor) for examples, options and more. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
{ | ||
"name": "@cartamd/plugin-anchor", | ||
"version": "3.0.0", | ||
"type": "module", | ||
"main": "./dist/index.js", | ||
"types": "./dist/index.d.ts", | ||
"license": "MIT", | ||
"scripts": { | ||
"dev": "vite dev", | ||
"build": "vite build && npm run package", | ||
"preview": "vite preview", | ||
"package": "svelte-kit sync && svelte-package && publint", | ||
"prepublishOnly": "npm run package", | ||
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", | ||
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/BearToCode/carta.git" | ||
}, | ||
"exports": { | ||
".": { | ||
"types": "./dist/index.d.ts", | ||
"svelte": "./dist/index.js" | ||
}, | ||
"./default.css": "./dist/default.css", | ||
"./default-theme.css": "./dist/default.css" | ||
}, | ||
"files": [ | ||
"dist", | ||
"!dist/**/*.test.*", | ||
"!dist/**/*.spec.*" | ||
], | ||
"dependencies": { | ||
"slugify": "^1.6.6" | ||
}, | ||
"peerDependencies": { | ||
"carta-md": "^3.1.0", | ||
"marked": "^9.1.5", | ||
"svelte": "^3.54.0 || ^4.0.0" | ||
}, | ||
"devDependencies": { | ||
"@sveltejs/adapter-auto": "^2.0.0", | ||
"@sveltejs/kit": "^1.5.0", | ||
"@sveltejs/package": "^2.0.0", | ||
"carta-md": "workspace:*", | ||
"publint": "^0.1.9", | ||
"svelte": "^3.54.0 || ^4.0.0", | ||
"svelte-check": "^3.0.1", | ||
"tslib": "^2.4.1", | ||
"typescript": "^5.0.0", | ||
"vite": "^4.3.9", | ||
"marked": "^9.1.5" | ||
}, | ||
"svelte": "./dist/index.js", | ||
"keywords": [ | ||
"carta", | ||
"markdown", | ||
"editor", | ||
"marked", | ||
"text editor", | ||
"marked editor", | ||
"slash", | ||
"syntax highlighting", | ||
"emoji", | ||
"katex" | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
// See https://kit.svelte.dev/docs/types#app | ||
// for information about these interfaces | ||
declare global { | ||
namespace App { | ||
// interface Error {} | ||
// interface Locals {} | ||
// interface PageData {} | ||
// interface Platform {} | ||
} | ||
} | ||
|
||
export {}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
<!doctype html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="utf-8" /> | ||
<link rel="icon" href="%sveltekit.assets%/favicon.png" /> | ||
<meta name="viewport" content="width=device-width, initial-scale=1" /> | ||
%sveltekit.head% | ||
</head> | ||
<body data-sveltekit-preload-data="hover"> | ||
<div>%sveltekit.body%</div> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
.carta-renderer .anchor-link { | ||
visibility: hidden; | ||
opacity: 0.6; | ||
} | ||
|
||
.carta-renderer h1:hover .anchor-link, | ||
.carta-renderer h2:hover .anchor-link, | ||
.carta-renderer h3:hover .anchor-link, | ||
.carta-renderer h4:hover .anchor-link, | ||
.carta-renderer h5:hover .anchor-link, | ||
.carta-renderer h6:hover .anchor-link { | ||
visibility: visible; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
import type { CartaExtension } from 'carta-md'; | ||
import { generateUniqueSlug } from './slug'; | ||
export * from './default.css?inline'; | ||
|
||
export interface AnchorExtensionOptions { | ||
/** | ||
* Maximum depth of headers to generate anchors for. Defaults to 6. | ||
*/ | ||
maxDepth?: number; | ||
} | ||
|
||
/** | ||
* Carta anchor plugin. Adds support to render anchor links in header tags. | ||
*/ | ||
export const anchor = (options?: AnchorExtensionOptions): CartaExtension => { | ||
let slugs: string[] = []; | ||
|
||
const maxDepth = options?.maxDepth ?? 6; | ||
|
||
return { | ||
// Reset the slug history after rendering completes, so the links persist after re-rendering | ||
listeners: [ | ||
['carta-render', () => (slugs = [])], | ||
['carta-render-ssr', () => (slugs = [])] | ||
], | ||
markedExtensions: [ | ||
{ | ||
renderer: { | ||
heading(text, level, raw) { | ||
if (level > maxDepth) { | ||
return false; | ||
} | ||
|
||
const slug = generateUniqueSlug(raw, slugs); | ||
|
||
return ` | ||
<h${level}> | ||
<span>${text}</span> | ||
<a id="${slug}" href="#${slug}" class="anchor-link"> | ||
<svg xmlns="http://www.w3.org/2000/svg" | ||
viewBox="0 0 16 16" width="16" height="16"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg> | ||
</a> | ||
</h${level}>`; | ||
} | ||
} | ||
} | ||
] | ||
}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import slugify from 'slugify'; | ||
|
||
function generateSlug(raw: string) { | ||
const base = slugify(raw, { | ||
lower: true, | ||
remove: /[^a-zA-Z0-9_\- ]/g | ||
}); | ||
return base; | ||
} | ||
|
||
export function generateUniqueSlug(raw: string, slugs: string[]) { | ||
const base = generateSlug(raw); | ||
let slug = base; | ||
|
||
let i = 1; | ||
// Add unique suffix to slug if it already exists | ||
while (slugs.includes(slug)) { | ||
slug = `${base}-${i}`; | ||
i++; | ||
} | ||
slugs.push(slug); | ||
return slug; | ||
} |
Oops, something went wrong.