From 2423859af23f084abda44fb530a1def7f8e7bdcc Mon Sep 17 00:00:00 2001 From: Jonathan Bossenger Date: Wed, 25 Sep 2024 15:09:21 +0200 Subject: [PATCH] [Interactive code block] Add "theme mode" in the code editor (#353) ## What? This PR attempts to add theme support to the code editor mode, so that users can set up a plugin or theme in the code editor mode. ## Why? I would like to be able to set up practical activities for learners on Learn.WordPress.org around both plugin and theme development, using the WordPress Playground block ## How? ## Testing Instructions 1. Check out the [jonathanbossenger:351-code-editor-theme-support](https://github.com/jonathanbossenger/playground-tools/tree/351-code-editor-theme-support) branch 2. Load and instance of the playground in the Site Editor 3. Change the Code Editor Mode to "Theme" 4. Create a style.css and templates/index.html block theme files 5. Run the playground preview 6. The two theme files should activate as the active theme in the preview Fixes #351 --- ...d-plugin.ts => download-zipped-package.ts} | 17 +++++-- .../components/playground-preview/index.tsx | 25 ++++++--- .../playground-preview/write-theme-files.ts | 36 +++++++++++++ .../wordpress-playground-block/src/edit.tsx | 51 ++++++++++++++----- 4 files changed, 105 insertions(+), 24 deletions(-) rename packages/wordpress-playground-block/src/components/playground-preview/{download-zipped-plugin.ts => download-zipped-package.ts} (80%) create mode 100644 packages/wordpress-playground-block/src/components/playground-preview/write-theme-files.ts diff --git a/packages/wordpress-playground-block/src/components/playground-preview/download-zipped-plugin.ts b/packages/wordpress-playground-block/src/components/playground-preview/download-zipped-package.ts similarity index 80% rename from packages/wordpress-playground-block/src/components/playground-preview/download-zipped-plugin.ts rename to packages/wordpress-playground-block/src/components/playground-preview/download-zipped-package.ts index 07b24f32..e77ae3db 100644 --- a/packages/wordpress-playground-block/src/components/playground-preview/download-zipped-plugin.ts +++ b/packages/wordpress-playground-block/src/components/playground-preview/download-zipped-package.ts @@ -4,12 +4,23 @@ import { // @ts-ignore } from 'https://playground.wordpress.net/client/index.js'; -export default async function downloadZippedPlugin(client: PlaygroundClient) { +export default async function downloadZippedPackage( + client: PlaygroundClient, + codeEditorMode +) { const docroot = await client.documentRoot; - const pluginPath = docroot + '/wp-content/plugins/demo-plugin'; + + let pluginPath = docroot + '/wp-content/plugins/demo-plugin'; + let fileName = 'wordpress-playground-plugin.zip'; + + if (codeEditorMode == 'theme') { + pluginPath = docroot + '/wp-content/themes/demo-theme'; + fileName = 'wordpress-playground-theme.zip'; + } + const zipFile = new File( [await zipPlaygroundFiles(client, pluginPath)], - 'wordpress-playground-plugin.zip', + fileName, { type: 'application/zip', } diff --git a/packages/wordpress-playground-block/src/components/playground-preview/index.tsx b/packages/wordpress-playground-block/src/components/playground-preview/index.tsx index b6776464..105d8419 100644 --- a/packages/wordpress-playground-block/src/components/playground-preview/index.tsx +++ b/packages/wordpress-playground-block/src/components/playground-preview/index.tsx @@ -32,7 +32,8 @@ import { import useEditorFiles, { isErrorLogFile } from './use-editor-files'; import { LanguageSupport } from '@codemirror/language'; import { writePluginFiles } from './write-plugin-files'; -import downloadZippedPlugin from './download-zipped-plugin'; +import { writeThemeFiles } from './write-theme-files'; +import downloadZippedPackage from './download-zipped-package'; import classnames from 'classnames'; import FileManagementModals, { FileManagerRef } from './file-management-modals'; import { @@ -90,6 +91,7 @@ function PlaygroundPreview({ blueprintUrl, configurationSource, codeEditor, + codeEditorMode, codeEditorSideBySide, codeEditorReadOnly, codeEditorTranspileJsx, @@ -277,7 +279,7 @@ function PlaygroundPreview({ 500 ); - await reinstallEditedPlugin(); + await reinstallEditedCode(); if (configurationSource === 'block-attributes') { let postId = 0; @@ -363,7 +365,7 @@ function PlaygroundPreview({ const [transpilationFailures, setTranspilationFailures] = useState< TranspilationFailure[] >([]); - async function reinstallEditedPlugin() { + async function reinstallEditedCode() { if (!playgroundClientRef.current || !codeEditor) { return; } @@ -372,6 +374,7 @@ function PlaygroundPreview({ const client = playgroundClientRef.current; let finalFiles = files; + if (codeEditorTranspileJsx) { const { failures, transpiledFiles } = await transpilePluginFiles( finalFiles @@ -388,12 +391,17 @@ function PlaygroundPreview({ } finalFiles = transpiledFiles; } - await writePluginFiles(client, finalFiles); + + if (codeEditorMode === 'theme') { + await writeThemeFiles(client, finalFiles); + } else { + await writePluginFiles(client, finalFiles); + } } const handleReRunCode = useCallback(() => { async function doHandleRun() { - await reinstallEditedPlugin(); + await reinstallEditedCode(); // Refresh Playground iframe const lastPath = await playgroundClientRef.current!.getCurrentURL(); @@ -406,7 +414,7 @@ function PlaygroundPreview({ } else { doHandleRun(); } - }, [reinstallEditedPlugin]); + }, [reinstallEditedCode]); const keymapExtension = useMemo( () => @@ -552,8 +560,9 @@ function PlaygroundPreview({ className="file-tab file-tab-extra" onClick={() => { if (playgroundClientRef.current) { - downloadZippedPlugin( - playgroundClientRef.current + downloadZippedPackage( + playgroundClientRef.current, + codeEditorMode ); } }} diff --git a/packages/wordpress-playground-block/src/components/playground-preview/write-theme-files.ts b/packages/wordpress-playground-block/src/components/playground-preview/write-theme-files.ts new file mode 100644 index 00000000..5d331f00 --- /dev/null +++ b/packages/wordpress-playground-block/src/components/playground-preview/write-theme-files.ts @@ -0,0 +1,36 @@ +import type { EditorFile } from '../../index'; +import { + PlaygroundClient, + activateTheme, + // @ts-ignore +} from 'https://playground.wordpress.net/client/index.js'; + +export const writeThemeFiles = async ( + client: PlaygroundClient, + files: EditorFile[] +) => { + const docroot = await client.documentRoot; + const themeFolderName = 'demo-theme'; + const themePath = docroot + '/wp-content/themes/' + themeFolderName; + if (await client.fileExists(themePath)) { + await client.rmdir(themePath, { + recursive: true, + }); + } + await client.mkdir(themePath); + + for (const file of files) { + const filePath = `${themePath}/${file.name}`; + const parentDir = filePath.split('/').slice(0, -1).join('/'); + await client.mkdir(parentDir); + await client.writeFile(filePath, file.contents); + } + + try { + await activateTheme(client, { + themeFolderName, + }); + } catch (e) { + console.error(e); + } +}; diff --git a/packages/wordpress-playground-block/src/edit.tsx b/packages/wordpress-playground-block/src/edit.tsx index 8b5d0ba4..e82d633d 100644 --- a/packages/wordpress-playground-block/src/edit.tsx +++ b/packages/wordpress-playground-block/src/edit.tsx @@ -6,6 +6,7 @@ import { useState, useRef } from '@wordpress/element'; import { ToggleControl, SelectControl, + RadioControl, TextareaControl, Panel, PanelBody, @@ -143,6 +144,8 @@ export default withBase64Attrs(function Edit({ requireLivePreviewActivation, } = attributes; + const showJSXTranspileOption = codeEditorMode === 'plugin'; + return (
- { - setAttributes({ - codeEditorTranspileJsx: - !codeEditorTranspileJsx, - }); + { + if (value === 'theme') { + setAttributes({ + codeEditorMode: value, + codeEditorTranspileJsx: false, + }); + } else { + setAttributes({ + codeEditorMode: value, + }); + } }} /> + {showJSXTranspileOption && ( + { + setAttributes({ + codeEditorTranspileJsx: + !codeEditorTranspileJsx, + }); + }} + /> + )}