You've already forked obsidian-visualiser
First version
This commit is contained in:
15
transformer/canvas/module.ts
Normal file
15
transformer/canvas/module.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { resolve } from 'path'
|
||||
import { defineNuxtModule } from '@nuxt/kit'
|
||||
|
||||
export default defineNuxtModule({
|
||||
setup(_options, nuxt) {
|
||||
nuxt.options.nitro.externals = nuxt.options.nitro.externals || {}
|
||||
nuxt.options.nitro.externals.inline = nuxt.options.nitro.externals.inline || []
|
||||
nuxt.options.nitro.externals.inline.push(resolve('./transformer/canvas/module'))
|
||||
|
||||
// @ts-ignore
|
||||
nuxt.hook('content:context', (contentContext) => {
|
||||
contentContext.transformers.push(resolve('./transformer/canvas/transformer'))
|
||||
})
|
||||
}
|
||||
})
|
||||
122
transformer/canvas/transformer.ts
Normal file
122
transformer/canvas/transformer.ts
Normal file
@@ -0,0 +1,122 @@
|
||||
import type { MarkdownOptions, MarkdownPlugin, MarkdownParsedContent } from '@nuxt/content/dist/runtime/types'
|
||||
import { defineTransformer } from '@nuxt/content/transformers'
|
||||
import slugify from 'slugify'
|
||||
import { withoutTrailingSlash, withLeadingSlash } from 'ufo'
|
||||
|
||||
import { parseMarkdown } from '@nuxtjs/mdc/dist/runtime'
|
||||
import { type State } from 'mdast-util-to-hast'
|
||||
import { normalizeUri } from 'micromark-util-sanitize-uri'
|
||||
import { type Properties, type Element } from 'hast'
|
||||
import { type Link } from 'mdast'
|
||||
import { isRelative } from 'ufo'
|
||||
|
||||
export default defineTransformer({
|
||||
name: 'canvas',
|
||||
extensions: ['.canvas'],
|
||||
async parse(_id, rawContent, options) {
|
||||
const config = { ...options } as MarkdownOptions
|
||||
config.rehypePlugins = await importPlugins(config.rehypePlugins)
|
||||
config.remarkPlugins = await importPlugins(config.remarkPlugins)
|
||||
|
||||
await Promise.all(rawContent.nodes?.map(async (e: any) => {
|
||||
if(e.text !== undefined)
|
||||
{
|
||||
e.text = await parseMarkdown(e.text as string, {
|
||||
remark: {
|
||||
plugins: config.remarkPlugins
|
||||
},
|
||||
rehype: {
|
||||
options: {
|
||||
handlers: {
|
||||
link: link as any
|
||||
}
|
||||
},
|
||||
plugins: config.rehypePlugins
|
||||
}
|
||||
})
|
||||
}
|
||||
}));
|
||||
|
||||
return {
|
||||
_id,
|
||||
body: rawContent,
|
||||
_type: 'canvas',
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
async function importPlugins(plugins: Record<string, false | MarkdownPlugin> = {}) {
|
||||
const resolvedPlugins: Record<string, false | MarkdownPlugin & { instance: any }> = {}
|
||||
for (const [name, plugin] of Object.entries(plugins)) {
|
||||
if (plugin) {
|
||||
resolvedPlugins[name] = {
|
||||
instance: plugin.instance || await import(/* @vite-ignore */ name).then(m => m.default || m),
|
||||
options: plugin
|
||||
}
|
||||
} else {
|
||||
resolvedPlugins[name] = false
|
||||
}
|
||||
}
|
||||
return resolvedPlugins
|
||||
}
|
||||
|
||||
function link(state: State, node: Link & { attributes?: Properties }) {
|
||||
const properties: Properties = {
|
||||
...((node.attributes || {})),
|
||||
href: normalizeUri(normalizeLink(node.url))
|
||||
}
|
||||
|
||||
if (node.title !== null && node.title !== undefined) {
|
||||
properties.title = node.title
|
||||
}
|
||||
|
||||
const result: Element = {
|
||||
type: 'element',
|
||||
tagName: 'a',
|
||||
properties,
|
||||
children: state.all(node)
|
||||
}
|
||||
state.patch(node, result)
|
||||
return state.applyData(node, result)
|
||||
}
|
||||
|
||||
function normalizeLink(link: string) {
|
||||
const match = link.match(/#.+$/)
|
||||
const hash = match ? match[0] : ''
|
||||
if (link.replace(/#.+$/, '').endsWith('.md') && (isRelative(link) || (!/^https?/.test(link) && !link.startsWith('/')))) {
|
||||
return (generatePath(link.replace('.md' + hash, ''), { forceLeadingSlash: false }) + hash)
|
||||
} else {
|
||||
return link
|
||||
}
|
||||
}
|
||||
|
||||
const generatePath = (path: string, { forceLeadingSlash = true, respectPathCase = false } = {}): string => {
|
||||
path = path.split('/').map(part => slugify(refineUrlPart(part), { lower: !respectPathCase })).join('/')
|
||||
return forceLeadingSlash ? withLeadingSlash(withoutTrailingSlash(path)) : path
|
||||
}
|
||||
|
||||
const SEMVER_REGEX = /^(\d+)(\.\d+)*(\.x)?$/
|
||||
|
||||
function refineUrlPart(name: string): string {
|
||||
name = name.split(/[/:]/).pop()!
|
||||
// Match 1, 1.2, 1.x, 1.2.x, 1.2.3.x,
|
||||
if (SEMVER_REGEX.test(name)) {
|
||||
return name
|
||||
}
|
||||
|
||||
return (
|
||||
name
|
||||
/**
|
||||
* Remove numbering
|
||||
*/
|
||||
.replace(/(\d+\.)?(.*)/, '$2')
|
||||
/**
|
||||
* Remove index keyword
|
||||
*/
|
||||
.replace(/^index(\.draft)?$/, '')
|
||||
/**
|
||||
* Remove draft keyword
|
||||
*/
|
||||
.replace(/\.draft$/, '')
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user