docusaurus-live-brython 3.0.0-beta.9 → 3.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (175) hide show
  1. package/.devcontainer/devcontainer.json +38 -0
  2. package/.prettierignore +17 -0
  3. package/.prettierrc +9 -8
  4. package/CHANGELOG.md +5 -0
  5. package/README.md +7 -4
  6. package/lib/assets/py_back_trace.py +2 -1
  7. package/lib/index.d.ts +1 -7
  8. package/lib/index.d.ts.map +1 -0
  9. package/lib/index.js +94 -16
  10. package/lib/options.d.ts +1 -0
  11. package/lib/options.d.ts.map +1 -0
  12. package/lib/options.js +2 -2
  13. package/lib/theme/CodeBlock/index.d.ts +3 -3
  14. package/lib/theme/CodeBlock/index.d.ts.map +1 -0
  15. package/lib/theme/CodeBlock/index.jsx +24 -14
  16. package/lib/theme/CodeEditor/Actions/DownloadCode.d.ts +1 -0
  17. package/lib/theme/CodeEditor/Actions/DownloadCode.d.ts.map +1 -0
  18. package/lib/theme/CodeEditor/Actions/DownloadCode.jsx +8 -8
  19. package/lib/theme/CodeEditor/Actions/Reset.d.ts +1 -0
  20. package/lib/theme/CodeEditor/Actions/Reset.d.ts.map +1 -0
  21. package/lib/theme/CodeEditor/Actions/Reset.jsx +5 -5
  22. package/lib/theme/CodeEditor/Actions/RunCode.d.ts +2 -1
  23. package/lib/theme/CodeEditor/Actions/RunCode.d.ts.map +1 -0
  24. package/lib/theme/CodeEditor/Actions/RunCode.jsx +4 -4
  25. package/lib/theme/CodeEditor/Actions/ShowRaw.d.ts +1 -0
  26. package/lib/theme/CodeEditor/Actions/ShowRaw.d.ts.map +1 -0
  27. package/lib/theme/CodeEditor/Actions/ShowRaw.jsx +13 -7
  28. package/lib/theme/CodeEditor/Actions/ShowSyncStatus.d.ts +1 -0
  29. package/lib/theme/CodeEditor/Actions/ShowSyncStatus.d.ts.map +1 -0
  30. package/lib/theme/CodeEditor/Actions/ShowSyncStatus.jsx +21 -16
  31. package/lib/theme/CodeEditor/Actions/styles.module.css +2 -3
  32. package/lib/theme/CodeEditor/BrythonCommunicator.d.ts +2 -1
  33. package/lib/theme/CodeEditor/BrythonCommunicator.d.ts.map +1 -0
  34. package/lib/theme/CodeEditor/BrythonCommunicator.jsx +13 -9
  35. package/lib/theme/CodeEditor/Button/index.d.ts +3 -2
  36. package/lib/theme/CodeEditor/Button/index.d.ts.map +1 -0
  37. package/lib/theme/CodeEditor/Button/index.jsx +1 -1
  38. package/lib/theme/CodeEditor/Button/styles.module.css +1 -1
  39. package/lib/theme/CodeEditor/CodeHistory/index.d.ts +1 -0
  40. package/lib/theme/CodeEditor/CodeHistory/index.d.ts.map +1 -0
  41. package/lib/theme/CodeEditor/CodeHistory/index.jsx +26 -15
  42. package/lib/theme/CodeEditor/CodeHistory/styles.module.css +31 -31
  43. package/lib/theme/CodeEditor/ContextEditor/index.d.ts +22 -0
  44. package/lib/theme/CodeEditor/ContextEditor/index.d.ts.map +1 -0
  45. package/lib/theme/CodeEditor/ContextEditor/index.jsx +36 -0
  46. package/lib/theme/CodeEditor/Editor/EditorAce.d.ts +2 -1
  47. package/lib/theme/CodeEditor/Editor/EditorAce.d.ts.map +1 -0
  48. package/lib/theme/CodeEditor/Editor/EditorAce.jsx +17 -14
  49. package/lib/theme/CodeEditor/Editor/Header/index.d.ts +2 -1
  50. package/lib/theme/CodeEditor/Editor/Header/index.d.ts.map +1 -0
  51. package/lib/theme/CodeEditor/Editor/Header/index.jsx +12 -12
  52. package/lib/theme/CodeEditor/Editor/Header/styles.module.css +7 -7
  53. package/lib/theme/CodeEditor/Editor/HiddenCode/index.d.ts +8 -0
  54. package/lib/theme/CodeEditor/Editor/HiddenCode/index.d.ts.map +1 -0
  55. package/lib/theme/CodeEditor/Editor/HiddenCode/index.jsx +27 -0
  56. package/lib/theme/CodeEditor/Editor/HiddenCode/styles.module.css +52 -0
  57. package/lib/theme/CodeEditor/Editor/Result/Graphics/Canvas.d.ts +1 -0
  58. package/lib/theme/CodeEditor/Editor/Result/Graphics/Canvas.d.ts.map +1 -0
  59. package/lib/theme/CodeEditor/Editor/Result/Graphics/Canvas.jsx +8 -9
  60. package/lib/theme/CodeEditor/Editor/Result/Graphics/Turtle.d.ts +1 -0
  61. package/lib/theme/CodeEditor/Editor/Result/Graphics/Turtle.d.ts.map +1 -0
  62. package/lib/theme/CodeEditor/Editor/Result/Graphics/Turtle.jsx +11 -11
  63. package/lib/theme/CodeEditor/Editor/Result/Graphics/index.d.ts +4 -3
  64. package/lib/theme/CodeEditor/Editor/Result/Graphics/index.d.ts.map +1 -0
  65. package/lib/theme/CodeEditor/Editor/Result/Graphics/index.jsx +12 -10
  66. package/lib/theme/CodeEditor/Editor/Result/Graphics/styles.module.css +2 -2
  67. package/lib/theme/CodeEditor/Editor/Result/index.d.ts +2 -3
  68. package/lib/theme/CodeEditor/Editor/Result/index.d.ts.map +1 -0
  69. package/lib/theme/CodeEditor/Editor/Result/index.jsx +6 -9
  70. package/lib/theme/CodeEditor/Editor/Result/styles.module.css +15 -10
  71. package/lib/theme/CodeEditor/Editor/index.d.ts +6 -3
  72. package/lib/theme/CodeEditor/Editor/index.d.ts.map +1 -0
  73. package/lib/theme/CodeEditor/Editor/index.jsx +34 -28
  74. package/lib/theme/CodeEditor/Editor/styles.module.css +15 -7
  75. package/lib/theme/CodeEditor/Editor/utils/checkForButtonClick.d.ts +1 -0
  76. package/lib/theme/CodeEditor/Editor/utils/checkForButtonClick.d.ts.map +1 -0
  77. package/lib/theme/CodeEditor/Editor/utils/saveSvg.d.ts +1 -0
  78. package/lib/theme/CodeEditor/Editor/utils/saveSvg.d.ts.map +1 -0
  79. package/lib/theme/CodeEditor/Editor/utils/saveSvg.js +19 -8
  80. package/lib/theme/CodeEditor/Editor/utils/svgWithoutAnimations.d.ts +1 -0
  81. package/lib/theme/CodeEditor/Editor/utils/svgWithoutAnimations.d.ts.map +1 -0
  82. package/lib/theme/CodeEditor/Editor/utils/svgWithoutAnimations.js +43 -49
  83. package/lib/theme/CodeEditor/Icon/icons.d.ts +4 -1
  84. package/lib/theme/CodeEditor/Icon/icons.d.ts.map +1 -0
  85. package/lib/theme/CodeEditor/Icon/icons.js +3 -1
  86. package/lib/theme/CodeEditor/Icon/index.d.ts +4 -2
  87. package/lib/theme/CodeEditor/Icon/index.d.ts.map +1 -0
  88. package/lib/theme/CodeEditor/Icon/index.jsx +10 -3
  89. package/lib/theme/CodeEditor/Icon/styles.module.css +1 -1
  90. package/lib/theme/CodeEditor/WithScript/ScriptContext.d.ts +8 -0
  91. package/lib/theme/CodeEditor/WithScript/ScriptContext.d.ts.map +1 -0
  92. package/lib/theme/CodeEditor/WithScript/ScriptContext.jsx +27 -0
  93. package/lib/theme/CodeEditor/WithScript/Storage.d.ts +2 -1
  94. package/lib/theme/CodeEditor/WithScript/Storage.d.ts.map +1 -0
  95. package/lib/theme/CodeEditor/WithScript/Types.d.ts +12 -4
  96. package/lib/theme/CodeEditor/WithScript/Types.d.ts.map +1 -0
  97. package/lib/theme/CodeEditor/WithScript/bryRunner.d.ts +3 -0
  98. package/lib/theme/CodeEditor/WithScript/bryRunner.d.ts.map +1 -0
  99. package/lib/theme/CodeEditor/WithScript/bryRunner.js +29 -0
  100. package/lib/theme/CodeEditor/WithScript/createStore.d.ts +4 -0
  101. package/lib/theme/CodeEditor/WithScript/createStore.d.ts.map +1 -0
  102. package/lib/theme/CodeEditor/WithScript/{Store.jsx → createStore.js} +62 -74
  103. package/lib/theme/CodeEditor/WithScript/helpers.d.ts +1 -4
  104. package/lib/theme/CodeEditor/WithScript/helpers.d.ts.map +1 -0
  105. package/lib/theme/CodeEditor/WithScript/helpers.js +4 -14
  106. package/lib/theme/CodeEditor/constants.d.ts +1 -0
  107. package/lib/theme/CodeEditor/constants.d.ts.map +1 -0
  108. package/lib/theme/CodeEditor/hooks/index.d.ts +3 -0
  109. package/lib/theme/CodeEditor/hooks/index.d.ts.map +1 -0
  110. package/lib/theme/CodeEditor/hooks/index.js +2 -0
  111. package/lib/theme/CodeEditor/hooks/useScript.d.ts +3 -0
  112. package/lib/theme/CodeEditor/hooks/useScript.d.ts.map +1 -0
  113. package/lib/theme/CodeEditor/hooks/useScript.js +4 -0
  114. package/lib/theme/CodeEditor/hooks/useStore.d.ts +3 -0
  115. package/lib/theme/CodeEditor/hooks/useStore.d.ts.map +1 -0
  116. package/lib/theme/CodeEditor/hooks/useStore.js +10 -0
  117. package/lib/theme/CodeEditor/index.d.ts +24 -5
  118. package/lib/theme/CodeEditor/index.d.ts.map +1 -0
  119. package/lib/theme/CodeEditor/index.jsx +17 -16
  120. package/lib/theme/CodeEditor/styles.module.css +28 -30
  121. package/og-image.md +23 -0
  122. package/package.json +35 -20
  123. package/src/assets/py_back_trace.py +2 -1
  124. package/src/index.ts +96 -25
  125. package/src/options.ts +12 -12
  126. package/src/theme/CodeBlock/index.tsx +44 -68
  127. package/src/theme/CodeEditor/Actions/DownloadCode.tsx +23 -22
  128. package/src/theme/CodeEditor/Actions/Reset.tsx +14 -12
  129. package/src/theme/CodeEditor/Actions/RunCode.tsx +14 -11
  130. package/src/theme/CodeEditor/Actions/ShowRaw.tsx +17 -11
  131. package/src/theme/CodeEditor/Actions/ShowSyncStatus.tsx +32 -27
  132. package/src/theme/CodeEditor/Actions/styles.module.css +2 -3
  133. package/src/theme/CodeEditor/BrythonCommunicator.tsx +16 -19
  134. package/src/theme/CodeEditor/Button/index.tsx +17 -13
  135. package/src/theme/CodeEditor/Button/styles.module.css +1 -1
  136. package/src/theme/CodeEditor/CodeHistory/index.tsx +32 -20
  137. package/src/theme/CodeEditor/CodeHistory/styles.module.css +31 -31
  138. package/src/theme/CodeEditor/ContextEditor/index.tsx +74 -0
  139. package/src/theme/CodeEditor/Editor/EditorAce.tsx +20 -16
  140. package/src/theme/CodeEditor/Editor/Header/index.tsx +13 -19
  141. package/src/theme/CodeEditor/Editor/Header/styles.module.css +7 -7
  142. package/src/theme/CodeEditor/Editor/HiddenCode/index.tsx +49 -0
  143. package/src/theme/CodeEditor/Editor/HiddenCode/styles.module.css +52 -0
  144. package/src/theme/CodeEditor/Editor/Result/Graphics/Canvas.tsx +25 -22
  145. package/src/theme/CodeEditor/Editor/Result/Graphics/Turtle.tsx +23 -19
  146. package/src/theme/CodeEditor/Editor/Result/Graphics/index.tsx +16 -16
  147. package/src/theme/CodeEditor/Editor/Result/Graphics/styles.module.css +2 -2
  148. package/src/theme/CodeEditor/Editor/Result/index.tsx +7 -13
  149. package/src/theme/CodeEditor/Editor/Result/styles.module.css +15 -10
  150. package/src/theme/CodeEditor/Editor/index.tsx +67 -65
  151. package/src/theme/CodeEditor/Editor/styles.module.css +15 -7
  152. package/src/theme/CodeEditor/Editor/utils/checkForButtonClick.ts +5 -5
  153. package/src/theme/CodeEditor/Editor/utils/saveSvg.ts +63 -53
  154. package/src/theme/CodeEditor/Editor/utils/svgWithoutAnimations.ts +182 -201
  155. package/src/theme/CodeEditor/Icon/icons.ts +27 -13
  156. package/src/theme/CodeEditor/Icon/index.tsx +31 -11
  157. package/src/theme/CodeEditor/Icon/styles.module.css +1 -1
  158. package/src/theme/CodeEditor/WithScript/ScriptContext.tsx +36 -0
  159. package/src/theme/CodeEditor/WithScript/Storage.ts +3 -3
  160. package/src/theme/CodeEditor/WithScript/Types.ts +17 -11
  161. package/src/theme/CodeEditor/WithScript/bryRunner.ts +39 -0
  162. package/src/theme/CodeEditor/WithScript/createStore.ts +276 -0
  163. package/src/theme/CodeEditor/WithScript/helpers.ts +16 -26
  164. package/src/theme/CodeEditor/constants.ts +9 -11
  165. package/src/theme/CodeEditor/hooks/index.ts +2 -0
  166. package/src/theme/CodeEditor/hooks/useScript.ts +9 -0
  167. package/src/theme/CodeEditor/hooks/useStore.ts +15 -0
  168. package/src/theme/CodeEditor/index.tsx +45 -31
  169. package/src/theme/CodeEditor/styles.module.css +28 -30
  170. package/src/typings.d.ts +11 -0
  171. package/lib/theme/CodeEditor/WithScript/Store.d.ts +0 -15
  172. package/lib/types.d.ts +0 -28
  173. package/lib/types.js +0 -1
  174. package/src/theme/CodeEditor/WithScript/Store.tsx +0 -294
  175. package/src/types.ts +0 -29
