Skip to content

Commit

Permalink
Fix review comments
Browse files Browse the repository at this point in the history
  • Loading branch information
marcodejongh authored and conorhastings committed Oct 31, 2018
1 parent 57a28f9 commit e8e24a5
Show file tree
Hide file tree
Showing 5 changed files with 121 additions and 36 deletions.
55 changes: 55 additions & 0 deletions __tests__/__snapshots__/light-async.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,61 @@ exports[`SyntaxHighlighter async load language if not registered 1`] = `
</pre>
`;

exports[`SyntaxHighlighter render as text if language doesnt exist 1`] = `
<pre
style={
Object {
"MozHyphens": "none",
"MozTabSize": "4",
"OTabSize": "4",
"WebkitHyphens": "none",
"background": "#f5f2f0",
"color": "black",
"fontFamily": "Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace",
"hyphens": "none",
"lineHeight": "1.5",
"margin": ".5em 0",
"msHyphens": "none",
"overflow": "auto",
"padding": "1em",
"tabSize": "4",
"textAlign": "left",
"textShadow": "0 1px white",
"whiteSpace": "pre",
"wordBreak": "normal",
"wordSpacing": "normal",
"wordWrap": "normal",
}
}
>
<code
style={
Object {
"MozHyphens": "none",
"MozTabSize": "4",
"OTabSize": "4",
"WebkitHyphens": "none",
"background": "none",
"color": "black",
"fontFamily": "Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace",
"hyphens": "none",
"lineHeight": "1.5",
"msHyphens": "none",
"tabSize": "4",
"textAlign": "left",
"textShadow": "0 1px white",
"whiteSpace": "pre",
"wordBreak": "normal",
"wordSpacing": "normal",
"wordWrap": "normal",
}
}
>
print('hello')
</code>
</pre>
`;

