growi-renderer.js 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. /**
  2. * reveal.js growi-renderer plugin.
  3. */
  4. (function(root, factory) {
  5. // get AppContainer instance from parent window
  6. const appContainer = window.parent.appContainer;
  7. const growiRendererPlugin = factory(appContainer);
  8. growiRendererPlugin.initialize();
  9. }(this, (appContainer) => {
  10. /* eslint-disable no-useless-escape */
  11. const DEFAULT_SLIDE_SEPARATOR = '^\r?\n---\r?\n$';
  12. const DEFAULT_ELEMENT_ATTRIBUTES_SEPARATOR = '\\\.element\\\s*?(.+?)$';
  13. const DEFAULT_SLIDE_ATTRIBUTES_SEPARATOR = '\\\.slide:\\\s*?(\\\S.+?)$';
  14. /* eslint-enable no-useless-escape */
  15. const growiRenderer = appContainer.getRenderer('editor');
  16. let marked;
  17. /**
  18. * Add data separator before lines
  19. * starting with '#' to markdown.
  20. */
  21. function divideSlides() {
  22. const sections = document.querySelectorAll('[data-markdown]');
  23. for (let i = 0, len = sections.length; i < len; i++) {
  24. const section = sections[i];
  25. const markdown = marked.getMarkdownFromSlide(section);
  26. const context = { markdown };
  27. const interceptorManager = appContainer.interceptorManager;
  28. let dataSeparator = section.getAttribute('data-separator') || DEFAULT_SLIDE_SEPARATOR;
  29. // replace string '\n' to LF code.
  30. dataSeparator = dataSeparator.replace(/\\n/g, '\n');
  31. const replaceValue = `${dataSeparator}#`;
  32. // detach code block.
  33. interceptorManager.process('prePreProcess', context);
  34. // if there is only '\n' in the first line, replace it.
  35. context.markdown = context.markdown.replace(/^\n/, '');
  36. // add data separator to markdown.
  37. context.markdown = context.markdown.replace(/[\n]+#/g, replaceValue);
  38. // restore code block.
  39. interceptorManager.process('postPreProcess', context);
  40. section.innerHTML = marked.createMarkdownSlide(context.markdown);
  41. }
  42. }
  43. /**
  44. * Converts data-markdown slides to HTML slides by GrowiRenderer.
  45. */
  46. function convertSlides() {
  47. const sections = document.querySelectorAll('[data-markdown]');
  48. let markdown;
  49. const interceptorManager = appContainer.interceptorManager;
  50. for (let i = 0, len = sections.length; i < len; i++) {
  51. const section = sections[i];
  52. // Only parse the same slide once
  53. if (!section.getAttribute('data-markdown-parsed')) {
  54. section.setAttribute('data-markdown-parsed', 'true');
  55. const notes = section.querySelector('aside.notes');
  56. markdown = marked.getMarkdownFromSlide(section);
  57. const context = { markdown };
  58. interceptorManager.process('preRender', context)
  59. .then(() => { return interceptorManager.process('prePreProcess', context) })
  60. .then(() => {
  61. context.markdown = growiRenderer.preProcess(context.markdown);
  62. })
  63. .then(() => { return interceptorManager.process('postPreProcess', context) })
  64. .then(() => {
  65. context.parsedHTML = growiRenderer.process(context.markdown);
  66. })
  67. .then(() => { return interceptorManager.process('prePostProcess', context) })
  68. .then(() => {
  69. context.parsedHTML = growiRenderer.postProcess(context.parsedHTML);
  70. })
  71. .then(() => { return interceptorManager.process('postPostProcess', context) })
  72. .then(() => { return interceptorManager.process('preRenderHtml', context) })
  73. .then(() => { return interceptorManager.process('postRenderHtml', context) })
  74. .then(() => {
  75. section.innerHTML = context.parsedHTML;
  76. });
  77. marked.addAttributes(section, section, null, section.getAttribute('data-element-attributes')
  78. || section.parentNode.getAttribute('data-element-attributes')
  79. || DEFAULT_ELEMENT_ATTRIBUTES_SEPARATOR,
  80. section.getAttribute('data-attributes')
  81. || section.parentNode.getAttribute('data-attributes')
  82. || DEFAULT_SLIDE_ATTRIBUTES_SEPARATOR);
  83. // If there were notes, we need to re-add them after
  84. // having overwritten the section's HTML
  85. if (notes) {
  86. section.appendChild(notes);
  87. }
  88. }
  89. }
  90. }
  91. // API
  92. return {
  93. async initialize() {
  94. marked = require('./markdown').default(growiRenderer.process);
  95. divideSlides();
  96. marked.processSlides();
  97. convertSlides();
  98. },
  99. };
  100. }));