From 5a19a7c3959dbf9083247958437f165dd761dbb4 Mon Sep 17 00:00:00 2001 From: chriskirknielsen Date: Sun, 23 May 2021 18:48:50 -0400 Subject: [PATCH 1/6] Add context info to getAttribute Allows to pull in laguange dynamically --- src/HighlightPairedShortcode.js | 5 +++-- src/getAttributes.js | 16 ++++++++++------ src/markdownSyntaxHighlightOptions.js | 7 ++++--- test/GetAttributesTest.js | 1 + 4 files changed, 18 insertions(+), 11 deletions(-) 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..0a91b1c 100644 --- a/src/getAttributes.js +++ b/src/getAttributes.js @@ -1,4 +1,10 @@ -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}".` @@ -15,7 +21,7 @@ function attributeEntryToString([key, value]) { * ```js getAttributes({ tabindex: 0, - 'data-language': 'JavaScript', + 'data-language': function (context) { return content.language; }, 'data-otherStuff': 'value' }) // => ' tabindex="0" data-language="JavaScript" data-otherStuff="value"' ``` @@ -23,13 +29,11 @@ function attributeEntryToString([key, value]) { * @param {{[s: string]: string | number}} attributes An object with key-value pairs that represent attributes. * @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"');
 });

From e7f21cf37c7e3d10fe4840e6a41f2dc83b3171e6 Mon Sep 17 00:00:00 2001
From: chriskirknielsen 
Date: Sun, 23 May 2021 19:56:17 -0400
Subject: [PATCH 2/6] Fix context -> context typo in example comment

---
 src/getAttributes.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/getAttributes.js b/src/getAttributes.js
index 0a91b1c..f37680a 100644
--- a/src/getAttributes.js
+++ b/src/getAttributes.js
@@ -21,7 +21,7 @@ function attributeEntryToString(attribute, context) {
  * ```js
   getAttributes({
     tabindex: 0,
-    'data-language': function (context) { return content.language; },
+    'data-language': function (context) { return context.language; },
     'data-otherStuff': 'value'
   }) // => ' tabindex="0" data-language="JavaScript" data-otherStuff="value"'
   ```

From 24ed545b960883c9dff0d0e767db462e8f43687e Mon Sep 17 00:00:00 2001
From: chriskirknielsen 
Date: Mon, 24 May 2021 21:47:36 -0400
Subject: [PATCH 3/6] Update error message to take callback function into
 account

---
 src/getAttributes.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/getAttributes.js b/src/getAttributes.js
index f37680a..ed3da93 100644
--- a/src/getAttributes.js
+++ b/src/getAttributes.js
@@ -7,7 +7,7 @@ function attributeEntryToString(attribute, context) {
 
   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}"`;

From dff1b01e08f4ba304945f2c78f34754aab6c326d Mon Sep 17 00:00:00 2001
From: chriskirknielsen 
Date: Sun, 23 May 2021 19:56:17 -0400
Subject: [PATCH 4/6] Fix content -> context typo in example comment

---
 src/getAttributes.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/getAttributes.js b/src/getAttributes.js
index 0a91b1c..f37680a 100644
--- a/src/getAttributes.js
+++ b/src/getAttributes.js
@@ -21,7 +21,7 @@ function attributeEntryToString(attribute, context) {
  * ```js
   getAttributes({
     tabindex: 0,
-    'data-language': function (context) { return content.language; },
+    'data-language': function (context) { return context.language; },
     'data-otherStuff': 'value'
   }) // => ' tabindex="0" data-language="JavaScript" data-otherStuff="value"'
   ```

From 8d793f52d95251e3e578e4e57dd1a608127d1e1a Mon Sep 17 00:00:00 2001
From: chriskirknielsen 
Date: Mon, 24 May 2021 21:47:36 -0400
Subject: [PATCH 5/6] Update error message to take callback function into
 account

---
 src/getAttributes.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/getAttributes.js b/src/getAttributes.js
index f37680a..ed3da93 100644
--- a/src/getAttributes.js
+++ b/src/getAttributes.js
@@ -7,7 +7,7 @@ function attributeEntryToString(attribute, context) {
 
   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}"`;

From 8878bc31236b99cf88a715a3c269f184a391d567 Mon Sep 17 00:00:00 2001
From: chriskirknielsen 
Date: Wed, 26 May 2021 09:04:09 -0400
Subject: [PATCH 6/6] Detail the context variable in function definition

---
 src/getAttributes.js | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/src/getAttributes.js b/src/getAttributes.js
index ed3da93..e2285ef 100644
--- a/src/getAttributes.js
+++ b/src/getAttributes.js
@@ -27,6 +27,10 @@ function attributeEntryToString(attribute, context) {
   ```
  *
  * @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, context) {