package/src/index.ts CHANGED
@@ -5,15 +5,15 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
 
8
-
9
8
  /**
10
9
  * Notes
11
10
  * - how to add static files: https://github.com/facebook/docusaurus/discussions/6907
12
11
  * ---> sitemap plugin: https://github.com/facebook/docusaurus/blob/main/packages/docusaurus-plugin-sitemap/src/index.ts
13
12
  * - call brython with arguments: https://github.com/brython-dev/brython/issues/2421
14
- *
13
+ *
15
14
  */
16
15
 
16
+ import { readDefaultCodeTranslationMessages } from '@docusaurus/theme-translations';
17
17
  import type { HtmlTags, LoadContext, Plugin } from '@docusaurus/types';
18
18
  // eslint-disable-next-line import/no-extraneous-dependencies, import/order
19
19
  import logger from '@docusaurus/logger';
@@ -26,33 +26,94 @@ const __dirname = path.dirname(fileURLToPath(import.meta.url));
26
26
  export const NAME = 'docusaurus-live-brython' as const;
27
27
  export const DEFAULT_LIB_DIR = 'bry-libs' as const;
28
28
 
29
- const theme: Plugin<{ remoteHeadTags: HtmlTags[] }> = (
30
- context: LoadContext,
31
- options: ThemeOptions,
32
- ) => {
29
+ const extractImports = (script: string): string[] => {
30
+ const imports: string[] = [];
31
+ script.split('\n').forEach((line) => {
32
+ const fromImport = line.match(/from\s+(\w+)\s+import\s+/);
33
+ if (fromImport) {
34
+ return imports.push(fromImport[1]);
35
+ }
36
+ const importImport = line.match(/import\s+(\w+)/);
37
+ if (importImport) {
38
+ return imports.push(importImport[1]);
39
+ }
40
+ });
41
+ return imports;
42
+ };
43
+
44
+ const theme: Plugin<{ remoteHeadTags: HtmlTags[] }> = (context: LoadContext, options: ThemeOptions) => {
45
+ const {
46
+ i18n: { currentLocale }
47
+ } = context;
33
48
  const libDir = options.libDir || DEFAULT_LIB_DIR;
49
+ const isRemote = /https?:\/\//.test(libDir);
50
+ const isHashRouter = context.siteConfig.future?.experimental_router === 'hash';
34
51
  return {
35
52
  name: NAME,
36
53
  async loadContent() {
37
- if (!options.skipCopyAssetsToLibDir) {
38
- const staticDir = path.join(context.siteDir, context.siteConfig.staticDirectories[0], libDir);
54
+ const staticDir = path.join(context.siteDir, context.siteConfig.staticDirectories[0], libDir);
55
+ let assets: string[] = [];
56
+ const bryModules: { name: string; content: string }[] = [];
57
+ if (!options.skipCopyAssetsToLibDir && !isRemote) {
39
58
  await fs.ensureDir(staticDir);
40
59
  if (process.env.NODE_ENV !== 'production') {
41
- const assets = fs.readdirSync(path.join(__dirname, 'assets'));
60
+ assets = fs.readdirSync(path.join(__dirname, 'assets'));
42
61
  for (const asset of assets) {
43
62
  const assetFile = path.join(__dirname, 'assets', asset);
44
63
  const assetOutFile = path.join(staticDir, asset);
45
64
  logger.info(`copy "${asset}" to "${assetOutFile}"`);
46
65
  await fs.copyFile(assetFile, assetOutFile);
47
66
  }
48
- return assets;
49
67
  }
50
68
  }
69
+ if (isHashRouter && !isRemote) {
70
+ const libs = await fs.readdir(staticDir);
71
+ const libraries: { [key: string]: string } = {};
72
+ for (const lib of libs) {
73
+ const libPath = path.join(staticDir, lib);
74
+ if (libPath.endsWith('.py')) {
75
+ const libContent = await fs.readFile(libPath, 'utf-8');
76
+ libraries[lib.replace(/\.py$/i, '')] = libContent;
77
+ }
78
+ }
79
+ const libNames = Object.keys(libraries);
80
+ for (const libName of libNames) {
81
+ const libContent = libraries[libName];
82
+ const imports = extractImports(libContent);
83
+ const injectAt = Math.max(
84
+ ...bryModules.map((lib, idx) => (imports.includes(lib.name) ? idx : -1)),
85
+ -1
86
+ );
87
+ if (injectAt < 0) {
88
+ bryModules.splice(0, 0, { name: libName, content: libContent });
89
+ } else if (injectAt + 1 < bryModules.length) {
90
+ bryModules.splice(injectAt + 1, 0, {
91
+ name: libName,
92
+ content: libContent
93
+ });
94
+ } else {
95
+ bryModules.push({ name: libName, content: libContent });
96
+ }
97
+ }
98
+ }
99
+ return {
100
+ assets: assets,
101
+ bryModules: bryModules
102
+ };
103
+ },
104
+ getDefaultCodeTranslationMessages() {
105
+ return readDefaultCodeTranslationMessages({
106
+ locale: currentLocale,
107
+ name: NAME
108
+ });
51
109
  },
52
110
  async contentLoaded({ content, actions }) {
53
111
  const { setGlobalData } = actions;
54
- const libDir = (options.libDir || DEFAULT_LIB_DIR).replace(/(\/|\\)/g, '');
55
- setGlobalData({ libDir: `${context.baseUrl}${libDir}/`, syncMaxOnceEvery: options.syncMaxOnceEvery || DEFAULT_OPTIONS.syncMaxOnceEvery});
112
+ const libUrl = isRemote ? libDir : path.join(context.baseUrl, libDir, '/');
113
+ setGlobalData({
114
+ libDir: libUrl,
115
+ syncMaxOnceEvery: options.syncMaxOnceEvery || DEFAULT_OPTIONS.syncMaxOnceEvery
116
+ });
56
117
  },
57
118
  configureWebpack() {
58
119
  return {
@@ -61,9 +122,9 @@ const theme: Plugin<{ remoteHeadTags: HtmlTags[] }> = (
61
122
  {
62
123
  test: /\.raw\.*/,
63
124
  type: 'asset/source'
64
- },
65
- ],
66
- },
125
+ }
126
+ ]
127
+ }
67
128
  };
68
129
  },
