From efdef9081ffc74cb96c1468075730bce0cd12474 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20H=C3=B6ltje?= Date: Sat, 24 Mar 2018 13:26:35 -0400 Subject: [PATCH] remark-prismjs: add aliases for languages (#4688) * remark-prismjs: refactor tests into pre and code * remark-prismjs: add aliases for languages This allows specifying aliases for languages when using prismjs. Fixes #4549 --- packages/gatsby-remark-prismjs/README.md | 5 + .../src/__tests__/__snapshots__/index.js.snap | 135 +++++++++++++++--- .../src/__tests__/index.js | 77 ++++++---- packages/gatsby-remark-prismjs/src/index.js | 12 +- 4 files changed, 179 insertions(+), 50 deletions(-) diff --git a/packages/gatsby-remark-prismjs/README.md b/packages/gatsby-remark-prismjs/README.md index b514d9c4afe17..39cd77849baf6 100644 --- a/packages/gatsby-remark-prismjs/README.md +++ b/packages/gatsby-remark-prismjs/README.md @@ -34,6 +34,11 @@ plugins: [ // A suggested value for English speakers is the non-ascii // character '›'. inlineCodeMarker: null, + // This lets you set up language aliases. For example, + // setting this to '{ sh: "bash" }' will let you use + // the language "sh" which will highlight using the + // bash highlighter. + aliases: {}, }, }, ], diff --git a/packages/gatsby-remark-prismjs/src/__tests__/__snapshots__/index.js.snap b/packages/gatsby-remark-prismjs/src/__tests__/__snapshots__/index.js.snap index 2c7e81cffdc03..23fbb7bf76515 100644 --- a/packages/gatsby-remark-prismjs/src/__tests__/__snapshots__/index.js.snap +++ b/packages/gatsby-remark-prismjs/src/__tests__/__snapshots__/index.js.snap @@ -44,6 +44,49 @@ Object { } `; +exports[`remark prism plugin generates a
 tag with aliases applied 1`] = `
+Object {
+  "children": Array [
+    Object {
+      "lang": "foobar",
+      "position": Position {
+        "end": Object {
+          "column": 4,
+          "line": 3,
+          "offset": 21,
+        },
+        "indent": Array [
+          1,
+          1,
+        ],
+        "start": Object {
+          "column": 1,
+          "line": 1,
+          "offset": 0,
+        },
+      },
+      "type": "html",
+      "value": "
+
// Fake
+
", + }, + ], + "position": Object { + "end": Object { + "column": 4, + "line": 3, + "offset": 21, + }, + "start": Object { + "column": 1, + "line": 1, + "offset": 0, + }, + }, + "type": "root", +} +`; + exports[`remark prism plugin generates a
 tag with class="language-*" prefix by default 1`] = `
 Object {
   "children": Array [
@@ -88,7 +131,7 @@ Object {
 }
 `;
 
-exports[`remark prism plugin generates inline  tag with a custom class prefix if configured 1`] = `
+exports[`remark prism plugin generates an inline  tag that handles language specifiers 1`] = `
 Object {
   "children": Array [
     Object {
@@ -96,9 +139,9 @@ Object {
         Object {
           "position": Position {
             "end": Object {
-              "column": 10,
+              "column": 29,
               "line": 1,
-              "offset": 9,
+              "offset": 28,
             },
             "indent": Array [],
             "start": Object {
@@ -108,14 +151,15 @@ Object {
             },
           },
           "type": "html",
-          "value": "foo bar",
+          "value": ".foo { color: red }
+",
         },
       ],
       "position": Position {
         "end": Object {
-          "column": 10,
+          "column": 29,
           "line": 1,
-          "offset": 9,
+          "offset": 28,
         },
         "indent": Array [],
         "start": Object {
@@ -129,9 +173,9 @@ Object {
   ],
   "position": Object {
     "end": Object {
-      "column": 10,
+      "column": 29,
       "line": 1,
-      "offset": 9,
+      "offset": 28,
     },
     "start": Object {
       "column": 1,
@@ -143,7 +187,7 @@ Object {
 }
 `;
 
-exports[`remark prism plugin generates inline  tag with class="language-*" prefix by default 1`] = `
+exports[`remark prism plugin generates an inline  tag with a custom class prefix if configured 1`] = `
 Object {
   "children": Array [
     Object {
@@ -163,7 +207,7 @@ Object {
             },
           },
           "type": "html",
-          "value": "foo bar",
+          "value": "foo bar",
         },
       ],
       "position": Position {
@@ -198,7 +242,7 @@ Object {
 }
 `;
 
-exports[`remark prism plugin inlineCode handles language specifiers 1`] = `
+exports[`remark prism plugin generates an inline  tag with aliases applied 1`] = `
 Object {
   "children": Array [
     Object {
@@ -206,9 +250,9 @@ Object {
         Object {
           "position": Position {
             "end": Object {
-              "column": 29,
+              "column": 16,
               "line": 1,
-              "offset": 28,
+              "offset": 15,
             },
             "indent": Array [],
             "start": Object {
@@ -218,15 +262,15 @@ Object {
             },
           },
           "type": "html",
-          "value": ".foo { color: red }
+          "value": "Fake
 ",
         },
       ],
       "position": Position {
         "end": Object {
-          "column": 29,
+          "column": 16,
           "line": 1,
-          "offset": 28,
+          "offset": 15,
         },
         "indent": Array [],
         "start": Object {
@@ -240,9 +284,64 @@ Object {
   ],
   "position": Object {
     "end": Object {
-      "column": 29,
+      "column": 16,
       "line": 1,
-      "offset": 28,
+      "offset": 15,
+    },
+    "start": Object {
+      "column": 1,
+      "line": 1,
+      "offset": 0,
+    },
+  },
+  "type": "root",
+}
+`;
+
+exports[`remark prism plugin generates an inline  tag with class="language-*" prefix by default 1`] = `
+Object {
+  "children": Array [
+    Object {
+      "children": Array [
+        Object {
+          "position": Position {
+            "end": Object {
+              "column": 10,
+              "line": 1,
+              "offset": 9,
+            },
+            "indent": Array [],
+            "start": Object {
+              "column": 1,
+              "line": 1,
+              "offset": 0,
+            },
+          },
+          "type": "html",
+          "value": "foo bar",
+        },
+      ],
+      "position": Position {
+        "end": Object {
+          "column": 10,
+          "line": 1,
+          "offset": 9,
+        },
+        "indent": Array [],
+        "start": Object {
+          "column": 1,
+          "line": 1,
+          "offset": 0,
+        },
+      },
+      "type": "paragraph",
+    },
+  ],
+  "position": Object {
+    "end": Object {
+      "column": 10,
+      "line": 1,
+      "offset": 9,
     },
     "start": Object {
       "column": 1,
diff --git a/packages/gatsby-remark-prismjs/src/__tests__/index.js b/packages/gatsby-remark-prismjs/src/__tests__/index.js
index c246c7aebffc9..271aed83b77e4 100644
--- a/packages/gatsby-remark-prismjs/src/__tests__/index.js
+++ b/packages/gatsby-remark-prismjs/src/__tests__/index.js
@@ -2,38 +2,59 @@ const remark = require(`remark`)
 const plugin = require(`../index`)
 
 describe(`remark prism plugin`, () => {
-  it(`generates a 
 tag with class="language-*" prefix by default`, () => {
-    const code = `\`\`\`js\n// Fake\n\`\`\``
-    const markdownAST = remark.parse(code)
-    plugin({ markdownAST })
-    expect(markdownAST).toMatchSnapshot()
-  })
+  describe(`generates a 
 tag`, () => {
+    it(`with class="language-*" prefix by default`, () => {
+      const code = `\`\`\`js\n// Fake\n\`\`\``
+      const markdownAST = remark.parse(code)
+      plugin({ markdownAST })
+      expect(markdownAST).toMatchSnapshot()
+    })
 
-  it(`generates a 
 tag with a custom class prefix if configured`, () => {
-    const code = `\`\`\`js\n// Fake\n\`\`\``
-    const markdownAST = remark.parse(code)
-    plugin({ markdownAST }, { classPrefix: `custom-` })
-    expect(markdownAST).toMatchSnapshot()
-  })
+    it(`with a custom class prefix if configured`, () => {
+      const code = `\`\`\`js\n// Fake\n\`\`\``
+      const markdownAST = remark.parse(code)
+      plugin({ markdownAST }, { classPrefix: `custom-` })
+      expect(markdownAST).toMatchSnapshot()
+    })
 
-  it(`generates inline  tag with class="language-*" prefix by default`, () => {
-    const code = `\`foo bar\``
-    const markdownAST = remark.parse(code)
-    plugin({ markdownAST })
-    expect(markdownAST).toMatchSnapshot()
+    it(`with aliases applied`, () => {
+      const code = `\`\`\`foobar\n// Fake\n\`\`\``
+      const markdownAST = remark.parse(code)
+      plugin({ markdownAST }, { aliases: { foobar: `javascript` } })
+      expect(markdownAST).toMatchSnapshot()
+    })
   })
 
-  it(`generates inline  tag with a custom class prefix if configured`, () => {
-    const code = `\`foo bar\``
-    const markdownAST = remark.parse(code)
-    plugin({ markdownAST }, { classPrefix: `custom-` })
-    expect(markdownAST).toMatchSnapshot()
-  })
+  describe(`generates an inline  tag`, () => {
+    it(`with class="language-*" prefix by default`, () => {
+      const code = `\`foo bar\``
+      const markdownAST = remark.parse(code)
+      plugin({ markdownAST })
+      expect(markdownAST).toMatchSnapshot()
+    })
+
+    it(`with a custom class prefix if configured`, () => {
+      const code = `\`foo bar\``
+      const markdownAST = remark.parse(code)
+      plugin({ markdownAST }, { classPrefix: `custom-` })
+      expect(markdownAST).toMatchSnapshot()
+    })
+
+    it(`that handles language specifiers`, () => {
+      const code = `\`css🍺  .foo { color: red }\``
+      const markdownAST = remark.parse(code)
+      plugin({ markdownAST }, { inlineCodeMarker: `🍺  ` })
+      expect(markdownAST).toMatchSnapshot()
+    })
 
-  it(`inlineCode handles language specifiers`, () => {
-    const code = `\`css🍺  .foo { color: red }\``
-    const markdownAST = remark.parse(code)
-    plugin({ markdownAST }, { inlineCodeMarker: `🍺  ` })
-    expect(markdownAST).toMatchSnapshot()
+    it(`with aliases applied`, () => {
+      const code = `\`foobar : Fake\``
+      const markdownAST = remark.parse(code)
+      plugin(
+        { markdownAST },
+        { inlineCodeMarker: ` : `, aliases: { foobar: `javascript` } }
+      )
+      expect(markdownAST).toMatchSnapshot()
+    })
   })
 })
diff --git a/packages/gatsby-remark-prismjs/src/index.js b/packages/gatsby-remark-prismjs/src/index.js
index 31181f336a797..c02aa7ad1f1d4 100644
--- a/packages/gatsby-remark-prismjs/src/index.js
+++ b/packages/gatsby-remark-prismjs/src/index.js
@@ -5,8 +5,13 @@ const highlightCode = require(`./highlight-code`)
 
 module.exports = (
   { markdownAST },
-  { classPrefix = `language-`, inlineCodeMarker = null } = {}
+  { classPrefix = `language-`, inlineCodeMarker = null, aliases = {} } = {}
 ) => {
+  const normalizeLanguage = lang => {
+    const lower = lang.toLowerCase()
+    return aliases[lower] || lower
+  }
+
   visit(markdownAST, `code`, node => {
     let language = node.lang
     let { splitLanguage, highlightLines } = parseLineNumberRange(language)
@@ -20,8 +25,7 @@ module.exports = (
     // @see https://github.com/PrismJS/prism/blob/1d5047df37aacc900f8270b1c6215028f6988eb1/themes/prism.css#L49-L54
     let languageName = `text`
     if (language) {
-      language = language.toLowerCase()
-      languageName = language
+      languageName = normalizeLanguage(language)
     }
 
     // Allow users to specify a custom class prefix to avoid breaking
@@ -49,7 +53,7 @@ module.exports = (
     if (inlineCodeMarker) {
       let [language, restOfValue] = node.value.split(`${inlineCodeMarker}`, 2)
       if (language && restOfValue) {
-        languageName = language.toLowerCase()
+        languageName = normalizeLanguage(language)
         node.value = restOfValue
       }
     }