feat: enhance Wiki Link syntax to support line and column positions

This commit is contained in:
purocean
2024-06-18 00:48:10 +08:00
parent 74ebb11555
commit 03f0dcd824
5 changed files with 50 additions and 12 deletions
+1 -1
View File
@@ -69,7 +69,7 @@ Type '/' in the editor to get prompts
*[HTML]: Hyper Text Markup Language
*[W3C]: World Wide Web Consortium
The HTML specification is maintained by the W3C.
+ Wiki Link: Supports using `[[filename#anchor|display text]]` syntax to link documents, such as [[README#Highlights|Highlights]]
+ Wiki Link: Supports using `[[filename#anchor|display text]]` or `[[filename:line,column|display text]]` syntax to link documents, such as [[README#Highlights|Features]] [[README:3,4]]
## Github Alerts
+1 -1
View File
@@ -70,7 +70,7 @@ define:
*[HTML]: Hyper Text Markup Language
*[W3C]: World Wide Web Consortium
The HTML specification is maintained by the W3C.
+ Wiki 链接:支持使用 `[[文件名#锚点|显示文本]]` 语法来链接文档,如 [[README#Highlights|特色功能]]
+ Wiki 链接:支持使用 `[[文件名#锚点|显示文本]]` 或 `[[文件名:行,列|显示文本]]` 语法来链接文档,如 [[README#Highlights|特色功能]] [[README:3,4]]
## Github Alerts
@@ -358,6 +358,7 @@ body.find-in-preview-highlight ::selection {
}
a[href$=".md"],
a[href*=".md:"],
a[href*=".md#"] {
&:after {
content: '\200D\2002';
+34 -5
View File
@@ -1,6 +1,6 @@
import StateCore from 'markdown-it/lib/rules_core/state_core'
import Token from 'markdown-it/lib/token'
import { Plugin } from '@fe/context'
import ctx, { Plugin } from '@fe/context'
import store from '@fe/support/store'
import { removeQuery, sleep } from '@fe/utils'
import { isElectron, isWindows } from '@fe/support/env'
@@ -142,10 +142,33 @@ function handleLink (link: HTMLAnchorElement): boolean {
}
const tmp = decodeURI(href).split('#')
const rePos = /:([0-9]+),?([0-9]+)?$/
const setPosition = (line: number, column: number) => {
ctx.view.disableSyncScrollAwhile(() => {
if (ctx.editor.isDefault()) {
ctx.editor.highlightLine(line, true, 1000)
ctx.editor.getEditor().setPosition({ lineNumber: line, column })
ctx.editor.getEditor().focus()
}
ctx.view.highlightLine(line, true, 1000)
})
}
const parsePathPos = (path: string): {pos: [number, number] | null, path: string} => {
const match = path.match(rePos)
let pos: [number, number] | null = null
if (match) {
path = path.replace(rePos, '')
pos = [parseInt(match[1]), match[2] ? parseInt(match[2]) : 1]
}
return { pos, path }
}
const _switchDoc = async () => {
let path = normalizeSep(tmp[0])
let { path, pos } = parsePathPos(normalizeSep(tmp[0]))
const dir = dirname(filePath || '')
// wiki link
@@ -159,13 +182,15 @@ function handleLink (link: HTMLAnchorElement): boolean {
const file: Doc = { path, type: 'file', name: basename(path), repo: fileRepo }
return switchDoc(file)
return switchDoc(file).then(() => {
pos && setPosition(pos[0], pos[1])
})
}
const path = normalizeSep(tmp[0])
const file: Doc = { path, type: 'file', name: basename(path), repo: fileRepo }
const isMarkdownFile = /(\.md$|\.md#)/.test(href)
const isMarkdownFile = /(\.md$|\.md#|\.md:)/.test(href)
const supportOpenDirectly = isMarkdownFile || getAllCustomEditors().some(x => x.when?.({ doc: file }))
if (supportOpenDirectly) {
@@ -194,6 +219,10 @@ function handleLink (link: HTMLAnchorElement): boolean {
el && scrollIntoView(el)
})
return true
} else if (href && href.startsWith(':') && rePos.test(href)) { // for pos
const { pos } = parsePathPos(href)
pos && setPosition(pos[0], pos[1])
return true
} else {
return false
}
+13 -5
View File
@@ -1,9 +1,10 @@
import ctx, { Plugin } from '@fe/context'
import type StateInline from 'markdown-it/lib/rules_inline/state_inline'
const reMatch = /^\s*([^[#|]*)?(?:#([^|]*))?(?:\|([^\]]*))?\s*$/
const reMatch = /^([^[#|]*)?(?:#([^#|]*))?(?:\|([^\]]*))?$/
const reExternalLink = /^[a-zA-Z]{1,8}:\/\/.*/
const reExtName = /\.[^/]+$/
const rePos = /(:\d{1,6},?\d{0,6})$/
function wikiLinks (state: StateInline, silent?: boolean) {
// check [[
@@ -22,7 +23,7 @@ function wikiLinks (state: StateInline, silent?: boolean) {
return false
}
const link = (parts[1] || '').trim()
let link = (parts[1] || '').trim()
const hash = parts[2] || ''
const label = parts[3] || ''
@@ -33,14 +34,21 @@ function wikiLinks (state: StateInline, silent?: boolean) {
// internal link
if (!reExternalLink.test(link)) {
let posStr = ''
const posMatch = link.match(rePos)
if (posMatch) {
link = link.replace(rePos, '')
posStr = posMatch[1]
}
const fileName = link.split('/').pop()
text = label || (fileName ? fileName + hashStr : url)
text = label || (fileName ? (fileName + posStr + hashStr) : url)
// no extension name
if (link && !reExtName.test(link)) {
url = `${link}.md${hashStr}`
url = `${link}.md${posStr}${hashStr}`
} else if (!link) {
url = hashStr
url = posStr + hashStr
text = label || hash || url
}
}