Skip to content

Commit

Permalink
try different approach to JSX
Browse files Browse the repository at this point in the history
  • Loading branch information
joshgoebel committed Feb 19, 2020
1 parent a34abcb commit b8b2a95
Show file tree
Hide file tree
Showing 3 changed files with 127 additions and 21 deletions.
33 changes: 12 additions & 21 deletions src/languages/javascript.js
Expand Up @@ -5,15 +5,9 @@ Category: common, scripting
Website: https://developer.mozilla.org/en-US/docs/Web/JavaScript
*/

import { JSX_MODE, JSX_LANGUAGE } from "./lib/jsx";

export default function(hljs) {
var FRAGMENT = {
begin: '<>',
end: '</>'
};
var XML_TAG = {
begin: /<[A-Za-z0-9\\._:-]+/,
end: /\/[A-Za-z0-9\\._:-]+>|\/>/
};
var IDENT_RE = '[A-Za-z$_][0-9A-Za-z$_]*';
var KEYWORDS = {
keyword:
Expand Down Expand Up @@ -94,6 +88,15 @@ export default function(hljs) {
hljs.C_LINE_COMMENT_MODE
]);

const containers = [
hljs.APOS_STRING_MODE,
hljs.QUOTE_STRING_MODE,
TEMPLATE_STRING,
hljs.C_BLOCK_COMMENT_MODE,
hljs.C_LINE_COMMENT_MODE
];
hljs.registerLanguage("_jsx", JSX_LANGUAGE({containers}));

return {
aliases: ['js', 'jsx', 'mjs', 'cjs'],
keywords: KEYWORDS,
Expand Down Expand Up @@ -198,19 +201,7 @@ export default function(hljs) {
end: /\s*/,
skip: true,
},
{ // JSX
variants: [
{ begin: FRAGMENT.begin, end: FRAGMENT.end },
{ begin: XML_TAG.begin, end: XML_TAG.end }
],
subLanguage: 'xml',
contains: [
{
begin: XML_TAG.begin, end: XML_TAG.end, skip: true,
contains: ['self']
}
]
},
JSX_MODE
],
relevance: 0
},
Expand Down
110 changes: 110 additions & 0 deletions src/languages/lib/jsx.js
@@ -0,0 +1,110 @@
import { inherit } from "../../lib/utils";

const FRAGMENT = {
begin: '<>',
end: '</>'
};
const XML_TAG = {
begin: /<[A-Za-z0-9\\._:-]+/,
end: /\/[A-Za-z0-9\\._:-]+>|\/>/
};

export const JSX_MODE = { // JSX
variants: [
{ begin: FRAGMENT.begin, end: FRAGMENT.end },
{ begin: XML_TAG.begin, end: XML_TAG.end }
],
subLanguage: '_jsx',
contains: [
{
begin: XML_TAG.begin, end: XML_TAG.end, skip: true,
contains: ['self']
}
]
};

// note: this is not a language grammar itself but when called
// it returns a function that is the language grammar
// This could be improved if our registerLanguage API was enhanced
// to support passing options to grammars.
export const JSX_LANGUAGE = function({containers}) {

// containers are any blocks which could prevent an inline JS mode
// from ending... inline javascript is denoted with `{ code }`
// so an example would be a string: ` { "}" }` Become the } is
// inside the container it should be ignored and not counted as
// ending the inline JS snippet
//
// these are passed in because it makes sense that these would
// already be defined by the parent language
containers = containers.map((x) =>
// we need these to be quiet, and not output
inherit(x, {skip: true, className: null})
)

return function (hljs) {

const XML_IDENT_RE = '[A-Za-z0-9\\._:-]+';
const XML_ENTITIES = {
className: 'symbol',
begin: '&[a-z]+;|&#[0-9]+;|&#x[a-f0-9]+;'
};
const INLINE_JS = {
begin: /{/,
end: /}/,
// needs to eat strings, regex, comments, etc.
contains: [].concat(containers),
subLanguage: "javascript"
};
const TAG_INTERNALS = {
endsWithParent: true,
illegal: /</,
relevance: 0,
contains: [
hljs.C_LINE_COMMENT_MODE,
{
className: 'attr',
begin: XML_IDENT_RE,
relevance: 0
},
{
begin: /=\s*/,
relevance: 0,
contains: [
{
className: 'string',
endsParent: true,
variants: [
{begin: /"/, end: /"/, contains: [XML_ENTITIES]},
{begin: /'/, end: /'/, contains: [XML_ENTITIES]},
{begin: /[^\s"'=<>`]+/}
]
}
]
}
]
};
const SIMPLE_TAG = {
className: 'tag',
begin: '</?', end: '/?>',
contains: [
{
className: 'name', begin: /[^\/><\s]+/, relevance: 0
},
TAG_INTERNALS
]
}

return {
className:"xml",
case_insensitive: true,
disableAutodetect: true,
contains: [
SIMPLE_TAG,
INLINE_JS
]
};

}
}

5 changes: 5 additions & 0 deletions test/markup/javascript/jsx.txt
Expand Up @@ -16,8 +16,13 @@ class App extends Component {
return (
<BrowserRouter>
<div>
{/* comment */}
{ test "}" }
<Route path="/about" component={About} />
<Route path="/contact" component={Contact} />
<div
box="yes" // comment
/>
</div>
</BrowserRouter>
);
Expand Down

0 comments on commit b8b2a95

Please sign in to comment.