@diplodoc/transform
Version:
A simple transformer of text in YFM (Yandex Flavored Markdown) to HTML
142 lines • 5.55 kB
JavaScript
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
const chalk_1 = require("chalk");
const github_slugger_1 = __importDefault(require("github-slugger"));
const utils_1 = require("markdown-it/lib/common/utils");
const slugify_1 = __importDefault(require("slugify"));
const utils_2 = require("../../utils");
const constants_1 = require("./constants");
function createLinkTokens(state, id, title, setId = false, href) {
const open = new state.Token('link_open', 'a', 1);
const close = new state.Token('link_close', 'a', -1);
if (setId) {
open.attrSet('id', id);
}
open.attrSet('href', href + '#' + id);
open.attrSet('class', 'yfm-anchor');
open.attrSet('aria-hidden', 'true');
// SEO: render invisible heading title because link must have text content.
const hiddenDesc = new state.Token('anchor_hidden_desc', '', 0);
hiddenDesc.content = title;
return [open, hiddenDesc, close];
}
const getCustomIds = (content) => {
const ids = [];
content.replace(constants_1.CUSTOM_ID_REGEXP, (match, customId) => {
if (match !== constants_1.CUSTOM_ID_EXCEPTION) {
ids.push(customId);
}
return '';
});
return ids.length ? ids : null;
};
const removeCustomId = (content) => {
if (constants_1.CUSTOM_ID_REGEXP.test(content)) {
return content
.replace(constants_1.CUSTOM_ID_REGEXP, (match) => {
if (match === constants_1.CUSTOM_ID_EXCEPTION) {
return match;
}
return '';
})
.trim();
}
return content;
};
const removeCustomIds = (token) => {
var _a;
token.content = removeCustomId(token.content);
(_a = token.children) === null || _a === void 0 ? void 0 : _a.forEach((child) => {
child.content = removeCustomId(child.content);
});
};
const index = (md, options) => {
const { extractTitle, path, log, supportGithubAnchors, getPublicPath, disableCommonAnchors } = options;
const plugin = (state) => {
/* Do not use the plugin if it is included in the file */
if (state.env.includes && state.env.includes.length) {
return;
}
const href = getPublicPath ? getPublicPath(options, state.env.path) : '';
const ids = {};
const tokens = state.tokens;
let i = 0;
const slugger = new github_slugger_1.default();
while (i < tokens.length) {
const token = tokens[i];
const isHeading = token.type === 'heading_open';
if (isHeading) {
const { title, level } = (0, utils_2.headingInfo)(tokens, i);
const inlineToken = tokens[i + 1];
let id = token.attrGet('id');
let ghId;
if (!title) {
log.warn(`Header without title${path ? ` in ${(0, chalk_1.bold)(path)}` : ''}`);
}
if (level < 2 && extractTitle) {
// if there are any custom ids in the level 1 heading we should clear them
removeCustomIds(tokens[i + 1]);
i += 3;
continue;
}
const customIds = getCustomIds(inlineToken.content);
if (customIds) {
id = customIds[0];
removeCustomIds(tokens[i + 1]);
}
else {
id = (0, slugify_1.default)(title, {
lower: true,
remove: /[^\w\s$_\-,;=/]+/g,
});
ghId = slugger.slug(title);
}
token.attrSet('id', id);
if (ids[id]) {
id = id + ids[id]++;
token.attrSet('id', id);
}
else {
ids[id] = 1;
}
const allAnchorIds = customIds ? customIds : [id];
const anchorTitle = removeCustomId(title).replace(/`/g, '');
allAnchorIds.forEach((customId) => {
var _a, _b;
const setId = id !== customId;
if (!disableCommonAnchors) {
const linkTokens = createLinkTokens(state, customId, anchorTitle, setId, href);
(_a = inlineToken.children) === null || _a === void 0 ? void 0 : _a.unshift(...linkTokens);
}
if (supportGithubAnchors) {
const ghLinkTokens = createLinkTokens(state, ghId, anchorTitle, true, href);
(_b = inlineToken.children) === null || _b === void 0 ? void 0 : _b.unshift(...ghLinkTokens);
}
});
i += 3;
continue;
}
i++;
}
};
try {
md.core.ruler.after('includes', 'anchors', plugin);
}
catch (_a) {
try {
md.core.ruler.after('curly_attributes', 'anchors', plugin);
}
catch (_b) {
md.core.ruler.push('anchors', plugin);
}
}
md.renderer.rules.anchor_hidden_desc = function (tokens, index) {
return ('<span class="visually-hidden" data-no-index="true">' +
(0, utils_1.escapeHtml)(tokens[index].content) +
'</span>');
};
};
module.exports = index;
//# sourceMappingURL=index.js.map
;