docusaurus-live-brython 3.0.0-beta.11 → 3.0.0-beta.5

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 (75) hide show
  1. package/lib/index.d.ts +7 -0
  2. package/lib/index.js +0 -15
  3. package/lib/theme/CodeBlock/index.jsx +2 -2
  4. package/lib/theme/CodeEditor/Actions/DownloadCode.jsx +2 -2
  5. package/lib/theme/CodeEditor/Actions/Reset.jsx +2 -2
  6. package/lib/theme/CodeEditor/Actions/RunCode.d.ts +1 -1
  7. package/lib/theme/CodeEditor/Actions/RunCode.jsx +2 -2
  8. package/lib/theme/CodeEditor/Actions/ShowRaw.jsx +2 -2
  9. package/lib/theme/CodeEditor/Actions/ShowSyncStatus.jsx +3 -3
  10. package/lib/theme/CodeEditor/BrythonCommunicator.jsx +2 -2
  11. package/lib/theme/CodeEditor/Button/index.d.ts +2 -2
  12. package/lib/theme/CodeEditor/Button/index.jsx +1 -1
  13. package/lib/theme/CodeEditor/CodeHistory/index.jsx +2 -2
  14. package/lib/theme/CodeEditor/Editor/EditorAce.jsx +2 -2
  15. package/lib/theme/CodeEditor/Editor/Header/index.d.ts +1 -1
  16. package/lib/theme/CodeEditor/Editor/Header/index.jsx +6 -6
  17. package/lib/theme/CodeEditor/Editor/Result/Graphics/Canvas.d.ts +2 -2
  18. package/lib/theme/CodeEditor/Editor/Result/Graphics/Canvas.jsx +7 -7
  19. package/lib/theme/CodeEditor/Editor/Result/Graphics/Turtle.d.ts +2 -2
  20. package/lib/theme/CodeEditor/Editor/Result/Graphics/Turtle.jsx +8 -8
  21. package/lib/theme/CodeEditor/Editor/Result/Graphics/index.d.ts +3 -3
  22. package/lib/theme/CodeEditor/Editor/Result/Graphics/index.jsx +6 -6
  23. package/lib/theme/CodeEditor/Editor/Result/index.d.ts +3 -1
  24. package/lib/theme/CodeEditor/Editor/Result/index.jsx +3 -2
  25. package/lib/theme/CodeEditor/Editor/index.d.ts +1 -1
  26. package/lib/theme/CodeEditor/Editor/index.jsx +11 -11
  27. package/lib/theme/CodeEditor/Editor/utils/saveSvg.js +1 -1
  28. package/lib/theme/CodeEditor/Icon/index.d.ts +2 -2
  29. package/lib/theme/CodeEditor/Icon/index.jsx +1 -1
  30. package/lib/theme/CodeEditor/WithScript/Storage.d.ts +1 -1
  31. package/lib/theme/CodeEditor/WithScript/Store.d.ts +7 -1
  32. package/lib/theme/CodeEditor/WithScript/Store.jsx +235 -2
  33. package/lib/theme/CodeEditor/WithScript/Types.d.ts +0 -1
  34. package/lib/theme/CodeEditor/index.d.ts +3 -3
  35. package/lib/theme/CodeEditor/index.jsx +6 -6
  36. package/lib/types.d.ts +28 -0
  37. package/lib/types.js +1 -0
  38. package/package.json +20 -74
  39. package/src/index.ts +0 -10
  40. package/src/theme/CodeBlock/index.tsx +3 -2
  41. package/src/theme/CodeEditor/Actions/DownloadCode.tsx +2 -2
  42. package/src/theme/CodeEditor/Actions/Reset.tsx +2 -2
  43. package/src/theme/CodeEditor/Actions/RunCode.tsx +3 -3
  44. package/src/theme/CodeEditor/Actions/ShowRaw.tsx +2 -2
  45. package/src/theme/CodeEditor/Actions/ShowSyncStatus.tsx +3 -3
  46. package/src/theme/CodeEditor/BrythonCommunicator.tsx +3 -3
  47. package/src/theme/CodeEditor/Button/index.tsx +3 -3
  48. package/src/theme/CodeEditor/CodeHistory/index.tsx +2 -2
  49. package/src/theme/CodeEditor/Editor/EditorAce.tsx +2 -2
  50. package/src/theme/CodeEditor/Editor/Header/index.tsx +7 -7
  51. package/src/theme/CodeEditor/Editor/Result/Graphics/Canvas.tsx +7 -7
  52. package/src/theme/CodeEditor/Editor/Result/Graphics/Turtle.tsx +8 -8
  53. package/src/theme/CodeEditor/Editor/Result/Graphics/index.tsx +7 -7
  54. package/src/theme/CodeEditor/Editor/Result/index.tsx +6 -2
  55. package/src/theme/CodeEditor/Editor/index.tsx +15 -13
  56. package/src/theme/CodeEditor/Editor/utils/saveSvg.ts +1 -1
  57. package/src/theme/CodeEditor/Editor/utils/svgWithoutAnimations.ts +1 -1
  58. package/src/theme/CodeEditor/Icon/index.tsx +2 -2
  59. package/src/theme/CodeEditor/WithScript/Storage.ts +1 -1
  60. package/src/theme/CodeEditor/WithScript/Store.tsx +269 -3
  61. package/src/theme/CodeEditor/WithScript/Types.ts +0 -1
  62. package/src/theme/CodeEditor/index.tsx +8 -8
  63. package/src/types.ts +29 -0
  64. package/lib/theme/CodeEditor/WithScript/createStore.d.ts +0 -2
  65. package/lib/theme/CodeEditor/WithScript/createStore.js +0 -223
  66. package/lib/theme/CodeEditor/hooks/index.d.ts +0 -2
  67. package/lib/theme/CodeEditor/hooks/index.js +0 -2
  68. package/lib/theme/CodeEditor/hooks/useScript.d.ts +0 -4
  69. package/lib/theme/CodeEditor/hooks/useScript.js +0 -10
  70. package/lib/theme/CodeEditor/hooks/useStore.d.ts +0 -2
  71. package/lib/theme/CodeEditor/hooks/useStore.js +0 -4
  72. package/src/theme/CodeEditor/WithScript/createStore.ts +0 -247
  73. package/src/theme/CodeEditor/hooks/index.ts +0 -2
  74. package/src/theme/CodeEditor/hooks/useScript.ts +0 -15
  75. package/src/theme/CodeEditor/hooks/useStore.ts +0 -9
