Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add context info and callback to getAttributes #50

Merged
merged 7 commits into from
Jun 28, 2022
5 changes: 3 additions & 2 deletions src/HighlightPairedShortcode.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
22 changes: 15 additions & 7 deletions src/getAttributes.js
Original file line number Diff line number Diff line change
@@ -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}"`;
Expand All @@ -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 <pre> and <code> must be an object. Received: " + JSON.stringify(attributes));
Expand Down
7 changes: 4 additions & 3 deletions src/markdownSyntaxHighlightOptions.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 "";
Expand Down
1 change: 1 addition & 0 deletions test/GetAttributesTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -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"');
});