examples.js 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. /**
  2. * Manage examples
  3. */
  4. (function() {
  5. var examples = {};
  6. var treeURL = 'https://api.github.com/repos/PrismJS/prism/git/trees/gh-pages?recursive=1';
  7. var treePromise = new Promise(function (resolve) {
  8. $u.xhr({
  9. url: treeURL,
  10. callback: function (xhr) {
  11. if (xhr.status < 400) {
  12. resolve(JSON.parse(xhr.responseText).tree);
  13. }
  14. }
  15. });
  16. });
  17. var languages = components.languages;
  18. for (var id in languages) {
  19. if (id === 'meta') {
  20. continue;
  21. }
  22. (function (id) {
  23. var language = languages[id];
  24. var checked = false;
  25. if (language.option === 'default') {
  26. checked = true;
  27. }
  28. language.enabled = checked;
  29. language.path = languages.meta.path.replace(/\{id}/g, id) + '.js';
  30. language.examplesPath = languages.meta.examplesPath.replace(/\{id}/g, id) + '.html';
  31. fileExists(language.examplesPath).then(function (exists) {
  32. $u.element.create('label', {
  33. attributes: {
  34. 'data-id': id,
  35. 'title': !exists ? 'No examples are available for this language.' : ''
  36. },
  37. className: !exists ? 'unavailable' : '',
  38. contents: [
  39. {
  40. tag: 'input',
  41. properties: {
  42. type: 'checkbox',
  43. name: 'language',
  44. value: id,
  45. checked: checked && exists,
  46. disabled: !exists,
  47. onclick: function () {
  48. $$('input[name="' + this.name + '"]').forEach(function (input) {
  49. languages[input.value].enabled = input.checked;
  50. });
  51. update(id);
  52. }
  53. }
  54. },
  55. language.title
  56. ],
  57. inside: '#languages'
  58. });
  59. examples[id] = $u.element.create('section', {
  60. 'id': 'language-' + id,
  61. 'className': 'language-' + id,
  62. inside: '#examples'
  63. });
  64. if (checked) {
  65. update(id);
  66. }
  67. });
  68. }(id));
  69. }
  70. function fileExists(filepath) {
  71. return treePromise.then(function (tree) {
  72. for (var i = 0, l = tree.length; i < l; i++) {
  73. if (tree[i].path === filepath) {
  74. return true;
  75. }
  76. }
  77. return false;
  78. });
  79. }
  80. function getFileContents(filepath) {
  81. return new Promise(function (resolve, reject) {
  82. $u.xhr({
  83. url: filepath,
  84. callback: function (xhr) {
  85. if (xhr.status < 400 && xhr.responseText) {
  86. resolve(xhr.responseText);
  87. } else {
  88. reject();
  89. }
  90. }
  91. });
  92. });
  93. }
  94. function update(id) {
  95. var language = languages[id];
  96. if (language.enabled) {
  97. if (!language.examplesPromise) {
  98. language.examplesPromise = getFileContents(language.examplesPath);
  99. }
  100. language.examplesPromise.then(function (contents) {
  101. examples[id].innerHTML = contents;
  102. loadLanguage(id).then(function () {
  103. var elements = examples[id].querySelectorAll('code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code');
  104. for (var i=0, element; element = elements[i++];) {
  105. Prism.highlightElement(element);
  106. }
  107. });
  108. });
  109. } else {
  110. examples[id].innerHTML = '';
  111. }
  112. }
  113. /**
  114. * Loads a language, including all dependencies
  115. *
  116. * @param {string} lang the language to load
  117. * @type {Promise} the promise which resolves as soon as everything is loaded
  118. */
  119. function loadLanguage (lang)
  120. {
  121. // at first we need to fetch all dependencies for the main language
  122. // Note: we need to do this, even if the main language already is loaded (just to be sure..)
  123. //
  124. // We load an array of all dependencies and call recursively this function on each entry
  125. //
  126. // dependencies is now an (possibly empty) array of loading-promises
  127. var dependencies = getDependenciesOfLanguage(lang).map(loadLanguage);
  128. // We create a promise, which will resolve, as soon as all dependencies are loaded.
  129. // They need to be fully loaded because the main language may extend them.
  130. return Promise.all(dependencies)
  131. .then(function () {
  132. // If the main language itself isn't already loaded, load it now
  133. // and return the newly created promise (we chain the promises).
  134. // If the language is already loaded, just do nothing - the next .then()
  135. // will immediately be called
  136. if (!Prism.languages[lang]) {
  137. return new Promise(function (resolve) {
  138. $u.script('components/prism-' + lang + '.js', resolve);
  139. });
  140. }
  141. });
  142. }
  143. /**
  144. * Returns all dependencies (as identifiers) of a specific language
  145. *
  146. * @param {string} lang
  147. * @returns {Array.<string>} the list of dependencies. Empty if the language has none.
  148. */
  149. function getDependenciesOfLanguage (lang)
  150. {
  151. if (!components.languages[lang] || !components.languages[lang].require)
  152. {
  153. return [];
  154. }
  155. return ($u.type(components.languages[lang].require) === "array")
  156. ? components.languages[lang].require
  157. : [components.languages[lang].require];
  158. }
  159. }());