docusaurus-live-brython 3.0.0-beta.8 → 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.
- package/.devcontainer/devcontainer.json +38 -0
- package/.prettierignore +17 -0
- package/.prettierrc +9 -8
- package/CHANGELOG.md +5 -0
- package/README.md +7 -4
- package/lib/assets/py_back_trace.py +2 -1
- package/lib/index.d.ts +1 -7
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +94 -16
- package/lib/options.d.ts +1 -0
- package/lib/options.d.ts.map +1 -0
- package/lib/options.js +2 -2
- package/lib/theme/CodeBlock/index.d.ts +3 -3
- package/lib/theme/CodeBlock/index.d.ts.map +1 -0
- package/lib/theme/CodeBlock/index.jsx +24 -14
- package/lib/theme/CodeEditor/Actions/DownloadCode.d.ts +1 -0
- package/lib/theme/CodeEditor/Actions/DownloadCode.d.ts.map +1 -0
- package/lib/theme/CodeEditor/Actions/DownloadCode.jsx +8 -8
- package/lib/theme/CodeEditor/Actions/Reset.d.ts +1 -0
- package/lib/theme/CodeEditor/Actions/Reset.d.ts.map +1 -0
- package/lib/theme/CodeEditor/Actions/Reset.jsx +5 -5
- package/lib/theme/CodeEditor/Actions/RunCode.d.ts +2 -1
- package/lib/theme/CodeEditor/Actions/RunCode.d.ts.map +1 -0
- package/lib/theme/CodeEditor/Actions/RunCode.jsx +4 -4
- package/lib/theme/CodeEditor/Actions/ShowRaw.d.ts +1 -0
- package/lib/theme/CodeEditor/Actions/ShowRaw.d.ts.map +1 -0
- package/lib/theme/CodeEditor/Actions/ShowRaw.jsx +13 -7
- package/lib/theme/CodeEditor/Actions/ShowSyncStatus.d.ts +1 -0
- package/lib/theme/CodeEditor/Actions/ShowSyncStatus.d.ts.map +1 -0
- package/lib/theme/CodeEditor/Actions/ShowSyncStatus.jsx +21 -16
- package/lib/theme/CodeEditor/Actions/styles.module.css +2 -3
- package/lib/theme/CodeEditor/BrythonCommunicator.d.ts +2 -1
- package/lib/theme/CodeEditor/BrythonCommunicator.d.ts.map +1 -0
- package/lib/theme/CodeEditor/BrythonCommunicator.jsx +13 -9
- package/lib/theme/CodeEditor/Button/index.d.ts +3 -2
- package/lib/theme/CodeEditor/Button/index.d.ts.map +1 -0
- package/lib/theme/CodeEditor/Button/index.jsx +1 -1
- package/lib/theme/CodeEditor/Button/styles.module.css +1 -1
- package/lib/theme/CodeEditor/CodeHistory/index.d.ts +1 -0
- package/lib/theme/CodeEditor/CodeHistory/index.d.ts.map +1 -0
- package/lib/theme/CodeEditor/CodeHistory/index.jsx +26 -15
- package/lib/theme/CodeEditor/CodeHistory/styles.module.css +31 -31
- package/lib/theme/CodeEditor/ContextEditor/index.d.ts +22 -0
- package/lib/theme/CodeEditor/ContextEditor/index.d.ts.map +1 -0
- package/lib/theme/CodeEditor/ContextEditor/index.jsx +36 -0
- package/lib/theme/CodeEditor/Editor/EditorAce.d.ts +2 -1
- package/lib/theme/CodeEditor/Editor/EditorAce.d.ts.map +1 -0
- package/lib/theme/CodeEditor/Editor/EditorAce.jsx +17 -14
- package/lib/theme/CodeEditor/Editor/Header/index.d.ts +2 -1
- package/lib/theme/CodeEditor/Editor/Header/index.d.ts.map +1 -0
- package/lib/theme/CodeEditor/Editor/Header/index.jsx +12 -12
- package/lib/theme/CodeEditor/Editor/Header/styles.module.css +7 -7
- package/lib/theme/CodeEditor/Editor/HiddenCode/index.d.ts +8 -0
- package/lib/theme/CodeEditor/Editor/HiddenCode/index.d.ts.map +1 -0
- package/lib/theme/CodeEditor/Editor/HiddenCode/index.jsx +27 -0
- package/lib/theme/CodeEditor/Editor/HiddenCode/styles.module.css +52 -0
- package/lib/theme/CodeEditor/Editor/Result/Graphics/Canvas.d.ts +1 -0
- package/lib/theme/CodeEditor/Editor/Result/Graphics/Canvas.d.ts.map +1 -0
- package/lib/theme/CodeEditor/Editor/Result/Graphics/Canvas.jsx +8 -9
- package/lib/theme/CodeEditor/Editor/Result/Graphics/Turtle.d.ts +1 -0
- package/lib/theme/CodeEditor/Editor/Result/Graphics/Turtle.d.ts.map +1 -0
- package/lib/theme/CodeEditor/Editor/Result/Graphics/Turtle.jsx +11 -11
- package/lib/theme/CodeEditor/Editor/Result/Graphics/index.d.ts +4 -3
- package/lib/theme/CodeEditor/Editor/Result/Graphics/index.d.ts.map +1 -0
- package/lib/theme/CodeEditor/Editor/Result/Graphics/index.jsx +12 -10
- package/lib/theme/CodeEditor/Editor/Result/Graphics/styles.module.css +2 -2
- package/lib/theme/CodeEditor/Editor/Result/index.d.ts +2 -3
- package/lib/theme/CodeEditor/Editor/Result/index.d.ts.map +1 -0
- package/lib/theme/CodeEditor/Editor/Result/index.jsx +6 -9
- package/lib/theme/CodeEditor/Editor/Result/styles.module.css +15 -10
- package/lib/theme/CodeEditor/Editor/index.d.ts +6 -3
- package/lib/theme/CodeEditor/Editor/index.d.ts.map +1 -0
- package/lib/theme/CodeEditor/Editor/index.jsx +34 -28
- package/lib/theme/CodeEditor/Editor/styles.module.css +15 -7
- package/lib/theme/CodeEditor/Editor/utils/checkForButtonClick.d.ts +1 -0
- package/lib/theme/CodeEditor/Editor/utils/checkForButtonClick.d.ts.map +1 -0
- package/lib/theme/CodeEditor/Editor/utils/saveSvg.d.ts +1 -0
- package/lib/theme/CodeEditor/Editor/utils/saveSvg.d.ts.map +1 -0
- package/lib/theme/CodeEditor/Editor/utils/saveSvg.js +19 -8
- package/lib/theme/CodeEditor/Editor/utils/svgWithoutAnimations.d.ts +1 -0
- package/lib/theme/CodeEditor/Editor/utils/svgWithoutAnimations.d.ts.map +1 -0
- package/lib/theme/CodeEditor/Editor/utils/svgWithoutAnimations.js +43 -49
- package/lib/theme/CodeEditor/Icon/icons.d.ts +4 -1
- package/lib/theme/CodeEditor/Icon/icons.d.ts.map +1 -0
- package/lib/theme/CodeEditor/Icon/icons.js +3 -1
- package/lib/theme/CodeEditor/Icon/index.d.ts +4 -2
- package/lib/theme/CodeEditor/Icon/index.d.ts.map +1 -0
- package/lib/theme/CodeEditor/Icon/index.jsx +10 -3
- package/lib/theme/CodeEditor/Icon/styles.module.css +1 -1
- package/lib/theme/CodeEditor/WithScript/ScriptContext.d.ts +8 -0
- package/lib/theme/CodeEditor/WithScript/ScriptContext.d.ts.map +1 -0
- package/lib/theme/CodeEditor/WithScript/ScriptContext.jsx +27 -0
- package/lib/theme/CodeEditor/WithScript/Storage.d.ts +2 -1
- package/lib/theme/CodeEditor/WithScript/Storage.d.ts.map +1 -0
- package/lib/theme/CodeEditor/WithScript/Types.d.ts +12 -4
- package/lib/theme/CodeEditor/WithScript/Types.d.ts.map +1 -0
- package/lib/theme/CodeEditor/WithScript/bryRunner.d.ts +3 -0
- package/lib/theme/CodeEditor/WithScript/bryRunner.d.ts.map +1 -0
- package/lib/theme/CodeEditor/WithScript/bryRunner.js +29 -0
- package/lib/theme/CodeEditor/WithScript/createStore.d.ts +4 -0
- package/lib/theme/CodeEditor/WithScript/createStore.d.ts.map +1 -0
- package/lib/theme/CodeEditor/WithScript/{Store.jsx → createStore.js} +62 -74
- package/lib/theme/CodeEditor/WithScript/helpers.d.ts +1 -4
- package/lib/theme/CodeEditor/WithScript/helpers.d.ts.map +1 -0
- package/lib/theme/CodeEditor/WithScript/helpers.js +4 -14
- package/lib/theme/CodeEditor/constants.d.ts +1 -0
- package/lib/theme/CodeEditor/constants.d.ts.map +1 -0
- package/lib/theme/CodeEditor/hooks/index.d.ts +3 -0
- package/lib/theme/CodeEditor/hooks/index.d.ts.map +1 -0
- package/lib/theme/CodeEditor/hooks/index.js +2 -0
- package/lib/theme/CodeEditor/hooks/useScript.d.ts +3 -0
- package/lib/theme/CodeEditor/hooks/useScript.d.ts.map +1 -0
- package/lib/theme/CodeEditor/hooks/useScript.js +4 -0
- package/lib/theme/CodeEditor/hooks/useStore.d.ts +3 -0
- package/lib/theme/CodeEditor/hooks/useStore.d.ts.map +1 -0
- package/lib/theme/CodeEditor/hooks/useStore.js +10 -0
- package/lib/theme/CodeEditor/index.d.ts +24 -5
- package/lib/theme/CodeEditor/index.d.ts.map +1 -0
- package/lib/theme/CodeEditor/index.jsx +17 -16
- package/lib/theme/CodeEditor/styles.module.css +28 -30
- package/og-image.md +23 -0
- package/package.json +39 -20
- package/src/assets/py_back_trace.py +2 -1
- package/src/index.ts +96 -25
- package/src/options.ts +12 -12
- package/src/theme/CodeBlock/index.tsx +44 -68
- package/src/theme/CodeEditor/Actions/DownloadCode.tsx +23 -22
- package/src/theme/CodeEditor/Actions/Reset.tsx +14 -12
- package/src/theme/CodeEditor/Actions/RunCode.tsx +14 -11
- package/src/theme/CodeEditor/Actions/ShowRaw.tsx +17 -11
- package/src/theme/CodeEditor/Actions/ShowSyncStatus.tsx +32 -27
- package/src/theme/CodeEditor/Actions/styles.module.css +2 -3
- package/src/theme/CodeEditor/BrythonCommunicator.tsx +16 -19
- package/src/theme/CodeEditor/Button/index.tsx +17 -13
- package/src/theme/CodeEditor/Button/styles.module.css +1 -1
- package/src/theme/CodeEditor/CodeHistory/index.tsx +32 -20
- package/src/theme/CodeEditor/CodeHistory/styles.module.css +31 -31
- package/src/theme/CodeEditor/ContextEditor/index.tsx +74 -0
- package/src/theme/CodeEditor/Editor/EditorAce.tsx +20 -16
- package/src/theme/CodeEditor/Editor/Header/index.tsx +13 -19
- package/src/theme/CodeEditor/Editor/Header/styles.module.css +7 -7
- package/src/theme/CodeEditor/Editor/HiddenCode/index.tsx +49 -0
- package/src/theme/CodeEditor/Editor/HiddenCode/styles.module.css +52 -0
- package/src/theme/CodeEditor/Editor/Result/Graphics/Canvas.tsx +25 -22
- package/src/theme/CodeEditor/Editor/Result/Graphics/Turtle.tsx +23 -19
- package/src/theme/CodeEditor/Editor/Result/Graphics/index.tsx +16 -16
- package/src/theme/CodeEditor/Editor/Result/Graphics/styles.module.css +2 -2
- package/src/theme/CodeEditor/Editor/Result/index.tsx +7 -13
- package/src/theme/CodeEditor/Editor/Result/styles.module.css +15 -10
- package/src/theme/CodeEditor/Editor/index.tsx +67 -65
- package/src/theme/CodeEditor/Editor/styles.module.css +15 -7
- package/src/theme/CodeEditor/Editor/utils/checkForButtonClick.ts +5 -5
- package/src/theme/CodeEditor/Editor/utils/saveSvg.ts +63 -53
- package/src/theme/CodeEditor/Editor/utils/svgWithoutAnimations.ts +182 -201
- package/src/theme/CodeEditor/Icon/icons.ts +27 -13
- package/src/theme/CodeEditor/Icon/index.tsx +31 -11
- package/src/theme/CodeEditor/Icon/styles.module.css +1 -1
- package/src/theme/CodeEditor/WithScript/ScriptContext.tsx +36 -0
- package/src/theme/CodeEditor/WithScript/Storage.ts +3 -3
- package/src/theme/CodeEditor/WithScript/Types.ts +17 -11
- package/src/theme/CodeEditor/WithScript/bryRunner.ts +39 -0
- package/src/theme/CodeEditor/WithScript/createStore.ts +276 -0
- package/src/theme/CodeEditor/WithScript/helpers.ts +16 -26
- package/src/theme/CodeEditor/constants.ts +9 -11
- package/src/theme/CodeEditor/hooks/index.ts +2 -0
- package/src/theme/CodeEditor/hooks/useScript.ts +9 -0
- package/src/theme/CodeEditor/hooks/useStore.ts +15 -0
- package/src/theme/CodeEditor/index.tsx +45 -31
- package/src/theme/CodeEditor/styles.module.css +28 -30
- package/src/typings.d.ts +11 -0
- package/lib/theme/CodeEditor/WithScript/Store.d.ts +0 -15
- package/lib/types.d.ts +0 -28
- package/lib/types.js +0 -1
- package/src/theme/CodeEditor/WithScript/Store.tsx +0 -294
- package/src/types.ts +0 -29
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from browser import document, window # type: ignore
|
|
2
2
|
import sys
|
|
3
|
+
import time
|
|
3
4
|
|
|
4
5
|
# @source https://github.com/brython-dev/brython/blob/master/www/src/Lib/tb.py
|
|
5
6
|
# instead of "print()" to "console.log()" in the original code, we use "notify()" to send the output to the react world
|
|
@@ -23,7 +24,7 @@ class EventOutput:
|
|
|
23
24
|
|
|
24
25
|
def flush(self):
|
|
25
26
|
if len(self.buf) > 0:
|
|
26
|
-
notify(self.node_id, {'type': self.out_type, 'output': self.buf})
|
|
27
|
+
notify(self.node_id, {'type': self.out_type, 'output': self.buf, 'time': time.time()})
|
|
27
28
|
self.buf = ''
|
|
28
29
|
|
|
29
30
|
def __len__(self):
|
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
|
|
30
|
-
|
|
31
|
-
|
|
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
|
-
|
|
38
|
-
|
|
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
|
-
|
|
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
|
|
55
|
-
setGlobalData({
|
|
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:
|
|
83
|
-
referrerpolicy:
|
|
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:
|
|
92
|
-
referrerpolicy:
|
|
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://
|
|
52
|
-
brythonStdlibSrc: 'https://
|
|
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
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
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
|
|
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
|
|
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(
|
|
41
|
-
|
|
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
|
-
|
|
45
|
-
|
|
46
|
-
|
|
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):
|
|
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
|
|
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
|
-
<
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
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 {
|
|
3
|
-
import 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
|
|
8
|
-
const
|
|
9
|
-
const
|
|
10
|
-
const
|
|
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=
|
|
13
|
+
icon="Download"
|
|
15
14
|
onClick={() => {
|
|
16
|
-
const downloadLink = document.createElement(
|
|
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
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
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 {
|
|
3
|
-
import Button, { Color } from '
|
|
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
|
|
8
|
-
const pristine =
|
|
9
|
-
|
|
7
|
+
const store = useStore();
|
|
8
|
+
const pristine = useScript(store, 'pristineCode');
|
|
9
|
+
|
|
10
10
|
const onReset = () => {
|
|
11
|
-
const shouldReset = window.confirm(
|
|
12
|
-
|
|
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 {
|
|
3
|
-
import Button, { Color } from '
|
|
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
|
|
15
|
-
const 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
|
-
|
|
28
|
-
|
|
29
|
-
|
|
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 {
|
|
3
|
-
import Button, { Color } from '
|
|
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
|
|
8
|
-
const 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.
|
|
13
|
+
onClick={() => store.setShowRaw(!showRaw)}
|
|
14
14
|
color={showRaw ? Color.Primary : Color.Secondary}
|
|
15
15
|
title={
|
|
16
|
-
showRaw
|
|
17
|
-
|
|
18
|
-
|
|
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;
|