gitbook-plugin-include-codeblock
Version:
GitBook plugin for including file
331 lines (266 loc) • 10.5 kB
JavaScript
// LICENSE : MIT
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.containIncludeCommand = containIncludeCommand;
exports.embedCode = embedCode;
exports.generateEmbedCode = generateEmbedCode;
exports.getContent = getContent;
exports.parse = parse;
exports.parseValue = parseValue;
exports.parseVariablesFromLabel = parseVariablesFromLabel;
exports.splitLabelToCommands = splitLabelToCommands;
exports.strip = strip;
var _options = require("./options.js");
var _unescapeString = require("./unescape-string.js");
var _languageDetection = require("./language-detection");
var _marker = require("./marker");
var _slicer = require("./slicer");
var _title = require("./title");
var _template = require("./template");
var _backtickMaker = require("./backtick-maker");
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
function _iterableToArrayLimit(arr, i) { var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; if (_i == null) return; var _arr = []; var _n = true; var _d = false; var _s, _e; try { for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
var path = require("path");
var Handlebars = require("handlebars");
var markdownLinkFormatRegExp = /\[(?=((?:[^\]]|\\.)*))\1\]\((?=((?:[^)]|\\.)*))\2\)/gm;
var keyEx = "\\w+";
var kvsepEx = "[:=]";
var spacesEx = "\\s*";
var quoteEx = "[\"']";
var valEx = "(?:[^'\"\\\\]|\\\\.)*";
var argEx = "".concat(quoteEx).concat(valEx).concat(quoteEx, "|true|false");
var expressionEx = "(".concat(keyEx, ")").concat(kvsepEx).concat(spacesEx, "(").concat(argEx, ")");
var expressionRegExp = new RegExp(expressionEx, "g");
var markerRegExp = /^\s*(([-\w\s]*,?)*)$/;
/**
* A counter to count how many code are imported.
*/
var codeCounter = function () {
var count = 0;
return function () {
return count++;
}; // Return and increment
}();
/**
* split label to commands
* @param {string} label
* @returns {Array}
*/
function splitLabelToCommands() {
var label = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : "";
var result = label.split(/(:|[,\s])/);
if (!result) {
return [];
} // remove null command
return result.map(function (command) {
return command.trim();
}).filter(function (command) {
return command.length > 0;
});
}
/**
* Unindent code
* @param {string} s
* @return {string}
*/
function strip(s) {
// inspired from https://github.com/rails/rails/blob/master/activesupport/lib/active_support/core_ext/string/strip.rb
if (s === undefined || s === "") {
return s;
}
var indents = s.split(/\n/).map(function (s) {
return s.match(/^[ \t]*(?=\S)/);
}).filter(function (m) {
return m;
}).map(function (m) {
return m[0];
});
var smallestIndent = indents.sort(function (a, b) {
return a.length - b.length;
})[0];
return s.replace(new RegExp("^".concat(smallestIndent), "gm"), "");
}
/**
* if contain "include" or "import" command, then return true
* @param {Array} commands
* @returns {boolean}
*/
function containIncludeCommand() {
var commands = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
var reg = /^(include|import)$/;
return commands.length > 0 ? reg.test(commands[0].trim()) : false;
}
/**
* Parse the given value to the given type. Returns the value if valid, otherwise returns undefined.
* @param {string} value
* @param {string} type "string", "boolean"
* @param {string} key
* @return {boolean|string|undefined}
*/
function parseValue(value, type, key) {
if (type === "string") {
var unescapedvalue = (0, _unescapeString.unescapeString)(value.substring(1, value.length - 1));
if (key === "marker" && !markerRegExp.test(unescapedvalue)) {
console.error("include-codeblock: parseVariablesFromLabel: invalid value " + "`".concat(unescapedvalue, "` in key `marker`"));
return undefined;
}
return unescapedvalue;
}
if (type === "boolean") {
if (["true", '"true"', "'true'"].indexOf(value) >= 0) {
return true;
}
if (["false", '"false"', "'false'"].indexOf(value) >= 0) {
return false;
}
console.error("include-codeblock: parseVariablesFromLabel: invalid value " + "`".concat(value, "` in key `").concat(key, "`. Expect true or false."));
return undefined;
}
console.error("include-codeblock: parseVariablesFromLabel: unknown key type `".concat(type, "` (see options.js)"));
return undefined;
}
/** Parse the command label and return a new key-value object
* @example
* [import,title:"<thetitle>",label:"<thelabel>"](path/to/file.ext)
* @param {object} kvMap
* @param {string} label
* @return {object}
*/
function parseVariablesFromLabel(kvMap, label) {
var kv = Object.assign({}, kvMap);
var match = "";
while (match = expressionRegExp.exec(label)) {
var key = match[1];
if (key === "include" || key === "import") {
key = "marker";
}
var value = match[2];
if (!Object.prototype.hasOwnProperty.call(kv, key)) {
console.error("include-codeblock: parseVariablesFromLabel: unknown key " + "`".concat(key, "` (see options.js)"));
return;
}
var parsedValue = parseValue(value, _typeof(_options.defaultKeyValueMap[key]), key);
if (parsedValue !== undefined) {
kv[key] = parsedValue;
}
}
return Object.freeze(kv);
}
/**
* generate code from options
* @param {object} kvMap
* @param {string} fileName
* @param {string} originalPath
* @param {string} content
* @param {string} backtick
* @return {string}
*/
function generateEmbedCode(kvMap, _ref) {
var fileName = _ref.fileName,
originalPath = _ref.originalPath,
content = _ref.content,
backtick = _ref.backtick;
var tContent = (0, _template.getTemplateContent)(kvMap);
var kv = Object.assign({}, kvMap);
var count = (0, _title.hasTitle)(kv) ? codeCounter() : -1;
(0, _options.checkMapTypes)(kvMap, "generatedEmbedCode");
var contextMap = Object.assign({}, kvMap, {
content: content,
count: count,
fileName: fileName,
originalPath: originalPath,
backtick: backtick
}); // compile template
var handlebars = Handlebars.compile(tContent); // compile with data.
return handlebars(contextMap);
}
/**
* return content from file or url.
* @param {string} filePath it should be absolute path
* @return {string}
*/
function getContent(filePath) {
return (0, _template.readFileFromPath)(filePath);
}
/**
* generate code with options
* @param {object} kvMap
* @param {string} filePath
* @param {string} originalPath
* @param {string} label
* @return {string}
*/
function embedCode(kvMap, _ref2) {
var filePath = _ref2.filePath,
originalPath = _ref2.originalPath,
label = _ref2.label;
var code = getContent(filePath);
var fileName = path.basename(filePath);
var kvmparsed = parseVariablesFromLabel(kvMap, label);
var kvm = (0, _languageDetection.getLang)(kvmparsed, originalPath);
var unindent = kvm.unindent;
var content = code; // Slice content via line numbers.
if ((0, _slicer.hasSliceRange)(label)) {
var _getSliceRange = (0, _slicer.getSliceRange)(label),
_getSliceRange2 = _slicedToArray(_getSliceRange, 2),
start = _getSliceRange2[0],
end = _getSliceRange2[1];
content = (0, _slicer.sliceCode)(code, start, end, unindent);
} else if ((0, _marker.hasMarker)(kvm)) {
// Slice content via markers.
var marker = (0, _marker.getMarker)(kvm);
content = (0, _marker.removeMarkers)((0, _marker.markerSliceCode)(code, marker));
}
if (unindent === true) {
content = strip(content);
}
var backtick = (0, _backtickMaker.codeBlockBacktick)(content);
return generateEmbedCode(kvm, {
fileName: fileName,
originalPath: originalPath,
content: content,
backtick: backtick
});
}
/**
* Parse command using options from pluginConfig.
* @param {string} content
* @param {string} baseDir
* @param {{template?: string}} options
* @return {Array}
*/
function parse(content, baseDir) {
var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
var results = [];
var kvMap = (0, _options.initOptions)(options);
var res = true;
while (res = markdownLinkFormatRegExp.exec(content)) {
var _res = res,
_res2 = _slicedToArray(_res, 3),
all = _res2[0],
label = _res2[1],
originalPath = _res2[2];
var commands = splitLabelToCommands(label);
if (containIncludeCommand(commands)) {
var absolutePath = path.resolve(baseDir, originalPath);
var replacedContent = embedCode(kvMap, {
filePath: absolutePath,
originalPath: originalPath,
label: label
});
results.push({
target: all,
replaced: replacedContent
});
}
}
return results;
}
//# sourceMappingURL=parser.js.map