diff --git a/.eslintrc.json b/.eslintrc.json index ffdf0cfc..d1bbe284 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,6 +1,6 @@ { "extends": "plugin:@wordpress/eslint-plugin/recommended", - "env":{ + "env": { "browser": true }, "rules": { @@ -14,12 +14,8 @@ "react/jsx-boolean-value": "error", "unicorn/no-abusive-eslint-disable": "error" }, - "ignorePatterns": [ - "src/lib" - ], - "plugins":[ - "unicorn" - ], + "ignorePatterns": [ "src/lib" ], + "plugins": [ "unicorn" ], "overrides": [ { "files": [ "**/test/**/*.js" ], diff --git a/admin/class-create-theme.php b/admin/class-create-theme.php deleted file mode 100644 index 4834ea47..00000000 --- a/admin/class-create-theme.php +++ /dev/null @@ -1,500 +0,0 @@ -theme = wp_get_theme(); - } - - function create_block_theme_enqueue() { - global $pagenow; - - if ( 'site-editor.php' !== $pagenow ) { - return; - } - - $asset_file = include plugin_dir_path( dirname( __FILE__ ) ) . 'build/plugin-sidebar.asset.php'; - - wp_register_script( - 'create-block-theme-slot-fill', - plugins_url( 'build/plugin-sidebar.js', dirname( __FILE__ ) ), - $asset_file['dependencies'], - $asset_file['version'] - ); - wp_enqueue_script( - 'create-block-theme-slot-fill', - ); - - // Enable localization in the plugin sidebar. - wp_set_script_translations( 'create-block-theme-slot-fill', 'create-block-theme' ); - } - - function create_admin_menu() { - if ( ! wp_is_block_theme() ) { - return; - } - $page_title = _x( 'Create Block Theme', 'UI String', 'create-block-theme' ); - $menu_title = _x( 'Create Block Theme', 'UI String', 'create-block-theme' ); - add_theme_page( $page_title, $menu_title, 'edit_theme_options', 'create-block-theme', array( 'CBT_Theme_Form', 'create_admin_form_page' ) ); - - add_action( 'admin_enqueue_scripts', array( 'CBT_Theme_Form', 'form_script' ) ); - } - - function save_theme_locally( $export_type ) { - CBT_Theme_Templates::add_templates_to_local( $export_type ); - CBT_Theme_JSON::add_theme_json_to_local( $export_type ); - } - - function save_variation( $export_type, $theme ) { - CBT_Theme_JSON::add_theme_json_variation_to_local( 'variation', $theme ); - } - - public function download_file( $file, $filename ) { - // Set headers. - header( 'Content-Type: application/zip' ); - header( 'Content-Disposition: attachment; filename=' . $filename ); - header( 'Content-Length: ' . filesize( $file ) ); - - // Send file. - readfile( $file ); - - // Delete file. - unlink( $file ); - } - - /** - * Export activated child theme - */ - function export_child_theme( $theme ) { - if ( $theme['name'] ) { - // Used when CREATING a child theme - $theme['slug'] = CBT_Theme_Utils::get_theme_slug( $theme['name'] ); - } else { - // Used with EXPORTING a child theme - $theme['slug'] = wp_get_theme()->get( 'TextDomain' ); - } - - // Create ZIP file in the temporary directory. - $filename = tempnam( get_temp_dir(), $theme['slug'] ); - $zip = CBT_Theme_Zip::create_zip( $filename ); - - $zip = CBT_Theme_Zip::copy_theme_to_zip( $zip, null, null ); - $zip = CBT_Theme_Zip::add_templates_to_zip( $zip, 'current', $theme['slug'] ); - $zip = CBT_Theme_Zip::add_theme_json_to_zip( $zip, CBT_Theme_JSON_Resolver::export_theme_data( 'current' ) ); - - $zip->close(); - - // Download the ZIP file. - $this->download_file( $filename, $theme['slug'] . '.zip' ); - - return $filename; - } - - /** - * Create a sibling theme of the activated theme - */ - function create_sibling_theme( $theme, $screenshot ) { - $theme_slug = CBT_Theme_Utils::get_theme_slug( $theme['name'] ); - - // Sanitize inputs. - $theme['name'] = sanitize_text_field( $theme['name'] ); - $theme['description'] = sanitize_text_field( $theme['description'] ); - $theme['uri'] = sanitize_text_field( $theme['uri'] ); - $theme['author'] = sanitize_text_field( $theme['author'] ); - $theme['author_uri'] = sanitize_text_field( $theme['author_uri'] ); - $theme['tags_custom'] = sanitize_text_field( $theme['tags_custom'] ); - $theme['image_credits'] = sanitize_textarea_field( $theme['image_credits'] ); - $theme['recommended_plugins'] = sanitize_textarea_field( $theme['recommended_plugins'] ); - $theme['font_credits'] = sanitize_textarea_field( $theme['font_credits'] ); - $theme['slug'] = $theme_slug; - $theme['template'] = wp_get_theme()->get( 'Template' ); - $theme['text_domain'] = $theme_slug; - - // Create ZIP file in the temporary directory. - $filename = tempnam( get_temp_dir(), $theme['slug'] ); - $zip = CBT_Theme_Zip::create_zip( $filename ); - - $zip = CBT_Theme_Zip::copy_theme_to_zip( $zip, $theme['slug'], $theme['name'] ); - $zip = CBT_Theme_Zip::add_templates_to_zip( $zip, 'current', $theme['slug'] ); - $zip = CBT_Theme_Zip::add_theme_json_to_zip( $zip, CBT_Theme_JSON_Resolver::export_theme_data( 'current' ) ); - - // Add readme.txt. - $zip->addFromStringToTheme( - 'readme.txt', - CBT_Theme_Readme::create( $theme ) - ); - - // Augment style.css - $css_contents = file_get_contents( get_stylesheet_directory() . '/style.css' ); - // Remove metadata from style.css file - $css_contents = trim( substr( $css_contents, strpos( $css_contents, '*/' ) + 2 ) ); - // Add new metadata - $css_contents = CBT_Theme_Styles::build_style_css( $theme ) . $css_contents; - $zip->addFromStringToTheme( - 'style.css', - $css_contents - ); - - // Add / replace screenshot. - if ( CBT_Theme_Utils::is_valid_screenshot( $screenshot ) ) { - $zip->addFileToTheme( - $screenshot['tmp_name'], - 'screenshot.png' - ); - } - - $zip->close(); - - header( 'Content-Type: application/zip' ); - header( 'Content-Disposition: attachment; filename=' . $theme['slug'] . '.zip' ); - header( 'Content-Length: ' . filesize( $filename ) ); - flush(); - echo readfile( $filename ); - die(); - } - - /** - * Clone the activated theme to create a new theme - */ - function clone_theme( $theme, $screenshot ) { - $theme_slug = CBT_Theme_Utils::get_theme_slug( $theme['name'] ); - - // Sanitize inputs. - $theme['name'] = sanitize_text_field( $theme['name'] ); - $theme['description'] = sanitize_text_field( $theme['description'] ); - $theme['uri'] = sanitize_text_field( $theme['uri'] ); - $theme['author'] = sanitize_text_field( $theme['author'] ); - $theme['author_uri'] = sanitize_text_field( $theme['author_uri'] ); - $theme['tags_custom'] = sanitize_text_field( $theme['tags_custom'] ); - $theme['image_credits'] = sanitize_textarea_field( $theme['image_credits'] ); - $theme['recommended_plugins'] = sanitize_textarea_field( $theme['recommended_plugins'] ); - $theme['font_credits'] = sanitize_textarea_field( $theme['font_credits'] ); - $theme['slug'] = $theme_slug; - $theme['template'] = ''; - $theme['text_domain'] = $theme_slug; - - // Use previous theme's tags if custom tags are empty. - if ( empty( $theme['tags_custom'] ) ) { - $theme['tags_custom'] = implode( ', ', $this->theme->get( 'Tags' ) ); - } - - // Create ZIP file in the temporary directory. - $filename = tempnam( get_temp_dir(), $theme['slug'] ); - $zip = CBT_Theme_Zip::create_zip( $filename ); - - $zip = CBT_Theme_Zip::copy_theme_to_zip( $zip, $theme['slug'], $theme['name'] ); - - $zip = CBT_Theme_Zip::add_templates_to_zip( $zip, 'all', $theme['slug'] ); - $zip = CBT_Theme_Zip::add_theme_json_to_zip( $zip, CBT_Theme_JSON_Resolver::export_theme_data( 'all' ) ); - - // Add readme.txt. - $zip->addFromStringToTheme( - 'readme.txt', - CBT_Theme_Readme::create( $theme ) - ); - - // Augment style.css - $css_contents = file_get_contents( get_stylesheet_directory() . '/style.css' ); - // Remove metadata from style.css file - $css_contents = trim( substr( $css_contents, strpos( $css_contents, '*/' ) + 2 ) ); - // Add new metadata - $css_contents = CBT_Theme_Styles::build_style_css( $theme ) . $css_contents; - $zip->addFromStringToTheme( - 'style.css', - $css_contents - ); - - // Add / replace screenshot. - if ( CBT_Theme_Utils::is_valid_screenshot( $screenshot ) ) { - $zip->addFileToTheme( - $screenshot['tmp_name'], - 'screenshot.png' - ); - } - - $zip->close(); - - header( 'Content-Type: application/zip' ); - header( 'Content-Disposition: attachment; filename=' . $theme['slug'] . '.zip' ); - header( 'Content-Length: ' . filesize( $filename ) ); - flush(); - readfile( $filename ); - unlink( $filename ); - exit; - } - - /** - * Create a child theme of the activated theme - */ - function create_child_theme( $theme, $screenshot ) { - $parent_theme_slug = CBT_Theme_Utils::get_theme_slug( $this->theme->get( 'Name' ) ); - $child_theme_slug = CBT_Theme_Utils::get_theme_slug( $theme['name'] ); - - // Sanitize inputs. - $theme['name'] = sanitize_text_field( $theme['name'] ); - $theme['description'] = sanitize_text_field( $theme['description'] ); - $theme['uri'] = sanitize_text_field( $theme['uri'] ); - $theme['author'] = sanitize_text_field( $theme['author'] ); - $theme['author_uri'] = sanitize_text_field( $theme['author_uri'] ); - $theme['tags_custom'] = sanitize_text_field( $theme['tags_custom'] ); - $theme['image_credits'] = sanitize_textarea_field( $theme['image_credits'] ); - $theme['recommended_plugins'] = sanitize_textarea_field( $theme['recommended_plugins'] ); - $theme['font_credits'] = sanitize_textarea_field( $theme['font_credits'] ); - $theme['is_child_theme'] = true; - $theme['text_domain'] = $child_theme_slug; - $theme['template'] = $parent_theme_slug; - $theme['slug'] = $child_theme_slug; - - // Create ZIP file in the temporary directory. - $filename = tempnam( get_temp_dir(), $theme['slug'] ); - $zip = CBT_Theme_Zip::create_zip( $filename ); - - $zip = CBT_Theme_Zip::add_templates_to_zip( $zip, 'user', $theme['slug'] ); - $zip = CBT_Theme_Zip::add_theme_json_to_zip( $zip, CBT_Theme_JSON_Resolver::export_theme_data( 'user' ) ); - - // Add readme.txt. - $zip->addFromStringToTheme( - 'readme.txt', - CBT_Theme_Readme::create( $theme ) - ); - - // Add style.css. - $zip->addFromStringToTheme( - 'style.css', - CBT_Theme_Styles::build_style_css( $theme ) - ); - - // Add / replace screenshot. - if ( CBT_Theme_Utils::is_valid_screenshot( $screenshot ) ) { - $zip->addFileToTheme( - $screenshot['tmp_name'], - 'screenshot.png' - ); - } - - $zip->close(); - - header( 'Content-Type: application/zip' ); - header( 'Content-Disposition: attachment; filename=' . $theme['slug'] . '.zip' ); - header( 'Content-Length: ' . filesize( $filename ) ); - flush(); - echo readfile( $filename ); - die(); - } - - /** - * Export activated parent theme - */ - function export_theme( $theme ) { - $theme['slug'] = $this->theme->get( 'TextDomain' ); - - // Create ZIP file in the temporary directory. - $filename = tempnam( get_temp_dir(), $theme['slug'] ); - $zip = CBT_Theme_Zip::create_zip( $filename ); - - $zip = CBT_Theme_Zip::copy_theme_to_zip( $zip, null, null ); - $zip = CBT_Theme_Zip::add_templates_to_zip( $zip, 'all', null ); - $zip = CBT_Theme_Zip::add_theme_json_to_zip( $zip, CBT_Theme_JSON_Resolver::export_theme_data( 'all' ) ); - - $zip->close(); - - header( 'Content-Type: application/zip' ); - header( 'Content-Disposition: attachment; filename=' . $theme['slug'] . '.zip' ); - header( 'Content-Length: ' . filesize( $filename ) ); - flush(); - echo readfile( $filename ); - die(); - } - - function create_blank_theme( $theme, $screenshot ) { - $theme_slug = CBT_Theme_Utils::get_theme_slug( $theme['name'] ); - - // Sanitize inputs. - $theme['name'] = sanitize_text_field( $theme['name'] ); - $theme['description'] = sanitize_text_field( $theme['description'] ); - $theme['uri'] = sanitize_text_field( $theme['uri'] ); - $theme['author'] = sanitize_text_field( $theme['author'] ); - $theme['author_uri'] = sanitize_text_field( $theme['author_uri'] ); - $theme['tags_custom'] = sanitize_text_field( $theme['tags_custom'] ); - $theme['image_credits'] = sanitize_textarea_field( $theme['image_credits'] ); - $theme['recommended_plugins'] = sanitize_textarea_field( $theme['recommended_plugins'] ); - $theme['font_credits'] = sanitize_textarea_field( $theme['font_credits'] ); - $theme['template'] = ''; - $theme['slug'] = $theme_slug; - $theme['text_domain'] = $theme_slug; - - // Create theme directory. - $source = plugin_dir_path( __DIR__ ) . 'assets/boilerplate'; - $blank_theme_path = get_theme_root() . DIRECTORY_SEPARATOR . $theme['slug']; - if ( ! file_exists( $blank_theme_path ) ) { - wp_mkdir_p( $blank_theme_path ); - // Add readme.txt. - file_put_contents( - $blank_theme_path . DIRECTORY_SEPARATOR . 'readme.txt', - CBT_Theme_Readme::create( $theme ) - ); - - // Add new metadata. - $css_contents = CBT_Theme_Styles::build_style_css( $theme ); - - // Add style.css. - file_put_contents( - $blank_theme_path . DIRECTORY_SEPARATOR . 'style.css', - $css_contents - ); - - $iterator = new \RecursiveIteratorIterator( - new \RecursiveDirectoryIterator( $source, \RecursiveDirectoryIterator::SKIP_DOTS ), - \RecursiveIteratorIterator::SELF_FIRST - ); - - foreach ( - $iterator as $item - ) { - if ( $item->isDir() ) { - wp_mkdir_p( $blank_theme_path . DIRECTORY_SEPARATOR . $iterator->getSubPathname() ); - } else { - copy( $item, $blank_theme_path . DIRECTORY_SEPARATOR . $iterator->getSubPathname() ); - } - } - - // Overwrite default screenshot if one is provided. - if ( CBT_Theme_Utils::is_valid_screenshot( $screenshot ) ) { - file_put_contents( - $blank_theme_path . DIRECTORY_SEPARATOR . 'screenshot.png', - file_get_contents( $screenshot['tmp_name'] ) - ); - } - - if ( ! defined( 'IS_GUTENBERG_PLUGIN' ) ) { - global $wp_version; - $theme_json_version = 'wp/' . substr( $wp_version, 0, 3 ); - $schema = '"$schema": "https://schemas.wp.org/' . $theme_json_version . '/theme.json"'; - $theme_json_path = $blank_theme_path . DIRECTORY_SEPARATOR . 'theme.json'; - $theme_json_string = file_get_contents( $theme_json_path ); - $theme_json_string = str_replace( '"$schema": "https://schemas.wp.org/trunk/theme.json"', $schema, $theme_json_string ); - file_put_contents( $theme_json_path, $theme_json_string ); - } - } - } - - function blockbase_save_theme() { - if ( ! empty( $_GET['page'] ) && 'create-block-theme' === $_GET['page'] && ! empty( $_POST['theme'] ) ) { - - // Check user capabilities. - if ( ! current_user_can( 'edit_theme_options' ) ) { - return add_action( 'admin_notices', array( 'CBT_Form_Messages', 'admin_notice_error_theme_name' ) ); - } - - // Check nonce - if ( ! wp_verify_nonce( $_POST['nonce'], 'create_block_theme' ) ) { - return add_action( 'admin_notices', array( 'CBT_Form_Messages', 'admin_notice_error_theme_name' ) ); - } - - if ( 'save' === $_POST['theme']['type'] ) { - // Avoid running if WordPress dosn't have permission to overwrite the theme folder - if ( ! wp_is_writable( get_stylesheet_directory() ) ) { - return add_action( 'admin_notices', array( 'CBT_Form_Messages', 'admin_notice_error_theme_file_permissions' ) ); - } - - if ( is_child_theme() ) { - $this->save_theme_locally( 'current' ); - } else { - $this->save_theme_locally( 'all' ); - } - CBT_Theme_Styles::clear_user_styles_customizations(); - CBT_Theme_Templates::clear_user_templates_customizations(); - - add_action( 'admin_notices', array( 'CBT_Form_Messages', 'admin_notice_save_success' ) ); - } elseif ( 'variation' === $_POST['theme']['type'] ) { - if ( '' === $_POST['theme']['variation'] ) { - return add_action( 'admin_notices', array( 'CBT_Form_Messages', 'admin_notice_error_variation_name' ) ); - } - - // Avoid running if WordPress dosn't have permission to write the theme folder - if ( ! wp_is_writable( get_stylesheet_directory() ) ) { - return add_action( 'admin_notices', array( 'CBT_Form_Messages', 'admin_notice_error_theme_file_permissions' ) ); - } - - if ( is_child_theme() ) { - $this->save_variation( 'current', $_POST['theme'] ); - } else { - $this->save_variation( 'all', $_POST['theme'] ); - } - CBT_Theme_Styles::clear_user_styles_customizations(); - - add_action( 'admin_notices', array( 'CBT_Form_Messages', 'admin_notice_variation_success' ) ); - } elseif ( 'blank' === $_POST['theme']['type'] ) { - // Avoid running if WordPress dosn't have permission to write the themes folder - if ( ! wp_is_writable( get_theme_root() ) ) { - return add_action( 'admin_notices', array( 'CBT_Form_Messages', 'admin_notice_error_themes_file_permissions' ) ); - } - - if ( '' === $_POST['theme']['name'] ) { - return add_action( 'admin_notices', array( 'CBT_Form_Messages', 'admin_notice_error_theme_name' ) ); - } - $this->create_blank_theme( $_POST['theme'], $_FILES['screenshot'] ); - - add_action( 'admin_notices', array( 'CBT_Form_Messages', 'admin_notice_blank_success' ) ); - } elseif ( ! class_exists( 'ZipArchive' ) ) { - // Avoid running if ZipArchive is not enabled. - add_action( 'admin_notices', array( 'CBT_Form_Messages', 'admin_notice_error_unsupported_zip_archive' ) ); - } elseif ( is_child_theme() ) { - if ( 'sibling' === $_POST['theme']['type'] ) { - if ( '' === $_POST['theme']['name'] ) { - return add_action( 'admin_notices', array( 'CBT_Form_Messages', 'admin_notice_error_theme_name' ) ); - } - $this->create_sibling_theme( $_POST['theme'], $_FILES['screenshot'] ); - } else { - $this->export_child_theme( $_POST['theme'] ); - } - add_action( 'admin_notices', array( 'CBT_Form_Messages', 'admin_notice_export_success' ) ); - } else { - if ( 'child' === $_POST['theme']['type'] ) { - if ( '' === $_POST['theme']['name'] ) { - return add_action( 'admin_notices', array( 'CBT_Form_Messages', 'admin_notice_error_theme_name' ) ); - } - $this->create_child_theme( $_POST['theme'], $_FILES['screenshot'] ); - } elseif ( 'clone' === $_POST['theme']['type'] ) { - if ( '' === $_POST['theme']['name'] ) { - return add_action( 'admin_notices', array( 'CBT_Form_Messages', 'admin_notice_error_theme_name' ) ); - } - $this->clone_theme( $_POST['theme'], $_FILES['screenshot'] ); - } else { - $this->export_theme( $_POST['theme'] ); - } - add_action( 'admin_notices', array( 'CBT_Form_Messages', 'admin_notice_export_success' ) ); - } - } - } -} diff --git a/admin/css/form.css b/admin/css/form.css deleted file mode 100644 index e4904377..00000000 --- a/admin/css/form.css +++ /dev/null @@ -1,93 +0,0 @@ -.appearance_page_create-block-theme h2 { - margin-bottom: 0; -} - -.appearance_page_create-block-theme p.description { - margin-bottom: 1rem; -} - -.appearance_page_create-block-theme .submit { - clear: both; -} - -#col-left label, -.theme-form label, -.theme-form legend { - font-weight: 600; -} - -.theme-tag-form-control label { - font-weight: 400; -} - -.theme-form label { - display: block; - margin-bottom: 0.25rem; -} - -/* Theme Tag Checkboxes */ -.theme-tags { - display: grid; - margin-top: 0.5rem; -} - -.theme-tags fieldset { - margin-bottom: 1rem; -} - -.theme-tags legend { - margin-bottom: 1rem; -} - -.theme-tags label { - display: inline-block; - margin-left: 0.25rem; - margin-bottom: 0.25rem; -} - -#features-tags { - display: grid; -} - -.theme-tag-form-control { - margin-bottom: 0.5rem; -} - -@media screen and (min-width: 600px) { - .theme-tags { - grid-template-columns: 1fr 1fr; - } - - /* Feature tags have items than other categores, so display the list in 2 columns on wider screens. */ - #features-tags { - grid-template-columns: 1fr 1fr; - grid-column: 1 / 3; - margin-top: 1rem; - } -} - -@media screen and (min-width: 783px) { - .theme-tags fieldset { - margin-bottom: 0.5rem; - } - - .theme-tags legend { - margin-bottom: 0.5rem; - } - - /* Checkboxes shrink to standard size. */ - .theme-tag-form-control { - margin-bottom: 0; - } -} - -@media screen and (min-width: 1440px) { - .theme-tags { - grid-template-columns: 1fr 1fr 1fr 1fr; - } - - #features-tags { - grid-column: 3 / 5; - margin-top: 0; - } -} diff --git a/admin/index.php b/admin/index.php deleted file mode 100644 index 8142269b..00000000 --- a/admin/index.php +++ /dev/null @@ -1 +0,0 @@ - { - form.toggleAttribute( 'hidden', true ); - } ); -} - -// Handle theme tag validation -function validateThemeTags( tagCategory ) { - if ( ! tagCategory ) return; - let checkboxes; - - if ( 'subject' === tagCategory ) { - checkboxes = 'input[name="theme[tags-subject][]"]'; - } - - // Maximum number of checkboxes that can be selected - const max = 3; - - // Run validation on form load - limitCheckboxSelection( checkboxes, max ); - - const allCheckboxes = document.querySelectorAll( checkboxes ); - - // Run validation on each checkbox change - if ( allCheckboxes.length > max ) { - for ( let i = 0; i < allCheckboxes.length; i++ ) { - allCheckboxes[ i ].addEventListener( 'change', function () { - limitCheckboxSelection( checkboxes, max ); - } ); - } - } -} - -// Takes a checkbox selector and limits the number of checkboxes that can be selected -function limitCheckboxSelection( checkboxesSelector, max = 0 ) { - if ( ! checkboxesSelector ) return; - - const checked = document.querySelectorAll( - `${ checkboxesSelector }:checked` - ); - const unchecked = document.querySelectorAll( - `${ checkboxesSelector }:not(:checked)` - ); - - if ( checked.length >= max ) { - for ( let i = 0; i < unchecked.length; i++ ) { - unchecked[ i ].setAttribute( 'disabled', true ); - } - } else { - for ( let i = 0; i < unchecked.length; i++ ) { - unchecked[ i ].removeAttribute( 'disabled' ); - } - } -} - -// Store active theme tags when page is loaded -let activeThemeTags = []; -function onWindowLoad() { - activeThemeTags = document.querySelectorAll( - '.theme-tags input[type="checkbox"]:checked' - ); -} - -window.addEventListener( 'load', onWindowLoad ); -window.addEventListener( 'load', prepareThemeNameValidation ); - -function prepareThemeNameValidation() { - const themeNameInput = document.getElementById( 'theme-name' ); - if ( themeNameInput ) { - themeNameInput.addEventListener( 'input', validateThemeNameInput ); - } -} - -function slugify( text ) { - // Removes spaces - return text.toLowerCase().replace( / /g, '' ); -} - -function slugifyUnderscores( text ) { - // Replaces spaces with underscores - return text.toLowerCase().replace( / /g, '_' ); -} - -function slugifyDashes( text ) { - // Replaces spaces with dashes - return text.toLowerCase().replace( / /g, '-' ); -} - -function slugifyNoDashes( text ) { - // Removes spaces, dashes, and underscores - return text.toLowerCase().replace( / /g, '' ).replace( /[-_]/g, '' ); -} - -const ERROR_NAME_NOT_AVAILABLE = __( - 'Theme name is not available in the WordPress.org theme directory', - 'create-block-theme' -); -const ERROR_NAME_CONTAINS_THEME = __( - 'Theme name cannot contain the word "theme"', - 'create-block-theme' -); -const ERROR_NAME_CONTAINS_WORDPRESS = __( - 'Theme name cannot contain the word "WordPress"', - 'create-block-theme' -); - -function isThemeNameValid( themeName ) { - // Check the validity of the theme name following the WordPress.org theme directory rules - // https://meta.svn.wordpress.org/sites/trunk/wordpress.org/public_html/wp-content/plugins/theme-directory/class-wporg-themes-upload.php - - /* eslint-disable @wordpress/no-unused-vars-before-return */ - const lowerCaseName = themeName.toLowerCase(); - const slug = slugify( themeName ); - const slugDashes = slugifyUnderscores( themeName ); - const slugUnderscores = slugifyDashes( themeName ); - const slugNoDashes = slugifyNoDashes( themeName ); - - const validityStatus = { - isValid: true, - errorMessage: '', - }; - - // Check if the theme contains the word theme - if ( lowerCaseName.includes( 'theme' ) ) { - validityStatus.isValid = false; - validityStatus.errorMessage = ERROR_NAME_CONTAINS_THEME; - return validityStatus; - } - - // Check if the theme name contains WordPress - if ( slugNoDashes.includes( 'wordpress' ) ) { - validityStatus.isValid = false; - validityStatus.errorMessage = ERROR_NAME_CONTAINS_WORDPRESS; - return validityStatus; - } - - // Check if the theme name is available - const isNameAvailable = () => { - // default to empty array if the unavailable theme names are not loaded yet from the API - const notAvailableSlugs = window.wpOrgThemeDirectory.themeSlugs || []; - - // Compare the theme name to the list of unavailable theme names using several different slug formats - return ! notAvailableSlugs.some( - ( s ) => - s === slug || - s === slugDashes || - s === slugUnderscores || - slugifyNoDashes( s ) === slugNoDashes - ); - }; - - if ( ! isNameAvailable() ) { - validityStatus.isValid = false; - validityStatus.errorMessage = ERROR_NAME_NOT_AVAILABLE; - return validityStatus; - } - - return validityStatus; -} - -function validateThemeNameInput() { - const themeName = this?.value; - if ( ! themeName ) return true; - - // Check if theme name is available - const validityStatus = isThemeNameValid( themeName ); - - if ( ! validityStatus.isValid ) { - this.setCustomValidity( validityStatus.errorMessage ); - this.reportValidity(); - } else { - this.setCustomValidity( '' ); - } -} - -// Resets all theme tag states (checked, disabled) to default values -function resetThemeTags( themeType ) { - // Clear all checkboxes - const allCheckboxes = document.querySelectorAll( - '.theme-tags input[type="checkbox"]' - ); - allCheckboxes.forEach( ( checkbox ) => { - checkbox.checked = false; - checkbox.removeAttribute( 'disabled' ); - } ); - - // Recheck default tags - const defaultTags = document.querySelectorAll( - '.theme-tags input[type="checkbox"].default-tag' - ); - defaultTags.forEach( ( checkbox ) => { - checkbox.checked = true; - } ); - - if ( 'blank' !== themeType ) { - // Recheck active theme tags - if ( ! activeThemeTags ) return; - - activeThemeTags.forEach( ( checkbox ) => { - checkbox.checked = true; - } ); - } -} - -function resetThemeName() { - const themeNameInput = document.getElementById( 'theme-name' ); - themeNameInput.value = ''; - themeNameInput.setCustomValidity( '' ); -} diff --git a/admin/wp-org-theme-directory.php b/admin/wp-org-theme-directory.php deleted file mode 100644 index bcb77f1a..00000000 --- a/admin/wp-org-theme-directory.php +++ /dev/null @@ -1,77 +0,0 @@ - 'GET', - 'callback' => array( 'CBT_WP_Theme_Directory', 'get_theme_names' ), - 'permission_callback' => function () { - return current_user_can( 'edit_theme_options' ); - }, - ) - ); - - } - - public static function get_theme_names() { - $html = wp_safe_remote_get( self::THEME_NAMES_ENDPOINT ); - - if ( is_wp_error( $html ) ) { - return $html; - } - - // parse the html response extracting all the a inside li elements - $pattern = '/
  • (.*?)<\/a><\/li>/'; - preg_match_all( $pattern, $html['body'], $matches ); - - // Revemo the / from the end of the theme name - $cleaned_names = array_map( - function ( $name ) { - return str_replace( '/', '', $name ); - }, - $matches[1] - ); - - $names = array( 'names' => $cleaned_names ); - return rest_ensure_response( $names ); - } - - function assets_enqueue() { - $asset_file = include( plugin_dir_path( dirname( __FILE__ ) ) . 'build/wp-org-theme-directory.asset.php' ); - - wp_register_script( - 'wp-org-theme-directory', - plugins_url( 'build/wp-org-theme-directory.js', dirname( __FILE__ ) ), - $asset_file['dependencies'], - $asset_file['version'] - ); - - wp_enqueue_script( - 'wp-org-theme-directory', - ); - - // Initialize and empty array of theme names to be shared between different client side scripts - wp_localize_script( - 'wp-org-theme-directory', - 'wpOrgThemeDirectory', - array( - 'themeSlugs' => null, - ) - ); - } - -} diff --git a/assets/faq_fonts.webp b/assets/faq_fonts.webp new file mode 100644 index 00000000..176c97a2 Binary files /dev/null and b/assets/faq_fonts.webp differ diff --git a/assets/faq_icon.webp b/assets/faq_icon.webp new file mode 100644 index 00000000..8edad83c Binary files /dev/null and b/assets/faq_icon.webp differ diff --git a/assets/faq_save.webp b/assets/faq_save.webp new file mode 100644 index 00000000..b2e87d30 Binary files /dev/null and b/assets/faq_save.webp differ diff --git a/assets/header_logo.webp b/assets/header_logo.webp new file mode 100644 index 00000000..d0776cdc Binary files /dev/null and b/assets/header_logo.webp differ diff --git a/includes/class-create-block-theme-admin-landing.php b/includes/class-create-block-theme-admin-landing.php new file mode 100644 index 00000000..8592f3d3 --- /dev/null +++ b/includes/class-create-block-theme-admin-landing.php @@ -0,0 +1,52 @@ + plugins_url( 'create-block-theme/assets/' ), + 'editor_url' => admin_url( 'site-editor.php?canvas=edit' ), + ) + ); + + // Enable localization in the app. + wp_set_script_translations( 'create-block-theme-app', 'create-block-theme' ); + + echo '
    '; + } +} diff --git a/includes/class-create-block-theme-api.php b/includes/class-create-block-theme-api.php index a7886d8d..b6f6c241 100644 --- a/includes/class-create-block-theme-api.php +++ b/includes/class-create-block-theme-api.php @@ -1,5 +1,21 @@ loader = new CBT_Plugin_Loader(); @@ -57,10 +56,9 @@ private function load_dependencies() { * @access private */ private function define_admin_hooks() { - - $plugin_admin = new CBT_WP_Admin(); - $wp_theme_directory = new CBT_WP_Theme_Directory(); - $plugin_api = new CBT_Theme_API(); + $plugin_api = new CBT_Theme_API(); + $editor_tools = new CBT_Editor_Tools(); + $admin_landing = new CBT_Admin_Landing(); } /** diff --git a/admin/create-theme/cbt-zip-archive.php b/includes/create-theme/cbt-zip-archive.php similarity index 100% rename from admin/create-theme/cbt-zip-archive.php rename to includes/create-theme/cbt-zip-archive.php diff --git a/admin/create-theme/form-messages.php b/includes/create-theme/form-messages.php similarity index 100% rename from admin/create-theme/form-messages.php rename to includes/create-theme/form-messages.php diff --git a/admin/resolver_additions.php b/includes/create-theme/resolver_additions.php similarity index 100% rename from admin/resolver_additions.php rename to includes/create-theme/resolver_additions.php diff --git a/admin/create-theme/theme-create.php b/includes/create-theme/theme-create.php similarity index 100% rename from admin/create-theme/theme-create.php rename to includes/create-theme/theme-create.php diff --git a/admin/create-theme/theme-fonts.php b/includes/create-theme/theme-fonts.php similarity index 100% rename from admin/create-theme/theme-fonts.php rename to includes/create-theme/theme-fonts.php diff --git a/admin/create-theme/theme-form.php b/includes/create-theme/theme-form.php similarity index 100% rename from admin/create-theme/theme-form.php rename to includes/create-theme/theme-form.php diff --git a/admin/create-theme/theme-json.php b/includes/create-theme/theme-json.php similarity index 100% rename from admin/create-theme/theme-json.php rename to includes/create-theme/theme-json.php diff --git a/admin/create-theme/theme-locale.php b/includes/create-theme/theme-locale.php similarity index 100% rename from admin/create-theme/theme-locale.php rename to includes/create-theme/theme-locale.php diff --git a/admin/create-theme/theme-media.php b/includes/create-theme/theme-media.php similarity index 100% rename from admin/create-theme/theme-media.php rename to includes/create-theme/theme-media.php diff --git a/admin/create-theme/theme-patterns.php b/includes/create-theme/theme-patterns.php similarity index 100% rename from admin/create-theme/theme-patterns.php rename to includes/create-theme/theme-patterns.php diff --git a/admin/create-theme/theme-readme.php b/includes/create-theme/theme-readme.php similarity index 100% rename from admin/create-theme/theme-readme.php rename to includes/create-theme/theme-readme.php diff --git a/admin/create-theme/theme-styles.php b/includes/create-theme/theme-styles.php similarity index 100% rename from admin/create-theme/theme-styles.php rename to includes/create-theme/theme-styles.php diff --git a/admin/create-theme/theme-tags.php b/includes/create-theme/theme-tags.php similarity index 100% rename from admin/create-theme/theme-tags.php rename to includes/create-theme/theme-tags.php diff --git a/admin/create-theme/theme-templates.php b/includes/create-theme/theme-templates.php similarity index 100% rename from admin/create-theme/theme-templates.php rename to includes/create-theme/theme-templates.php diff --git a/admin/create-theme/theme-utils.php b/includes/create-theme/theme-utils.php similarity index 100% rename from admin/create-theme/theme-utils.php rename to includes/create-theme/theme-utils.php diff --git a/admin/create-theme/theme-zip.php b/includes/create-theme/theme-zip.php similarity index 100% rename from admin/create-theme/theme-zip.php rename to includes/create-theme/theme-zip.php diff --git a/package.json b/package.json index 396f4477..b956e989 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,7 @@ "simple-git": "^3.18.0" }, "scripts": { - "build": "wp-scripts build src/plugin-sidebar.js src/wp-org-theme-directory.js", + "build": "wp-scripts build src/admin-landing-page.js src/plugin-sidebar.js", "format": "wp-scripts format", "lint:css": "wp-scripts lint-style", "lint:css:fix": "npm run lint:css -- --fix", @@ -57,7 +57,7 @@ "test:php:watch": "wp-env run cli --env-cwd='wp-content/plugins/create-block-theme' composer run-script test:watch", "test:php:setup": "wp-env start", "packages-update": "wp-scripts packages-update", - "start": "wp-scripts start src/plugin-sidebar.js src/wp-org-theme-directory.js", + "start": "wp-scripts start src/admin-landing-page.js src/plugin-sidebar.js", "composer": "wp-env run cli --env-cwd=wp-content/plugins/create-block-theme composer", "update-version": "node update-version-and-changelog.js", "prepare": "husky install", diff --git a/src/admin-landing-page.js b/src/admin-landing-page.js new file mode 100644 index 00000000..03d870f2 --- /dev/null +++ b/src/admin-landing-page.js @@ -0,0 +1,24 @@ +/** + * WordPress dependencies + */ +import { createRoot } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import './admin-landing-page.scss'; +import LandingPage from './landing-page/landing-page'; + +function App() { + return ; +} + +window.addEventListener( + 'load', + function () { + const domNode = document.getElementById( 'create-block-theme-app' ); + const root = createRoot( domNode ); + root.render( ); + }, + false +); diff --git a/src/admin-landing-page.scss b/src/admin-landing-page.scss new file mode 100644 index 00000000..0407f6f9 --- /dev/null +++ b/src/admin-landing-page.scss @@ -0,0 +1,80 @@ +@import "../node_modules/@wordpress/base-styles/mixins"; +@include wordpress-admin-schemes(); + + +.create-block-theme { + &__landing-page { + background-color: #fff; + margin-left: -20px; + a, + button { + color: #3858e9; + } + &__header { + width: 100%; + background-color: #2d59f2; + margin: 0; + } + &__body { + font-weight: 200; + padding: 40px 0; + p { + margin-top: 0; + } + h1, + h2, + h3, + h4, + h5, + h6 { + margin-top: 0.3em; + margin-bottom: 0.3em; + } + h2 { + font-size: 2em; + } + h3 { + font-size: 1em; + } + @media screen and (max-width: 775px) { + flex-direction: column; + h2 { + font-size: 1.5em; + } + } + &__left-column { + flex: 1; + margin: 0 60px; + button { + font-size: 1.75em; + @media screen and (max-width: 775px) { + font-size: 1.25em; + } + } + } + &__right-column { + max-width: 330px; + margin: 0 60px; + @media screen and (max-width: 775px) { + max-width: 100%; + } + p { + margin-bottom: 0; + } + } + + &__faq { + img { + max-width: 100%; + } + p { + padding: 10px; + font-style: italic; + } + details { + padding-bottom: 20px; + } + } + } + } +} diff --git a/src/editor-sidebar/create-panel.js b/src/editor-sidebar/create-panel.js index 227e86b4..b80aa1fb 100644 --- a/src/editor-sidebar/create-panel.js +++ b/src/editor-sidebar/create-panel.js @@ -4,7 +4,6 @@ import { __ } from '@wordpress/i18n'; import { useState } from '@wordpress/element'; import { useDispatch, useSelect } from '@wordpress/data'; -import apiFetch from '@wordpress/api-fetch'; import { store as noticesStore } from '@wordpress/notices'; import { // eslint-disable-next-line @wordpress/no-unsafe-wp-apis @@ -24,6 +23,11 @@ import { addCard, copy } from '@wordpress/icons'; * Internal dependencies */ import ScreenHeader from './screen-header'; +import { + createBlankTheme, + createClonedTheme, + createChildTheme, +} from '../resolvers'; export const CreateThemePanel = ( { createType } ) => { const { createErrorNotice } = useDispatch( noticesStore ); @@ -55,17 +59,10 @@ export const CreateThemePanel = ( { createType } ) => { }; const handleCreateBlankClick = () => { - apiFetch( { - path: '/create-block-theme/v1/create-blank', - method: 'POST', - data: theme, - headers: { - 'Content-Type': 'application/json', - }, - } ) + createBlankTheme( theme ) .then( () => { // eslint-disable-next-line no-alert - alert( + window.alert( __( 'Theme created successfully. The editor will now reload.', 'create-block-theme' @@ -85,17 +82,10 @@ export const CreateThemePanel = ( { createType } ) => { }; const handleCloneClick = () => { - apiFetch( { - path: '/create-block-theme/v1/clone', - method: 'POST', - data: theme, - headers: { - 'Content-Type': 'application/json', - }, - } ) + createClonedTheme( theme ) .then( () => { // eslint-disable-next-line no-alert - alert( + window.alert( __( 'Theme cloned successfully. The editor will now reload.', 'create-block-theme' @@ -115,17 +105,10 @@ export const CreateThemePanel = ( { createType } ) => { }; const handleCreateChildClick = () => { - apiFetch( { - path: '/create-block-theme/v1/create-child', - method: 'POST', - data: theme, - headers: { - 'Content-Type': 'application/json', - }, - } ) + createChildTheme( theme ) .then( () => { // eslint-disable-next-line no-alert - alert( + window.alert( __( 'Child theme created successfully. The editor will now reload.', 'create-block-theme' diff --git a/src/editor-sidebar/create-variation-panel.js b/src/editor-sidebar/create-variation-panel.js index 083a875e..6a26481a 100644 --- a/src/editor-sidebar/create-variation-panel.js +++ b/src/editor-sidebar/create-variation-panel.js @@ -33,7 +33,7 @@ export const CreateVariationPanel = () => { postCreateThemeVariation( theme.name ) .then( () => { // eslint-disable-next-line no-alert - alert( + window.alert( __( 'Theme variation created successfully. The editor will now reload.', 'create-block-theme' diff --git a/src/editor-sidebar/metadata-editor-modal.js b/src/editor-sidebar/metadata-editor-modal.js index 524573bc..f42c2f95 100644 --- a/src/editor-sidebar/metadata-editor-modal.js +++ b/src/editor-sidebar/metadata-editor-modal.js @@ -80,7 +80,7 @@ export const ThemeMetadataEditorModal = ( { onRequestClose } ) => { postUpdateThemeMetadata( theme ) .then( () => { // eslint-disable-next-line no-alert - alert( + window.alert( __( 'Theme updated successfully. The editor will now reload.', 'create-block-theme' diff --git a/src/editor-sidebar/save-panel.js b/src/editor-sidebar/save-panel.js index 438a3652..116d04a9 100644 --- a/src/editor-sidebar/save-panel.js +++ b/src/editor-sidebar/save-panel.js @@ -62,7 +62,7 @@ export const SaveThemePanel = () => { } ) .then( () => { // eslint-disable-next-line no-alert - alert( + window.alert( __( 'Theme saved successfully. The editor will now reload.', 'create-block-theme' diff --git a/src/landing-page/create-modal.js b/src/landing-page/create-modal.js new file mode 100644 index 00000000..0688430d --- /dev/null +++ b/src/landing-page/create-modal.js @@ -0,0 +1,165 @@ +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; +import { useState } from '@wordpress/element'; +import { + // eslint-disable-next-line @wordpress/no-unsafe-wp-apis + __experimentalHStack as HStack, + // eslint-disable-next-line @wordpress/no-unsafe-wp-apis + __experimentalVStack as VStack, + // eslint-disable-next-line @wordpress/no-unsafe-wp-apis + __experimentalText as Text, + Modal, + Button, + TextControl, + TextareaControl, +} from '@wordpress/components'; + +/** + * Internal dependencies + */ +import { + createBlankTheme, + createClonedTheme, + createChildTheme, +} from '../resolvers'; + +export const CreateThemeModal = ( { onRequestClose, creationType } ) => { + const [ errorMessage, setErrorMessage ] = useState( null ); + + const [ theme, setTheme ] = useState( { + name: '', + description: '', + author: '', + } ); + + const renderCreateButtonText = ( type ) => { + switch ( type ) { + case 'blank': + return __( + 'Create and Activate Blank Theme', + 'create-block-theme' + ); + case 'clone': + return __( 'Clone Block Theme', 'create-block-theme' ); + case 'child': + return __( 'Create Child Theme', 'create-block-theme' ); + } + }; + + const createBlockTheme = async () => { + let constructionFunction = null; + switch ( creationType ) { + case 'blank': + constructionFunction = createBlankTheme; + break; + case 'clone': + constructionFunction = createClonedTheme; + break; + case 'child': + constructionFunction = createChildTheme; + break; + } + + if ( ! constructionFunction ) { + return; + } + constructionFunction( theme ) + .then( () => { + // eslint-disable-next-line no-alert + window.alert( + __( + 'Theme created successfully. The editor will now load.', + 'create-block-theme' + ) + ); + window.location = '/wp-admin/site-editor.php?canvas=edit'; + } ) + .catch( ( error ) => { + setErrorMessage( + error.message || + __( + 'An error occurred while attempting to create the theme.', + 'create-block-theme' + ) + ); + } ); + }; + + if ( errorMessage ) { + return ( + +

    { errorMessage }

    +
    + ); + } + + return ( + + + + { __( + "Let's get started creating a new Block Theme.", + 'create-block-theme' + ) } + + + setTheme( { ...theme, name: value } ) + } + /> + + + { __( + '(Tip: You can edit all of this and more in the Editor later.)', + 'create-block-theme' + ) } + + + setTheme( { ...theme, description: value } ) + } + placeholder={ __( + 'A short description of the theme', + 'create-block-theme' + ) } + /> + + setTheme( { ...theme, author: value } ) + } + placeholder={ __( + 'the WordPress team', + 'create-block-theme' + ) } + /> + + + + + + ); +}; diff --git a/src/landing-page/landing-page.js b/src/landing-page/landing-page.js new file mode 100644 index 00000000..1d4682bc --- /dev/null +++ b/src/landing-page/landing-page.js @@ -0,0 +1,290 @@ +/** + * WordPress dependencies + */ +import { sprintf, __ } from '@wordpress/i18n'; +import { useState, createInterpolateElement } from '@wordpress/element'; +import { store as coreStore } from '@wordpress/core-data'; +import { useSelect } from '@wordpress/data'; +import { + Button, + ExternalLink, + // eslint-disable-next-line @wordpress/no-unsafe-wp-apis + __experimentalVStack as VStack, + // eslint-disable-next-line @wordpress/no-unsafe-wp-apis + __experimentalHStack as HStack, +} from '@wordpress/components'; + +/** + * Internal dependencies + */ +import { downloadExportedTheme } from '../resolvers'; +import { downloadFile } from '../utils'; +import { CreateThemeModal } from './create-modal'; + +export default function LandingPage() { + const [ createModalType, setCreateModalType ] = useState( false ); + + const themeName = useSelect( ( select ) => + select( coreStore ).getCurrentTheme() + )?.name?.raw; + + const handleExportClick = async () => { + const response = await downloadExportedTheme(); + downloadFile( response ); + }; + + return ( +
    + { createModalType && ( + setCreateModalType( false ) } + /> + ) } + +

    + { +

    + + + +

    + { __( + 'What would you like to do?', + 'create-block-theme' + ) } +

    +

    + { createInterpolateElement( + __( + 'You can do everything from within the Editor but here are a few things you can do to get started.', + 'create-block-theme' + ), + { + a: ( + // eslint-disable-next-line jsx-a11y/anchor-has-content + + ), + } + ) } +

    + +

    + { __( + 'Export a zip file ready to be imported into another WordPress environment.', + 'create-block-theme' + ) } +

    + +

    + { __( + 'Start from scratch! Create a blank theme to get started with your own design ideas.', + 'create-block-theme' + ) } +

    + +

    + { __( + 'Use the currently activated theme as a starting point.', + 'create-block-theme' + ) } +

    + +

    + { __( + 'Make a theme that uses the currently activated theme as a parent.', + 'create-block-theme' + ) } +

    + + +

    { __( 'About the Plugin', 'create-block-theme' ) }

    +

    + { __( + "Create Block Theme is a tool to help you make Block Themes using the WordPress Editor. It does this by adding tools to the Editor to help you create and manage your theme. Themes created with Create Block Theme don't require Create Block Theme to be installed on the site where the theme is used.", + 'create-block-theme' + ) } +

    +

    + { __( 'Do you need some help?', 'create-block-theme' ) } +

    +

    + { createInterpolateElement( + __( + 'Have a question? Ask for some help in the forums.', + 'create-block-theme' + ), + { + ExternalLink: ( + + ), + } + ) } +

    +

    + { createInterpolateElement( + __( + 'Found a bug? Report it on GitHub.', + 'create-block-theme' + ), + { + ExternalLink: ( + + ), + } + ) } +

    +

    + { createInterpolateElement( + __( + 'Want to contribute? Check out the project on GitHub.', + 'create-block-theme' + ), + { + ExternalLink: ( + + ), + } + ) } +

    +
    +

    { __( 'FAQ', 'create-block-theme' ) }

    +
    + + { __( + 'How do I access the features of Create Block Theme from within the editor?', + 'create-block-theme' + ) } + +

    + { __( + 'There is a new panel accessible from the WordPress Editor which you can open by clicking on a new icon to the right of the “Save” button, at the top of the Editor.', + 'create-block-theme' + ) } +

    + { +
    +
    + + { __( + 'How do I save the customizations I made with the Editor to the Theme?', + 'create-block-theme' + ) } + +

    + { __( + 'In the Create Block Theme Panel click "Save Changes to Theme". You will be presented with a number of options of which things you want to be saved to your theme. Make your choices and then click "Save Changes".', + 'create-block-theme' + ) } +

    + { +
    +
    + + { __( + 'How do I install and remove fonts?', + 'create-block-theme' + ) } + +

    + { __( + 'First Install and activate a font from any source using the WordPress Font Library. Then, using the Create Block Theme Panel select “Save Changes To Theme” and select “Save Fonts” before saving the theme. All of the active fonts will be activated in the theme and deactivated in the system (and may be safely deleted from the system). Any fonts that are installed in the theme that have been deactivated with the WordPress Font Library will be removed from the theme.', + 'create-block-theme' + ) } +

    + { +
    +
    +
    + +
    + ); +} diff --git a/src/resolvers.js b/src/resolvers.js index 3176f8a9..65f725ab 100644 --- a/src/resolvers.js +++ b/src/resolvers.js @@ -4,17 +4,13 @@ import apiFetch from '@wordpress/api-fetch'; export async function fetchThemeJson() { - const fetchOptions = { + return apiFetch( { path: '/create-block-theme/v1/get-theme-data', method: 'GET', headers: { 'Content-Type': 'application/json', }, - }; - - try { - const response = await apiFetch( fetchOptions ); - + } ).then( ( response ) => { if ( ! response?.data || 'SUCCESS' !== response?.status ) { throw new Error( `Failed to fetch theme data: ${ @@ -22,24 +18,78 @@ export async function fetchThemeJson() { }` ); } - return JSON.stringify( response?.data, null, 2 ); - } catch ( e ) { - // @todo: handle error - } + } ); +} + +export async function createBlankTheme( theme ) { + return apiFetch( { + path: '/create-block-theme/v1/create-blank', + method: 'POST', + data: theme, + headers: { + 'Content-Type': 'application/json', + }, + } ).then( ( response ) => { + if ( 'SUCCESS' !== response?.status ) { + throw new Error( + `Failed to create blank theme: ${ + response?.message || response?.status + }` + ); + } + return response; + } ); +} + +export async function createClonedTheme( theme ) { + return apiFetch( { + path: '/create-block-theme/v1/clone', + method: 'POST', + data: theme, + headers: { + 'Content-Type': 'application/json', + }, + } ).then( ( response ) => { + if ( 'SUCCESS' !== response?.status ) { + throw new Error( + `Failed to clone theme: ${ + response?.message || response?.status + }` + ); + } + return response; + } ); +} + +export async function createChildTheme( theme ) { + return apiFetch( { + path: '/create-block-theme/v1/create-child', + method: 'POST', + data: theme, + headers: { + 'Content-Type': 'application/json', + }, + } ).then( ( response ) => { + if ( 'SUCCESS' !== response?.status ) { + throw new Error( + `Failed to create child theme: ${ + response?.message || response?.status + }` + ); + } + return response; + } ); } export async function fetchReadmeData() { - const fetchOptions = { + return apiFetch( { path: '/create-block-theme/v1/get-readme-data', method: 'GET', headers: { 'Content-Type': 'application/json', }, - }; - - try { - const response = await apiFetch( fetchOptions ); + } ).then( ( response ) => { if ( ! response?.data || 'SUCCESS' !== response?.status ) { throw new Error( `Failed to fetch readme data: ${ @@ -48,9 +98,7 @@ export async function fetchReadmeData() { ); } return response?.data; - } catch ( e ) { - // @todo: handle error - } + } ); } export async function postCreateThemeVariation( name ) { diff --git a/src/wp-org-theme-directory.js b/src/wp-org-theme-directory.js deleted file mode 100644 index 8d350c6f..00000000 --- a/src/wp-org-theme-directory.js +++ /dev/null @@ -1,20 +0,0 @@ -/** - * WordPress dependencies - */ -import apiFetch from '@wordpress/api-fetch'; - -async function loadUnavailableThemeNames() { - const requestOptions = { - path: '/create-block-theme/v1/wp-org-theme-names', - }; - - try { - const request = await apiFetch( requestOptions ); - window.wpOrgThemeDirectory.themeSlugs = request.names; - } catch ( error ) { - // eslint-disable-next-line no-console - console.error( error ); - } -} - -window.addEventListener( 'load', loadUnavailableThemeNames );