diff --git a/src/HighlightPairedShortcode.js b/src/HighlightPairedShortcode.js index 5dbd602..9fa5ec7 100644 --- a/src/HighlightPairedShortcode.js +++ b/src/HighlightPairedShortcode.js @@ -4,8 +4,9 @@ const HighlightLinesGroup = require("./HighlightLinesGroup"); const getAttributes = require("./getAttributes"); module.exports = function (content, language, highlightNumbers, options = {}) { - const preAttributes = getAttributes(options.preAttributes); - const codeAttributes = getAttributes(options.codeAttributes); + const context = { content: content, language: language, options: options }; + const preAttributes = getAttributes(options.preAttributes, context); + const codeAttributes = getAttributes(options.codeAttributes, context); // default to on if(options.trim === undefined || options.trim === true) { diff --git a/src/getAttributes.js b/src/getAttributes.js index 590de1c..e2285ef 100644 --- a/src/getAttributes.js +++ b/src/getAttributes.js @@ -1,7 +1,13 @@ -function attributeEntryToString([key, value]) { +function attributeEntryToString(attribute, context) { + let [key, value] = attribute; + + if (typeof value === "function") { // Callback must return a string or a number + value = value(context); // Run the provided callback and store the result + } + if (typeof value !== "string" && typeof value !== "number") throw new Error( - `Attribute "${key}" must have a value of type string or number not "${typeof value}".` + `Attribute "${key}" must have, or evaluate to, a value of type string or number, not "${typeof value}".` ); return `${key}="${value}"`; @@ -15,21 +21,23 @@ function attributeEntryToString([key, value]) { * ```js getAttributes({ tabindex: 0, - 'data-language': 'JavaScript', + 'data-language': function (context) { return context.language; }, 'data-otherStuff': 'value' }) // => ' tabindex="0" data-language="JavaScript" data-otherStuff="value"' ``` * * @param {{[s: string]: string | number}} attributes An object with key-value pairs that represent attributes. + * @param {object} context An object with the current context. + * @param {string} context.content The code to parse and highlight. + * @param {string} context.language The language for the current instance. + * @param {object} context.options The options passed to the syntax highlighter. * @returns {string} A string containing the above HTML attributes preceded by a single space. */ -function getAttributes(attributes) { +function getAttributes(attributes, context) { if (!attributes) { return ""; } else if (typeof attributes === "object") { - const formattedAttributes = Object.entries(attributes).map( - attributeEntryToString - ); + const formattedAttributes = Object.entries(attributes).map(entry => attributeEntryToString(entry, context)); return formattedAttributes.length ? ` ${formattedAttributes.join(" ")}` : ""; } else if (typeof attributes === "string") { throw new Error("Syntax highlighter plugin custom attributes on
and must be an object. Received: " + JSON.stringify(attributes));
diff --git a/src/markdownSyntaxHighlightOptions.js b/src/markdownSyntaxHighlightOptions.js
index 967378f..92dca53 100644
--- a/src/markdownSyntaxHighlightOptions.js
+++ b/src/markdownSyntaxHighlightOptions.js
@@ -4,10 +4,11 @@ const HighlightLinesGroup = require("./HighlightLinesGroup");
const getAttributes = require("./getAttributes");
module.exports = function (options = {}) {
- const preAttributes = getAttributes(options.preAttributes);
- const codeAttributes = getAttributes(options.codeAttributes);
-
return function(str, language) {
+ const context = { content: str, language: language, options: options };
+ const preAttributes = getAttributes(options.preAttributes, context);
+ const codeAttributes = getAttributes(options.codeAttributes, context);
+
if(!language) {
// empty string means defer to the upstream escaping code built into markdown lib.
return "";
diff --git a/test/GetAttributesTest.js b/test/GetAttributesTest.js
index 1f84cbc..cef91a5 100644
--- a/test/GetAttributesTest.js
+++ b/test/GetAttributesTest.js
@@ -15,4 +15,5 @@ test("Object syntax", t => {
t.is(ga({}), "");
t.is(ga({ hi: 1 }), ' hi="1"');
t.is(ga({ hi: 1, bye: 2 }), ' hi="1" bye="2"');
+ t.is(ga({ hi: function(ctx) { return '1'; }, bye: 2 }), ' hi="1" bye="2"');
});