@@ -1,9 +1,9 @@
1
1
  import * as React from 'react';
2
- import { DOM_ELEMENT_IDS } from '@theme/CodeEditor/constants';
3
- import Graphics from '@theme/CodeEditor/Editor/Result/Graphics';
2
+ import { DOM_ELEMENT_IDS } from '../../../constants';
3
+ import GraphicsResult from '.';
4
4
  import styles from './styles.module.css';
5
- import { useScript, useStore } from '@theme/CodeEditor/hooks';
6
- import Button from '@theme/CodeEditor/Button';
5
+ import { useScript, useStore } from '../../../WithScript/Store';
6
+ import Button from '../../../Button';
7
7
 
8
8
  const downloadCanvas = (canvasId: string) => {
9
9
  const canvas = document.getElementById(canvasId) as HTMLCanvasElement;
@@ -25,13 +25,13 @@ const downloadCanvas = (canvasId: string) => {
25
25
  document.body.removeChild(downloadLink);
26
26
  };
27
27
 
28
- const Canvas = () => {
28
+ const CanvasResult = () => {
29
29
  const { store } = useScript();
30
30
  // const { codeId } = useStore(store, (state) => ({codeId: state.codeId}));
31
31
  const codeId = useStore(store, (state) => state.codeId);
32
32
 
33
33
  return (
34
- <Graphics
34
+ <GraphicsResult
35
35
  controls={
36
36
  <Button
37
37
  icon='Download'
@@ -58,4 +58,4 @@ const Canvas = () => {
58
58
  )
59
59
  };
60
60
 
61
- export default Canvas;
61
+ export default CanvasResult;
@@ -1,18 +1,18 @@
1
1
  import * as React from 'react';
2
2
  import styles from './styles.module.css';
3
- import { DOM_ELEMENT_IDS } from '@theme/CodeEditor/constants';
4
- import Graphics from '@theme/CodeEditor/Editor/Result/Graphics';
5
- import { saveSvg } from '@theme/CodeEditor/Editor/utils/saveSvg';
6
- import { useScript, useStore } from '@theme/CodeEditor/hooks';
7
- import Button from '@theme/CodeEditor/Button';
3
+ import { DOM_ELEMENT_IDS } from '../../../constants';
4
+ import GraphicsResult from '.';
5
+ import { saveSvg } from '../../utils/saveSvg';
6
+ import { useScript, useStore } from '../../../WithScript/Store';
7
+ import Button, { Color } from '../../../Button';
8
8
  import clsx from 'clsx';
9
9
 
10
- const Turtle = () => {
10
+ const TurtleResult = () => {
11
11
  const { store } = useScript();
12
12
  const codeId = useStore(store, (state) => state.codeId);
13
13
  const code = useStore(store, (state) => state.code);
14
14
  return (
15
- <Graphics
15
+ <GraphicsResult
16
16
  controls={
17
17
  <React.Fragment>
18
18
  <Button
@@ -45,4 +45,4 @@ const Turtle = () => {
45
45
  )
46
46
  }
47
47
 
48
- export default Turtle;
48
+ export default TurtleResult;
@@ -1,16 +1,16 @@
1
1
  import * as React from 'react';
2
2
  import styles from './styles.module.css';
3
- import { DOM_ELEMENT_IDS } from '@theme/CodeEditor/constants';
3
+ import { DOM_ELEMENT_IDS } from '../../../constants';
4
4
  import Draggable from 'react-draggable';
5
- import { checkForButtonClick } from '@theme/CodeEditor/Editor/utils/checkForButtonClick';
6
- import { useScript, useStore } from '@theme/CodeEditor/hooks';
7
- import Button from '@theme/CodeEditor/Button';
5
+ import { checkForButtonClick } from '../../utils/checkForButtonClick';
6
+ import { useScript, useStore } from '../../../WithScript/Store';
7
+ import Button from '../../../Button';
8
8
  import clsx from 'clsx';
9
- export interface Props {
9
+ interface Props {
10
10
  controls?: JSX.Element;
11
11
  main?: JSX.Element;
12
12
  }
13
- const Graphics = (props: Props) => {
13
+ const GraphicsResult = (props: Props) => {
14
14
  const { store } = useScript();
15
15
  const codeId = useStore(store, (state) => state.codeId);
16
16
  return (
@@ -44,4 +44,4 @@ const Graphics = (props: Props) => {
44
44
  );
45
45
  };
46
46
 
47
- export default Graphics;
47
+ export default GraphicsResult;
@@ -1,9 +1,13 @@
1
1
  import * as React from 'react';
2
2
  import styles from './styles.module.css';
3
+ // @ts-ignore
3
4
  import CodeBlock from '@theme/CodeBlock';
4
- import { useScript, useStore } from '@theme/CodeEditor/hooks';
5
+ import { useScript, useStore } from '../../WithScript/Store';
5
6
 
6
- const Result = () => {
7
+ interface Props {
8
+ }
9
+
10
+ const Result = (props: Props) => {
7
11
  const { store } = useScript();
8
12
  const logs = useStore(store, (state) => state.logs);
9
13
  if (logs.length === 0) {
@@ -1,16 +1,18 @@
1
1
  import * as React from "react";
2
+ import clsx from "clsx";
3
+ import styles from "./styles.module.css";
2
4
  import {
3
5
  DOM_ELEMENT_IDS,
4
- } from "@theme/CodeEditor/constants";
5
- import { useScript, useStore } from '@theme/CodeEditor/hooks';
6
- import Result from "@theme/CodeEditor/Editor/Result";
7
- import Turtle from "@theme/CodeEditor/Editor/Result/Graphics/Turtle";
8
- import Canvas from "@theme/CodeEditor/Editor/Result/Graphics/Canvas";
9
- import Graphics from "@theme/CodeEditor/Editor/Result/Graphics";
10
- import Header from "@theme/CodeEditor/Editor/Header";
11
- import EditorAce from "@theme/CodeEditor/Editor/EditorAce";
6
+ } from "../constants";
7
+ import { useScript, useStore } from '../WithScript/Store';
8
+ import Result from "./Result";
9
+ import TurtleResult from "./Result/Graphics/Turtle";
10
+ import CanvasResult from "./Result/Graphics/Canvas";
11
+ import GraphicsResult from "./Result/Graphics";
12
+ import Header from "./Header";
13
+ import EditorAce from "./EditorAce";
12
14
 
13
- export interface Props {
15
+ interface Props {
14
16
  slim: boolean;
15
17
  title: string;
16
18
  resettable: boolean;
@@ -52,13 +54,13 @@ const Editor = (props: Props) => {
52
54
  {isGraphicsmodalOpen && (
53
55
  <>
54
56
  {hasTurtleOutput && (
55
- <Turtle />
57
+ <TurtleResult />
56
58
  )}
57
59
  {hasCanvasOutput && (
58
- <Canvas />
60
+ <CanvasResult />
59
61
  )}
60
62
  {!hasCanvasOutput && !hasTurtleOutput && (
61
- <Graphics />
63
+ <GraphicsResult />
62
64
  )}
63
65
  </>
64
66
  )}
@@ -68,4 +70,4 @@ const Editor = (props: Props) => {
68
70
  );
69
71
  };
70
72
 
71
- export default Editor;
73
+ export default Editor;
@@ -1,4 +1,4 @@
1
- import { removeAnimations } from "@theme/CodeEditor/Editor/utils/svgWithoutAnimations";
1
+ import { removeAnimations } from "./svgWithoutAnimations";
2
2
 
3
3
  const duration = (anim: SVGAnimateElement) => {
4
4
  const dur = anim.getAttribute('dur') || '';
@@ -1,4 +1,4 @@
1
- import { parse, RootNode, Node } from "svg-parser";
1
+ import { parse, RootNode, ElementNode, Node } from "svg-parser";
2
2
 
3
3
  const objToAttr = (obj: Object) => {
4
4
  return Object.entries(obj || {})
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import * as Icons from '@theme/CodeEditor/Icon/icons';
2
+ import * as Icons from './icons';
3
3
  import styles from './styles.module.css';
4
4
  import clsx from 'clsx';
5
5
 
@@ -13,7 +13,7 @@ export enum Color {
13
13
  Link = 'var(--ifm-color-link)'
14
14
  }
15
15
 
16
- export interface Props {
16
+ interface Props {
17
17
  icon: keyof typeof Icons;
18
18
  size?: number | string;
19
19
  spin?: boolean;
@@ -1,4 +1,4 @@
1
- import type { StorageSlot, StoredScript } from "@theme/CodeEditor/WithScript/Types";
1
+ import type { StorageSlot, StoredScript } from "./Types";
2
2
 
3
3
  export const getStorageScript = (storage: StorageSlot): StoredScript | undefined => {
4
4
  const storedCode = storage.get();
@@ -1,10 +1,264 @@
1
- import React from "react";
1
+ import React, { useCallback } from "react";
2
+ import { useSyncExternalStore } from "react";
3
+ import { v4 as uuidv4 } from 'uuid';
4
+ import { checkCanvasOutput, checkGraphicsOutput, checkTurtleOutput, getPreCode, sanitizePyScript } from "./helpers";
5
+ import { ReactContextError, createStorageSlot } from "@docusaurus/theme-common";
2
6
  import { usePluginData } from "@docusaurus/useGlobalData";
3
- import { type InitState, type Store } from "@theme/CodeEditor/WithScript/Types";
4
- import { createStore } from "@theme/CodeEditor/WithScript/createStore";
7
+ import { DOM_ELEMENT_IDS } from "../constants";
8
+ import throttle from 'lodash/throttle';
9
+ import { getStorageScript, syncStorageScript } from "./Storage";
10
+ import { type InitState, type LogMessage, type Script, Status, type Store, type StoredScript, type Version } from "./Types";
11
+ export const createStore = (props: InitState, libDir: string, syncMaxOnceEvery: number): Store => {
12
+ const canSave = !!props.id;
13
+ const id = props.id || uuidv4();
14
+ const codeId = `code.${props.title || props.lang}.${id}`.replace(/(-|\.)/g, '_');
15
+ const createdAt = new Date();
16
+ const storageKey = `code.${props.title || 'code_block'}.${id}`;
17
+ const storage = createStorageSlot(storageKey);
18
+ storage.listen((e) => {
19
+ if (e.key === storageKey) {
20
+ try {
21
+ if (e.newValue) {
22
+ const script = JSON.parse(e.newValue) as StoredScript;
23
+ if (new Date(script.updatedAt) > state.updatedAt) {
24
+ loadData(storage);
25
+ }
26
+ }
27
+ } catch (err) {
28
+ console.warn(err);
29
+ }
30
+ }
31
+ });
32
+
33
+ const loadData = (store) => {
34
+ setState((s) => ({...s, status: canSave ? Status.SYNCING : s.status}));
35
+ const script = getStorageScript(store);
36
+ const loadedCode = script?.code ? prepareCode(script.code, { codeOnly: true }) : {};
37
+ addVersion.cancel();
38
+ if (!state.isLoaded) {
39
+ setState((s) => ({
40
+ ...s,
41
+ isLoaded: true,
42
+ ...(script || {}),
43
+ ...loadedCode,
44
+ versions: script?.versions || [],
45
+ versionsLoaded: true,
46
+ status: canSave ? Status.SUCCESS : s.status
47
+ }));
48
+ return Status.SUCCESS;
49
+ }
50
+ if (script) {
51
+ setState((s) => ({...s, ...script, ...loadedCode, status: canSave ? Status.SUCCESS : s.status, versionsLoaded: true}));
52
+ return Status.SUCCESS;
53
+ }
54
+ setState((s) => ({...s, status: canSave ? Status.ERROR : s.status}));
55
+ return Status.ERROR;
56
+ }
57
+
58
+
59
+ const prepareCode = (raw: string, config: { codeOnly?: boolean, stateNotInitialized?: boolean } = {}) => {
60
+ const { pre, code } = config.codeOnly
61
+ ? { pre: getPreCode(state.pristineCode).pre, code: raw }
62
+ : getPreCode(raw);
63
+ const hasEdits = code !== (config.stateNotInitialized ? getPreCode(props.raw).code : state.pristineCode);
64
+ const updatedAt = new Date();
65
+ const hasCanvasOutput = checkCanvasOutput(raw);
66
+ const hasTurtleOutput = checkTurtleOutput(raw);
67
+ const hasGraphicsOutput = checkGraphicsOutput(raw);
68
+ if (props.versioned && !config.stateNotInitialized) {
69
+ addVersion({code: code, createdAt: updatedAt, version: state.versions.length + 1});
70
+ }
71
+ return {
72
+ code: code,
73
+ preCode: pre,
74
+ hasCanvasOutput: hasCanvasOutput,
75
+ hasTurtleOutput: hasTurtleOutput,
76
+ hasGraphicsOutput: hasGraphicsOutput,
77
+ hasEdits: hasEdits,
78
+ updatedAt: updatedAt
79
+ };
80
+ }
81
+
82
+ const setCode = (raw: string, action?: 'insert' | 'remove' | string) => {
83
+ if (state.isPasted && action === 'remove') {
84
+ return;
85
+ }
86
+ const data = prepareCode(raw);
87
+ setState(
88
+ (state) => ({
89
+ ...state,
90
+ ...data
91
+ })
92
+ );
93
+ if (props.id) {
94
+ const toStore: StoredScript = {code: data.code, createdAt: state.createdAt, updatedAt: data.updatedAt, versions: state.versions};
95
+ if (state.isPasted) {
96
+ addVersion.flush();
97
+ if (toStore.versions.length > 0) {
98
+ toStore.versions[toStore.versions.length - 1].pasted = true;
99
+ }
100
+ set(toStore);
101
+ set.flush();
102
+ state.isPasted = false;
103
+ } else {
104
+ set(toStore);
105
+ }
106
+ }
107
+ };
108
+
109
+ const execScript = () => {
110
+ const toExec = `${state.code}`;
111
+ const lineShift = state.preCode.split(/\n/).length;
112
+ const src = `from brython_runner import run
113
+ run("""${sanitizePyScript(toExec || '')}""", '${codeId}', ${lineShift})
114
+ `;
115
+ if (!(window as any).__BRYTHON__) {
116
+ alert('Brython not loaded');
117
+ return;
118
+ }
119
+ setState((s) => ({...s, isExecuting: true, isGraphicsmodalOpen: state.hasGraphicsOutput}));
120
+ const active = document.getElementById(DOM_ELEMENT_IDS.communicator(state.codeId));
121
+ active.setAttribute('data--start-time', `${Date.now()}`);
122
+ /**
123
+ * ensure that the script is executed after the current event loop.
124
+ * Otherwise, the brython script will not be able to access the graphics output.
125
+ */
126
+ setTimeout(() => {
127
+ (window as any).__BRYTHON__.runPythonSource(
128
+ src,
129
+ {
130
+ pythonpath: [libDir]
131
+ }
132
+ );
133
+ }, 0);
134
+ };
135
+ const load = async () => {
136
+ return loadData(storage);
137
+ };
138
+ const _set = async (script: StoredScript) => {
139
+ setState((s) => ({...s, status: canSave ? Status.SYNCING : s.status}));
140
+ if (syncStorageScript(script, storage)) {
141
+ setState((s) => ({...s, status: canSave ? Status.SUCCESS : s.status}));
142
+ return Status.SUCCESS;
143
+ }
144
+ setState((s) => ({...s, status: canSave ? Status.ERROR : s.status}));
145
+ return Status.ERROR;
146
+ };
147
+
148
+ const set = throttle(
149
+ _set,
150
+ syncMaxOnceEvery,
151
+ {leading: false, trailing: true}
152
+ );
153
+
154
+ const _addVersion = (version: Version) => {
155
+ if (!props.versioned || !props.id) {
156
+ return;
157
+ }
158
+ const versions = [...state.versions];
159
+ versions.push(version);
160
+ setState((s) => ({...s, versions: versions}));
161
+ }
162
+ const addVersion = throttle(
163
+ _addVersion,
164
+ syncMaxOnceEvery,
165
+ {leading: false, trailing: true}
166
+ );
167
+
168
+ const saveNow = async () => {
169
+ addVersion.flush();
170
+ return set.flush();
171
+ }
172
+
173
+ const del = async () => {
174
+ storage.del();
175
+ return Status.SUCCESS;
176
+ }
177
+ const codeData = prepareCode(props.raw, { stateNotInitialized: true });
178
+ const setExecuting = (isExecuting: boolean) => {
179
+ setState((s) => ({...s, isExecuting: isExecuting}))
180
+ };
181
+ const addLogMessage = (log: LogMessage) => {
182
+ setState((s) => ({...s, logs: [...s.logs, log]}));
183
+ };
184
+ const clearLogMessages = () => {
185
+ setState((s) => ({...s, logs: []}));
186
+ };
187
+ const closeGraphicsModal = () => {
188
+ setState((s) => ({...s, isGraphicsmodalOpen: false}));
189
+ };
190
+ const stopScript = () => {
191
+ const code = document.getElementById(DOM_ELEMENT_IDS.communicator(state.codeId));
192
+ if (code) {
193
+ code.removeAttribute('data--start-time');
194
+ }
195
+ };
196
+ let state: Script = {
197
+ id: id,
198
+ codeId: codeId,
199
+ lang: props.lang,
200
+ showRaw: false,
201
+ pristineCode: codeData.code,
202
+ isExecuting: false,
203
+ logs: [],
204
+ isGraphicsmodalOpen: false,
205
+ hasEdits: false,
206
+ createdAt: createdAt,
207
+ isLoaded: false,
208
+ status: Status.IDLE,
209
+ versions: [],
210
+ versionsLoaded: false,
211
+ isPasted: false,
212
+ ...codeData
213
+ };
214
+
215
+
216
+ const getState = () => state;
217
+ const listeners = new Set<() => void>();
218
+ const setState = (fn: (state: Script) => Script) => {
219
+ state = fn(state);
220
+ listeners.forEach((l) => l());
221
+ };
222
+ const subscribe = (listener: () => void) => {
223
+ listeners.add(listener);
224
+ return () => listeners.delete(listener);
225
+ };
226
+ const loadVersions = async () => {
227
+ // noop
228
+ state.isLoaded = false;
229
+ load();
230
+ setState((s) => ({...s, versionsLoaded: true}));
231
+ return Promise.resolve();
232
+ }
233
+
234
+ return {
235
+ getState,
236
+ setState,
237
+ subscribe,
238
+ saveNow,
239
+ addLogMessage,
240
+ clearLogMessages,
241
+ closeGraphicsModal,
242
+ setCode,
243
+ execScript,
244
+ setExecuting,
245
+ stopScript,
246
+ load,
247
+ loadVersions
248
+ } satisfies Store;
249
+ };
250
+
251
+ type Selector<T, R> = (state: T) => R;
252
+ export const useStore = <T, R>(store: Store<T>, selector: Selector<T, R>): R => {
253
+ return useSyncExternalStore(
254
+ store.subscribe,
255
+ useCallback(() => selector(store.getState()), [store, selector])
256
+ );
257
+ }
5
258
 
6
259
  export const Context = React.createContext<{store: Store} | undefined>(undefined);
7
260
 
261
+
8
262
  const ScriptContext = (props: InitState & { children: React.ReactNode; }) => {
9
263
  const {libDir, syncMaxOnceEvery} = usePluginData('docusaurus-live-brython') as {libDir: string, syncMaxOnceEvery: number};
10
264
  const [store, setStore] = React.useState<Store | null>(null);
@@ -25,4 +279,16 @@ const ScriptContext = (props: InitState & { children: React.ReactNode; }) => {
25
279
  );
26
280
  }
27
281
 
282
+ export function useScript(): {store: Store} {
283
+ const context = React.useContext(Context);
284
+ if (context === null) {
285
+ throw new ReactContextError(
286
+ 'ScriptContextProvider',
287
+ 'The Component must be a child of the CodeContextProvider component',
288
+ );
289
+ }
290
+ return context;
291
+ }
292
+
293
+
28
294
  export default ScriptContext;
@@ -13,7 +13,6 @@ export interface StoredScript {
13
13
  versions: Version[];
14
14
  }
15
15
 
16
- export type Selector<T, R> = (state: T) => R;
17
16
  export interface Script extends StoredScript {
18
17
  /**
19
18
  * this is normally a uuid
@@ -1,13 +1,14 @@
1
1
  import * as React from 'react';
2
2
  import styles from './styles.module.css';
3
- import Editor from '@theme/CodeEditor/Editor';
4
- import BrythonCommunicator from '@theme/CodeEditor/BrythonCommunicator';
3
+ import Editor from './Editor';
4
+ import BrythonCommunicator from './BrythonCommunicator';
5
5
  import clsx from 'clsx';
6
- import { useScript, useStore } from '@theme/CodeEditor/hooks';
6
+ import useIsBrowser from '@docusaurus/useIsBrowser';
7
+ import { useScript, useStore } from './WithScript/Store';
7
8
  import BrowserOnly from '@docusaurus/BrowserOnly';
8
- import CodeHistory from '@theme/CodeEditor/CodeHistory';
9
+ import CodeHistory from './CodeHistory';
9
10
 
10
- export interface Props {
11
+ interface Props {
11
12
  slim: boolean;
12
13
  readonly: boolean;
13
14
  children: React.ReactNode;
@@ -23,7 +24,7 @@ export interface Props {
23
24
  noHistory: boolean;
24
25
  }
25
26
 
26
- const CodeEditor = (props: Props) => {
27
+ const PyAceEditor = (props: Props) => {
27
28
  const { store } = useScript();
28
29
  const lang = useStore(store, (state) => state.lang);
29
30
  return (
@@ -53,5 +54,4 @@ const CodeEditor = (props: Props) => {
53
54
  );
54
55
  };
55
56
 
56
- export default CodeEditor;
57
-
57
+ export default PyAceEditor;
package/src/types.ts ADDED
@@ -0,0 +1,29 @@
1
+
2
+ export type ThemeOptions = {
3
+ /**
4
+ * The path to the brython source file.
5
+ * @default 'https://raw.githack.com/brython-dev/brython/master/www/src/brython.js
6
+ */
7
+ brython_src?: string;
8
+ /**
9
+ * The path to the brython standard library source file.
10
+ * @default 'https://raw.githack.com/brython-dev/brython/master/www/src/brython_stdlib.js'
11
+ */
12
+ brython_stdlib_src?: string;
13
+ /**
14
+ * The folder path to brython specific libraries.
15
+ * When a python file imports a module, the module is searched in the libDir directory.
16
+ * By default, the libDir is created in the static folder and the needed python files are copied there.
17
+ * This can be changed by setting skipCopyAssetsToLibDir to true and setting libDir to a custom path.
18
+ * Make sure to copy the needed python files to the custom libDir.
19
+ * @default '/bry-libs/'
20
+ */
21
+ libDir?: string;
22
+ /**
23
+ * Skip copying the brython specific libraries to the libDir.
24
+ * Make sure to copy the needed python files to the custom libDir yourself.
25
+ * @ref [needed python files](https://github.com/lebalz/docusaurus-live-brython/tree/main/src/assets)
26
+ * @default false
27
+ */
28
+ skipCopyAssetsToLibDir?: boolean;
29
+ }
@@ -1,2 +0,0 @@
1
- import { type InitState, type Store } from "@theme/CodeEditor/WithScript/Types";
2
- export declare const createStore: (props: InitState, libDir: string, syncMaxOnceEvery: number) => Store;