69
130
  getThemePath() {
@@ -72,36 +133,46 @@ const theme: Plugin<{ remoteHeadTags: HtmlTags[] }> = (
72
133
  getTypeScriptThemePath() {
73
134
  return '../src/theme';
74
135
  },
75
- injectHtmlTags() {
136
+ injectHtmlTags({ content }: { content: { bryModules: { name: string; content: string }[] } }) {
76
137
  return {
77
138
  headTags: [
78
139
  {
79
140
  tagName: 'script',
80
141
  attributes: {
81
142
  src: options.brythonSrc || DEFAULT_OPTIONS.brythonSrc,
82
- crossorigin: "anonymous",
83
- referrerpolicy: "no-referrer",
143
+ crossorigin: 'anonymous',
144
+ referrerpolicy: 'no-referrer',
84
145
  defer: 'defer'
85
- },
146
+ }
86
147
  },
87
148
  {
88
149
  tagName: 'script',
89
150
  attributes: {
90
151
  src: options.brythonStdlibSrc || DEFAULT_OPTIONS.brythonStdlibSrc,
91
- crossorigin: "anonymous",
92
- referrerpolicy: "no-referrer",
152
+ crossorigin: 'anonymous',
153
+ referrerpolicy: 'no-referrer',
93
154
  defer: 'defer'
94
- },
155
+ }
95
156
  }
96
157
  ],
158
+ postBodyTags: content.bryModules.map((module) => {
159
+ return {
160
+ tagName: 'script',
161
+ attributes: {
162
+ id: module.name,
163
+ type: 'text/python'
164
+ },
165
+ innerHTML: module.content
166
+ };
167
+ })
97
168
  };
98
169
  },
99
170
  getSwizzleComponentList() {
100
171
  return [];
101
172
  }
102
173
  } as Plugin;
