Update packages/remark-wiki-link/src/lib/remarkWikiLink.ts
Some checks failed
Release / Release (push) Failing after 1h6m8s
Some checks failed
Release / Release (push) Failing after 1h6m8s
This commit is contained in:
parent
816db6858c
commit
47b4ffece8
@ -1,42 +1,203 @@
|
|||||||
import { toMarkdown } from "mdast-util-wiki-link";
|
import { isSupportedFileFormat } from './isSupportedFileFormat';
|
||||||
import { syntax, SyntaxOptions } from "./syntax";
|
|
||||||
import { fromMarkdown, FromMarkdownOptions } from "./fromMarkdown";
|
|
||||||
|
|
||||||
let warningIssued = false;
|
const defaultWikiLinkResolver = (target: string) => {
|
||||||
|
// for [[#heading]] links
|
||||||
|
if (!target) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
let permalink = target.replace(/\/index$/, '');
|
||||||
|
// TODO what to do with [[index]] link?
|
||||||
|
if (permalink.length === 0) {
|
||||||
|
permalink = '/';
|
||||||
|
}
|
||||||
|
return [permalink];
|
||||||
|
};
|
||||||
|
|
||||||
type RemarkWikiLinkOptions = FromMarkdownOptions & SyntaxOptions;
|
export interface FromMarkdownOptions {
|
||||||
|
pathFormat?:
|
||||||
function remarkWikiLink(opts: RemarkWikiLinkOptions = {}) {
|
| 'raw' // default; use for regular relative or absolute paths
|
||||||
const data = this.data(); // this is a reference to the processor
|
| 'obsidian-absolute' // use for Obsidian-style absolute paths (with no leading slash)
|
||||||
|
| 'obsidian-short'; // use for Obsidian-style shortened paths (shortest path possible)
|
||||||
function add(field, value) {
|
permalinks?: string[]; // list of permalinks to match possible permalinks of a wiki link against
|
||||||
if (data[field]) data[field].push(value);
|
wikiLinkResolver?: (name: string) => string[]; // function to resolve wiki links to an array of possible permalinks
|
||||||
else data[field] = [value];
|
newClassName?: string; // class name to add to links that don't have a matching permalink
|
||||||
|
wikiLinkClassName?: string; // class name to add to all wiki links
|
||||||
|
hrefTemplate?: (permalink: string) => string; // function to generate the href attribute of a link
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
export function getImageSize(size: string) {
|
||||||
!warningIssued &&
|
// eslint-disable-next-line prefer-const
|
||||||
((this.Parser &&
|
let [width, height] = size.split('x');
|
||||||
this.Parser.prototype &&
|
|
||||||
this.Parser.prototype.blockTokenizers) ||
|
if (!height) height = width;
|
||||||
(this.Compiler &&
|
|
||||||
this.Compiler.prototype &&
|
return { width, height };
|
||||||
this.Compiler.prototype.visitors))
|
}
|
||||||
) {
|
|
||||||
warningIssued = true;
|
// mdas-util-from-markdown extension
|
||||||
console.warn(
|
// https://github.com/syntax-tree/mdast-util-from-markdown#extension
|
||||||
"[remark-wiki-link] Warning: please upgrade to remark 13 to use this plugin"
|
function fromMarkdown(opts: FromMarkdownOptions = {}) {
|
||||||
|
const pathFormat = opts.pathFormat || 'raw';
|
||||||
|
const permalinks = opts.permalinks || [];
|
||||||
|
const wikiLinkResolver = opts.wikiLinkResolver || defaultWikiLinkResolver;
|
||||||
|
const newClassName = opts.newClassName || 'new';
|
||||||
|
const wikiLinkClassName = opts.wikiLinkClassName || 'internal';
|
||||||
|
const defaultHrefTemplate = (permalink: string) => permalink;
|
||||||
|
|
||||||
|
const hrefTemplate = opts.hrefTemplate || defaultHrefTemplate;
|
||||||
|
|
||||||
|
function top(stack) {
|
||||||
|
return stack[stack.length - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
function enterWikiLink(token) {
|
||||||
|
this.enter(
|
||||||
|
{
|
||||||
|
type: 'wikiLink',
|
||||||
|
data: {
|
||||||
|
isEmbed: token.isType === 'embed',
|
||||||
|
target: null, // the target of the link, e.g. "Foo Bar#Heading" in "[[Foo Bar#Heading]]"
|
||||||
|
alias: null, // the alias of the link, e.g. "Foo" in "[[Foo Bar|Foo]]"
|
||||||
|
permalink: null, // TODO shouldn't this be named just "link"?
|
||||||
|
exists: null, // TODO is this even needed here?
|
||||||
|
// fields for mdast-util-to-hast (used e.g. by remark-rehype)
|
||||||
|
hName: null,
|
||||||
|
hProperties: null,
|
||||||
|
hChildren: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
token
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// add extensions to packages used by remark-parse
|
function exitWikiLinkTarget(token) {
|
||||||
// micromark extensions
|
const target = this.sliceSerialize(token);
|
||||||
add("micromarkExtensions", syntax(opts));
|
const current = top(this.stack);
|
||||||
// mdast-util-from-markdown extensions
|
current.data.target = target;
|
||||||
add("fromMarkdownExtensions", fromMarkdown(opts));
|
|
||||||
// mdast-util-to-markdown extensions
|
|
||||||
add("toMarkdownExtensions", toMarkdown(opts));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default remarkWikiLink;
|
function exitWikiLinkAlias(token) {
|
||||||
export { remarkWikiLink };
|
const alias = this.sliceSerialize(token);
|
||||||
|
const current = top(this.stack);
|
||||||
|
current.data.alias = alias;
|
||||||
|
}
|
||||||
|
|
||||||
|
function exitWikiLink(token) {
|
||||||
|
const wikiLink = top(this.stack)
|
||||||
|
const {
|
||||||
|
data: {isEmbed, target, alias},
|
||||||
|
} = wikiLink;
|
||||||
|
this.exit(token);
|
||||||
|
// eslint-disable-next-line no-useless-escape
|
||||||
|
const wikiLinkWithHeadingPattern = /^(.*?)(#.*)?$/u;
|
||||||
|
const [, path, heading = ''] = target.match(wikiLinkWithHeadingPattern);
|
||||||
|
|
||||||
|
const possibleWikiLinkPermalinks = wikiLinkResolver(path);
|
||||||
|
|
||||||
|
const matchingPermalink = permalinks.find((e) => {
|
||||||
|
return possibleWikiLinkPermalinks.find((p) => {
|
||||||
|
if (pathFormat === 'obsidian-short') {
|
||||||
|
if (e === p || e.endsWith(p)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else if (pathFormat === 'obsidian-absolute') {
|
||||||
|
if (e === '/' + p) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (e === p) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// TODO this is ugly
|
||||||
|
const link =
|
||||||
|
matchingPermalink ||
|
||||||
|
(pathFormat === 'obsidian-absolute'
|
||||||
|
? '/' + possibleWikiLinkPermalinks[0]
|
||||||
|
: possibleWikiLinkPermalinks[0]) ||
|
||||||
|
'';
|
||||||
|
|
||||||
|
wikiLink.data.exists = !!matchingPermalink;
|
||||||
|
wikiLink.data.permalink = link;
|
||||||
|
// remove leading # if the target is a heading on the same page
|
||||||
|
const displayName = alias || target.replace(/^#/, '');
|
||||||
|
const headingId = heading.replace(/\s+/g, '-').toLowerCase();
|
||||||
|
let classNames = wikiLinkClassName;
|
||||||
|
if (!matchingPermalink) {
|
||||||
|
classNames += ' ' + newClassName;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isEmbed) {
|
||||||
|
const [isSupportedFormat, format] = isSupportedFileFormat(target);
|
||||||
|
if (!isSupportedFormat) {
|
||||||
|
// Temporarily render note transclusion as a regular wiki link
|
||||||
|
if (!format) {
|
||||||
|
wikiLink.data.hName = 'a';
|
||||||
|
wikiLink.data.hProperties = {
|
||||||
|
className: classNames + ' ' + 'transclusion',
|
||||||
|
href: hrefTemplate(link) + headingId,
|
||||||
|
};
|
||||||
|
wikiLink.data.hChildren = [{ type: 'text', value: displayName }];
|
||||||
|
} else {
|
||||||
|
wikiLink.data.hName = 'p';
|
||||||
|
wikiLink.data.hChildren = [
|
||||||
|
{
|
||||||
|
type: 'text',
|
||||||
|
value: `![[${target}]]`,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
} else if (format === 'pdf') {
|
||||||
|
wikiLink.data.hName = 'iframe';
|
||||||
|
wikiLink.data.hProperties = {
|
||||||
|
className: classNames,
|
||||||
|
width: '100%',
|
||||||
|
src: `${hrefTemplate(link)}#toolbar=0`,
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
const hasDimensions = alias && /^\d+(x\d+)?$/.test(alias);
|
||||||
|
// Take the target as alt text except if alt name was provided [[target|alt text]]
|
||||||
|
const altText = hasDimensions || !alias ? target : alias;
|
||||||
|
|
||||||
|
wikiLink.data.hName = 'img';
|
||||||
|
wikiLink.data.hProperties = {
|
||||||
|
className: classNames,
|
||||||
|
src: hrefTemplate(link),
|
||||||
|
alt: altText
|
||||||
|
};
|
||||||
|
|
||||||
|
if (hasDimensions) {
|
||||||
|
const { width, height } = getImageSize(alias as string);
|
||||||
|
Object.assign(wikiLink.data.hProperties, {
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
wikiLink.data.hName = 'a';
|
||||||
|
wikiLink.data.hProperties = {
|
||||||
|
className: classNames,
|
||||||
|
href: hrefTemplate(link) + headingId,
|
||||||
|
};
|
||||||
|
wikiLink.data.hChildren = [{ type: 'text', value: displayName }];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
enter: {
|
||||||
|
wikiLink: enterWikiLink,
|
||||||
|
},
|
||||||
|
exit: {
|
||||||
|
wikiLinkTarget: exitWikiLinkTarget,
|
||||||
|
wikiLinkAlias: exitWikiLinkAlias,
|
||||||
|
wikiLink: exitWikiLink,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export { fromMarkdown };
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user