gatsby-plugin-mdx
Version:
MDX integration for Gatsby
553 lines (548 loc) • 16.8 kB
JavaScript
const { camelCase } = require(`change-case`)
const styleToObject = require(`style-to-object`)
const camelCaseCSS = require(`camelcase-css`)
const t = require(`@babel/types`)
// object retrieved from https://github.com/facebook/react/blob/master/packages/react-dom/src/shared/possibleStandardNames.js
const TRANSLATIONS = new Map([
// HTML
[`accept`, `accept`],
[`acceptcharset`, `acceptCharset`],
[`accept-charset`, `acceptCharset`],
[`accesskey`, `accessKey`],
[`action`, `action`],
[`allowfullscreen`, `allowFullScreen`],
[`alt`, `alt`],
[`as`, `as`],
[`async`, `async`],
[`autocapitalize`, `autoCapitalize`],
[`autocomplete`, `autoComplete`],
[`autocorrect`, `autoCorrect`],
[`autofocus`, `autoFocus`],
[`autoplay`, `autoPlay`],
[`autosave`, `autoSave`],
[`capture`, `capture`],
[`cellpadding`, `cellPadding`],
[`cellspacing`, `cellSpacing`],
[`challenge`, `challenge`],
[`charset`, `charSet`],
[`checked`, `checked`],
[`children`, `children`],
[`cite`, `cite`],
[`class`, `className`],
[`classid`, `classID`],
[`classname`, `className`],
[`cols`, `cols`],
[`colspan`, `colSpan`],
[`content`, `content`],
[`contenteditable`, `contentEditable`],
[`contextmenu`, `contextMenu`],
[`controls`, `controls`],
[`controlslist`, `controlsList`],
[`coords`, `coords`],
[`crossorigin`, `crossOrigin`],
[`dangerouslysetinnerhtml`, `dangerouslySetInnerHTML`],
[`data`, `data`],
[`datetime`, `dateTime`],
[`default`, `default`],
[`defaultchecked`, `defaultChecked`],
[`defaultvalue`, `defaultValue`],
[`defer`, `defer`],
[`dir`, `dir`],
[`disabled`, `disabled`],
[`disablepictureinpicture`, `disablePictureInPicture`],
[`download`, `download`],
[`draggable`, `draggable`],
[`enctype`, `encType`],
[`for`, `htmlFor`],
[`form`, `form`],
[`formmethod`, `formMethod`],
[`formaction`, `formAction`],
[`formenctype`, `formEncType`],
[`formnovalidate`, `formNoValidate`],
[`formtarget`, `formTarget`],
[`frameborder`, `frameBorder`],
[`headers`, `headers`],
[`height`, `height`],
[`hidden`, `hidden`],
[`high`, `high`],
[`href`, `href`],
[`hreflang`, `hrefLang`],
[`htmlfor`, `htmlFor`],
[`httpequiv`, `httpEquiv`],
[`http-equiv`, `httpEquiv`],
[`icon`, `icon`],
[`id`, `id`],
[`innerhtml`, `innerHTML`],
[`inputmode`, `inputMode`],
[`integrity`, `integrity`],
[`is`, `is`],
[`itemid`, `itemID`],
[`itemprop`, `itemProp`],
[`itemref`, `itemRef`],
[`itemscope`, `itemScope`],
[`itemtype`, `itemType`],
[`keyparams`, `keyParams`],
[`keytype`, `keyType`],
[`kind`, `kind`],
[`label`, `label`],
[`lang`, `lang`],
[`list`, `list`],
[`loop`, `loop`],
[`low`, `low`],
[`manifest`, `manifest`],
[`marginwidth`, `marginWidth`],
[`marginheight`, `marginHeight`],
[`max`, `max`],
[`maxlength`, `maxLength`],
[`media`, `media`],
[`mediagroup`, `mediaGroup`],
[`method`, `method`],
[`min`, `min`],
[`minlength`, `minLength`],
[`multiple`, `multiple`],
[`muted`, `muted`],
[`name`, `name`],
[`nomodule`, `noModule`],
[`nonce`, `nonce`],
[`novalidate`, `noValidate`],
[`open`, `open`],
[`optimum`, `optimum`],
[`pattern`, `pattern`],
[`placeholder`, `placeholder`],
[`playsinline`, `playsInline`],
[`poster`, `poster`],
[`preload`, `preload`],
[`profile`, `profile`],
[`radiogroup`, `radioGroup`],
[`readonly`, `readOnly`],
[`referrerpolicy`, `referrerPolicy`],
[`rel`, `rel`],
[`required`, `required`],
[`reversed`, `reversed`],
[`role`, `role`],
[`rows`, `rows`],
[`rowspan`, `rowSpan`],
[`sandbox`, `sandbox`],
[`scope`, `scope`],
[`scoped`, `scoped`],
[`scrolling`, `scrolling`],
[`seamless`, `seamless`],
[`selected`, `selected`],
[`shape`, `shape`],
[`size`, `size`],
[`sizes`, `sizes`],
[`span`, `span`],
[`spellcheck`, `spellCheck`],
[`src`, `src`],
[`srcdoc`, `srcDoc`],
[`srclang`, `srcLang`],
[`srcset`, `srcSet`],
[`start`, `start`],
[`step`, `step`],
[`style`, `style`],
[`summary`, `summary`],
[`tabindex`, `tabIndex`],
[`target`, `target`],
[`title`, `title`],
[`type`, `type`],
[`usemap`, `useMap`],
[`value`, `value`],
[`width`, `width`],
[`wmode`, `wmode`],
[`wrap`, `wrap`],
// SVG
[`about`, `about`],
[`accentheight`, `accentHeight`],
[`accent-height`, `accentHeight`],
[`accumulate`, `accumulate`],
[`additive`, `additive`],
[`alignmentbaseline`, `alignmentBaseline`],
[`alignment-baseline`, `alignmentBaseline`],
[`allowreorder`, `allowReorder`],
[`alphabetic`, `alphabetic`],
[`amplitude`, `amplitude`],
[`arabicform`, `arabicForm`],
[`arabic-form`, `arabicForm`],
[`ascent`, `ascent`],
[`attributename`, `attributeName`],
[`attributetype`, `attributeType`],
[`autoreverse`, `autoReverse`],
[`azimuth`, `azimuth`],
[`basefrequency`, `baseFrequency`],
[`baselineshift`, `baselineShift`],
[`baseline-shift`, `baselineShift`],
[`baseprofile`, `baseProfile`],
[`bbox`, `bbox`],
[`begin`, `begin`],
[`bias`, `bias`],
[`by`, `by`],
[`calcmode`, `calcMode`],
[`capheight`, `capHeight`],
[`cap-height`, `capHeight`],
[`clip`, `clip`],
[`clippath`, `clipPath`],
[`clip-path`, `clipPath`],
[`clippathunits`, `clipPathUnits`],
[`cliprule`, `clipRule`],
[`clip-rule`, `clipRule`],
[`color`, `color`],
[`colorinterpolation`, `colorInterpolation`],
[`color-interpolation`, `colorInterpolation`],
[`colorinterpolationfilters`, `colorInterpolationFilters`],
[`color-interpolation-filters`, `colorInterpolationFilters`],
[`colorprofile`, `colorProfile`],
[`color-profile`, `colorProfile`],
[`colorrendering`, `colorRendering`],
[`color-rendering`, `colorRendering`],
[`contentscripttype`, `contentScriptType`],
[`contentstyletype`, `contentStyleType`],
[`cursor`, `cursor`],
[`cx`, `cx`],
[`cy`, `cy`],
[`d`, `d`],
[`datatype`, `datatype`],
[`decelerate`, `decelerate`],
[`descent`, `descent`],
[`diffuseconstant`, `diffuseConstant`],
[`direction`, `direction`],
[`display`, `display`],
[`divisor`, `divisor`],
[`dominantbaseline`, `dominantBaseline`],
[`dominant-baseline`, `dominantBaseline`],
[`dur`, `dur`],
[`dx`, `dx`],
[`dy`, `dy`],
[`edgemode`, `edgeMode`],
[`elevation`, `elevation`],
[`enablebackground`, `enableBackground`],
[`enable-background`, `enableBackground`],
[`end`, `end`],
[`exponent`, `exponent`],
[`externalresourcesrequired`, `externalResourcesRequired`],
[`fill`, `fill`],
[`fillopacity`, `fillOpacity`],
[`fill-opacity`, `fillOpacity`],
[`fillrule`, `fillRule`],
[`fill-rule`, `fillRule`],
[`filter`, `filter`],
[`filterres`, `filterRes`],
[`filterunits`, `filterUnits`],
[`floodopacity`, `floodOpacity`],
[`flood-opacity`, `floodOpacity`],
[`floodcolor`, `floodColor`],
[`flood-color`, `floodColor`],
[`focusable`, `focusable`],
[`fontfamily`, `fontFamily`],
[`font-family`, `fontFamily`],
[`fontsize`, `fontSize`],
[`font-size`, `fontSize`],
[`fontsizeadjust`, `fontSizeAdjust`],
[`font-size-adjust`, `fontSizeAdjust`],
[`fontstretch`, `fontStretch`],
[`font-stretch`, `fontStretch`],
[`fontstyle`, `fontStyle`],
[`font-style`, `fontStyle`],
[`fontvariant`, `fontVariant`],
[`font-variant`, `fontVariant`],
[`fontweight`, `fontWeight`],
[`font-weight`, `fontWeight`],
[`format`, `format`],
[`from`, `from`],
[`fx`, `fx`],
[`fy`, `fy`],
[`g1`, `g1`],
[`g2`, `g2`],
[`glyphname`, `glyphName`],
[`glyph-name`, `glyphName`],
[`glyphorientationhorizontal`, `glyphOrientationHorizontal`],
[`glyph-orientation-horizontal`, `glyphOrientationHorizontal`],
[`glyphorientationvertical`, `glyphOrientationVertical`],
[`glyph-orientation-vertical`, `glyphOrientationVertical`],
[`glyphref`, `glyphRef`],
[`gradienttransform`, `gradientTransform`],
[`gradientunits`, `gradientUnits`],
[`hanging`, `hanging`],
[`horizadvx`, `horizAdvX`],
[`horiz-adv-x`, `horizAdvX`],
[`horizoriginx`, `horizOriginX`],
[`horiz-origin-x`, `horizOriginX`],
[`ideographic`, `ideographic`],
[`imagerendering`, `imageRendering`],
[`image-rendering`, `imageRendering`],
[`in2`, `in2`],
[`in`, `in`],
[`inlist`, `inlist`],
[`intercept`, `intercept`],
[`k1`, `k1`],
[`k2`, `k2`],
[`k3`, `k3`],
[`k4`, `k4`],
[`k`, `k`],
[`kernelmatrix`, `kernelMatrix`],
[`kernelunitlength`, `kernelUnitLength`],
[`kerning`, `kerning`],
[`keypoints`, `keyPoints`],
[`keysplines`, `keySplines`],
[`keytimes`, `keyTimes`],
[`lengthadjust`, `lengthAdjust`],
[`letterspacing`, `letterSpacing`],
[`letter-spacing`, `letterSpacing`],
[`lightingcolor`, `lightingColor`],
[`lighting-color`, `lightingColor`],
[`limitingconeangle`, `limitingConeAngle`],
[`local`, `local`],
[`markerend`, `markerEnd`],
[`marker-end`, `markerEnd`],
[`markerheight`, `markerHeight`],
[`markermid`, `markerMid`],
[`marker-mid`, `markerMid`],
[`markerstart`, `markerStart`],
[`marker-start`, `markerStart`],
[`markerunits`, `markerUnits`],
[`markerwidth`, `markerWidth`],
[`mask`, `mask`],
[`maskcontentunits`, `maskContentUnits`],
[`maskunits`, `maskUnits`],
[`mathematical`, `mathematical`],
[`mode`, `mode`],
[`numoctaves`, `numOctaves`],
[`offset`, `offset`],
[`opacity`, `opacity`],
[`operator`, `operator`],
[`order`, `order`],
[`orient`, `orient`],
[`orientation`, `orientation`],
[`origin`, `origin`],
[`overflow`, `overflow`],
[`overlineposition`, `overlinePosition`],
[`overline-position`, `overlinePosition`],
[`overlinethickness`, `overlineThickness`],
[`overline-thickness`, `overlineThickness`],
[`paintorder`, `paintOrder`],
[`paint-order`, `paintOrder`],
[`panose1`, `panose1`],
[`panose-1`, `panose1`],
[`pathlength`, `pathLength`],
[`patterncontentunits`, `patternContentUnits`],
[`patterntransform`, `patternTransform`],
[`patternunits`, `patternUnits`],
[`pointerevents`, `pointerEvents`],
[`pointer-events`, `pointerEvents`],
[`points`, `points`],
[`pointsatx`, `pointsAtX`],
[`pointsaty`, `pointsAtY`],
[`pointsatz`, `pointsAtZ`],
[`prefix`, `prefix`],
[`preservealpha`, `preserveAlpha`],
[`preserveaspectratio`, `preserveAspectRatio`],
[`primitiveunits`, `primitiveUnits`],
[`property`, `property`],
[`r`, `r`],
[`radius`, `radius`],
[`refx`, `refX`],
[`refy`, `refY`],
[`renderingintent`, `renderingIntent`],
[`rendering-intent`, `renderingIntent`],
[`repeatcount`, `repeatCount`],
[`repeatdur`, `repeatDur`],
[`requiredextensions`, `requiredExtensions`],
[`requiredfeatures`, `requiredFeatures`],
[`resource`, `resource`],
[`restart`, `restart`],
[`result`, `result`],
[`results`, `results`],
[`rotate`, `rotate`],
[`rx`, `rx`],
[`ry`, `ry`],
[`scale`, `scale`],
[`security`, `security`],
[`seed`, `seed`],
[`shaperendering`, `shapeRendering`],
[`shape-rendering`, `shapeRendering`],
[`slope`, `slope`],
[`spacing`, `spacing`],
[`specularconstant`, `specularConstant`],
[`specularexponent`, `specularExponent`],
[`speed`, `speed`],
[`spreadmethod`, `spreadMethod`],
[`startoffset`, `startOffset`],
[`stddeviation`, `stdDeviation`],
[`stemh`, `stemh`],
[`stemv`, `stemv`],
[`stitchtiles`, `stitchTiles`],
[`stopcolor`, `stopColor`],
[`stop-color`, `stopColor`],
[`stopopacity`, `stopOpacity`],
[`stop-opacity`, `stopOpacity`],
[`strikethroughposition`, `strikethroughPosition`],
[`strikethrough-position`, `strikethroughPosition`],
[`strikethroughthickness`, `strikethroughThickness`],
[`strikethrough-thickness`, `strikethroughThickness`],
[`string`, `string`],
[`stroke`, `stroke`],
[`strokedasharray`, `strokeDasharray`],
[`stroke-dasharray`, `strokeDasharray`],
[`strokedashoffset`, `strokeDashoffset`],
[`stroke-dashoffset`, `strokeDashoffset`],
[`strokelinecap`, `strokeLinecap`],
[`stroke-linecap`, `strokeLinecap`],
[`strokelinejoin`, `strokeLinejoin`],
[`stroke-linejoin`, `strokeLinejoin`],
[`strokemiterlimit`, `strokeMiterlimit`],
[`stroke-miterlimit`, `strokeMiterlimit`],
[`strokewidth`, `strokeWidth`],
[`stroke-width`, `strokeWidth`],
[`strokeopacity`, `strokeOpacity`],
[`stroke-opacity`, `strokeOpacity`],
[`suppresscontenteditablewarning`, `suppressContentEditableWarning`],
[`suppresshydrationwarning`, `suppressHydrationWarning`],
[`surfacescale`, `surfaceScale`],
[`systemlanguage`, `systemLanguage`],
[`tablevalues`, `tableValues`],
[`targetx`, `targetX`],
[`targety`, `targetY`],
[`textanchor`, `textAnchor`],
[`text-anchor`, `textAnchor`],
[`textdecoration`, `textDecoration`],
[`text-decoration`, `textDecoration`],
[`textlength`, `textLength`],
[`textrendering`, `textRendering`],
[`text-rendering`, `textRendering`],
[`to`, `to`],
[`transform`, `transform`],
[`typeof`, `typeof`],
[`u1`, `u1`],
[`u2`, `u2`],
[`underlineposition`, `underlinePosition`],
[`underline-position`, `underlinePosition`],
[`underlinethickness`, `underlineThickness`],
[`underline-thickness`, `underlineThickness`],
[`unicode`, `unicode`],
[`unicodebidi`, `unicodeBidi`],
[`unicode-bidi`, `unicodeBidi`],
[`unicoderange`, `unicodeRange`],
[`unicode-range`, `unicodeRange`],
[`unitsperem`, `unitsPerEm`],
[`units-per-em`, `unitsPerEm`],
[`unselectable`, `unselectable`],
[`valphabetic`, `vAlphabetic`],
[`v-alphabetic`, `vAlphabetic`],
[`values`, `values`],
[`vectoreffect`, `vectorEffect`],
[`vector-effect`, `vectorEffect`],
[`version`, `version`],
[`vertadvy`, `vertAdvY`],
[`vert-adv-y`, `vertAdvY`],
[`vertoriginx`, `vertOriginX`],
[`vert-origin-x`, `vertOriginX`],
[`vertoriginy`, `vertOriginY`],
[`vert-origin-y`, `vertOriginY`],
[`vhanging`, `vHanging`],
[`v-hanging`, `vHanging`],
[`videographic`, `vIdeographic`],
[`v-ideographic`, `vIdeographic`],
[`viewbox`, `viewBox`],
[`viewtarget`, `viewTarget`],
[`visibility`, `visibility`],
[`vmathematical`, `vMathematical`],
[`v-mathematical`, `vMathematical`],
[`vocab`, `vocab`],
[`widths`, `widths`],
[`wordspacing`, `wordSpacing`],
[`word-spacing`, `wordSpacing`],
[`writingmode`, `writingMode`],
[`writing-mode`, `writingMode`],
[`x1`, `x1`],
[`x2`, `x2`],
[`x`, `x`],
[`xchannelselector`, `xChannelSelector`],
[`xheight`, `xHeight`],
[`x-height`, `xHeight`],
[`xlinkactuate`, `xlinkActuate`],
[`xlink:actuate`, `xlinkActuate`],
[`xlinkarcrole`, `xlinkArcrole`],
[`xlink:arcrole`, `xlinkArcrole`],
[`xlinkhref`, `xlinkHref`],
[`xlink:href`, `xlinkHref`],
[`xlinkrole`, `xlinkRole`],
[`xlink:role`, `xlinkRole`],
[`xlinkshow`, `xlinkShow`],
[`xlink:show`, `xlinkShow`],
[`xlinktitle`, `xlinkTitle`],
[`xlink:title`, `xlinkTitle`],
[`xlinktype`, `xlinkType`],
[`xlink:type`, `xlinkType`],
[`xmlbase`, `xmlBase`],
[`xml:base`, `xmlBase`],
[`xmllang`, `xmlLang`],
[`xml:lang`, `xmlLang`],
[`xmlns`, `xmlns`],
[`xml:space`, `xmlSpace`],
[`xmlnsxlink`, `xmlnsXlink`],
[`xmlns:xlink`, `xmlnsXlink`],
[`xmlspace`, `xmlSpace`],
[`y1`, `y1`],
[`y2`, `y2`],
[`y`, `y`],
[`ychannelselector`, `yChannelSelector`],
[`z`, `z`],
[`zoomandpan`, `zoomAndPan`],
])
const propsKeysVisitor = {
ObjectProperty(node) {
if (TRANSLATIONS.has(node.node.key.extra.rawValue)) {
const translated = TRANSLATIONS.get(node.node.key.value)
if (translated) {
node.node.key.value = translated
}
}
},
}
const jsxAttributeFromHTMLAttributeVisitor = {
JSXAttribute: function (node) {
const nameNode = node.node.name
const name = nameNode.name
const translated = TRANSLATIONS.get(name)
if (translated) {
nameNode.name = translated
} else if (name === `props`) {
node.traverse(propsKeysVisitor)
} else if (
name.includes(`-`) &&
!name.startsWith(`data`) &&
!name.startsWith(`aria`)
) {
nameNode.name = camelCase(name)
}
if (
nameNode.name === `style` &&
node.node.value.type === `StringLiteral`
// node.node.value.type !== "JSXExpressionContainer"
) {
const styleArray = []
styleToObject(node.node.value.extra.rawValue, function (
name,
value,
declaration
) {
styleArray.push([camelCaseCSS(name), value])
})
node.node.value = t.jSXExpressionContainer(
t.objectExpression(
styleArray.map(([key, value]) =>
t.objectProperty(t.StringLiteral(key), t.stringLiteral(value))
)
)
)
}
},
}
module.exports = function attrs() {
return {
visitor: {
JSXElement: function (path) {
path.traverse(jsxAttributeFromHTMLAttributeVisitor)
},
},
}
}