Skip to content

Commit

Permalink
Standardized dependency logic implementation (#1998)
Browse files Browse the repository at this point in the history
This adds a standard logic for handling dependencies between Prism components.

Right now, the download page, the `loadLanguages` function, and the test suite use the new dependency system.
  • Loading branch information
RunDevelopment committed Dec 16, 2019
1 parent a7f7009 commit 7a4a0c7
Show file tree
Hide file tree
Showing 9 changed files with 860 additions and 197 deletions.
2 changes: 1 addition & 1 deletion components.js

Large diffs are not rendered by default.

57 changes: 34 additions & 23 deletions components.json
Expand Up @@ -60,7 +60,7 @@
"css": {
"title": "CSS",
"option": "default",
"peerDependencies": "markup"
"modify": "markup"
},
"clike": {
"title": "C-like",
Expand All @@ -70,7 +70,7 @@
"javascript": {
"title": "JavaScript",
"require": "clike",
"peerDependencies": "markup",
"modify": "markup",
"alias": "js",
"option": "default"
},
Expand All @@ -85,7 +85,7 @@
"actionscript": {
"title": "ActionScript",
"require": "javascript",
"peerDependencies": "markup",
"modify": "markup",
"owner": "Golmote"
},
"ada": {
Expand Down Expand Up @@ -235,6 +235,7 @@
"css-extras": {
"title": "CSS Extras",
"require": "css",
"modify": "css",
"owner": "milesj"
},
"d": {
Expand Down Expand Up @@ -374,7 +375,7 @@
"haml": {
"title": "Haml",
"require": "ruby",
"peerDependencies": [
"optional": [
"css",
"css-extras",
"coffeescript",
Expand Down Expand Up @@ -409,8 +410,10 @@
},
"http": {
"title": "HTTP",
"peerDependencies": [
"optional": [
"css",
"javascript",
"json",
"markup"
],
"owner": "danielgtaylor"
Expand Down Expand Up @@ -455,14 +458,17 @@
"javadoc": {
"title": "JavaDoc",
"require": ["markup", "java", "javadoclike"],
"peerDependencies": [
"modify": [
"java"
],
"optional": [
"scala"
],
"owner": "RunDevelopment"
},
"javadoclike": {
"title": "JavaDoc-like",
"peerDependencies": [
"modify": [
"java",
"javascript",
"php"
Expand All @@ -485,7 +491,8 @@
"jsdoc": {
"title": "JSDoc",
"require": ["javascript", "javadoclike"],
"peerDependencies": [
"modify": "javascript",
"optional": [
"actionscript",
"coffeescript"
],
Expand All @@ -494,7 +501,8 @@
"js-extras": {
"title": "JS Extras",
"require": "javascript",
"peerDependencies": [
"modify": "javascript",
"optional": [
"actionscript",
"coffeescript",
"flow",
Expand All @@ -506,7 +514,8 @@
"js-templates": {
"title": "JS Templates",
"require": "javascript",
"peerDependencies": [
"modify": "javascript",
"optional": [
"css",
"css-extras",
"graphql",
Expand Down Expand Up @@ -554,7 +563,7 @@
"less": {
"title": "Less",
"require": "css",
"peerDependencies": "css-extras",
"optional": "css-extras",
"owner": "Golmote"
},
"lilypond": {
Expand Down Expand Up @@ -627,7 +636,7 @@
"n4js": {
"title": "N4JS",
"require": "javascript",
"peerDependencies": [
"optional": [
"jsdoc"
],
"alias": "n4jsd",
Expand Down Expand Up @@ -670,7 +679,7 @@
"opencl": {
"title": "OpenCL",
"require": "cpp",
"peerDependencies": [
"modify": [
"c",
"cpp"
],
Expand Down Expand Up @@ -719,11 +728,13 @@
"phpdoc": {
"title": "PHPDoc",
"require": ["php", "javadoclike"],
"modify": "php",
"owner": "RunDevelopment"
},
"php-extras": {
"title": "PHP Extras",
"require": "php",
"modify": "php",
"owner": "milesj"
},
"plsql": {
Expand Down Expand Up @@ -756,7 +767,7 @@
"pug": {
"title": "Pug",
"require": ["markup", "javascript"],
"peerDependencies": [
"optional": [
"coffeescript",
"ejs",
"handlebars",
Expand All @@ -775,7 +786,7 @@
},
"pure": {
"title": "Pure",
"peerDependencies": [
"optional": [
"c",
"cpp",
"fortran"
Expand Down Expand Up @@ -803,7 +814,7 @@
"jsx": {
"title": "React JSX",
"require": ["markup", "javascript"],
"peerDependencies": [
"optional": [
"jsdoc",
"js-extras",
"js-templates"
Expand All @@ -825,7 +836,7 @@
},
"regex": {
"title": "Regex",
"peerDependencies": [
"modify": [
"actionscript",
"coffeescript",
"flow",
Expand Down Expand Up @@ -875,7 +886,7 @@
"scss": {
"title": "Sass (Scss)",
"require": "css",
"peerDependencies": "css-extras",
"optional": "css-extras",
"owner": "MoOx"
},
"scala": {
Expand Down Expand Up @@ -951,7 +962,7 @@
"textile": {
"title": "Textile",
"require": "markup",
"peerDependencies": "css",
"optional": "css",
"owner": "Golmote"
},
"toml": {
Expand Down Expand Up @@ -979,7 +990,7 @@
"typescript": {
"title": "TypeScript",
"require": "javascript",
"peerDependencies": "js-templates",
"optional": "js-templates",
"alias": "ts",
"owner": "vkbansal"
},
Expand Down Expand Up @@ -1084,7 +1095,7 @@
"show-invisibles": {
"title": "Show Invisibles",
"description": "Show hidden characters such as tabs and line breaks.",
"after": [
"optional": [
"autolinker",
"data-uri-highlight"
]
Expand Down Expand Up @@ -1155,7 +1166,7 @@
"title": "Keep Markup",
"description": "Prevents custom markup from being dropped out during highlighting.",
"owner": "Golmote",
"after": "normalize-whitespace",
"optional": "normalize-whitespace",
"noCSS": true
},
"command-line": {
Expand All @@ -1171,7 +1182,7 @@
"title": "Normalize Whitespace",
"description": "Supports multiple operations to normalize whitespace in code blocks.",
"owner": "zeitgeist87",
"after": "unescaped-markup",
"optional": "unescaped-markup",
"noCSS": true
},
"data-uri-highlight": {
Expand Down
107 changes: 37 additions & 70 deletions components/index.js
@@ -1,82 +1,49 @@
var components = require('../components.js');
var peerDependentsMap = null;

function getPeerDependentsMap() {
var peerDependentsMap = {};
Object.keys(components.languages).forEach(function (language) {
if (language === 'meta') {
return false;
}
if (components.languages[language].peerDependencies) {
var peerDependencies = components.languages[language].peerDependencies;
if (!Array.isArray(peerDependencies)) {
peerDependencies = [peerDependencies];
}
peerDependencies.forEach(function (peerDependency) {
if (!peerDependentsMap[peerDependency]) {
peerDependentsMap[peerDependency] = [];
}
peerDependentsMap[peerDependency].push(language);
});
}
});
return peerDependentsMap;
}

function getPeerDependents(mainLanguage) {
if (!peerDependentsMap) {
peerDependentsMap = getPeerDependentsMap();
const components = require('../components.js');
const getLoader = require('../dependencies');


/**
* The set of all languages which have been loaded using the below function.
*
* @type {Set<string>}
*/
const loadedLanguages = new Set();

/**
* Loads the given languages and adds them to the current Prism instance.
*
* If no languages are provided, __all__ Prism languages will be loaded.
*
* @param {string|string[]} [languages]
* @returns {void}
*/
function loadLanguages(languages) {
if (languages === undefined) {
languages = Object.keys(components.languages).filter(l => l != 'meta');
} else if (!Array.isArray(languages)) {
languages = [languages];
}
return peerDependentsMap[mainLanguage] || [];
}

function loadLanguages(arr, withoutDependencies) {
// If no argument is passed, load all components
if (!arr) {
arr = Object.keys(components.languages).filter(function (language) {
return language !== 'meta';
});
}
if (arr && !arr.length) {
return;
}

if (!Array.isArray(arr)) {
arr = [arr];
}
// the user might have loaded languages via some other way or used `prism.js` which already includes some
// we don't need to validate the ids because `getLoader` will ignore invalid ones
const loaded = [...loadedLanguages, ...Object.keys(Prism.languages)];

arr.forEach(function (language) {
if (!components.languages[language]) {
console.warn('Language does not exist ' + language);
getLoader(components, languages, loaded).load(lang => {
if (!(lang in components.languages)) {
console.warn('Language does not exist: ' + lang);
return;
}
// Load dependencies first
if (!withoutDependencies && components.languages[language].require) {
loadLanguages(components.languages[language].require);
}

var pathToLanguage = './prism-' + language;
const pathToLanguage = './prism-' + lang;

// remove from require cache and from Prism
delete require.cache[require.resolve(pathToLanguage)];
delete Prism.languages[language];
delete Prism.languages[lang];

require(pathToLanguage);

// Reload dependents
var dependents = getPeerDependents(language).filter(function (dependent) {
// If dependent language was already loaded,
// we want to reload it.
if (Prism.languages[dependent]) {
delete Prism.languages[dependent];
return true;
}
return false;
});
if (dependents.length) {
loadLanguages(dependents, true);
}
loadedLanguages.add(lang);
});
}

module.exports = function (arr) {
// Don't expose withoutDependencies
loadLanguages(arr);
};
module.exports = loadLanguages;

0 comments on commit 7a4a0c7

Please sign in to comment.