103
- }
174
+ };
104
175
 
105
176
  export default theme;
106
- export {validateThemeConfig} from './options';
107
- export {ThemeOptions, Options};
177
+ export { validateThemeConfig } from './options';
178
+ export { ThemeOptions, Options };
package/src/options.ts CHANGED
@@ -5,9 +5,9 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
 
8
- import {Joi} from '@docusaurus/utils-validation';
8
+ import { Joi } from '@docusaurus/utils-validation';
9
9
 
10
- import type {ThemeConfigValidationContext} from '@docusaurus/types';
10
+ import type { ThemeConfigValidationContext } from '@docusaurus/types';
11
11
 
12
12
  export type ThemeOptions = {
13
13
  /**
@@ -42,14 +42,13 @@ export type ThemeOptions = {
42
42
  * @default 1000
43
43
  */
44
44
  syncMaxOnceEvery: number;
45
- }
46
-
45
+ };
47
46
 
48
47
  export type Options = Partial<ThemeOptions>;
49
48
 
50
49
  export const DEFAULT_OPTIONS: ThemeOptions = {
51
- brythonSrc: 'https://raw.githack.com/brython-dev/brython/master/www/src/brython.js',
52
- brythonStdlibSrc: 'https://raw.githack.com/brython-dev/brython/master/www/src/brython_stdlib.js',
50
+ brythonSrc: 'https://cdn.jsdelivr.net/npm/brython@3.14/brython.min.js',
51
+ brythonStdlibSrc: 'https://cdn.jsdelivr.net/npm/brython@3.14/brython_stdlib.js',
53
52
  libDir: '/bry-libs/',
54
53
  skipCopyAssetsToLibDir: false,
55
54
  syncMaxOnceEvery: 1000
@@ -63,9 +62,10 @@ const ThemeOptionSchema = Joi.object<ThemeOptions>({
63
62
  syncMaxOnceEvery: Joi.number().default(DEFAULT_OPTIONS.syncMaxOnceEvery)
64
63
  });
65
64
 
66
- export function validateThemeConfig(
67
- {themeConfig, validate}: ThemeConfigValidationContext<Options, ThemeOptions>
68
- ): ThemeOptions {
69
- const validatedConfig = validate(ThemeOptionSchema, themeConfig);
70
- return validatedConfig;
71
- }
65
+ export function validateThemeConfig({
66
+ themeConfig,
67
+ validate
68
+ }: ThemeConfigValidationContext<Options, ThemeOptions>): ThemeOptions {
69
+ const validatedConfig = validate(ThemeOptionSchema, themeConfig);
70
+ return validatedConfig;
71
+ }
@@ -1,57 +1,51 @@
1
1
  import React from 'react';
2
- import CodeBlock, {type Props as CodeBlockType} from '@theme-init/CodeBlock';
3
- // @ts-ignore
2
+ import CodeBlock, { type Props as CodeBlockType } from '@theme-init/CodeBlock';
4
3
  import type { WrapperProps } from '@docusaurus/types';
5
4
  import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment';
6
- import CodeEditor from 'docusaurus-live-brython/theme/CodeEditor';
7
-
8
- import ScriptContext from 'docusaurus-live-brython/theme/CodeEditor/WithScript/Store';
5
+ import { type MetaProps } from '@theme/CodeEditor';
9
6
 
7
+ import ContextEditor, { splitCode } from '@theme/CodeEditor/ContextEditor';
8
+ import BrowserOnly from '@docusaurus/BrowserOnly';
10
9
 
11
10
  type Props = WrapperProps<typeof CodeBlockType>;
12
11
 
13
- interface MetaProps {
14
- reference?: boolean;
15
- live_jsx?: boolean;
16
- live_py?: boolean;
17
- id?: string;
18
- slim?: boolean;
19
- readonly?: boolean;
20
- noReset?: boolean;
21
- noDownload?: boolean;
22
- versioned?: boolean;
23
- noHistory?: boolean;
24
- noCompare?: boolean;
25
- maxLines?: string;
26
- title?: string
27
- }
28
-
29
-
30
12
  const sanitizedTitle = (id: string) => {
31
13
  if (!id) {
32
14
  return;
33
15
  }
34
- return id.replace(/--/g, '<<HYPHEN>>').replace(/__/g, '<<UNDERSCORE>>').replace(/[-_]/g, ' ').replace(/<<UNDERSCORE>>/g, '_').replace(/<<HYPHEN>>/g, '-')
35
- }
16
+ return id
17
+ .replace(/--/g, '<<HYPHEN>>')
18
+ .replace(/__/g, '<<UNDERSCORE>>')
19
+ .replace(/[-_]/g, ' ')
20
+ .replace(/<<UNDERSCORE>>/g, '_')
21
+ .replace(/<<HYPHEN>>/g, '-');
22
+ };
36
23
 
