feat: support emoji tags (closes #634)
| | |
| | | const calloutLineRegex = new RegExp(/^> *\[\!\w+\][+-]?.*$/, "gm") |
| | | // (?:^| ) -> non-capturing group, tag should start be separated by a space or be the start of the line |
| | | // #(...) -> capturing group, tag itself must start with # |
| | | // (?:[-_\p{L}])+ -> non-capturing group, non-empty string of (Unicode-aware) alpha-numeric characters, hyphens and/or underscores |
| | | // (?:\/[-_\p{L}]+)*) -> non-capturing group, matches an arbitrary number of tag strings separated by "/" |
| | | const tagRegex = new RegExp(/(?:^| )#((?:[-_\p{L}\d])+(?:\/[-_\p{L}\d]+)*)/, "gu") |
| | | // (?:[-_\p{L}\d\p{Z}])+ -> non-capturing group, non-empty string of (Unicode-aware) alpha-numeric characters and symbols, hyphens and/or underscores |
| | | // (?:\/[-_\p{L}\d\p{Z}]+)*) -> non-capturing group, matches an arbitrary number of tag strings separated by "/" |
| | | const tagRegex = new RegExp(/(?:^| )#((?:[-_\p{L}\d\p{Z}])+(?:\/[-_\p{L}\d\p{Z}]+)*)/, "gu") |
| | | const blockReferenceRegex = new RegExp(/\^([A-Za-z0-9]+)$/, "g") |
| | | |
| | | export const ObsidianFlavoredMarkdown: QuartzTransformerPlugin<Partial<Options> | undefined> = ( |
| | |
| | | if (/^\d+$/.test(tag)) { |
| | | return false |
| | | } |
| | | |
| | | tag = slugTag(tag) |
| | | if (file.data.frontmatter && !file.data.frontmatter.tags.includes(tag)) { |
| | | file.data.frontmatter.tags.push(tag) |
| | |
| | | import { slug } from "github-slugger" |
| | | import { slug as slugAnchor } from "github-slugger" |
| | | import type { Element as HastElement } from "hast" |
| | | // this file must be isomorphic so it can't use node libs (e.g. path) |
| | | |
| | |
| | | return res |
| | | } |
| | | |
| | | function sluggify(s: string): string { |
| | | return s |
| | | .split("/") |
| | | .map((segment) => segment.replace(/\s/g, "-").replace(/%/g, "-percent").replace(/\?/g, "-q")) // slugify all segments |
| | | .join("/") // always use / as sep |
| | | .replace(/\/$/, "") |
| | | } |
| | | |
| | | export function slugifyFilePath(fp: FilePath, excludeExt?: boolean): FullSlug { |
| | | fp = _stripSlashes(fp) as FilePath |
| | | let ext = _getFileExtension(fp) |
| | |
| | | ext = "" |
| | | } |
| | | |
| | | let slug = withoutFileExt |
| | | .split("/") |
| | | .map((segment) => segment.replace(/\s/g, "-").replace(/%/g, "-percent").replace(/\?/g, "-q")) // slugify all segments |
| | | .join("/") // always use / as sep |
| | | .replace(/\/$/, "") // remove trailing slash |
| | | let slug = sluggify(withoutFileExt) |
| | | |
| | | // treat _index as index |
| | | if (_endsWith(slug, "_index")) { |
| | |
| | | return [fp, anchor] |
| | | } |
| | | |
| | | export function slugAnchor(anchor: string) { |
| | | return slug(anchor) |
| | | } |
| | | |
| | | export function slugTag(tag: string) { |
| | | return tag |
| | | .split("/") |
| | | .map((tagSegment) => slug(tagSegment)) |
| | | .map((tagSegment) => sluggify(tagSegment)) |
| | | .join("/") |
| | | } |
| | | |