Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 | 94x 94x 94x 94x 94x 6x 6x 6x 1x 1x 1x 13x 13x 11x 56x 56x 56x 4x 52x 8x 44x 3x 11x 22x 20x 4x 4x | import * as he from 'he';
import { difference, uniq } from 'lodash-es';
import { marked } from 'marked';
import { getMailbox } from '../mods/mailbox';
import { wikiUriFormat } from '../mods/org/wiki';
import { QUALIFIED_USER_REGEX, TAG_REGEX } from './format';
import { getPath } from './http';
export function getMailboxes(markdown: string, origin = '') {
return extractPattern(markdown, /[_+]user\/[a-z0-9]+([./][a-z0-9]+)*(@[a-z0-9]+(\.[a-z0-9]+)*)?/g, undefined, QUALIFIED_USER_REGEX)
.map(u => getMailbox(u, origin));
}
export function getTags(markdown: string) {
return extractPattern(markdown, /#[_+]?[a-z0-9]+([./][a-z0-9]+)*/g, /#([a-z0-9]+([./][a-z0-9]+)*)/, TAG_REGEX);
}
export function extractPattern(markdown: string, pattern: RegExp, extractor?: RegExp, validator?: RegExp) {
const result: string[] = [];
if (!markdown) return result;
const matches = markdown.match(pattern);
for (const s of matches || []) {
const url = (extractor ? s.match(extractor)?.[1] : s)?.trim();
if (url && (!validator || validator.test(url))) {
result.push(url);
}
}
return result;
}
export function getIfNew<T>(list: T[], old?: T[]): T[] {
old ??= [];
const diff = difference(uniq(list), uniq(old));
if (!diff.length) return [];
return list;
}
/**
* Get the URLs embedded in markdown. These are rendered by looking up the Ref.
* External wiki embeds are rendered as links, and images that are not Refs
* (web, data and blob URLs, relative paths and tag queries) are rendered
* directly, so they are skipped. Images linking to a Ref page, either relative
* or under the given base URL, are rendered by looking up the Ref.
*/
export function getEmbeds(markdown: string, wikiPrefix?: string, wikiExternal = false, base = '') {
const result: string[] = [];
if (!markdown) return result;
marked.walkTokens(marked.lexer(markdown), t => {
const customType = t as any;
Iif (customType.type === 'bang-embed' && customType.href) {
result.push(customType.href);
} else if (customType.type === 'image' && customType.href && isRefPath(customType.href, base)) {
result.push(customType.href);
} else if (customType.type === 'image' && customType.href && /^[a-z][a-z0-9+.-]*:/i.test(customType.href) && !/^(https?|data|blob):/i.test(customType.href)) {
result.push(customType.href);
} else if (customType.type === 'wiki-embed' && customType.text && !wikiExternal) {
result.push(wikiUriFormat(customType.text, wikiPrefix));
}
});
return uniq(result);
}
function isRefPath(url: string, base: string) {
if (url.startsWith('/ref/')) return true;
if (!base) return false;
const refPrefix = base + 'ref/';
return url.startsWith(refPrefix) || url.startsWith(getPath(refPrefix)!);
}
export function getLinks(markdown: string, withText?: RegExp) {
const result: string[] = [];
marked.walkTokens(marked.lexer(markdown), t => {
if (t.type === 'link') {
if (!t.href) return;
if (withText && !withText.test(t.text)) return;
if (t.href.startsWith('mailto:')) t.href = he.decode(t.href);
result.push(t.href);
// @ts-ignore
}
if (withText) return;
const customType = t as any;
if (customType.text) {
if (customType.type === 'wiki' || customType.type === 'wiki-embed') {
result.push(wikiUriFormat(customType.text));
} else if (customType.type === 'embed') {
result.push(customType.text);
}
}
});
return result;
}
|