37
- const extractMetaProps = (props: {metastring?: string}): MetaProps => {
24
+ const extractMetaProps = (props: { metastring?: string }): MetaProps => {
38
25
  const metaString = (props?.metastring || '').replace(/\s*=\s*/g, '='); // remove spaces around =
39
26
  const metaRaw = metaString.split(/\s+/).map((s) => s.trim().split('='));
40
- return metaRaw.reduce((acc, [key, value]) => {
41
- if (!key) {
27
+ return metaRaw.reduce(
28
+ (acc, [key, value]) => {
29
+ if (!key) {
30
+ return acc;
31
+ }
32
+ /** casts to booleans and numbers. When no value was provided, true is used */
33
+ const val =
34
+ value === 'true'
35
+ ? true
36
+ : value === 'false'
37
+ ? false
38
+ : !Number.isNaN(Number(value))
39
+ ? Number(value)
40
+ : value || true;
41
+ acc[key] = val;
42
42
  return acc;
43
- }
44
- /** casts to booleans and numbers. When no value was provided, true is used */
45
- const val = value === 'true' ? true
46
- : value === 'false' ? false
47
- : !Number.isNaN(Number(value)) ? Number(value)
48
- : value || true;
49
- acc[key] = val;
50
- return acc;
51
- }, {} as {[key: string]: number | string | boolean});
52
- }
43
+ },
44
+ {} as { [key: string]: number | string | boolean }
45
+ );
46
+ };
53
47
 
