docs-and-graphs
Advanced tools
Comparing version 0.1.24 to 0.2.0
{ | ||
"name": "docs-and-graphs", | ||
"version": "0.1.24", | ||
"version": "0.2.0", | ||
"type": "module", | ||
@@ -11,8 +11,8 @@ "description": "", | ||
"dependencies": { | ||
"js-yaml": "^4.1.0", | ||
"linkify-it": "^4.0.1", | ||
"remark-frontmatter": "^4.0.1", | ||
"remark-gfm": "^3.0.1", | ||
"remark-parse": "^10.0.1", | ||
"remark-wiki-link": "^1.0.4", | ||
"unified": "^10.1.2", | ||
"js-yaml": "^4.1.0" | ||
"unified": "^10.1.2" | ||
}, | ||
@@ -19,0 +19,0 @@ "devDependencies": { |
@@ -1,47 +0,17 @@ | ||
import { parseWikilink, parseExternalLinks } from '../text/links.js' | ||
import { parseLinks } from '../text/links.js' | ||
import { getText } from './markdownAst.js' | ||
//@TODO do some profiling, if markdown use(wikiLinkPlugin) is too expensive do this externally in one place | ||
function findLinks ({ astNode, fullText }) { | ||
const nodeText = getText({ astNode, fullText }) | ||
const result = [] | ||
const ofInterest = (root) => (root.type === 'link' || root.type === | ||
'wikiLink' || root.type === 'image') | ||
function collectChilds (parent, data = []) { | ||
if (parent.children) { | ||
return parent.children.reduce((accumulator, currentValue) => { | ||
if (ofInterest(currentValue)) { | ||
return [currentValue, ...accumulator] | ||
} else { | ||
return collectChilds(currentValue, accumulator) | ||
} | ||
}, data) | ||
} else { | ||
return ofInterest(parent) ? [parent, ...data] : data | ||
for (const line of nodeText.split('\n')) { | ||
for (const link of parseLinks(line)) { | ||
result.push(link) | ||
} | ||
} | ||
} | ||
function findLinks ({ astNode, fullText }) { | ||
return collectChilds(astNode).map(node => { | ||
const text = getText({ astNode: node, fullText }) | ||
if (node.type === 'wikiLink') { | ||
return { | ||
type: 'wikiLink', ...parseWikilink(text), | ||
} | ||
} else if (node.type === 'link' || node.type === 'image') { | ||
const link = parseExternalLinks(text) | ||
if (!link) { | ||
return { | ||
type: 'link', value: node.url, | ||
} | ||
} | ||
return { | ||
type: 'link', ...link, | ||
} | ||
} | ||
return node | ||
}) | ||
return result | ||
} | ||
export { findLinks } |
import remarkFrontmatter from 'remark-frontmatter' | ||
import remarkGfm from 'remark-gfm' | ||
import remarkParse from 'remark-parse' | ||
import wikiLinkPlugin from 'remark-wiki-link' | ||
import { unified } from 'unified' | ||
@@ -11,4 +10,3 @@ | ||
use(remarkFrontmatter). | ||
use(remarkGfm). | ||
use(wikiLinkPlugin) | ||
use(remarkGfm) | ||
return { | ||
@@ -15,0 +13,0 @@ parse: (string) => { |
@@ -0,38 +1,88 @@ | ||
import linkify from 'linkify-it' | ||
import { trim } from './string.js' | ||
// [[hello|world]] -> {value:'hello', alias:'world'} | ||
const wikilinkRegex = /(!?)\[\[(.*?)(?:\|(.*?))?]]/ | ||
const wikilinkRegex = /(!?)\[\[(.*?)(?:\|(.*?))?]]/g | ||
function parseWikilink (str) { | ||
if (str === undefined || str === null) { | ||
return str | ||
} | ||
const match = str.match(wikilinkRegex) | ||
if (match) { | ||
const transclude = match[1] === '!' | ||
const result = { | ||
value: match[2], alias: match[3], | ||
const links = [] | ||
let match | ||
while ((match = wikilinkRegex.exec(str)) !== null) { | ||
const [, transclude, value, alias] = match | ||
const link = { type: 'internal', value, alias } | ||
if (transclude === '!') { | ||
link.transclude = true | ||
} | ||
if (transclude) { | ||
result.transclude = transclude | ||
if (alias) { | ||
link.alias = alias | ||
} | ||
return result | ||
links.push(link) | ||
} | ||
return links | ||
} | ||
// Matches things like [something](http://example.com) and just http://example.com | ||
// Matches things like [something](http://example.com) and [something](/path/file.png) | ||
const linkRegex = /(?:\[([^\]]+)\]\((https?:\/\/[^\s]+)\))|(https?:\/\/[^\s]+)$/ | ||
function captureLinks (string) { | ||
const regex = /\[([^\]]+)\]\(([^)]+)\)/g | ||
let match | ||
let links = [] | ||
function parseExternalLinks (str) { | ||
if (str === undefined || str === null) { | ||
return str | ||
while (match = regex.exec(string)) { | ||
links.push({ | ||
alias: match[1], value: match[2], | ||
}) | ||
} | ||
// @TODO find a lib to do these sort of things. | ||
const matches = str.match(linkRegex) | ||
if (matches) { | ||
return { | ||
alias: matches[1], value: (matches[2] || matches[3]).replace(/>$/, ''), | ||
return links | ||
} | ||
const linkifier = linkify() | ||
linkifier.tlds('onion', true) // Add unofficial `.onion` domain | ||
.add('git:', 'http:') // Add `git:` protocol as "alias" | ||
.add('ftp:', null) // Disable `ftp:` protocol | ||
.set({ fuzzyIP: true, fuzzyLink: false }) // Enable IPs in fuzzy links (without schema) | ||
// @TODO find a lib to do these sort of things. | ||
function parseNormalLinks (str) { | ||
const links = [] | ||
const urls = linkifier.match(str) ?? [] | ||
for (const { alias, value } of captureLinks(str)) { | ||
const candidate = urls.find(x => x.raw === trim(value)) | ||
if (candidate) { | ||
links.push({ | ||
type: 'external', alias, value: candidate.url, | ||
}) | ||
} else { | ||
links.push({ | ||
type: 'internal', alias, value, | ||
}) | ||
} | ||
} | ||
const mapped = new Set( | ||
links.filter(x => x.type === 'external').map(x => x.value)) | ||
for (const current of urls) { | ||
if (!mapped.has(current.url)) { | ||
links.push({ | ||
type: 'external', alias: undefined, value: current.url, | ||
}) | ||
} | ||
} | ||
return links | ||
} | ||
export { parseWikilink, parseExternalLinks } | ||
function parseLinks (str) { | ||
if (str === undefined || str === null) { | ||
return [] | ||
} | ||
return [...parseWikilink(str), ...parseNormalLinks(str)] | ||
} | ||
export { parseLinks } |
@@ -8,3 +8,2 @@ import { expect } from 'expect' | ||
} from '../../src/text/inlineFields.js' | ||
import { parseExternalLinks } from '../../src/text/links.js' | ||
@@ -11,0 +10,0 @@ const markdown = [ |
import { expect } from 'expect' | ||
import toMatchSnapshot from 'expect-mocha-snapshot' | ||
import { | ||
parseWikilink, parseExternalLinks, | ||
} from '../../src/text/links.js' | ||
import { parseLinks } from '../../src/text/links.js' | ||
@@ -24,2 +22,3 @@ const markdown = [ | ||
'[protocol unknown](file://)', | ||
'![Lovely image](../houses/img.png)', | ||
'<http://example.org>', | ||
@@ -30,28 +29,20 @@ '<https://example.org>'] | ||
describe('parseWikilink', async function () { | ||
describe('parseLinks', async function () { | ||
for (const current of markdown) { | ||
it(current, async function () { | ||
const result = parseWikilink(current) | ||
const result = parseLinks(current) | ||
expect(result).toMatchSnapshot(this) | ||
}) | ||
} | ||
}) | ||
describe('parseExternalLinks', async function () { | ||
for (const current of markdown) { | ||
it(current, async function () { | ||
const result = parseExternalLinks(current) | ||
expect(result).toMatchSnapshot(this) | ||
}) | ||
} | ||
it('parseLinks of undefined is []', async function () { | ||
const result = parseLinks(undefined) | ||
expect(result).toStrictEqual([]) | ||
}) | ||
it('parseExternalLinks of undefined is undefined', async function () { | ||
const result = parseExternalLinks(undefined) | ||
expect(result).toBe(undefined) | ||
it('parseLinks of null is []', async function () { | ||
const result = parseLinks(null) | ||
expect(result).toStrictEqual([]) | ||
}) | ||
it('parseExternalLinks of null is null', async function () { | ||
const result = parseExternalLinks(null) | ||
expect(result).toBe(null) | ||
}) | ||
}) |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
302392
6015
+ Addedlinkify-it@^4.0.1
+ Addedlinkify-it@4.0.1(transitive)
+ Addeduc.micro@1.0.6(transitive)
- Removedremark-wiki-link@^1.0.4
- Removed@babel/runtime@7.26.0(transitive)
- Removedcharacter-entities@1.2.4(transitive)
- Removedcharacter-entities-legacy@1.1.4(transitive)
- Removedcharacter-reference-invalid@1.1.4(transitive)
- Removedis-alphabetical@1.0.4(transitive)
- Removedis-alphanumerical@1.0.4(transitive)
- Removedis-decimal@1.0.4(transitive)
- Removedis-hexadecimal@1.0.4(transitive)
- Removedlongest-streak@2.0.4(transitive)
- Removedmdast-util-to-markdown@0.6.5(transitive)
- Removedmdast-util-to-string@2.0.0(transitive)
- Removedmdast-util-wiki-link@0.0.2(transitive)
- Removedmicromark-extension-wiki-link@0.0.4(transitive)
- Removedparse-entities@2.0.0(transitive)
- Removedregenerator-runtime@0.14.1(transitive)
- Removedremark-wiki-link@1.0.4(transitive)
- Removedrepeat-string@1.6.1(transitive)
- Removedzwitch@1.0.5(transitive)