UNPKG

@diplodoc/transform

Version:

A simple transformer of text in YFM (Yandex Flavored Markdown) to HTML

189 lines 7.68 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; const url_1 = __importDefault(require("url")); const chalk_1 = require("chalk"); const path_1 = __importStar(require("path")); const utils_1 = require("../../utils"); const utilsFS_1 = require("../../utilsFS"); function getTitleFromTokens(tokens) { var _a; let title = ''; let i = 0; while (i < tokens.length) { const token = tokens[i]; if ((token === null || token === void 0 ? void 0 : token.type) === 'heading_open') { const info = (0, utils_1.headingInfo)(tokens, i); title = (_a = info === null || info === void 0 ? void 0 : info.title) !== null && _a !== void 0 ? _a : ''; break; } i += 1; } return title; } const getTitle = (md, id, options) => { var _a; const { file, state, opts } = options; // Check the existed included store and extract it const included = (_a = md.included) === null || _a === void 0 ? void 0 : _a[file]; const fileTokens = (0, utilsFS_1.getFileTokens)(file, state, Object.assign(Object.assign({}, opts), { disableLint: true, disableTitleRefSubstitution: true, disableCircularError: true, inheritVars: false }), included); const sourceTokens = id ? (0, utils_1.findBlockTokens)(fileTokens, id) : fileTokens; return getTitleFromTokens(sourceTokens); }; const addTitle = (md, options) => { var _a; const { hash, state, isEmptyLink, tokens, idx, nextToken, href, currentPath, log, cache } = options; const id = hash && hash.slice(1); const key = [id, path_1.default].join('::'); const title = (_a = cache === null || cache === void 0 ? void 0 : cache.get(key)) !== null && _a !== void 0 ? _a : getTitle(md, id, options); cache === null || cache === void 0 ? void 0 : cache.set(key, title); if (title) { let textToken; if (isEmptyLink) { textToken = new state.Token('text', '', 0); tokens.splice(idx + 1, 0, textToken); } else { textToken = nextToken; } textToken.content = title; } else { log.warn(`Title not found: ${(0, chalk_1.bold)(href)} in ${(0, chalk_1.bold)(currentPath)}`); } }; function getDefaultPublicPath({ file, path, }, input) { return (0, path_1.relative)((0, path_1.parse)(path || '').dir, input || file || ''); } // eslint-disable-next-line complexity function processLink(md, state, tokens, idx, opts) { const { path: startPath, root, transformLink, notFoundCb, needSkipLinkFn, log, getPublicPath = getDefaultPublicPath, cache, skipLinkFileCheck = false, } = opts; const currentPath = state.env.path || startPath; const linkToken = tokens[idx]; const nextToken = tokens[idx + 1]; const originalHref = (0, utils_1.getHrefTokenAttr)(linkToken); if (!originalHref) { log.error(`Empty link in ${(0, chalk_1.bold)(startPath)}`); return; } const { pathname, hash } = url_1.default.parse(originalHref); let file; let fileExists; let isPageFile; if (!(0, utils_1.isLocalUrl)(originalHref)) { linkToken.attrSet('target', '_blank'); linkToken.attrSet('rel', 'noreferrer noopener'); return; } if (pathname) { file = (0, path_1.resolve)(path_1.default.parse(currentPath).dir, pathname); fileExists = skipLinkFileCheck || (0, utilsFS_1.isFileExists)(file); isPageFile = utils_1.PAGE_LINK_REGEXP.test(pathname); if (isPageFile && !fileExists) { let needShowError = true; if (needSkipLinkFn) { needShowError = !needSkipLinkFn(originalHref); } if (notFoundCb && needShowError) { notFoundCb(file.replace(root, '')); } if (needShowError) { log.error(`Link is unreachable: ${(0, chalk_1.bold)(originalHref)} in ${(0, chalk_1.bold)(currentPath)}`); } } } else if (hash) { file = startPath; fileExists = true; isPageFile = true; } else { return; } const isEmptyLink = nextToken.type === 'link_close'; const isTitleRefLink = nextToken.type === 'text' && nextToken.content === '{#T}'; if ((isEmptyLink || isTitleRefLink) && fileExists && isPageFile && !state.env.disableTitleRefSubstitution) { addTitle(md, { hash, file, state, opts, isEmptyLink, tokens, idx, nextToken, href: originalHref, currentPath, log, cache, }); } const patchedHref = !(0, path_1.isAbsolute)(originalHref) && !originalHref.includes('//') ? url_1.default.format(Object.assign(Object.assign({}, url_1.default.parse(originalHref)), { pathname: getPublicPath(opts, file) })) : originalHref; const linkHrefTransformer = transformLink || utils_1.defaultTransformLink; linkToken.attrSet('href', linkHrefTransformer(patchedHref)); } const index = (md, opts) => { const plugin = (state) => { var _a, _b; const tokens = state.tokens; let i = 0; while (i < tokens.length) { if (tokens[i].type === 'inline') { const childrenTokens = tokens[i].children || []; let j = 0; while (j < childrenTokens.length) { const token = childrenTokens[j]; const isLinkOpenToken = token.type === 'link_open'; const tokenClass = token.attrGet('class'); /* Don't process anchor links */ const isYfmAnchor = tokenClass ? tokenClass.includes('yfm-anchor') : false; const wasProcessedBefore = Boolean((_a = token.meta) === null || _a === void 0 ? void 0 : _a.yfmLinkPluginProcessed); if (isLinkOpenToken && !wasProcessedBefore && !isYfmAnchor) { processLink(md, state, childrenTokens, j, opts); (_b = token.meta) !== null && _b !== void 0 ? _b : (token.meta = {}); token.meta.yfmLinkPluginProcessed = true; } j++; } } i++; } }; try { md.core.ruler.before('includes', 'links', plugin); } catch (e) { md.core.ruler.push('links', plugin); } }; module.exports = index; //# sourceMappingURL=index.js.map