54
- export default function CodeBlockWrapper(props: Props): JSX.Element {
48
+ export default function CodeBlockWrapper(props: Props): React.ReactNode {
55
49
  const metaProps = extractMetaProps(props);
56
50
  const langMatch = ((props.className || '') as string).match(/language-(?<lang>\w*)/);
57
51
  let lang = langMatch?.groups?.lang?.toLocaleLowerCase() ?? '';
@@ -61,38 +55,20 @@ export default function CodeBlockWrapper(props: Props): JSX.Element {
61
55
  // if (metaProps.live_jsx) {
62
56
  // return <Playground scope={ReactLiveScope} {...props} />;
63
57
  // }
64
- if (metaProps.live_py && ExecutionEnvironment.canUseDOM) {
58
+ if (metaProps.live_py) {
65
59
  const title = props.title || metaProps.title;
66
-
67
- const rawcode: string = (props.children as string || '').replace(/\s*\n$/, '');
68
- let code = rawcode;
60
+ const { code } = splitCode((props.children as string) || '');
69
61
  return (
70
- <ScriptContext
71
- id={metaProps.id}
72
- lang={lang}
73
- title={title}
74
- raw={rawcode}
75
- readonly={!!metaProps.readonly}
76
- versioned={!!metaProps.versioned}
77
- >
78
- <CodeEditor
79
- {...props}
80
- {...metaProps}
81
- maxLines={metaProps.maxLines && Number.parseInt(metaProps.maxLines, 10)}
82
- readonly={!!metaProps.readonly}
83
- resettable={!metaProps.noReset}
84
- download={!metaProps.versioned && !metaProps.noDownload}
85
- slim={!!metaProps.slim}
86
- showLineNumbers={!(!!metaProps.slim && !/\n/.test(code))}
87
- versioned={!!metaProps.versioned}
88
- noHistory={!!metaProps.noHistory}
89
- noCompare={!!metaProps.noCompare}
90
- title={sanitizedTitle(title) || lang}
91
- />
92
- </ScriptContext>
62
+ <BrowserOnly fallback={<CodeBlock language={lang}>{code}</CodeBlock>}>
63
+ {() => {
64
+ return (
65
+ <ContextEditor {...props} {...metaProps} title={sanitizedTitle(title) || lang}>
66
+ {props.children}
67
+ </ContextEditor>
68
+ );
69
+ }}
70
+ </BrowserOnly>
93
71
  );
94
72
  }
95
- return (
96
- <CodeBlock {...props} />
97
- );
73
+ return <CodeBlock {...props} />;
98
74
  }
@@ -1,38 +1,39 @@
1
1
  import * as React from 'react';
2
- import { useScript, useStore } from 'docusaurus-live-brython/theme/CodeEditor/WithScript/Store';
3
- import Button, { Color } from 'docusaurus-live-brython/theme/CodeEditor/Button';
2
+ import { useStore, useScript } from '@theme/CodeEditor/hooks';
3
+ import Button from '@theme/CodeEditor/Button';
4
4
  import { translate } from '@docusaurus/Translate';
5
5
 
6
-
7
- const DownloadCode = (props: {title: string}) => {
8
- const { store } = useScript();
9
- const code = useStore(store, (state) => state.code);
10
- const lang = useStore(store, (state) => state.lang);
11
- const id = useStore(store, (state) => state.id);
6
+ const DownloadCode = (props: { title: string }) => {
7
+ const store = useStore();
8
+ const code = useScript(store, 'code');
9
+ const lang = useScript(store, 'lang');
10
+ const id = useScript(store, 'id');
12
11
  return (
13
12
  <Button
14
- icon='Download'
13
+ icon="Download"
15
14
  onClick={() => {
16
- const downloadLink = document.createElement("a");
17
- const file = new Blob([code],
18
- {type: 'text/plain;charset=utf-8'});
15
+ const downloadLink = document.createElement('a');
16
+ const file = new Blob([code], { type: 'text/plain;charset=utf-8' });
19
17
  downloadLink.href = URL.createObjectURL(file);
20
18
  const fExt = lang === 'python' ? '.py' : `.${lang}`;
21
- const fTitle = props.title === lang ? id : props.title
19
+ const fTitle = props.title === lang ? id : props.title;
22
20
  const fName = fTitle.endsWith(fExt) ? fTitle : `${fTitle}${fExt}`;
23
21
  downloadLink.download = fName;
24
22
  document.body.appendChild(downloadLink);
25
23
  downloadLink.click();
26
24
  document.body.removeChild(downloadLink);
27
25
  }}
28
- title={translate({
29
- message: 'Download code snippet {title}',
30
- id: 'theme.CodeEditor.Actions.DownloadCode.title'
31
- }, {
32
- title: props.title || id
33
- })}
26
+ title={translate(
27
+ {
28
+ message: 'Download code snippet {title}',
29
+ id: 'theme.CodeEditor.Actions.DownloadCode.title'
30
+ },
31
+ {
32
+ title: props.title || id
33
+ }
34
+ )}
34
35
  />
35
- )
36
- }
36
+ );
37
+ };
37
38
 
38
- export default DownloadCode;
39
+ export default DownloadCode;
@@ -1,16 +1,18 @@
1
1
  import * as React from 'react';
2
- import { useScript, useStore } from 'docusaurus-live-brython/theme/CodeEditor/WithScript/Store';
3
- import Button, { Color } from 'docusaurus-live-brython/theme/CodeEditor/Button';
2
+ import { useStore, useScript } from '@theme/CodeEditor/hooks';
3
+ import Button, { Color } from '@theme/CodeEditor/Button';
4
4
  import { translate } from '@docusaurus/Translate';
5
5
 
6
6
  const Reset = () => {
7
- const { store } = useScript();
8
- const pristine = useStore(store, (state) => state.pristineCode);
9
-
7
+ const store = useStore();
8
+ const pristine = useScript(store, 'pristineCode');
9
+
10
10
  const onReset = () => {
11
- const shouldReset = window.confirm(translate({
12
- message: 'Discard your edits? Your changes will be lost!'
13
- }));
11
+ const shouldReset = window.confirm(
12
+ translate({
13
+ message: 'Discard your edits? Your changes will be lost!'
14
+ })
15
+ );
14
16
  if (shouldReset) {
15
17
  store.setCode(pristine);
16
18
  }
@@ -21,11 +23,11 @@ const Reset = () => {
21
23
  title={translate({
22
24
  message: 'Discard Changes',
23
25
  description: 'Reset the code to its original state',
24
- id: 'theme.CodeEditor.Header.reset',
26
+ id: 'theme.CodeEditor.Header.reset'
25
27
  })}
26
28
  icon="Reset"
27
29
  />
28
- )
29
- }
30
+ );
31
+ };
30
32
 
31
- export default Reset;
33
+ export default Reset;
@@ -1,18 +1,18 @@
1
1
  import * as React from 'react';
2
- import { useScript, useStore } from 'docusaurus-live-brython/theme/CodeEditor/WithScript/Store';
3
- import Button, { Color } from 'docusaurus-live-brython/theme/CodeEditor/Button';
2
+ import { useStore, useScript } from '@theme/CodeEditor/hooks';
3
+ import Button, { Color } from '@theme/CodeEditor/Button';
4
4
  import { translate } from '@docusaurus/Translate';
5
5
  import styles from './styles.module.css';
6
6
  import clsx from 'clsx';
7
7
 
8
- interface Props {
8
+ export interface Props {
9
9
  title: string;
10
10
  slim: boolean;
11
11
  }
12
12
 
13
13
  const RunCode = (props: Props) => {
14
- const { store } = useScript();
15
- const isExecuting = useStore(store, (state) => state.isExecuting);
14
+ const store = useStore();
15
+ const isExecuting = useScript(store, 'isExecuting');
16
16
  return (
17
17
  <Button
18
18
  icon={isExecuting ? 'Python' : 'Play'}
@@ -21,14 +21,17 @@ const RunCode = (props: Props) => {
21
21
  className={clsx(styles.runCode, props.slim && styles.slim)}
22
22
  iconSize={props.slim ? '1.2em' : '1.6em'}
23
23
  onClick={() => {
24
- store.execScript()
24
+ store.execScript();
25
25
  }}
26
- title={translate({
27
- message: 'Run code snippet {title}',
28
- id: 'theme.CodeEditor.Actions.RunCode.title'
29
- }, {title: props.title})}
26
+ title={translate(
27
+ {
28
+ message: 'Run code snippet {title}',
29
+ id: 'theme.CodeEditor.Actions.RunCode.title'
30
+ },
31
+ { title: props.title }
32
+ )}
30
33
  />
31
34
  );
32
35
  };
33
36
 
34
- export default RunCode;
37
+ export default RunCode;
@@ -1,24 +1,30 @@
1
1
  import * as React from 'react';
2
- import { useScript, useStore } from 'docusaurus-live-brython/theme/CodeEditor/WithScript/Store';
3
- import Button, { Color } from 'docusaurus-live-brython/theme/CodeEditor/Button';
2
+ import { useStore, useScript } from '@theme/CodeEditor/hooks';
3
+ import Button, { Color } from '@theme/CodeEditor/Button';
4
4
  import { translate } from '@docusaurus/Translate';
5
5
 
6
6
  const ShowRaw = () => {
7
- const { store } = useScript();
8
- const showRaw = useStore(store, (state) => state.showRaw);
7
+ const store = useStore();
8
+ const showRaw = useScript(store, 'showRaw');
9
9
 
10
10
  return (
11
11
  <Button
12
12
  icon={showRaw ? 'EditCode' : 'Code'}
13
- onClick={() => store.setState((state) => ({...state, showRaw: !showRaw}))}
13
+ onClick={() => store.setShowRaw(!showRaw)}
14
14
  color={showRaw ? Color.Primary : Color.Secondary}
15
15
  title={
16
- showRaw
17
- ? translate({ message: 'Show edited Code', id: 'theme.CodeEditor.Actions.ShowCode.showEdited'})
18
- : translate({ message: 'Show initial code', id: 'theme.CodeEditor.Actions.ShowCode.showRaw'})
16
+ showRaw
17
+ ? translate({
18
+ message: 'Show edited Code',
19
+ id: 'theme.CodeEditor.Actions.ShowCode.showEdited'
20
+ })
21
+ : translate({
22
+ message: 'Show initial code',
23
+ id: 'theme.CodeEditor.Actions.ShowCode.showRaw'
24
+ })
19
25
  }
20
26
  />
21
- )
22
- }
27
+ );
28
+ };
23
29
 
24
- export default ShowRaw;
30
+ export default ShowRaw;
@@ -1,41 +1,46 @@
1
1
  import * as React from 'react';
2
- import { useScript, useStore } from 'docusaurus-live-brython/theme/CodeEditor/WithScript/Store';
3
- import Icon, { Color } from 'docusaurus-live-brython/theme/CodeEditor/Icon';
4
- import { Status } from 'docusaurus-live-brython/theme/CodeEditor/WithScript/Types';
2
+ import { useStore, useScript } from '@theme/CodeEditor/hooks';
3
+ import Icon, { Color } from '@theme/CodeEditor/Icon';
4
+ import { Status } from '@theme/CodeEditor/WithScript/Types';
5
+ import BrowserOnly from '@docusaurus/BrowserOnly';
5
6
 
6
7
  const ShowSyncStatus = () => {
7
- const { store } = useScript();
8
- const isLoaded = useStore(store, (state) => state.isLoaded);
9
- const status = useStore(store, (state) => state.status);
8
+ const store = useStore();
9
+ const isLoaded = useScript(store, 'isLoaded');
10
+ const status = useScript(store, 'status');
10
11
 
11
12
  React.useEffect(() => {
12
13
  if (status !== Status.IDLE) {
13
14
  const disposer = setTimeout(() => {
14
- store.setState((state) => ({ ...state, status: Status.IDLE }));
15
+ store.setStatus(Status.IDLE);
15
16
  }, 1200);
16
17
  return () => clearTimeout(disposer);
17
18
  }
18
19
  }, [status, store]);
19
20
 
20
21
  return (
21
- <>
22
- {!isLoaded && (
23
- <Icon icon='Sync' spin size={'1.2em'} color={Color.Primary}/>
24
- )}
25
- <div style={{flexGrow: 1, flexShrink: 1, flexBasis: 0}}></div>
26
- <span style={{ minWidth: '1em' }}>
27
- {status === Status.SYNCING && (
28
- <Icon icon='Sync' spin size={'1.2em'} color={Color.Primary}/>
29
- )}
30
- {status === Status.SUCCESS && (
31
- <Icon icon='Check' size={'1.2em'} color={Color.Success}/>
32
- )}
33
- {status === Status.ERROR && (
34
- <Icon icon='Close' size={'1.2em'} color={Color.Danger}/>
35
- )}
36
- </span>
37
- </>
38
- )
39
- }
22
+ <BrowserOnly fallback={null}>
23
+ {() => {
24
+ return (
25
+ <>
26
+ {!isLoaded && <Icon icon="Sync" spin size={'1.2em'} color={Color.Primary} />}
27
+ <div style={{ flexGrow: 1, flexShrink: 1, flexBasis: 0 }}></div>
28
+ <span style={{ minWidth: '1em' }}>
29
+ {status === Status.SYNCING && (
30
+ <Icon icon="Sync" spin size={'1.2em'} color={Color.Primary} />
31
+ )}
32
+ {status === Status.SUCCESS && (
33
+ <Icon icon="Check" size={'1.2em'} color={Color.Success} />
34
+ )}
35
+ {status === Status.ERROR && (
36
+ <Icon icon="Close" size={'1.2em'} color={Color.Danger} />
37
+ )}
38
+ </span>
39
+ </>
40
+ );
41
+ }}
42
+ </BrowserOnly>
43
+ );
44
+ };
40
45
 
41
- export default ShowSyncStatus;
46
+ export default ShowSyncStatus;