AppContainer.js 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. import { Container } from 'unstated';
  2. import GrowiRenderer from '../util/GrowiRenderer';
  3. import { i18nFactory } from '../util/i18n';
  4. /**
  5. * Service container related to options for Application
  6. * @extends {Container} unstated Container
  7. */
  8. export default class AppContainer extends Container {
  9. constructor() {
  10. super();
  11. this.config = JSON.parse(document.getElementById('growi-context-hydrate').textContent || '{}');
  12. // init i18n
  13. const currentUserElem = document.getElementById('growi-current-user');
  14. let userLocaleId;
  15. if (currentUserElem != null) {
  16. const currentUser = JSON.parse(currentUserElem.textContent);
  17. userLocaleId = currentUser?.lang;
  18. }
  19. this.i18n = i18nFactory(userLocaleId);
  20. this.containerInstances = {};
  21. this.componentInstances = {};
  22. this.rendererInstances = {};
  23. }
  24. /**
  25. * Workaround for the mangling in production build to break constructor.name
  26. */
  27. static getClassName() {
  28. return 'AppContainer';
  29. }
  30. initApp() {
  31. this.injectToWindow();
  32. }
  33. initContents() {
  34. const body = document.querySelector('body');
  35. this.isDocSaved = true;
  36. this.originRenderer = new GrowiRenderer(this);
  37. const isPluginEnabled = body.dataset.pluginEnabled === 'true';
  38. if (isPluginEnabled) {
  39. this.initPlugins();
  40. }
  41. this.injectToWindow();
  42. }
  43. initPlugins() {
  44. const growiPlugin = window.growiPlugin;
  45. growiPlugin.installAll(this, this.originRenderer);
  46. }
  47. injectToWindow() {
  48. window.appContainer = this;
  49. const originRenderer = this.getOriginRenderer();
  50. window.growiRenderer = originRenderer;
  51. // backward compatibility
  52. window.crowi = this;
  53. window.crowiRenderer = originRenderer;
  54. window.crowiPlugin = window.growiPlugin;
  55. }
  56. getConfig() {
  57. return this.config;
  58. }
  59. /**
  60. * Register unstated container instance
  61. * @param {object} instance unstated container instance
  62. */
  63. registerContainer(instance) {
  64. if (instance == null) {
  65. throw new Error('The specified instance must not be null');
  66. }
  67. const className = instance.constructor.getClassName();
  68. if (this.containerInstances[className] != null) {
  69. throw new Error('The specified instance couldn\'t register because the same type object has already been registered');
  70. }
  71. this.containerInstances[className] = instance;
  72. }
  73. /**
  74. * Get registered unstated container instance
  75. * !! THIS METHOD SHOULD ONLY BE USED FROM unstated CONTAINERS !!
  76. * !! From component instances, inject containers with `import { Subscribe } from 'unstated'` !!
  77. *
  78. * @param {string} className
  79. */
  80. getContainer(className) {
  81. return this.containerInstances[className];
  82. }
  83. /**
  84. * Register React component instance
  85. * @param {string} id
  86. * @param {object} instance React component instance
  87. */
  88. registerComponentInstance(id, instance) {
  89. if (instance == null) {
  90. throw new Error('The specified instance must not be null');
  91. }
  92. this.componentInstances[id] = instance;
  93. }
  94. /**
  95. * Get registered React component instance
  96. * @param {string} id
  97. */
  98. getComponentInstance(id) {
  99. return this.componentInstances[id];
  100. }
  101. getOriginRenderer() {
  102. return this.originRenderer;
  103. }
  104. /**
  105. * factory method
  106. */
  107. getRenderer(mode) {
  108. if (this.rendererInstances[mode] != null) {
  109. return this.rendererInstances[mode];
  110. }
  111. const renderer = new GrowiRenderer(this, this.originRenderer);
  112. // setup
  113. renderer.initMarkdownItConfigurers(mode);
  114. renderer.setup(mode);
  115. // register
  116. this.rendererInstances[mode] = renderer;
  117. return renderer;
  118. }
  119. }