diff --git a/package-lock.json b/package-lock.json
index 60b5595192c..6eb692724fe 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -22274,6 +22274,12 @@
"node": ">= 12"
}
},
+ "node_modules/html-to-image": {
+ "version": "1.11.13",
+ "resolved": "https://registry.npmjs.org/html-to-image/-/html-to-image-1.11.13.tgz",
+ "integrity": "sha512-cuOPoI7WApyhBElTTb9oqsawRvZ0rHhaHwghRLlTuffoD1B2aDemlCruLeZrUIIdvG7gs9xeELEPm6PhuASqrg==",
+ "license": "MIT"
+ },
"node_modules/html-webpack-plugin": {
"version": "5.6.6",
"dev": true,
@@ -41487,6 +41493,7 @@
"get-user-media-promise": "1.1.4",
"graphql": "^14.7.0",
"highlight.js": "^10.7.3",
+ "html-to-image": "^1.11.13",
"immutable": "3.8.3",
"intl": "1.2.5",
"js-base64": "2.6.4",
diff --git a/packages/scratch-gui/package.json b/packages/scratch-gui/package.json
index 1d94e2ee51a..cf0537da5ad 100644
--- a/packages/scratch-gui/package.json
+++ b/packages/scratch-gui/package.json
@@ -152,6 +152,7 @@
"get-user-media-promise": "1.1.4",
"graphql": "^14.7.0",
"highlight.js": "^10.7.3",
+ "html-to-image": "^1.11.13",
"immutable": "3.8.3",
"intl": "1.2.5",
"js-base64": "2.6.4",
@@ -176,7 +177,7 @@
"react-intl": "6.8.9",
"react-modal": "3.16.3",
"react-popover": "0.5.10",
- "react-redux": "8.1.3",
+ "react-redux": "^8.0.0",
"react-responsive": "9.0.2",
"react-style-proptype": "3.2.2",
"react-tabs": "5.2.0",
diff --git a/packages/scratch-gui/src/containers/ruby-tab.jsx b/packages/scratch-gui/src/containers/ruby-tab.jsx
index a7bbb1dfa90..a5ad0e7e31a 100644
--- a/packages/scratch-gui/src/containers/ruby-tab.jsx
+++ b/packages/scratch-gui/src/containers/ruby-tab.jsx
@@ -47,6 +47,8 @@ import AutoCorrectModal from '../components/auto-correct-modal/auto-correct-moda
import RubyScriptPreview from '../components/ruby-script-preview/ruby-script-preview.jsx';
import {generatePreviewCode} from '../lib/ruby-script-preview';
import {autoCorrect, defaultSettings as defaultAutoCorrectSettings} from '../lib/auto-correct';
+import {downloadRubyAsImage} from '../lib/ruby-screenshot';
+import cameraIcon from '../components/blocks-screenshot-button/icon--camera.svg';
import styles from './ruby-tab/ruby-tab.css';
import {loadMonacoLocale} from '../lib/monaco-i18n-helper';
import {getPrism, loadPrism} from '../lib/prism-parser';
@@ -422,6 +424,14 @@ const RubyTab = props => {
onFontSizeChange(DEFAULT_FONT_SIZE);
}, [onFontSizeChange]);
+ const handleScreenshot = useCallback(() => {
+ if (!editorRef.current) return;
+ const target = vm.editingTarget;
+ const spriteName = target ? target.sprite.name : 'sprite';
+ const title = props.projectTitle || 'project';
+ downloadRubyAsImage(editorRef.current, title, spriteName);
+ }, [vm, props.projectTitle]);
+
const handleSelectTarget = useCallback(targetId => {
const target = vm.runtime.getTargetById(targetId);
if (target) vm.setEditingTarget(target.id);
@@ -967,6 +977,20 @@ const RubyTab = props => {
+