exports[`SyntaxHighlighter renders fortran highlighted text 1`] = `
<pre
style={
Expand Down
30 changes: 20 additions & 10 deletions __tests__/async-syntax-highlighter.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,25 @@ import AsyncSyntaxHighlighter from "../src/async-syntax-highlighter";

test('AsyncSyntaxHighlighter registerLanguage when registerLanguage is undefined', () => {
const SyntaxHighlighter = AsyncSyntaxHighlighter({});

SyntaxHighlighter.registerLanguage("test", {});
expect(SyntaxHighlighter.languages).toEqual([]);

expect(() => {
SyntaxHighlighter.registerLanguage("test", {});
}).toThrowError();

expect(SyntaxHighlighter.languages.size).toEqual(0);
});

test('AsyncSyntaxHighlighter registerLanguage when registerLanguage is defined but astGenerator isn\'t', () => {
const registerLanguage = jest.fn();
const SyntaxHighlighter = AsyncSyntaxHighlighter({ registerLanguage });

SyntaxHighlighter.registerLanguage("test", {});
expect(SyntaxHighlighter.languages).toEqual([ { name: "test", language: {} }]);

const language = {
123: 456
};

SyntaxHighlighter.registerLanguage("test", language);
expect(SyntaxHighlighter.languages.get('test')).toEqual(language);
expect(SyntaxHighlighter.languages.size).toEqual(1);
});

test('AsyncSyntaxHighlighter registerLanguage when registerLanguage & astGenerator is defined', () => {
Expand All @@ -31,15 +39,17 @@ test('AsyncSyntaxHighlighter registerLanguage when registerLanguage & astGenerat
test('AsyncSyntaxHighlighter isRegistered when registerLanguage is not defined', () => {
const SyntaxHighlighter = AsyncSyntaxHighlighter({ });

expect(SyntaxHighlighter.isRegistered("test")).toEqual(true);
expect(() => {
SyntaxHighlighter.isRegistered("test", {});
}).toThrowError();
});

test('AsyncSyntaxHighlighter isRegistered when astGenerator is not defined it checks the languages array', () => {
const registerLanguage = jest.fn();

const SyntaxHighlighter = AsyncSyntaxHighlighter({ registerLanguage });
SyntaxHighlighter.astGenerator = null;
SyntaxHighlighter.languages.push({ name: 'test' })
SyntaxHighlighter.languages.set('test', {});
expect(SyntaxHighlighter.isRegistered('test')).toEqual(true);
});

Expand All @@ -48,7 +58,7 @@ test('AsyncSyntaxHighlighter isRegistered when astGenerator is defined it should

const SyntaxHighlighter = AsyncSyntaxHighlighter({ registerLanguage });
SyntaxHighlighter.astGenerator = null;
SyntaxHighlighter.languages.push({ name: 'test' })
SyntaxHighlighter.languages.set('test', {})
expect(SyntaxHighlighter.isRegistered('test')).toEqual(true);
});

Expand Down Expand Up @@ -82,7 +92,7 @@ test('AsyncSyntaxHighlighter loadAstGenerator when astGenerator resolves and it
const SyntaxHighlighter = AsyncSyntaxHighlighter({ loader, registerLanguage });
const testLanguage = { name: "cpp", language: { } };

SyntaxHighlighter.languages.push(testLanguage);
SyntaxHighlighter.languages.set(testLanguage.name, testLanguage.language)

await SyntaxHighlighter.loadAstGenerator();
expect(registerLanguage).toBeCalledWith(astGenerator, testLanguage.name, testLanguage.language)
Expand Down
4 changes: 1 addition & 3 deletions __tests__/light-async.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,14 @@ class Expire extends React.Component {
});


test('SyntaxHighlighter async load language if not registered', async () => {
test('SyntaxHighlighter render as text if language doesnt exist', () => {
const tree = renderer.create(
<SyntaxHighlighter language="nonexistinglanguage" style={prism}>
{
"print('hello')"
}
</SyntaxHighlighter>
)
await languageLoaders.python(jest.fn());
expect(tree.toJSON()).toMatchSnapshot();
});

Expand Down Expand Up @@ -82,7 +81,6 @@ test('When the code split is loaded - SyntaxHighlighter renders jsx highlighted

await languageLoaders.javascript(jest.fn());
expect(tree.toJSON()).toMatchSnapshot();

});

test('SyntaxHighlighter renders fortran highlighted text', async () => {
Expand Down
67 changes: 44 additions & 23 deletions src/async-syntax-highlighter.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,64 +2,73 @@ import React from 'react';
import highlight from './highlight';

export default (options) => {
const loader = options.loader;
const isLanguageRegistered = options.isLanguageRegistered;
const registerLanguage = options.registerLanguage;
const languageLoaders = options.languageLoaders;
const {
loader,
isLanguageRegistered,
registerLanguage,
languageLoaders,
noAsyncLoadingLanguages
} = options;

class ReactAsyncHighlighter extends React.PureComponent {
static astGenerator = null;
static highlightInstance = (highlight(null, {}));
static astGeneratorPromise = null;
static languages = [];
static languages = new Map();

static preload() {
return ReactAsyncHighlighter.loadAstGenerator();
}

static async loadLanguage(language) {
const languageLoader = languageLoaders[language];

if (typeof languageLoader === 'function') {
return languageLoader(ReactAsyncHighlighter.registerLanguage);
} else {
throw `Language ${language} not supported`
throw new Error(`Language ${language} not supported`);
}
}

static isSupportedLanguage(language) {
return ReactAsyncHighlighter.isRegistered(language) || typeof languageLoaders[language] === 'function';
}

static isRegistered = (language) => {
if(!registerLanguage) {
if(noAsyncLoadingLanguages) {
return true;
}

if(!registerLanguage) {
throw new Error('Current syntax highlighter doesn\'t support registration of languages');
}

if (!ReactAsyncHighlighter.astGenerator) {
// Ast generator not available yet, but language will be registered once it is.
return ReactAsyncHighlighter.languages.findIndex(item => item.name === language) > -1;
return ReactAsyncHighlighter.languages.has(language);
}

return isLanguageRegistered(ReactAsyncHighlighter.astGenerator, language);
}

static registerLanguage = (name, language) => {
if (!registerLanguage) {
return;
throw new Error('Current syntax highlighter doesn\'t support registration of languages');
}

if(ReactAsyncHighlighter.astGenerator) {
return registerLanguage(ReactAsyncHighlighter.astGenerator, name, language);
} else {
ReactAsyncHighlighter.languages.push({
name,
language
});
ReactAsyncHighlighter.languages.set(name, language);
}
};

static loadAstGenerator() {
ReactAsyncHighlighter.astGeneratorPromise = loader().then(astGenerator => {
ReactAsyncHighlighter.astGenerator = astGenerator;

if (registerLanguage && ReactAsyncHighlighter.languages.length) {
ReactAsyncHighlighter.languages.forEach(({ name, language }) => registerLanguage(astGenerator, name, language));
if (registerLanguage) {
ReactAsyncHighlighter.languages.forEach(( language, name ) => registerLanguage(astGenerator, name, language));
}
});

Expand All @@ -82,23 +91,35 @@ export default (options) => {
this.forceUpdate();
});
}

if(!ReactAsyncHighlighter.isRegistered(this.props.language) && languageLoaders) {
this.loadLanguage();
}
}

async loadLanguage() {
try {
ReactAsyncHighlighter.loadLanguage(this.props.language).then(() => {
this.forceUpdate();
});
} catch (error) {
console.log(error);
loadLanguage() {
const { language } = this.props;

if (language === 'text') {
return;
}

ReactAsyncHighlighter.loadLanguage(language).then(() => {
this.forceUpdate();
});
}

normalizeLanguage(language) {
return ReactAsyncHighlighter.isSupportedLanguage(language) ? language : 'text';
}

render() {
return (<ReactAsyncHighlighter.highlightInstance {...this.props} astGenerator={ReactAsyncHighlighter.astGenerator} />);
return (
<ReactAsyncHighlighter.highlightInstance
{...this.props}
language={this.normalizeLanguage(this.props.language)}
astGenerator={ReactAsyncHighlighter.astGenerator}
/>);
}
};

Expand Down
1 change: 1 addition & 0 deletions src/prism-async.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ export default createAsyncLoadingHighlighter({
// Webpack 3 returns module.exports as default as module, but webpack 4 returns module.exports as module.default
return module.default || module;
}),
noAsyncLoadingLanguages: true
});

0 comments on commit e8e24a5

Please sign in to comment.