-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: implement wikilink and embed images
- Loading branch information
Showing
6 changed files
with
263 additions
and
34 deletions.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
*.log | ||
index.js | ||
node_modules | ||
node_modules | ||
*.d.ts | ||
*.js |
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,63 @@ | ||
# Gatsby Remark Enhanced Wikilink | ||
|
||
A Gatsby Remark plugin that adds support to Enhanced Wikilink Syntax (e.g., Obsidian Internal Links) for Gatsby ^4.0.0 | ||
|
||
- To support file linking and image embedding, use with `gatsby-remark-images`, `gatsby-remark-copy-linked-files` and `gatsby-source-filesystem` | ||
- To be compatible with `gatsby-remark-autolink-headers`, the default implementation uses [Github Slugger](https://github.com/Flet/github-slugger) to slugify filenames and headings. This can be configured via setting a new `wikilinkToUrl` function. For more information, please see `Options` section below. | ||
|
||
## Supported Syntax | ||
|
||
- [x] Linking to MD files via `[[Internal Link#Heading | Alias]]` | ||
- [x] Linking to other files via `[[../path/document.pdf]]` | ||
- [x] Embed Images `![[../images/Hello.png]]` | ||
- [ ] Embed Notes `![[Internal Notes]]` | ||
|
||
## Installation | ||
|
||
```bash | ||
yarn add gatsby-remark-enhanced-wikilink | ||
``` | ||
|
||
## Usage | ||
|
||
Add the plugin to your Gatsby config: | ||
|
||
```js | ||
// gatsby-config.js | ||
plugins: [ | ||
{ | ||
resolve: "gatsby-transformer-remark", | ||
options: { | ||
plugins: [ | ||
{ | ||
resolve: 'gatsby-remark-obsidian', | ||
options: { | ||
stripBrackets: true, | ||
imageExtensions: ['png', 'jpg', 'jpeg'], | ||
fileFileExtensions: ['png', 'jpg', 'jpeg', 'pdf'] | ||
// see other options below | ||
}, | ||
}, | ||
] | ||
} | ||
}, | ||
], | ||
``` | ||
|
||
## Options | ||
|
||
```ts | ||
type WikilinkArgs = { | ||
fileName?: string; | ||
heading?: string; | ||
alias?: string; | ||
}; | ||
|
||
type Options = { | ||
stripBrackets?: boolean; | ||
wikilinkToUrl?: (args: WikilinkArgs) => string; | ||
wikilinkToLinkText?: (args: WikilinkArgs) => string; | ||
imageExtensions?: Array<string>; | ||
linkFileExtensions?: Array<string>; | ||
}; | ||
``` |
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 |
---|---|---|
@@ -1,24 +1,42 @@ | ||
{ | ||
"name": "gatsby-remark-wikilink", | ||
"name": "gatsby-remark-enhanced-wikilink", | ||
"version": "1.0.0", | ||
"description": "Add wikilinks to Gatsby Remark", | ||
"description": "A Gatsby Remark plugin that adds support to Enhanced Wikilink Syntax", | ||
"main": "index.js", | ||
"types": "index.d.ts", | ||
"author": "Anakorn Kyavatanakij <anakornk@gmail.com>", | ||
"license": "MIT", | ||
"keywords": [ | ||
"gatsby", | ||
"remark", | ||
"wikilink", | ||
"obsidian" | ||
], | ||
"files": [ | ||
"index.js", | ||
"index.d.ts" | ||
], | ||
"scripts": { | ||
"build": "tsc", | ||
"watch": "tsc --watch", | ||
"prepack": "tsc" | ||
}, | ||
"dependencies": { | ||
"github-slugger": "^1.4.0", | ||
"unist-util-visit": "^2.0.2" | ||
}, | ||
"devDependencies": { | ||
"@types/github-slugger": "^1.3.0", | ||
"@types/mdast": "^3.0.10", | ||
"@types/node": "^17.0.5", | ||
"typescript": "^4.5.4" | ||
}, | ||
"peerDependencies": { | ||
"gatsby": "^4.0.0" | ||
}, | ||
"scripts": { | ||
"build": "tsc", | ||
"watch": "tsc --watch" | ||
}, | ||
"dependencies": { | ||
"unist-util-visit": "^2.0.2", | ||
"mdast-util-to-string": "^2.0.0" | ||
"homepage": "https://github.com/anakornk/gatsby-remark-enhanced-wikilink#readme", | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/anakornk/gatsby-remark-enhanced-wikilink.git" | ||
} | ||
} |
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 |
---|---|---|
@@ -1,21 +1,162 @@ | ||
import visit from 'unist-util-visit'; | ||
import toString from 'mdast-util-to-string'; | ||
|
||
export = async ({ markdownAST }: any) => { | ||
visit(markdownAST, 'heading', (node: any) => { | ||
let { depth } = node; | ||
// Skip if not an h1 | ||
if (depth !== 1) return; | ||
// Grab the innerText of the heading node | ||
let text = toString(node); | ||
const html = ` | ||
<h1 style="color: rebeccapurple"> | ||
${text} | ||
</h1> | ||
`; | ||
node.type = 'html'; | ||
node.children = undefined; | ||
node.value = html; | ||
import { Node } from 'unist'; | ||
import GithubSlugger from 'github-slugger'; | ||
import type { Text } from 'mdast'; | ||
|
||
type WikilinkArgs = { | ||
fileName?: string; | ||
heading?: string; | ||
alias?: string; | ||
}; | ||
|
||
type Options = { | ||
stripBrackets?: boolean; | ||
wikilinkToUrl?: (args: WikilinkArgs) => string; | ||
wikilinkToLinkText?: (args: WikilinkArgs) => string; | ||
imageExtensions?: Array<string>; | ||
linkFileExtensions?: Array<string>; | ||
}; | ||
|
||
const slugify = GithubSlugger.slug; | ||
|
||
const defaultWikilinkToUrl: Options['wikilinkToUrl'] = ({ | ||
fileName, | ||
heading, | ||
}) => { | ||
return `${slugify(fileName)}${heading && `#${slugify(heading)}`}` || '#'; | ||
}; | ||
|
||
const defaultWikilinkToLinkText: Options['wikilinkToLinkText'] = ({ | ||
fileName, | ||
heading, | ||
alias, | ||
}) => { | ||
return ( | ||
alias || | ||
(fileName && heading && `${fileName} > ${heading}`) || | ||
fileName || | ||
`> ${heading}` | ||
); | ||
}; | ||
|
||
const wrapWithBrackets = (text: string, isEmbed: boolean = false) => { | ||
return isEmbed ? `![[${text}]]` : `[[${text}]]`; | ||
}; | ||
|
||
const transformWikilink = ( | ||
{ markdownAST }: { markdownAST: Node }, | ||
{ | ||
stripBrackets = true, | ||
wikilinkToUrl = defaultWikilinkToUrl, | ||
wikilinkToLinkText = defaultWikilinkToLinkText, | ||
imageExtensions = ['png', 'jpg', 'jpeg'], | ||
linkFileExtensions = ['png', 'jpg', 'jpeg', 'pdf'], | ||
}: Options | ||
) => { | ||
visit<Text>(markdownAST, 'text', (node, index, parent) => { | ||
if (!parent) return; | ||
|
||
const { value: text } = node; | ||
|
||
const wikilinkRegExp = /(!?)\[\[(.+?)\]\]/g; | ||
|
||
const result = []; | ||
let start = 0; | ||
|
||
let match = wikilinkRegExp.exec(text); | ||
|
||
// loop each match and transform wikilinks | ||
while (match) { | ||
const position = match.index; | ||
const fullMatchedString = match[0]; | ||
const isEmbed = match[1] === '!'; | ||
const wikilinkText = match[2]; | ||
|
||
if (start !== position) { | ||
result.push({ | ||
type: 'text', | ||
value: text.slice(start, position), | ||
}); | ||
} | ||
|
||
if (isEmbed) { | ||
const imageRegExp = new RegExp( | ||
`([^\\/]*)\\.(?:${imageExtensions.join('|')})$`, | ||
'i' | ||
); | ||
const imageMatch = wikilinkText.match(imageRegExp); | ||
if (imageMatch) { | ||
result.push({ | ||
type: 'image', | ||
url: wikilinkText, | ||
alt: imageMatch[1] || wikilinkText, | ||
}); | ||
} else { | ||
// TODO: Support embed MD | ||
result.push({ | ||
type: 'text', | ||
value: wrapWithBrackets(wikilinkText, true), | ||
}); | ||
} | ||
} else { | ||
const linkFileRegExp = new RegExp( | ||
`\\.(?:${linkFileExtensions.join('|')})$`, | ||
'i' | ||
); | ||
if (wikilinkText.match(linkFileRegExp)) { | ||
result.push({ | ||
type: 'link', | ||
url: wikilinkText, | ||
children: [ | ||
{ | ||
type: 'text', | ||
value: stripBrackets | ||
? wikilinkText | ||
: wrapWithBrackets(wikilinkText), | ||
}, | ||
], | ||
}); | ||
} else { | ||
// get file name, heading and alias | ||
const splitRegex = /([^#\|]*)(?:#?)([^\|]*)(?:\|?)(.*)/; // split wikilink text to fileName, heading and alias | ||
let [_, fileName, heading, alias] = wikilinkText.match( | ||
splitRegex | ||
) || [,]; | ||
fileName = fileName?.replace(/\.md$/, '').trim(); // support filename with md ext | ||
heading = heading?.trim(); | ||
alias = alias?.trim(); | ||
|
||
const url = wikilinkToUrl({ fileName, heading, alias }); | ||
const linkText = wikilinkToLinkText({ fileName, heading, alias }); | ||
|
||
result.push({ | ||
type: 'link', | ||
url: url, | ||
children: [ | ||
{ | ||
type: 'text', | ||
value: stripBrackets ? linkText : wrapWithBrackets(linkText), | ||
}, | ||
], | ||
}); | ||
} | ||
} | ||
|
||
start = position + fullMatchedString.length; | ||
match = wikilinkRegExp.exec(text); | ||
} | ||
|
||
// if there is at least one match | ||
if (result.length > 0) { | ||
// add the rest of the text that hasn't been matched | ||
if (start < text.length) { | ||
result.push({ type: 'text', value: text.slice(start) }); | ||
} | ||
// add siblings | ||
parent.children.splice(index, 1, ...result); | ||
return index + result.length; | ||
} | ||
}); | ||
return markdownAST; | ||
}; | ||
|
||
export = transformWikilink; |
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