commit 3e7bc6e67b40a981b8de5d17699b1f581a9ce02d Author: Ryan McCue Date: Thu Jun 5 11:48:47 2025 +0200 Initial export of the repository Signed-off-by: Ryan McCue diff --git a/.build-script b/.build-script new file mode 100755 index 0000000..9726f6d --- /dev/null +++ b/.build-script @@ -0,0 +1,4 @@ +#!/bin/bash -e + +# Install composer dependencies +composer install --no-dev --prefer-dist --optimize-autoloader --apcu-autoloader diff --git a/.config/constants.php b/.config/constants.php new file mode 100644 index 0000000..d8b803f --- /dev/null +++ b/.config/constants.php @@ -0,0 +1,8 @@ + REDIS_HOST, + 'port' => REDIS_PORT, +]; diff --git a/.config/load.php b/.config/load.php new file mode 100644 index 0000000..0279886 --- /dev/null +++ b/.config/load.php @@ -0,0 +1,7 @@ + /dev/null && pwd ) + +# Set up variables +BUILD_DIR="/tmp/fairserver-build" +CONTAINER_NAME="fair-builder" + +# Clean up any existing build directory +rm -rf "$BUILD_DIR" + +# Make a clean copy of the repo, using rsync +echo "Syncing to $BUILD_DIR…" >&2 +rsync \ + -a \ + --progress \ + --exclude='.git' \ + --exclude-from='.distignore' \ + "$SCRIPT_DIR/.." "$BUILD_DIR" + +# Run the build script inside a composer container +echo "Running build script…" >&2 +docker run \ + --rm \ + --name "$CONTAINER_NAME" \ + -v "$BUILD_DIR:/app" \ + -w /app \ + composer:latest \ + bash -c "./.build-script" + +echo "Building image…" >&2 +docker build \ + --tag ghcr.io/fairpm/server:latest \ + --build-context src="$BUILD_DIR" \ + "$SCRIPT_DIR/container" + +echo "Pushing to GitHub Container Registry…" >&2 +docker push ghcr.io/fairpm/server:latest diff --git a/bin/container/Dockerfile b/bin/container/Dockerfile new file mode 100644 index 0000000..0091ea9 --- /dev/null +++ b/bin/container/Dockerfile @@ -0,0 +1,56 @@ +ARG ALPINE_VERSION=3.21 +ARG SRC_DIR +FROM alpine:${ALPINE_VERSION} + +# Setup document root +WORKDIR /app + +# Install packages and remove default server definition +RUN apk add --no-cache \ + curl \ + php83 \ + php83-ctype \ + php83-curl \ + php83-dom \ + php83-fileinfo \ + php83-fpm \ + php83-gd \ + php83-intl \ + php83-mbstring \ + php83-mysqli \ + php83-opcache \ + php83-openssl \ + php83-phar \ + php83-session \ + php83-tokenizer \ + php83-xml \ + php83-xmlreader \ + php83-xmlwriter \ + supervisor + +# RUN ln -s /usr/bin/php83 /usr/bin/php +RUN ln -s /usr/sbin/php-fpm83 /usr/sbin/php-fpm + +# Configure PHP-FPM +ENV PHP_INI_DIR=/etc/php83 +COPY fpm-pool.conf ${PHP_INI_DIR}/php-fpm.d/www.conf +COPY php.ini ${PHP_INI_DIR}/conf.d/custom.ini + +# Make sure files/folders needed by the processes are accessible when they run under the nobody user +RUN chown -R nobody:nobody /app /run + +# Switch to use a non-root user from here on +USER nobody + +# Add application +COPY --chown=nobody --from=src . /app/ + +# Expose the port nginx is reachable on +EXPOSE 9000 + +# Let supervisord start nginx & php-fpm +# CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"] +CMD ["php-fpm", "-F"] + +# Configure a healthcheck to validate that everything is up&running +# HEALTHCHECK --timeout=10s CMD curl --silent --fail http://127.0.0.1:8080/fpm-ping || exit 1 diff --git a/bin/deploy.sh b/bin/deploy.sh new file mode 100755 index 0000000..70377c1 --- /dev/null +++ b/bin/deploy.sh @@ -0,0 +1,43 @@ +#!/bin/bash + +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +cd "$SCRIPT_DIR/.." + +# If rsync is not installed, install it +if ! command -v rsync &> /dev/null; then + echo "Installing rsync" + apt update + apt install -y rsync +fi + +# Check if DEPLOY_USER, DEPLOY_HOST, and DEPLOY_PASS are set +if [[ -z "$DEPLOY_USER" || -z "$DEPLOY_HOST" || -z "$DEPLOY_PASS" ]]; then + echo "Error: DEPLOY_USER, DEPLOY_HOST, and DEPLOY_PASS must be set." + exit 1 +fi + +# Force SSH to pull our password from the env var. +export SSH_ASKPASS='./bin/sshpass.sh' +export SSH_ASKPASS_REQUIRE='force' + +# Check if --apply is passed as an argument +if [[ "$1" == "--apply" ]]; then + DRY_RUN="" +else + DRY_RUN="--dry-run" +fi + +pwd +echo -n "Starting sync" +if [ -n "$DRY_RUN" ]; then + echo " (dry run)" +else + echo " (APPLYING)" +fi +rsync \ + -e "ssh -o StrictHostKeyChecking=no" \ + -avz \ + --progress \ + --delete $DRY_RUN \ + --exclude-from='.distignore' \ + ./content/ $DEPLOY_USER@$DEPLOY_HOST:html/wp-content/ diff --git a/bin/import-gp.sh b/bin/import-gp.sh new file mode 100644 index 0000000..9fd3807 --- /dev/null +++ b/bin/import-gp.sh @@ -0,0 +1,45 @@ +#!/bin/bash +set -eo pipefail + +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +cd "$SCRIPT_DIR/.." + +SLUG="$1" +if [ -z "$SLUG" ]; then + echo "Usage: $0 " + exit 1 +fi + +PROJECT_DIR="./gp-data/translations/$SLUG" + +if [ ! -d "$PROJECT_DIR" ]; then + echo "Project directory not found: $PROJECT_DIR" + exit 1 +fi + +# Import originals first. +echo "Importing originals (from en-gb)" >&2 +if [ ! -f "$PROJECT_DIR/en-gb/default.po" ]; then + echo "Originals file not found: $PROJECT_DIR/en-gb/default.po" + exit 1 +fi +wp $WP_ARGS glotpress import-originals "$SLUG" "$PROJECT_DIR/en-gb/default.po" + +for dir in "$PROJECT_DIR"/*; do + if [ ! -d "$dir" ]; then + continue + fi + + locale=$(basename "$dir") + echo "Importing translations for $locale" >&2 + for file in "$dir"/*.po; do + if [ ! -f "$file" ]; then + continue + fi + + set="$(basename "$file" .po)" + echo " Importing $set" >&2 + wp $WP_ARGS fair-translate translation-set ensure "$SLUG" "$locale" --set="$set" + wp $WP_ARGS glotpress translation-set import "$SLUG" "$locale" "$file" --set="$set" + done +done diff --git a/bin/pull.sh b/bin/pull.sh new file mode 100755 index 0000000..5fc720a --- /dev/null +++ b/bin/pull.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +cd $SCRIPT_DIR/.. + +# Force SSH to pull our password from the env var. +export SSH_ASKPASS='./bin/sshpass.sh' +export SSH_ASKPASS_REQUIRE='force' + +# same as -rlptgoD +# -r = recursive +OPTS='-r' +# -L = follow links +OPTS+=' -L' +# preserve permissions, group, owner +OPTS+=' -pgo' +# -t = preserve modification times +OPTS+=' -t' + +rsync \ + -vz \ + --exclude-from='.distignore' \ + $OPTS \ + $DEPLOY_USER@$DEPLOY_HOST:html/wp-content/ ./content/ diff --git a/bin/sshpass.sh b/bin/sshpass.sh new file mode 100755 index 0000000..cb40781 --- /dev/null +++ b/bin/sshpass.sh @@ -0,0 +1,2 @@ +#!/bin/bash +echo "$DEPLOY_PASS" diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..a51a72b --- /dev/null +++ b/composer.json @@ -0,0 +1,33 @@ +{ + "name": "openwebff/server", + "type": "project", + "repositories": [ + { + "type": "vcs", + "url": "https://github.com/GlotPress/GlotPress" + } + ], + "require": { + "composer/installers": "~2", + "humanmade/php-basic-auth": "^1.1", + "glotpress/glotpress-wp": "^4.0.1", + "johnbillion/query-monitor": "^3.17", + "johnpbloch/wordpress": "^6.8", + "pantheon-systems/wp-redis": "^1.4", + "humanmade/wp-redis-predis-client": "^0.1.2", + "afragen/git-updater": "dev-fair@dev" + }, + "extra": { + "installer-paths": { + "content/plugins/{$name}/": ["type:wordpress-plugin"], + "content/mu-plugins/{$name}/": ["type:wordpress-muplugin"], + "content/themes/{$name}/": ["type:wordpress-theme"] + } + }, + "config": { + "allow-plugins": { + "composer/installers": true, + "johnpbloch/wordpress-core-installer": true + } + } +} diff --git a/composer.lock b/composer.lock new file mode 100644 index 0000000..65f633a --- /dev/null +++ b/composer.lock @@ -0,0 +1,873 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "e75f9347be4ba8ada58a7950ad4fb199", + "packages": [ + { + "name": "afragen/git-updater", + "version": "dev-fair", + "source": { + "type": "git", + "url": "https://github.com/afragen/git-updater.git", + "reference": "fae366b4a6f1b6a7a300b2fdfd5d40100c8863be" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/afragen/git-updater/zipball/fae366b4a6f1b6a7a300b2fdfd5d40100c8863be", + "reference": "fae366b4a6f1b6a7a300b2fdfd5d40100c8863be", + "shasum": "" + }, + "require": { + "afragen/singleton": "^1.0", + "afragen/wordpress-plugin-readme-parser": "^1", + "afragen/wp-dismiss-notice": "*", + "php": ">=8.0" + }, + "require-dev": { + "wp-coding-standards/wpcs": "^3.0.0" + }, + "type": "wordpress-plugin", + "autoload": { + "psr-4": { + "Fragen\\Git_Updater\\": "src/Git_Updater/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Andy Fragen", + "email": "andy@thefragens.com", + "homepage": "https://thefragens.com", + "role": "Developer" + } + ], + "description": "A plugin to automatically update GitHub, Bitbucket, GitLab, or Gitea hosted plugins, themes, and language packs.", + "keywords": [ + "plugin", + "theme", + "updater", + "wordpress" + ], + "support": { + "issues": "https://github.com/afragen/git-updater/issues", + "source": "https://github.com/afragen/git-updater" + }, + "funding": [ + { + "url": "https://github.com/afragen", + "type": "github" + } + ], + "time": "2025-06-03T15:27:28+00:00" + }, + { + "name": "afragen/singleton", + "version": "1.0.5", + "source": { + "type": "git", + "url": "https://github.com/afragen/singleton.git", + "reference": "c93d90651dcf027bcd365d81bccf1eda73fe2f2d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/afragen/singleton/zipball/c93d90651dcf027bcd365d81bccf1eda73fe2f2d", + "reference": "c93d90651dcf027bcd365d81bccf1eda73fe2f2d", + "shasum": "" + }, + "require": { + "php": ">=5.6.5" + }, + "type": "library", + "autoload": { + "classmap": [ + "Singleton.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Andy Fragen", + "email": "andy@thefragens.com", + "homepage": "https://github.com/afragen/singleton", + "role": "Developer" + } + ], + "description": "A singleton static proxy generator.", + "keywords": [ + "singleton", + "wordpress" + ], + "support": { + "issues": "https://github.com/afragen/singleton/issues", + "source": "https://github.com/afragen/singleton/tree/1.0.5" + }, + "time": "2024-11-19T17:40:31+00:00" + }, + { + "name": "afragen/wordpress-plugin-readme-parser", + "version": "1.2024.12.10", + "source": { + "type": "git", + "url": "https://github.com/afragen/wordpress-plugin-readme-parser.git", + "reference": "803ccfc442d956aa04d69f4b234eda5d7f03afc4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/afragen/wordpress-plugin-readme-parser/zipball/803ccfc442d956aa04d69f4b234eda5d7f03afc4", + "reference": "803ccfc442d956aa04d69f4b234eda5d7f03afc4", + "shasum": "" + }, + "require": { + "erusev/parsedown": "^1.7", + "php": ">=5.4" + }, + "type": "library", + "autoload": { + "classmap": [ + "class-parser.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "WordPress.org", + "homepage": "https://meta.trac.wordpress.org/browser/sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/readme" + } + ], + "description": "A clone of the current WordPress.org Plugin Readme Parser, class-parser.php", + "keywords": [ + "parser", + "readme", + "wordpress" + ], + "support": { + "issues": "https://github.com/afragen/wordpress-plugin-readme-parser/issues", + "source": "https://github.com/afragen/wordpress-plugin-readme-parser/tree/1.2024.12.10" + }, + "time": "2024-12-10T23:43:17+00:00" + }, + { + "name": "afragen/wp-dismiss-notice", + "version": "0.3.7", + "source": { + "type": "git", + "url": "https://github.com/afragen/wp-dismiss-notice.git", + "reference": "3e2c694ca891fe94771457f54a3a5457a70c0aec" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/afragen/wp-dismiss-notice/zipball/3e2c694ca891fe94771457f54a3a5457a70c0aec", + "reference": "3e2c694ca891fe94771457f54a3a5457a70c0aec", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "type": "library", + "autoload": { + "classmap": [ + "wp-dismiss-notice.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Andy Fragen", + "email": "andy@thefragens.com", + "homepage": "https://thefragens.com", + "role": "Developer" + } + ], + "description": "Library for time dismissible WordPress admin notices.", + "support": { + "issues": "https://github.com/afragen/wp-dismiss-notice/issues", + "source": "https://github.com/afragen/wp-dismiss-notice" + }, + "time": "2023-05-30T21:45:15+00:00" + }, + { + "name": "composer/installers", + "version": "v2.3.0", + "source": { + "type": "git", + "url": "https://github.com/composer/installers.git", + "reference": "12fb2dfe5e16183de69e784a7b84046c43d97e8e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/installers/zipball/12fb2dfe5e16183de69e784a7b84046c43d97e8e", + "reference": "12fb2dfe5e16183de69e784a7b84046c43d97e8e", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.0 || ^2.0", + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "composer/composer": "^1.10.27 || ^2.7", + "composer/semver": "^1.7.2 || ^3.4.0", + "phpstan/phpstan": "^1.11", + "phpstan/phpstan-phpunit": "^1", + "symfony/phpunit-bridge": "^7.1.1", + "symfony/process": "^5 || ^6 || ^7" + }, + "type": "composer-plugin", + "extra": { + "class": "Composer\\Installers\\Plugin", + "branch-alias": { + "dev-main": "2.x-dev" + }, + "plugin-modifies-install-path": true + }, + "autoload": { + "psr-4": { + "Composer\\Installers\\": "src/Composer/Installers" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Kyle Robinson Young", + "email": "kyle@dontkry.com", + "homepage": "https://github.com/shama" + } + ], + "description": "A multi-framework Composer library installer", + "homepage": "https://composer.github.io/installers/", + "keywords": [ + "Dolibarr", + "Eliasis", + "Hurad", + "ImageCMS", + "Kanboard", + "Lan Management System", + "MODX Evo", + "MantisBT", + "Mautic", + "Maya", + "OXID", + "Plentymarkets", + "Porto", + "RadPHP", + "SMF", + "Starbug", + "Thelia", + "Whmcs", + "WolfCMS", + "agl", + "annotatecms", + "attogram", + "bitrix", + "cakephp", + "chef", + "cockpit", + "codeigniter", + "concrete5", + "concreteCMS", + "croogo", + "dokuwiki", + "drupal", + "eZ Platform", + "elgg", + "expressionengine", + "fuelphp", + "grav", + "installer", + "itop", + "known", + "kohana", + "laravel", + "lavalite", + "lithium", + "magento", + "majima", + "mako", + "matomo", + "mediawiki", + "miaoxing", + "modulework", + "modx", + "moodle", + "osclass", + "pantheon", + "phpbb", + "piwik", + "ppi", + "processwire", + "puppet", + "pxcms", + "reindex", + "roundcube", + "shopware", + "silverstripe", + "sydes", + "sylius", + "tastyigniter", + "wordpress", + "yawik", + "zend", + "zikula" + ], + "support": { + "issues": "https://github.com/composer/installers/issues", + "source": "https://github.com/composer/installers/tree/v2.3.0" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2024-06-24T20:46:46+00:00" + }, + { + "name": "erusev/parsedown", + "version": "1.7.4", + "source": { + "type": "git", + "url": "https://github.com/erusev/parsedown.git", + "reference": "cb17b6477dfff935958ba01325f2e8a2bfa6dab3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/erusev/parsedown/zipball/cb17b6477dfff935958ba01325f2e8a2bfa6dab3", + "reference": "cb17b6477dfff935958ba01325f2e8a2bfa6dab3", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35" + }, + "type": "library", + "autoload": { + "psr-0": { + "Parsedown": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Emanuil Rusev", + "email": "hello@erusev.com", + "homepage": "http://erusev.com" + } + ], + "description": "Parser for Markdown.", + "homepage": "http://parsedown.org", + "keywords": [ + "markdown", + "parser" + ], + "support": { + "issues": "https://github.com/erusev/parsedown/issues", + "source": "https://github.com/erusev/parsedown/tree/1.7.x" + }, + "time": "2019-12-30T22:54:17+00:00" + }, + { + "name": "glotpress/glotpress-wp", + "version": "4.0.1", + "source": { + "type": "git", + "url": "https://github.com/GlotPress/GlotPress.git", + "reference": "84cfcee8fec4de400469c901185fe1d65f7af797" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/GlotPress/GlotPress/zipball/84cfcee8fec4de400469c901185fe1d65f7af797", + "reference": "84cfcee8fec4de400469c901185fe1d65f7af797", + "shasum": "" + }, + "require": { + "php": ">=7.4" + }, + "require-dev": { + "dealerdirect/phpcodesniffer-composer-installer": "^1.0.0", + "gettext/languages": "^2.6", + "phpcompatibility/phpcompatibility-wp": "^2.1", + "phpunit/phpunit": "^9.6.15", + "wp-coding-standards/wpcs": "^2.2", + "yoast/phpunit-polyfills": "^2.0" + }, + "type": "wordpress-plugin", + "scripts": { + "format": [ + "@php ./vendor/bin/phpcbf --report=summary,source" + ], + "lint": [ + "@php ./vendor/bin/phpcs --report=summary,source" + ], + "test": [ + "@php ./vendor/bin/phpunit" + ], + "test:locales": [ + "@test --group locales" + ] + }, + "license": [ + "GPL-2.0-or-later" + ], + "description": "GlotPress is a collaborative, web-based software translation tool.", + "homepage": "https://glotpress.blog/", + "keywords": [ + "i18n", + "translations", + "wordpress" + ], + "support": { + "issues": "https://github.com/GlotPress/GlotPress/issues", + "forum": "https://wordpress.org/support/plugin/glotpress/", + "source": "https://github.com/GlotPress/GlotPress", + "docs": "https://glotpress.blog/the-manual/" + }, + "time": "2024-04-03T14:29:59+00:00" + }, + { + "name": "humanmade/php-basic-auth", + "version": "1.1.1", + "source": { + "type": "git", + "url": "https://github.com/humanmade/PHPBasicAuth.git", + "reference": "83e598d79df68054dc7b90cb171faaf95b601883" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/humanmade/PHPBasicAuth/zipball/83e598d79df68054dc7b90cb171faaf95b601883", + "reference": "83e598d79df68054dc7b90cb171faaf95b601883", + "shasum": "" + }, + "require-dev": { + "humanmade/coding-standards": "^0.7.0", + "phpunit/phpunit": "^7.5" + }, + "type": "wordpress-muplugin", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-3.0-or-later" + ], + "authors": [ + { + "name": "Chris Reynolds", + "email": "chris@humanmade.com" + } + ], + "description": "Basic PHP authentication for HM Dev and Staging environments.", + "homepage": "https://github.com/humanmade/PHPBasicAuth", + "support": { + "issues": "https://github.com/humanmade/PHPBasicAuth/issues", + "source": "https://github.com/humanmade/PHPBasicAuth/tree/1.1.1" + }, + "time": "2020-01-10T21:55:59+00:00" + }, + { + "name": "humanmade/wp-redis-predis-client", + "version": "0.1.2", + "source": { + "type": "git", + "url": "https://github.com/humanmade/wp-redis-predis-client.git", + "reference": "4fef0721054a756f3f2300c2227f565acea391bd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/humanmade/wp-redis-predis-client/zipball/4fef0721054a756f3f2300c2227f565acea391bd", + "reference": "4fef0721054a756f3f2300c2227f565acea391bd", + "shasum": "" + }, + "require": { + "predis/predis": "~1.1" + }, + "require-dev": { + "phpunit/phpunit": "^7.1.4" + }, + "type": "library", + "autoload": { + "files": [ + "functions.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "support": { + "issues": "https://github.com/humanmade/wp-redis-predis-client/issues", + "source": "https://github.com/humanmade/wp-redis-predis-client/tree/0.1.2" + }, + "time": "2025-01-24T17:01:53+00:00" + }, + { + "name": "johnbillion/query-monitor", + "version": "3.17.2", + "source": { + "type": "git", + "url": "https://github.com/johnbillion/query-monitor.git", + "reference": "e35dbc8ac937178d214c04552a0a802dacf6c79b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/johnbillion/query-monitor/zipball/e35dbc8ac937178d214c04552a0a802dacf6c79b", + "reference": "e35dbc8ac937178d214c04552a0a802dacf6c79b", + "shasum": "" + }, + "require": { + "composer/installers": "^1.0 || ^2.0", + "php": ">=7.4.0" + }, + "require-dev": { + "codeception/module-asserts": "^1.0", + "codeception/module-db": "^1.0", + "codeception/module-webdriver": "^1.0", + "codeception/util-universalframework": "^1.0", + "dealerdirect/phpcodesniffer-composer-installer": "0.7.2", + "johnbillion/plugin-infrastructure": "dev-trunk", + "johnbillion/wp-compat": "0.3.1", + "lucatume/wp-browser": "3.2.3", + "phpcompatibility/phpcompatibility-wp": "2.1.5", + "phpstan/phpstan": "1.12.11", + "phpstan/phpstan-deprecation-rules": "1.2.1", + "phpstan/phpstan-phpunit": "1.4.1", + "roots/wordpress-core-installer": "1.100.0", + "roots/wordpress-full": "*", + "squizlabs/php_codesniffer": "3.11.1", + "szepeviktor/phpstan-wordpress": "1.3.5", + "wp-coding-standards/wpcs": "2.3.0" + }, + "type": "wordpress-plugin", + "extra": { + "wordpress-install-dir": "vendor/wordpress/wordpress" + }, + "autoload": { + "classmap": [ + "classes", + "data", + "output" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-2.0-or-later" + ], + "authors": [ + { + "name": "John Blackbourn", + "homepage": "https://johnblackbourn.com/" + } + ], + "description": "The Developer Tools panel for WordPress.", + "homepage": "https://querymonitor.com/", + "support": { + "forum": "https://wordpress.org/support/plugin/query-monitor", + "issues": "https://github.com/johnbillion/query-monitor/issues", + "security": "https://patchstack.com/database/vdp/query-monitor", + "source": "https://github.com/johnbillion/query-monitor" + }, + "funding": [ + { + "url": "https://github.com/sponsors/johnbillion", + "type": "github" + } + ], + "time": "2025-02-04T22:13:08+00:00" + }, + { + "name": "johnpbloch/wordpress", + "version": "6.8.1", + "source": { + "type": "git", + "url": "https://github.com/johnpbloch/wordpress.git", + "reference": "1932f5ab26a420151c689a9c00505c70c4f91ab3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/johnpbloch/wordpress/zipball/1932f5ab26a420151c689a9c00505c70c4f91ab3", + "reference": "1932f5ab26a420151c689a9c00505c70c4f91ab3", + "shasum": "" + }, + "require": { + "johnpbloch/wordpress-core": "6.8.1", + "johnpbloch/wordpress-core-installer": "^1.0 || ^2.0", + "php": ">=7.0.0" + }, + "type": "package", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-2.0-or-later" + ], + "authors": [ + { + "name": "WordPress Community", + "homepage": "https://wordpress.org/about/" + } + ], + "description": "WordPress is open source software you can use to create a beautiful website, blog, or app.", + "homepage": "https://wordpress.org/", + "keywords": [ + "blog", + "cms", + "wordpress" + ], + "support": { + "docs": "https://developer.wordpress.org/", + "forum": "https://wordpress.org/support/", + "irc": "irc://irc.freenode.net/wordpress", + "issues": "https://core.trac.wordpress.org/", + "source": "https://core.trac.wordpress.org/browser" + }, + "time": "2025-04-30T16:52:55+00:00" + }, + { + "name": "johnpbloch/wordpress-core", + "version": "6.8.1", + "source": { + "type": "git", + "url": "https://github.com/johnpbloch/wordpress-core.git", + "reference": "702c3bda87abb47ae43f90c7b8868cf0b7dff1e2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/johnpbloch/wordpress-core/zipball/702c3bda87abb47ae43f90c7b8868cf0b7dff1e2", + "reference": "702c3bda87abb47ae43f90c7b8868cf0b7dff1e2", + "shasum": "" + }, + "require": { + "ext-json": "*", + "php": ">=7.2.24" + }, + "provide": { + "wordpress/core-implementation": "6.8.1" + }, + "type": "wordpress-core", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-2.0-or-later" + ], + "authors": [ + { + "name": "WordPress Community", + "homepage": "https://wordpress.org/about/" + } + ], + "description": "WordPress is open source software you can use to create a beautiful website, blog, or app.", + "homepage": "https://wordpress.org/", + "keywords": [ + "blog", + "cms", + "wordpress" + ], + "support": { + "forum": "https://wordpress.org/support/", + "irc": "irc://irc.freenode.net/wordpress", + "issues": "https://core.trac.wordpress.org/", + "source": "https://core.trac.wordpress.org/browser", + "wiki": "https://codex.wordpress.org/" + }, + "time": "2025-04-30T16:52:49+00:00" + }, + { + "name": "johnpbloch/wordpress-core-installer", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/johnpbloch/wordpress-core-installer.git", + "reference": "237faae9a60a4a2e1d45dce1a5836ffa616de63e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/johnpbloch/wordpress-core-installer/zipball/237faae9a60a4a2e1d45dce1a5836ffa616de63e", + "reference": "237faae9a60a4a2e1d45dce1a5836ffa616de63e", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.0 || ^2.0", + "php": ">=5.6.0" + }, + "conflict": { + "composer/installers": "<1.0.6" + }, + "require-dev": { + "composer/composer": "^1.0 || ^2.0", + "phpunit/phpunit": ">=5.7.27" + }, + "type": "composer-plugin", + "extra": { + "class": "johnpbloch\\Composer\\WordPressCorePlugin" + }, + "autoload": { + "psr-0": { + "johnpbloch\\Composer\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-2.0-or-later" + ], + "authors": [ + { + "name": "John P. Bloch", + "email": "me@johnpbloch.com" + } + ], + "description": "A custom installer to handle deploying WordPress with composer", + "keywords": [ + "wordpress" + ], + "support": { + "issues": "https://github.com/johnpbloch/wordpress-core-installer/issues", + "source": "https://github.com/johnpbloch/wordpress-core-installer/tree/master" + }, + "time": "2020-04-16T21:44:57+00:00" + }, + { + "name": "pantheon-systems/wp-redis", + "version": "1.4.5", + "source": { + "type": "git", + "url": "https://github.com/pantheon-systems/wp-redis.git", + "reference": "034f87e96fb778c0cea6c0407ecdd41a44661dc9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/pantheon-systems/wp-redis/zipball/034f87e96fb778c0cea6c0407ecdd41a44661dc9", + "reference": "034f87e96fb778c0cea6c0407ecdd41a44661dc9", + "shasum": "" + }, + "require-dev": { + "behat/behat": "^3.1", + "behat/mink-extension": "^2.2", + "behat/mink-goutte-driver": "^1.2", + "pantheon-systems/pantheon-wordpress-upstream-tests": "dev-master", + "pantheon-systems/pantheon-wp-coding-standards": "^2.0", + "pantheon-systems/wpunit-helpers": "^2.0", + "phpunit/phpunit": "^9", + "yoast/phpunit-polyfills": "^3.0" + }, + "type": "wordpress-plugin", + "autoload": { + "psr-4": { + "behat\\features\\bootstrap\\": "tests/behat/features/bootstrap/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-2.0-or-later" + ], + "authors": [ + { + "name": "Pantheon", + "email": "noreply@pantheon.io" + } + ], + "support": { + "issues": "https://github.com/pantheon-systems/wp-redis/issues", + "source": "https://github.com/pantheon-systems/wp-redis/tree/1.4.5" + }, + "time": "2025-01-21T18:55:01+00:00" + }, + { + "name": "predis/predis", + "version": "v1.1.10", + "source": { + "type": "git", + "url": "https://github.com/predis/predis.git", + "reference": "a2fb02d738bedadcffdbb07efa3a5e7bd57f8d6e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/predis/predis/zipball/a2fb02d738bedadcffdbb07efa3a5e7bd57f8d6e", + "reference": "a2fb02d738bedadcffdbb07efa3a5e7bd57f8d6e", + "shasum": "" + }, + "require": { + "php": ">=5.3.9" + }, + "require-dev": { + "phpunit/phpunit": "~4.8" + }, + "suggest": { + "ext-curl": "Allows access to Webdis when paired with phpiredis", + "ext-phpiredis": "Allows faster serialization and deserialization of the Redis protocol" + }, + "type": "library", + "autoload": { + "psr-4": { + "Predis\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Daniele Alessandri", + "email": "suppakilla@gmail.com", + "homepage": "http://clorophilla.net", + "role": "Creator & Maintainer" + }, + { + "name": "Till Krüss", + "homepage": "https://till.im", + "role": "Maintainer" + } + ], + "description": "Flexible and feature-complete Redis client for PHP and HHVM", + "homepage": "http://github.com/predis/predis", + "keywords": [ + "nosql", + "predis", + "redis" + ], + "support": { + "issues": "https://github.com/predis/predis/issues", + "source": "https://github.com/predis/predis/tree/v1.1.10" + }, + "funding": [ + { + "url": "https://github.com/sponsors/tillkruss", + "type": "github" + } + ], + "time": "2022-01-05T17:46:08+00:00" + } + ], + "packages-dev": [], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": { + "afragen/git-updater": 20 + }, + "prefer-stable": false, + "prefer-lowest": false, + "platform": {}, + "platform-dev": {}, + "plugin-api-version": "2.6.0" +} diff --git a/content/mu-plugins/10-autoloader.php b/content/mu-plugins/10-autoloader.php new file mode 100644 index 0000000..eff1ac1 --- /dev/null +++ b/content/mu-plugins/10-autoloader.php @@ -0,0 +1,42 @@ +enabled() ) { + + // Allows locally defined JETPACK_DEV_DEBUG constant to override filter. + if ( ! defined( 'JETPACK_DEV_DEBUG' ) ) { + // Keep jetpack from attempting external requests. + add_filter( 'jetpack_development_mode', '__return_true', 9999 ); + } + + // Prevent BuddyPress from falling back to Gravatar avatars. + add_filter( 'bp_core_fetch_avatar_no_grav', '__return_true' ); + + // Disable automatic updater updates. + add_filter( 'automatic_updater_disabled', '__return_true' ); + + // Tell WordPress we are on a version control system to add additional blocks. + add_filter( 'automatic_updates_is_vcs_checkout', '__return_true' ); + + // Disable translation updates. + add_filter( 'auto_update_translation', '__return_false' ); + + // Disable minor core updates. + add_filter( 'allow_minor_auto_core_updates', '__return_false' ); + + // Disable major core updates. + add_filter( 'allow_major_auto_core_updates', '__return_false' ); + + // Disable dev core updates. + add_filter( 'allow_dev_auto_core_updates', '__return_false' ); + + // Disable overall core updates. + add_filter( 'auto_update_core', '__return_false' ); + add_filter( 'wp_auto_update_core', '__return_false' ); + + // Disable automatic plugin and theme updates (used by WP to force push security fixes). + add_filter( 'auto_update_plugin', '__return_false' ); + add_filter( 'auto_update_theme', '__return_false' ); + + // Disable debug emails (used by core for rollback alerts in automatic update deployment). + add_filter( 'automatic_updates_send_debug_email', '__return_false' ); + + // Disable update emails (for when we push the new WordPress versions manually) as well + // as the notification there is a new version emails. + add_filter( 'auto_core_update_send_email', '__return_false' ); + add_filter( 'send_core_update_notification_email', '__return_false' ); + add_filter( 'automatic_updates_send_debug_email ', '__return_false', 1 ); + + // Get rid of the version number in the footer. + add_filter( 'update_footer', '__return_empty_string', 11 ); + + // Filter out the pre core option. + add_filter( 'pre_option_update_core', '__return_null' ); + + // Remove some actions. + remove_action( 'admin_init', 'wp_plugin_update_rows' ); + remove_action( 'admin_init', 'wp_theme_update_rows' ); + remove_action( 'admin_notices', 'maintenance_nag' ); + remove_action( 'init', 'wp_schedule_update_checks' ); + + // Add back the upload tab. + add_action( 'install_themes_upload', 'install_themes_upload', 10, 0 ); + + // Define core contants for more protection. + if ( ! defined( 'AUTOMATIC_UPDATER_DISABLED' ) ) { + define( 'AUTOMATIC_UPDATER_DISABLED', true ); + } + if ( ! defined( 'WP_AUTO_UPDATE_CORE' ) ) { + define( 'WP_AUTO_UPDATE_CORE', false ); + } + } + } + + /** + * If an instance exists, this returns it. If not, it creates one and + * returns it. + * + * @return $instance + */ + public static function getInstance() { + if ( ! self::$instance ) { + self::$instance = new self; + } + + return self::$instance; + } + + /** + * Load our textdomain for localization. + * + * @return void + */ + public function textdomain() { + load_plugin_textdomain( 'airplane-mode', false, dirname( plugin_basename( __FILE__ ) ) . '/languages/' ); + } + + /** + * Set our initial airplane mode setting to 'on' on activation. + */ + public function create_setting() { + add_site_option( 'airplane-mode', 'on' ); + set_transient( 'wporg_theme_feature_list', array(), 999999999999 ); + } + + /** + * Remove our setting on plugin deactivation. + */ + public function remove_setting() { + delete_option( 'airplane-mode' ); + delete_site_option( 'airplane-mode' ); + delete_transient( 'wporg_theme_feature_list' ); + } + + /** + * Helper function to check the current status. + * + * @return bool True if status is 'on'; false if not. + */ + public function enabled() { + + // Bail if CLI. + if ( defined( 'WP_CLI' ) and WP_CLI ) { + return false; + } + + // Pull our status from the options table. + $option = get_site_option( 'airplane-mode' ); + + // Backup check for regular options table. + if ( false === $option ) { + $option = get_option( 'airplane-mode' ); + } + + // Return the option flag. + return 'on' === $option; + } + + /** + * Check the URL of a stylesheet and remove any that are not on the local URL. + * + * @param string $source The source URL of the CSS sheet. + * + * @return string $source The same URL, or null. + */ + public function block_style_load( $source ) { + + // Bail if disabled. + if ( ! $this->enabled() ) { + return $source; + } + + // Parse the URL being passed to pull out the host. + $parsed = parse_url( $source, PHP_URL_HOST ); + + // First run the filter to allow a source host to get through. + if ( false === apply_filters( 'airplane_mode_parse_style', true, $parsed ) ) { + return $source; + } + + // If we don't share the same URL as the site itself, return null. Otherwise return the URL. + return isset( $parsed ) && false === strpos( home_url(), $parsed ) + ? new Airplane_Mode_WP_Error( 'airplane_mode_enabled', __( 'Airplane Mode blocked style', 'airplane-mode' ), array( + 'return' => '', + 'src' => $source, + ) ) + : $source; + } + + /** + * Check the URL of a JS file and remove any that are not on the local URL. + * + * @param string $source The source URL of the JS file. + * + * @return string $source The same URL, or null. + */ + public function block_script_load( $source ) { + + // Bail if disabled. + if ( ! $this->enabled() ) { + return $source; + } + + // Parse the URL being passed to pull out the host. + $parsed = parse_url( $source, PHP_URL_HOST ); + + // First run the filter to allow a source host to get through. + if ( false === apply_filters( 'airplane_mode_parse_script', true, $parsed ) ) { + return $source; + } + + // If we don't share the same URL as the site itself, return null. Otherwise return the URL. + return isset( $parsed ) && false === strpos( home_url(), $parsed ) + ? new Airplane_Mode_WP_Error( 'airplane_mode_enabled', __( 'Airplane Mode blocked script', 'airplane-mode' ), array( + 'return' => '', + 'src' => $source, + ) ) + : $source; + } + + /** + * Use our existing filter to check for local assets. + * + * @param boolean $block Whether to block the specific asset. Defaults to 'true'. + * @param array $parsed The URL of the asset, parsed. + * + * @return boolean + */ + public function bypass_asset_block( $block, $parsed ) { + + // Create an array of the approved local domains. + $local = apply_filters( 'airplane_mode_local_hosts', array( 'localhost', '127.0.0.1' ) ); + + // If our parsed URL host is in that array, return false. Otherwise, return our blocking choice. + return ! empty( $local ) && in_array( $parsed, $local ) ? false : $block; + } + + /** + * Block oEmbeds from displaying. + * + * @param string $html The embed HTML. + * @param string $url The attempted embed URL. + * @param array $attr An array of shortcode attributes. + * @param int $post_ID Post ID. + * + * @return string + */ + public function block_oembed_html( $html, $url, $attr, $post_ID ) { + return $this->enabled() ? sprintf( '

%s

', sprintf( __( 'Airplane Mode is enabled. oEmbed blocked for %1$s.', 'airplane-mode' ), esc_url( $url ) ) ) : $html; + } + + /** + * Add body class to front-end pages and login based on plugin status. + * + * @param array $classes The existing array of body classes. + * + * @return array $classes The updated array of body classes. + */ + public function body_class( $classes ) { + + // Add the class based on the current status. + $classes[] = $this->enabled() ? 'airplane-mode-enabled' : 'airplane-mode-disabled'; + + // Also add in the margin setup for Query Monitor because I'm a perfectionist. + if ( ! class_exists( 'QueryMonitor' ) || defined( 'QM_DISABLED' ) && QM_DISABLED ) { + $classes[] = 'airplane-mode-no-qm'; + } + + // Return our array of classes. + return $classes; + } + + /** + * Add body class to admin pages based on plugin status. + * + * @param string $classes The existing space-separated list of CSS classes. + * + * @return string $classes The updated space-separated list of CSS classes. + */ + public function admin_body_class( $classes ) { + + // First add the standard set of classes based on status. + $classes .= $this->enabled() ? ' airplane-mode-enabled' : ' airplane-mode-disabled'; + + // Also add in the margin setup for Query Monitor because I'm a perfectionist. + if ( ! class_exists( 'QueryMonitor' ) || defined( 'QM_DISABLED' ) && QM_DISABLED ) { + $classes .= ' airplane-mode-no-qm'; + } + + // Return our string of classes. + return $classes; + } + + /** + * Remove menu items for updates from a standard WP install. + * + * @return null + */ + public function admin_menu_items() { + + // Bail if disabled, or on a multisite. + if ( ! $this->enabled() || is_multisite() ) { + return; + } + + // Remove our items. + remove_submenu_page( 'index.php', 'update-core.php' ); + } + + /** + * Remove menu items for updates from a multisite instance. + * + * @return null + */ + public function ms_admin_menu_items() { + + // Bail if disabled or not on our network admin. + if ( ! $this->enabled() || ! is_network_admin() ) { + return; + } + + // Remove the items. + remove_submenu_page( 'index.php', 'upgrade.php' ); + } + + /** + * Replace all instances of gravatar with a local image file + * to remove the call to remote service. + * + * @param string $avatar Image tag for the user's avatar. + * @param int|object|string $id_or_email A user ID, email address, or comment object. + * @param int $size Square avatar width and height in pixels to retrieve. + * @param string $default URL to a default image to use if no avatar is available. + * @param string $alt Alternative text to use in the avatar image tag. + * + * @return string `` tag for the user's avatar. + */ + public function replace_gravatar( $avatar, $id_or_email, $size, $default, $alt ) { + + // Bail if disabled. + if ( ! $this->enabled() ) { + return $avatar; + } + + // Swap out the file for a base64 encoded image. + $image = 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=='; + $avatar = "{$alt}"; + + // Return the avatar. + return $avatar; + } + + /** + * Remove avatar images from the default avatar list. + * + * @param string $avatar_list List of default avatars. + * + * @return string Updated list with images removed. + */ + public function default_avatar( $avatar_list ) { + + // Bail if disabled. + if ( ! $this->enabled() ) { + return $avatar_list; + } + + // Remove images. + $avatar_list = preg_replace( '|]+)> |i', '', $avatar_list ); + + // Send back the list. + return $avatar_list; + } + + /** + * Disable all the HTTP requests being made with the action + * happening before the status check so others can allow certain + * items as desired. + * + * @param bool|array|WP_Error $status Whether to preempt an HTTP request return. Default false. + * @param array $args HTTP request arguments. + * @param string $url The request URL. + * + * @return bool|array|WP_Error A WP_Error object if Airplane Mode is enabled. Original $status if not. + */ + public function disable_http_reqs( $status = false, $args = array(), $url = '' ) { + + // Pass our data to the action to allow a bypass. + do_action( 'airplane_mode_http_args', $status, $args, $url ); + + if ( ! $this->enabled() ) { + return $status; + } + + $url_host = parse_url( $url, PHP_URL_HOST ); + + // Allow the request to pass through if the URL host matches the site's host. + if ( $url_host && parse_url( home_url(), PHP_URL_HOST ) === $url_host ) { + + // But allow this to be disabled via a filter. + if ( apply_filters( 'airplane_mode_allow_local_bypass', true, $url, $args ) ) { + return $status; + } + } + + // Allow certain HTTP API requests to pass through via a filter. + if ( apply_filters( 'airplane_mode_allow_http_api_request', false, $url, $args, $url_host ) ) { + return $status; + } + + // Disable the http requests if enabled. + return new WP_Error( 'airplane_mode_enabled', __( 'Airplane Mode is enabled', 'airplane-mode' ) ); + } + + /** + * Load our small CSS file for the toggle switch. + */ + public function toggle_css() { + + // Don't display CSS on the front-end if the admin bar is not loading. + if ( ! is_admin() && ! is_admin_bar_showing() ) { + return; + } + + // Set a suffix for loading the minified or normal. + $file = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? 'airplane-mode.css' : 'airplane-mode.min.css'; + + // Set a version for browser caching. + $vers = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? time() : AIRMDE_VER; + + // Load the CSS file itself. + wp_enqueue_style( 'airplane-mode', plugins_url( '/lib/css/' . $file, __FILE__ ), array(), $vers, 'all' ); + } + + /** + * Sets the mode. + * + * @param string $mode Desired mode ('on' or 'off'). + * + * @return bool Whether the setting changed. + */ + public function set_mode( $mode = 'on' ) { + + // Check what mode we're currently in, with "on" as a fallback. + if ( ! in_array( $mode, array( 'on', 'off' ) ) ) { + $mode = 'on'; + } + + // Update the setting. + $return = update_site_option( 'airplane-mode', $mode ); + + // Fire action to allow for functions to run on status change. + do_action( 'airplane_mode_status_change', $mode ); + + // And return the status we just set. + return $return; + } + + /** + * Enables airplane mode. + * + * @return bool Whether the setting changed. + */ + public function enable() { + return self::set_mode( 'on' ); + } + + /** + * Disables airplane mode. + * + * @return bool Whether the setting changed. + */ + public function disable() { + return self::set_mode( 'off' ); + } + + /** + * Check the user action from the toggle switch to set the option + * to 'on' or 'off'. + * + * @return void If any of the sanity checks fail and we bail early. + */ + public function toggle_check() { + + // Bail if current user doesn't have cap. + if ( ! current_user_can( 'manage_options' ) ) { + return; + } + + // Set a sanitized variable of our potential nonce and request. + $nonce = isset( $_GET['airmde_nonce'] ) ? sanitize_key( $_GET['airmde_nonce'] ) : ''; + $switch = isset( $_REQUEST['airplane-mode'] ) ? sanitize_key( $_REQUEST['airplane-mode'] ) : ''; + + // Check for our nonce. + if ( empty( $nonce ) || ! wp_verify_nonce( $nonce, 'airmde_nonce' ) ) { + return; + } + + // Now check for our query string. + if ( empty( $switch ) || ! in_array( $switch, array( 'on', 'off' ) ) ) { + return; + } + + // Delete old per-site option. + delete_option( 'airplane-mode' ); + + // Set our mode based on the toggle action. + self::set_mode( $switch ); + + // And go about our business. + wp_redirect( self::get_redirect() ); + exit; + } + + /** + * Fetch the URL to redirect to after toggling Airplane Mode. + * + * @return string The URL to redirect to. + */ + protected static function get_redirect() { + + // Return the args for the actual redirect. + $redirect = remove_query_arg( array( + 'airplane-mode', + 'airmde_nonce', + 'user_switched', + 'switched_off', + 'switched_back', + 'message', + 'update', + 'updated', + 'settings-updated', + 'saved', + 'activated', + 'activate', + 'deactivate', + 'enabled', + 'disabled', + 'locked', + 'skipped', + 'deleted', + 'trashed', + 'untrashed', + 'force-check', + ) ); + + // Redirect away from the update core page. + $redirect = str_replace( 'update-core.php', '', $redirect ); + + // And return the redirect. + return apply_filters( 'airplane_mode_redirect_url', $redirect ); + } + + /** + * Add our quick toggle to the admin bar to enable / disable. + * + * @param WP_Admin_Bar $wp_admin_bar The admin bar object. + * + * @return void if current user can't manage options and we bail early. + */ + public function admin_bar_toggle( WP_Admin_Bar $wp_admin_bar ) { + + // Bail if current user doesn't have cap. + if ( ! current_user_can( 'manage_options' ) ) { + return; + } + + // Get the current status. + $status = $this->enabled(); + + // Set a title message (translatable). + $title = $status ? __( 'Airplane Mode is enabled.', 'airplane-mode' ) : __( 'Airplane Mode is disabled.', 'airplane-mode' ); + + // Set our toggle variable parameter (in reverse since we want the opposite action). + $toggle = $status ? 'off' : 'on'; + + // Set my HTTP request count label to a blank string for now. + $label = ''; + + // Get and display the HTTP count when Query Monitor isn't active. + if ( ! class_exists( 'QueryMonitor' ) || defined( 'QM_DISABLED' ) && QM_DISABLED ) { + + // Pull my HTTP count. + $count = ! empty( $this->http_count ) ? number_format_i18n( $this->http_count ) : 0; + + $count_label = sprintf( _n( 'There was %s HTTP request.', 'There were %s HTTP requests.', $count, 'airplane-mode' ), $count ); + + // Build the markup for my label. + $label = ''; + $label .= '' . esc_html( $count_label ) . ''; + + // Amend the tooltip title with the count. + $title .= ' ' . $count_label; + } + + // Get our link with the status parameter. + $link = wp_nonce_url( add_query_arg( 'airplane-mode', $toggle ), 'airmde_nonce', 'airmde_nonce' ); + + // Now add the admin bar link. + $wp_admin_bar->add_node( + array( + 'id' => 'airplane-mode-toggle', + 'title' => '' . $label, + 'href' => esc_url( $link ), + 'position' => 0, + 'meta' => array( + 'title' => $title, + ), + ) + ); + } + + /** + * Filter a user's meta capabilities to prevent auto-updates from being attempted. + * + * @param array $caps Returns the user's actual capabilities. + * @param string $cap Capability name. + * + * @return array The user's filtered capabilities. + */ + public function prevent_auto_updates( $caps, $cap ) { + + // Check for being enabled and look for specific cap requirements. + if ( $this->enabled() && in_array( $cap, array( 'update_plugins', 'update_themes', 'update_core' ) ) ) { + $caps[] = 'do_not_allow'; + } + + // Send back the data array. + return $caps; + } + + /** + * Check the new status after airplane mode has been enabled or + * disabled and purge related transients. + * + * @param boolean $force Whether to force the purge. + * + * @return void + */ + public function purge_transients( $force = false ) { + + // First check for the filter to avoid this action overall. + if ( empty( $force ) && false === $clear = apply_filters( 'airplane_mode_purge_transients', true ) ) { + return; + } + + // Purge the transients related to updates when disabled or the force is called. + if ( ! $this->enabled() || ! empty( $force ) ) { + delete_site_transient( 'update_core' ); + delete_site_transient( 'update_plugins' ); + delete_site_transient( 'update_themes' ); + delete_site_transient( 'wporg_theme_feature_list' ); + } + } + + /** + * Remove all the various places WP does the update checks. As you can see there are a lot of them. + * + * @return null + */ + public function remove_update_crons() { + + // Bail if disabled. + if ( ! $this->enabled() ) { + return; + } + + // Do a quick check to make sure we can remove things. + if ( ! function_exists( 'remove_action' ) ) { + return; + } + + // Disable Theme Updates. + remove_action( 'load-update-core.php', 'wp_update_themes' ); + remove_action( 'load-themes.php', 'wp_update_themes' ); + remove_action( 'load-update.php', 'wp_update_themes' ); + remove_action( 'wp_update_themes', 'wp_update_themes' ); + remove_action( 'admin_init', '_maybe_update_themes' ); + + // Disable Plugin Updates. + remove_action( 'load-update-core.php', 'wp_update_plugins' ); + remove_action( 'load-plugins.php', 'wp_update_plugins' ); + remove_action( 'load-update.php', 'wp_update_plugins' ); + remove_action( 'wp_update_plugins', 'wp_update_plugins' ); + remove_action( 'admin_init', '_maybe_update_plugins' ); + + // Disable Core updates + + // Don't look for WordPress updates. Seriously! + remove_action( 'wp_version_check', 'wp_version_check' ); + remove_action( 'admin_init', '_maybe_update_core' ); + + // Not even maybe. + remove_action( 'wp_maybe_auto_update', 'wp_maybe_auto_update' ); + remove_action( 'admin_init', 'wp_maybe_auto_update' ); + remove_action( 'admin_init', 'wp_auto_update_core' ); + + // Don't forget when the language packs do it. + remove_action( 'upgrader_process_complete', array( 'Language_Pack_Upgrader', 'async_upgrade' ), 20 ); + remove_action( 'upgrader_process_complete', 'wp_version_check' ); + remove_action( 'upgrader_process_complete', 'wp_update_plugins' ); + remove_action( 'upgrader_process_complete', 'wp_update_themes' ); + } + + /** + * Remove all the various schedule hooks for themes, plugins, etc. + * + * @return null + */ + public function remove_schedule_hook() { + + // Bail if disabled. + if ( ! $this->enabled() ) { + return; + } + + // Clear all my hooks. + wp_clear_scheduled_hook( 'wp_update_themes' ); + wp_clear_scheduled_hook( 'wp_update_plugins' ); + wp_clear_scheduled_hook( 'wp_version_check' ); + wp_clear_scheduled_hook( 'wp_maybe_auto_update' ); + } + + /** + * Override the API call made for pulling themes from the .org repo. + * + * @param false|object|array $override Whether to override the WordPress.org Themes API. Default false. + * @param string $action Requested action. Likely values are 'theme_information', + * 'feature_list', or 'query_themes'. + * @param object $args Arguments used to query for installer pages from the Themes API. + * + * @return bool True if enabled, otherwise the existng value. + */ + public function bypass_theme_api_call( $override, $action, $args ) { + + // Bail if disabled. + if ( ! $this->enabled() ) { + return $override; + } + + // Return false on feature list to avoid the API call. + return ! empty( $action ) && 'feature_list' === $action ? true : $override; + } + + /** + * Hijack the expected themes API result. + * + * @param array|object|WP_Error $res WordPress.org Themes API response. + * @param string $action Requested action. Likely values are 'theme_information', + * 'feature_list', or 'query_themes'. + * @param object $args Arguments used to query for installer pages from the WordPress.org Themes API. + * + * @return bool An empty array if enabled, otherwise the existng result. + */ + public function bypass_theme_api_result( $res, $action, $args ) { + + // Bail if disabled. + if ( ! $this->enabled() ) { + return $res; + } + + // Return false on feature list to avoid the API call. + return ! empty( $action ) && in_array( $action, array( 'feature_list', 'query_themes' ) ) ? array() : $res; + } + + /** + * Always send back that the latest version of WordPress is the one we're running + * + * @return object the modified output with our information + */ + public function last_checked_core() { + + // Bail if disabled. + if ( ! $this->enabled() ) { + return false; + } + + // Call the global WP version. + global $wp_version; + + // Return our object. + return (object) array( + 'last_checked' => time(), + 'updates' => array(), + 'version_checked' => $wp_version, + ); + } + + /** + * Always send back that the latest version of our theme is the one we're running + * + * @return object the modified output with our information + */ + public function last_checked_themes() { + + // Bail if disabled. + if ( ! $this->enabled() ) { + return false; + } + + // Call the global WP version. + global $wp_version; + + // Set a blank data array. + $data = array(); + + // Build my theme data array. + foreach ( wp_get_themes() as $theme ) { + $data[ $theme->get_stylesheet() ] = $theme->get( 'Version' ); + } + + // Return our object. + return (object) array( + 'last_checked' => time(), + 'updates' => array(), + 'version_checked' => $wp_version, + 'checked' => $data, + ); + } + + /** + * Always send back that the latest version of our plugins are the one we're running + * + * @return object the modified output with our information + */ + public function last_checked_plugins() { + + // Bail if disabled. + if ( ! $this->enabled() ) { + return false; + } + + // Call the global WP version. + global $wp_version; + + // Set a blank data array. + $data = array(); + + // Add our plugin file if we don't have it. + if ( ! function_exists( 'get_plugins' ) ) { + require_once ABSPATH . 'wp-admin/includes/plugin.php'; + } + + // Build my plugin data array. + foreach ( get_plugins() as $file => $pl ) { + $data[ $file ] = $pl['Version']; + } + + // Return our object. + return (object) array( + 'last_checked' => time(), + 'updates' => array(), + 'version_checked' => $wp_version, + 'checked' => $data, + ); + } + + /** + * Filter for languages list transient. Returns locally available translations + * to avoid request into wp.org translation API. + * + * @param mixed $translations Translation data returned from transient API. + * + * @return array List of available languages. + */ + public function available_translations( $translations ) { + + // Bail if disabled. + if ( ! $this->enabled() ) { + return $translations; + } + + /** + * If transient still contains list of languages just use those. + * Otherwise fallback to mimicked data which we create here. + */ + if ( $translations && ! empty( $translations ) ) { + return $translations; + } else { + $installed_languages = get_available_languages(); + return $this->get_offline_languages( $installed_languages ); + } + } + + /** + * Returns list of languages installed locally with full mimicked meta data. + * + * @param array $installed_languages List of locally available languages. + * + * @return array List of available languages in offline mode. + */ + private function get_offline_languages( $installed_languages ) { + + // This is list of languages which are available from translations API. + $offline_languages = $this->get_offline_translation_information(); + + // Call the global WP version. + global $wp_version; + + // Tell WordPress that all translations are recent even though they can be old. + $date = date_i18n( 'Y-m-d H:is' , time() ); + + // Set an empty array of the available languages. + $available_languages = array(); + + // Loop through our installed languages. + foreach ( $installed_languages as $lang ) { + + // Try to mimick the data that WordPress puts into 'available_translations' transient. + $settings = array( + 'language' => $lang, + 'iso' => array( $lang ), + 'version' => $wp_version, + 'updated' => $date, + 'strings' => array( + 'continue' => __( 'Continue' ), + ), + 'package' => "https://downloads.wordpress.org/translation/core/{$wp_version}/{$lang}.zip", + ); + + // Combine the mimicked data with data we have stored in $offline_languages to give realistic output. + if ( isset( $offline_languages[ $lang ] ) ) { + $available_languages[ $lang ] = array_merge( $settings, $offline_languages[ $lang ] ); + } + } + + // And return our language sets. + return $available_languages; + } + + /** + * We can't use wp_get_available_translations() offine. + * This function tries to return something similiar. + * + * @return array List of wordpress language meta data. + */ + private function get_offline_translation_information() { + + // Build out the list of languages to use. + $languages = array( + 'af' => array( 'english_name' => 'Afrikaans', 'native_name' => 'Afrikaans' ), + 'ar' => array( 'english_name' => 'Arabic', 'native_name' => 'العربية' ), + 'ary' => array( 'english_name' => 'Moroccan Arabic', 'native_name' => 'العربية المغربية' ), + 'as' => array( 'english_name' => 'Assamese', 'native_name' => 'অসমীয়া' ), + 'az' => array( 'english_name' => 'Azerbaijani', 'native_name' => 'Azərbaycan dili' ), + 'azb' => array( 'english_name' => 'South Azerbaijani', 'native_name' => 'گؤنئی آذربایجان' ), + 'bel' => array( 'english_name' => 'Belarusian', 'native_name' => 'Беларуская мова' ), + 'bg_BG' => array( 'english_name' => 'Bulgarian', 'native_name' => 'Български' ), + 'bn_BD' => array( 'english_name' => 'Bengali', 'native_name' => 'বাংলা' ), + 'bo' => array( 'english_name' => 'Tibetan', 'native_name' => 'བོད་ཡིག' ), + 'bs_BA' => array( 'english_name' => 'Bosnian', 'native_name' => 'Bosanski' ), + 'ca' => array( 'english_name' => 'Catalan', 'native_name' => 'Català' ), + 'ceb' => array( 'english_name' => 'Cebuano', 'native_name' => 'Cebuano' ), + 'ckb' => array( 'english_name' => 'Kurdish (Sorani)', 'native_name' => 'كوردی‎' ), + 'cs_CZ' => array( 'english_name' => 'Czech', 'native_name' => 'Čeština‎' ), + 'cy' => array( 'english_name' => 'Welsh', 'native_name' => 'Cymraeg' ), + 'da_DK' => array( 'english_name' => 'Danish', 'native_name' => 'Dansk' ), + 'de_DE_formal' => array( 'english_name' => 'German (Formal)', 'native_name' => 'Deutsch (Sie)' ), + 'de_DE' => array( 'english_name' => 'German', 'native_name' => 'Deutsch' ), + 'de_CH_informal' => array( 'english_name' => 'German (Switzerland, Informal)', 'native_name' => 'Deutsch (Schweiz, Du)' ), + 'de_CH' => array( 'english_name' => 'German (Switzerland)', 'native_name' => 'Deutsch (Schweiz)' ), + 'dzo' => array( 'english_name' => 'Dzongkha', 'native_name' => 'རྫོང་ཁ' ), + 'el' => array( 'english_name' => 'Greek', 'native_name' => 'Ελληνικά' ), + 'en_CA' => array( 'english_name' => 'English (Canada)', 'native_name' => 'English (Canada)' ), + 'en_ZA' => array( 'english_name' => 'English (South Africa)', 'native_name' => 'English (South Africa)' ), + 'en_AU' => array( 'english_name' => 'English (Australia)', 'native_name' => 'English (Australia)' ), + 'en_NZ' => array( 'english_name' => 'English (New Zealand)', 'native_name' => 'English (New Zealand)' ), + 'en_GB' => array( 'english_name' => 'English (UK)', 'native_name' => 'English (UK)' ), + 'eo' => array( 'english_name' => 'Esperanto', 'native_name' => 'Esperanto' ), + 'es_CL' => array( 'english_name' => 'Spanish (Chile)', 'native_name' => 'Español de Chile' ), + 'es_AR' => array( 'english_name' => 'Spanish (Argentina)', 'native_name' => 'Español de Argentina' ), + 'es_PE' => array( 'english_name' => 'Spanish (Peru)', 'native_name' => 'Español de Perú' ), + 'es_MX' => array( 'english_name' => 'Spanish (Mexico)', 'native_name' => 'Español de México' ), + 'es_CO' => array( 'english_name' => 'Spanish (Colombia)', 'native_name' => 'Español de Colombia' ), + 'es_ES' => array( 'english_name' => 'Spanish (Spain)', 'native_name' => 'Español' ), + 'es_VE' => array( 'english_name' => 'Spanish (Venezuela)', 'native_name' => 'Español de Venezuela' ), + 'es_GT' => array( 'english_name' => 'Spanish (Guatemala)', 'native_name' => 'Español de Guatemala' ), + 'et' => array( 'english_name' => 'Estonian', 'native_name' => 'Eesti' ), + 'eu' => array( 'english_name' => 'Basque', 'native_name' => 'Euskara' ), + 'fa_IR' => array( 'english_name' => 'Persian', 'native_name' => 'فارسی' ), + 'fi' => array( 'english_name' => 'Finnish', 'native_name' => 'Suomi' ), + 'fr_BE' => array( 'english_name' => 'French (Belgium)', 'native_name' => 'Français de Belgique' ), + 'fr_FR' => array( 'english_name' => 'French (France)', 'native_name' => 'Français' ), + 'fr_CA' => array( 'english_name' => 'French (Canada)', 'native_name' => 'Français du Canada' ), + 'gd' => array( 'english_name' => 'Scottish Gaelic', 'native_name' => 'Gàidhlig' ), + 'gl_ES' => array( 'english_name' => 'Galician', 'native_name' => 'Galego' ), + 'gu' => array( 'english_name' => 'Gujarati', 'native_name' => 'ગુજરાતી' ), + 'haz' => array( 'english_name' => 'Hazaragi', 'native_name' => 'هزاره گی' ), + 'he_IL' => array( 'english_name' => 'Hebrew', 'native_name' => 'עִבְרִית' ), + 'hi_IN' => array( 'english_name' => 'Hindi', 'native_name' => 'हिन्दी' ), + 'hr' => array( 'english_name' => 'Croatian', 'native_name' => 'Hrvatski' ), + 'hu_HU' => array( 'english_name' => 'Hungarian', 'native_name' => 'Magyar' ), + 'hy' => array( 'english_name' => 'Armenian', 'native_name' => 'Հայերեն' ), + 'id_ID' => array( 'english_name' => 'Indonesian', 'native_name' => 'Bahasa Indonesia' ), + 'is_IS' => array( 'english_name' => 'Icelandic', 'native_name' => 'Íslenska' ), + 'it_IT' => array( 'english_name' => 'Italian', 'native_name' => 'Italiano' ), + 'ja' => array( 'english_name' => 'Japanese', 'native_name' => '日本語' ), + 'ka_GE' => array( 'english_name' => 'Georgian', 'native_name' => 'ქართული' ), + 'kab' => array( 'english_name' => 'Kabyle', 'native_name' => 'Taqbaylit' ), + 'km' => array( 'english_name' => 'Khmer', 'native_name' => 'ភាសាខ្មែរ' ), + 'ko_KR' => array( 'english_name' => 'Korean', 'native_name' => '한국어' ), + 'lo' => array( 'english_name' => 'Lao', 'native_name' => 'ພາສາລາວ' ), + 'lt_LT' => array( 'english_name' => 'Lithuanian', 'native_name' => 'Lietuvių kalba' ), + 'lv' => array( 'english_name' => 'Latvian', 'native_name' => 'Latviešu valoda' ), + 'mk_MK' => array( 'english_name' => 'Macedonian', 'native_name' => 'Македонски јазик' ), + 'ml_IN' => array( 'english_name' => 'Malayalam', 'native_name' => 'മലയാളം' ), + 'mn' => array( 'english_name' => 'Mongolian', 'native_name' => 'Монгол' ), + 'mr' => array( 'english_name' => 'Marathi', 'native_name' => 'मराठी' ), + 'ms_MY' => array( 'english_name' => 'Malay', 'native_name' => 'Bahasa Melayu' ), + 'my_MM' => array( 'english_name' => 'Myanmar (Burmese)', 'native_name' => 'ဗမာစာ' ), + 'nb_NO' => array( 'english_name' => 'Norwegian (Bokmål)', 'native_name' => 'Norsk bokmål' ), + 'ne_NP' => array( 'english_name' => 'Nepali', 'native_name' => 'नेपाली' ), + 'nl_BE' => array( 'english_name' => 'Dutch (Belgium)', 'native_name' => 'Nederlands (België)' ), + 'nl_NL' => array( 'english_name' => 'Dutch', 'native_name' => 'Nederlands' ), + 'nl_NL_formal' => array( 'english_name' => 'Dutch (Formal)', 'native_name' => 'Nederlands (Formeel)' ), + 'nn_NO' => array( 'english_name' => 'Norwegian (Nynorsk)', 'native_name' => 'Norsk nynorsk' ), + 'oci' => array( 'english_name' => 'Occitan', 'native_name' => 'Occitan' ), + 'pa_IN' => array( 'english_name' => 'Punjabi', 'native_name' => 'ਪੰਜਾਬੀ' ), + 'pl_PL' => array( 'english_name' => 'Polish', 'native_name' => 'Polski' ), + 'ps' => array( 'english_name' => 'Pashto', 'native_name' => 'پښتو' ), + 'pt_BR' => array( 'english_name' => 'Portuguese (Brazil)', 'native_name' => 'Português do Brasil' ), + 'pt_PT' => array( 'english_name' => 'Portuguese (Portugal)', 'native_name' => 'Português' ), + 'rhg' => array( 'english_name' => 'Rohingya', 'native_name' => 'Ruáinga' ), + 'ro_RO' => array( 'english_name' => 'Romanian', 'native_name' => 'Română' ), + 'ru_RU' => array( 'english_name' => 'Russian', 'native_name' => 'Русский' ), + 'sah' => array( 'english_name' => 'Sakha', 'native_name' => 'Сахалыы' ), + 'si_LK' => array( 'english_name' => 'Sinhala', 'native_name' => 'සිංහල' ), + 'sk_SK' => array( 'english_name' => 'Slovak', 'native_name' => 'Slovenčina' ), + 'sl_SI' => array( 'english_name' => 'Slovenian', 'native_name' => 'Slovenščina' ), + 'sq' => array( 'english_name' => 'Albanian', 'native_name' => 'Shqip' ), + 'sr_RS' => array( 'english_name' => 'Serbian', 'native_name' => 'Српски језик' ), + 'sv_SE' => array( 'english_name' => 'Swedish', 'native_name' => 'Svenska' ), + 'szl' => array( 'english_name' => 'Silesian', 'native_name' => 'Ślōnskŏ gŏdka' ), + 'ta_IN' => array( 'english_name' => 'Tamil', 'native_name' => 'தமிழ்' ), + 'tah' => array( 'english_name' => 'Tahitian', 'native_name' => 'Reo Tahiti' ), + 'te' => array( 'english_name' => 'Telugu', 'native_name' => 'తెలుగు' ), + 'th' => array( 'english_name' => 'Thai', 'native_name' => 'ไทย' ), + 'tl' => array( 'english_name' => 'Tagalog', 'native_name' => 'Tagalog' ), + 'tr_TR' => array( 'english_name' => 'Turkish', 'native_name' => 'Türkçe' ), + 'tt_RU' => array( 'english_name' => 'Tatar', 'native_name' => 'Татар теле' ), + 'ug_CN' => array( 'english_name' => 'Uighur', 'native_name' => 'Uyƣurqə' ), + 'uk' => array( 'english_name' => 'Ukrainian', 'native_name' => 'Українська' ), + 'ur' => array( 'english_name' => 'Urdu', 'native_name' => 'اردو' ), + 'uz_UZ' => array( 'english_name' => 'Uzbek', 'native_name' => 'O‘zbekcha' ), + 'vi' => array( 'english_name' => 'Vietnamese', 'native_name' => 'Tiếng Việt' ), + 'zh_CN' => array( 'english_name' => 'Chinese (China)', 'native_name' => '简体中文' ), + 'zh_HK' => array( 'english_name' => 'Chinese (Hong Kong)', 'native_name' => '香港中文版' ), + 'zh_TW' => array( 'english_name' => 'Chinese (Taiwan)', 'native_name' => '繁體中文' ), + ); + + // Allow adding or removing languages. + return apply_filters( 'airplane_mode_offline_languages', $languages ); + } + + /** + * Return an empty array of items requiring update for both themes and plugins + * + * @param array $items All the items being passed for update. + * + * @return array An empty array, or the original items if not enabled. + */ + public function remove_update_array( $items ) { + return ! $this->enabled() ? $items : array(); + } + + /** + * Remove the ability to update plugins/themes from single + * site and multisite bulk actions + * + * @param array $actions All the bulk actions. + * + * @return array $actions The remaining actions + */ + public function remove_bulk_actions( $actions ) { + + // Bail if disabled. + if ( ! $this->enabled() ) { + return $actions; + } + + // Set an array of items to be removed with optional filter. + if ( false === $remove = apply_filters( 'airplane_mode_bulk_items', array( 'update-selected', 'update', 'upgrade' ) ) ) { + return $actions; + } + + // Loop the item array and unset each. + foreach ( $remove as $key ) { + unset( $actions[ $key ] ); + } + + // Return the remaining. + return $actions; + } + + /** + * Remove the tabs on the plugin page to add new items + * since they require the WP connection and will fail. + * + * @param array $nonmenu_tabs All the tabs displayed. + * @return array $nonmenu_tabs The remaining tabs. + */ + public function plugin_add_tabs( $nonmenu_tabs ) { + + // Bail if disabled. + if ( ! $this->enabled() ) { + return $nonmenu_tabs; + } + + // Set an array of tabs to be removed with optional filter. + if ( false === $remove = apply_filters( 'airplane_mode_bulk_items', array( 'featured', 'popular', 'recommended', 'favorites', 'beta' ) ) ) { + return $nonmenu_tabs; + } + + // Loop the item array and unset each. + foreach ( $remove as $key ) { + unset( $nonmenu_tabs[ $key ] ); + } + + // Return the tabs. + return $nonmenu_tabs; + } + + /** + * Increase HTTP request counter by one. + * + * @return void + */ + public function count_http_requests() { + $this->http_count++; + } + + // End class. + } + +} // End class_exists. + +if ( ! class_exists( 'Airplane_Mode_WP_Error' ) ) { + + /** + * Extend the WP_Error class to include our own. + */ + class Airplane_Mode_WP_Error extends WP_Error { + + /** + * Get our error data and return it. + * + * @return string + */ + public function __tostring() { + $data = $this->get_error_data(); + return $data['return']; + } + + // End class. + } + +} + +// Instantiate our class. +$Airplane_Mode_Core = Airplane_Mode_Core::getInstance(); diff --git a/content/plugins/airplane-mode/inc/wp-cli.php b/content/plugins/airplane-mode/inc/wp-cli.php new file mode 100644 index 0000000..a1962b4 --- /dev/null +++ b/content/plugins/airplane-mode/inc/wp-cli.php @@ -0,0 +1,66 @@ +enable(); + WP_CLI::success( __( 'Airplane mode was enabled', 'airplane-mode' ) ); + } + + /** + * Disables airplane mode. + * + * ## EXAMPLES + * + * wp airplane-mode disable + * + * @when after_wp_load + * @subcommand off + * @alias disable + */ + function disable() { + Airplane_Mode_Core::getInstance()->disable(); + WP_CLI::success( __( 'Airplane mode was disabled', 'airplane-mode' ) ); + } + + /** + * Provides the status of airplane mode. + * + * ## EXAMPLES + * + * wp airplane-mode status + * + * @when after_wp_load + */ + function status() { + $on = 'on' === get_site_option( 'airplane-mode' ); + WP_CLI::success( $on ? __( 'Airplane mode is enabled', 'airplane-mode' ) : __( 'Airplane mode is disabled', 'airplane-mode' ) ); + } + + /** + * Purge the transients set from airplane mode. + * + * ## EXAMPLES + * + * wp airplane-mode clean + * + * @when after_wp_load + */ + function clean() { + Airplane_Mode_Core::getInstance()->purge_transients( true ); + WP_CLI::success( __( 'Transients have been cleared', 'airplane-mode' ) ); + } +} + +WP_CLI::add_command( 'airplane-mode', 'Airplane_Mode_Command' ); diff --git a/content/plugins/airplane-mode/languages/default.mo b/content/plugins/airplane-mode/languages/default.mo new file mode 100644 index 0000000..e9b7271 Binary files /dev/null and b/content/plugins/airplane-mode/languages/default.mo differ diff --git a/content/plugins/airplane-mode/languages/default.po b/content/plugins/airplane-mode/languages/default.po new file mode 100644 index 0000000..a8f37ed --- /dev/null +++ b/content/plugins/airplane-mode/languages/default.po @@ -0,0 +1,47 @@ +msgid "" +msgstr "" +"Project-Id-Version: Airplane Mode\n" +"POT-Creation-Date: 2015-12-07 17:24-0500\n" +"PO-Revision-Date: 2015-12-07 17:25-0500\n" +"Last-Translator: Andrew Norcross \n" +"Language-Team: \n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 1.8.6\n" +"X-Poedit-Basepath: ..\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Poedit-SourceCharset: UTF-8\n" +"X-Poedit-KeywordsList: _;__;_e;_n\n" +"X-Poedit-SearchPath-0: .\n" + +#: airplane-mode.php:365 +#, php-format +msgid "Airplane Mode is enabled. oEmbed blocked for %1$s." +msgstr "Airplane Mode is enabled. oEmbed blocked for %1$s." + +#: airplane-mode.php:475 +msgid "Airplane Mode is enabled" +msgstr "Airplane Mode is enabled" + +#: airplane-mode.php:583 +msgid "Airplane Mode is enabled." +msgstr "Airplane Mode is enabled." + +#: airplane-mode.php:583 +msgid "Airplane Mode is disabled." +msgstr "Airplane Mode is disabled." + +#: airplane-mode.php:592 +msgid "Active" +msgstr "Active" + +#: airplane-mode.php:592 +msgid "Inactive" +msgstr "Inactive" + +#: airplane-mode.php:609 +#, php-format +msgid "There was %s HTTP request." +msgstr "There was %s HTTP request." diff --git a/content/plugins/airplane-mode/lib/css/airplane-mode.css b/content/plugins/airplane-mode/lib/css/airplane-mode.css new file mode 100644 index 0000000..34d53ff --- /dev/null +++ b/content/plugins/airplane-mode/lib/css/airplane-mode.css @@ -0,0 +1,59 @@ +@font-face { + font-family: "airplanemodeicons"; + src:url("../fonts/airplanemodeicons.eot"); + src:url("../fonts/airplanemodeicons.eot?#iefix") format("embedded-opentype"), + url("../fonts/airplanemodeicons.woff") format("woff"), + url("../fonts/airplanemodeicons.ttf") format("truetype"), + url("../fonts/airplanemodeicons.svg#airplanemodeicons") format("svg"); + font-weight: normal; + font-style: normal; +} + +#wp-admin-bar-airplane-mode-toggle .ab-icon { + top: 1px; +} + +#wp-admin-bar-airplane-mode-toggle .ab-icon:before { + content: "\e000"; + font: normal 18px/1 airplanemodeicons; +} + +.airplane-mode-disabled #wp-admin-bar-airplane-mode-toggle .ab-icon:before { + content: "\e001"; +} + +#wpadminbar > #wp-toolbar > #wp-admin-bar-root-default > #wp-admin-bar-airplane-mode-toggle .ab-icon, +#wpadminbar #wp-admin-bar-airplane-mode-toggle .ab-icon, +#wpadminbar #wp-admin-bar-airplane-mode-toggle .ab-item::before { + margin-right: 0; +} + +.airplane-mode-no-qm #wpadminbar > #wp-toolbar > #wp-admin-bar-root-default > #wp-admin-bar-airplane-mode-toggle .ab-icon, +.airplane-mode-no-qm #wpadminbar #wp-admin-bar-airplane-mode-toggle .ab-icon, +.airplane-mode-no-qm #wpadminbar #wp-admin-bar-airplane-mode-toggle .ab-item::before { + margin-right: 6px; +} + + /* Set the opacity to mimic comment moderation queue. */ +.airplane-mode-disabled #wp-admin-bar-airplane-mode-toggle .ab-label { + /* Theoretically for IE 8 & 9 (more valid) */ + /* ...but not required as filter works too */ + /* should come BEFORE filter */ + -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=50)"; + + /* This works in IE 8 & 9 too */ + /* ... but also 5, 6, 7 */ + filter: alpha(opacity=50); /* IE 5-7 */ + + /* Modern Browsers */ + opacity: 0.5; +} + +.airplane-mode-enabled.plugin-install-php.branch-4-6 h1 a.upload-view-toggle, +.airplane-mode-enabled.plugin-install-php h1 a.upload, +.airplane-mode-enabled.plugin-install-php .wp-filter, +.airplane-mode-enabled.theme-install-php .wp-filter, +.airplane-mode-enabled .theme-browser.content-filterable.rendered, +.airplane-mode-enabled.theme-install-php a.browse-themes { + display: none !important; +} diff --git a/content/plugins/airplane-mode/lib/css/airplane-mode.min.css b/content/plugins/airplane-mode/lib/css/airplane-mode.min.css new file mode 100644 index 0000000..9cbe92d --- /dev/null +++ b/content/plugins/airplane-mode/lib/css/airplane-mode.min.css @@ -0,0 +1 @@ +@font-face{font-family:airplanemodeicons;src:url(../fonts/airplanemodeicons.eot);src:url(../fonts/airplanemodeicons.eot?#iefix) format("embedded-opentype"),url(../fonts/airplanemodeicons.woff) format("woff"),url(../fonts/airplanemodeicons.ttf) format("truetype"),url(../fonts/airplanemodeicons.svg#airplanemodeicons) format("svg");font-weight:400;font-style:normal}#wp-admin-bar-airplane-mode-toggle .ab-icon{top:1px}#wp-admin-bar-airplane-mode-toggle .ab-icon:before{content:"\e000";font:400 18px/1 airplanemodeicons}.airplane-mode-disabled #wp-admin-bar-airplane-mode-toggle .ab-icon:before{content:"\e001"}#wpadminbar #wp-admin-bar-airplane-mode-toggle .ab-icon,#wpadminbar #wp-admin-bar-airplane-mode-toggle .ab-item::before,#wpadminbar>#wp-toolbar>#wp-admin-bar-root-default>#wp-admin-bar-airplane-mode-toggle .ab-icon{margin-right:0}.airplane-mode-no-qm #wpadminbar #wp-admin-bar-airplane-mode-toggle .ab-icon,.airplane-mode-no-qm #wpadminbar #wp-admin-bar-airplane-mode-toggle .ab-item::before,.airplane-mode-no-qm #wpadminbar>#wp-toolbar>#wp-admin-bar-root-default>#wp-admin-bar-airplane-mode-toggle .ab-icon{margin-right:6px}.airplane-mode-disabled #wp-admin-bar-airplane-mode-toggle .ab-label{-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=50)";filter:alpha(opacity=50);opacity:.5}.airplane-mode-enabled .theme-browser.content-filterable.rendered,.airplane-mode-enabled.plugin-install-php .wp-filter,.airplane-mode-enabled.plugin-install-php h1 a.upload,.airplane-mode-enabled.plugin-install-php.branch-4-6 h1 a.upload-view-toggle,.airplane-mode-enabled.theme-install-php .wp-filter,.airplane-mode-enabled.theme-install-php a.browse-themes{display:none!important} \ No newline at end of file diff --git a/content/plugins/airplane-mode/lib/fonts/airplanemodeicons.eot b/content/plugins/airplane-mode/lib/fonts/airplanemodeicons.eot new file mode 100644 index 0000000..a412182 Binary files /dev/null and b/content/plugins/airplane-mode/lib/fonts/airplanemodeicons.eot differ diff --git a/content/plugins/airplane-mode/lib/fonts/airplanemodeicons.svg b/content/plugins/airplane-mode/lib/fonts/airplanemodeicons.svg new file mode 100644 index 0000000..93cbad2 --- /dev/null +++ b/content/plugins/airplane-mode/lib/fonts/airplanemodeicons.svg @@ -0,0 +1,12 @@ + + + +Generated by Fontastic.me + + + + + + + + diff --git a/content/plugins/airplane-mode/lib/fonts/airplanemodeicons.ttf b/content/plugins/airplane-mode/lib/fonts/airplanemodeicons.ttf new file mode 100644 index 0000000..f519817 Binary files /dev/null and b/content/plugins/airplane-mode/lib/fonts/airplanemodeicons.ttf differ diff --git a/content/plugins/airplane-mode/lib/fonts/airplanemodeicons.woff b/content/plugins/airplane-mode/lib/fonts/airplanemodeicons.woff new file mode 100644 index 0000000..268417e Binary files /dev/null and b/content/plugins/airplane-mode/lib/fonts/airplanemodeicons.woff differ diff --git a/content/plugins/airplane-mode/readme.txt b/content/plugins/airplane-mode/readme.txt new file mode 100644 index 0000000..d9e1875 --- /dev/null +++ b/content/plugins/airplane-mode/readme.txt @@ -0,0 +1,151 @@ +=== Airplane Mode === +Contributors: norcross, johnbillion, afragen, szepeviktor, chriscct7, markjaquith +Website Link: https://github.com/norcross/airplane-mode +Donate link: https://andrewnorcross.com/donate +Tags: external calls, HTTP +Requires at least: 4.4 +Tested up to: 5.3 +Stable tag: 0.2.5 +License: MIT +License URI: http://norcross.mit-license.org/ + +Control loading of external files when developing locally + +== Description == + +Control loading of external files when developing locally. WP loads certain external files (fonts, gravatar, etc) and makes external HTTP calls. This isn't usually an issue, unless you're working in an evironment without a web connection. This plugin removes / unhooks those actions to reduce load time and avoid errors due to missing files. + +Features + +* removes external JS and CSS files from loading +* replaces all instances of Gravatar with a local image to remove external call +* removes all HTTP requests +* disables all WP update checks for core, themes, and plugins +* includes toggle in admin bar for quick enable / disable + +== Installation == + +This section describes how to install the plugin and get it working. + +1. Upload `airplane-mode` to the `/wp-content/plugins/` directory. +1. Activate the plugin through the 'Plugins' menu in WordPress. +1. Toggle users as needed + +If you need offline activation, see [this script](https://gist.github.com/solepixel/e1d03f4dcd1b9e86552b3cc6937325bf) written by [Brian DiChiara](https://github.com/solepixel) + +== Frequently Asked Questions == + += Why do I need this? = + +Because you are a jet set developer who needs to work without internet. + + +== Screenshots == + + +== Changelog == + += 0.2.5 - 2019/11/15 +* Remove usage of method that's been deprecated in WordPress trunk. props @johnbillion + += 0.2.4 - 2017/12/13 +* Added localhost bypass for loading CSS and JS files when hot reloading. props @shadyvb +* Added additional hook removals for new automated updates and language packs. +* Removed outdated `create_function` call for PHP 7.2 compatibility. props @geminorum +* General cleanup + += 0.2.3 - 2017/03/05 +* Adding option to force transient purge +* Adding `clean` action to WP-CLI functions + += 0.2.2 - 2016/12/07 +* Adding WP-CLI support. props @markjaquith + += 0.2.1 - 2016/10/19 +* Fix settings page language drowdown when used offline. props @onnimonni + += 0.2.0 - 2016/08/26 +* modify CSS loading for front-end, removed loading for login page. props @barryceelen +* fixed WP.org theme API call request to avoid `WP_Error` return. props @onnimonni + += 0.1.9 - 2016/07/25 +* Prevent BuddyPress from falling back to Gravatar. props @johnbillion + += 0.1.8 - 2016/07/12 +* allow `JETPACK_DEV_DEBUG` constant to take priority over filter. props @kopepasah +* added additional CSS for upcoming 4.6. change to upload tab. + += 0.1.7 - 2016/05/18 +* allow local HTTP calls with optional filter. props @johnbillion +* add back index.php link to main dashboard menu item +* bumped minimum WP version requirement to 4.4 + += 0.1.6 - 2016/04/25 +* minor tweak to include CSS for new icon font + += 0.1.5 - 2016/04/24 +* adding custom icon font for display and removing label. props @barryceelen + += 0.1.4 - 2016/02/26 +* better setup for blocked external assets. props @johnbillion + += 0.1.3 - 2016/02/22 +* modified CSS rules to fix media bulk actions bar from disappearing +* moved `airplane_mode_status_change` action to run before redirect, and now includes the status being run. + += 0.1.2 - 2016/01/09 +* added back HTTP count when inactive +* removed HTTP count completely when Query Monitor is active + += 0.1.1 - 2016/01/06 +* fixed incorrect nonce check that was breaking toggle +* changed CSS and JS checks to include all themes and plugins as well as core + += 0.1.0 - 2015/12/30 +* added `airplane_mode_purge_transients` filter to bypass transient purge + += 0.0.9 - 2015/12/07 +* changed from colored circle to actual airplane icon for usability +* fixed dashboard link icon for multisite +* changed to exclude all external stylesheets, not just Open Sans +* added language files for translateable goodness +* general cleanup for WP coding standards + += 0.0.8 - 2015/05/18 +* added `class_exists` as now included in DesktopServer and collisions could result +* fixed `if ( ! defined ...` for `AIRMDE_BASE` constant + += 0.0.7 - 2015/04/21 = +* fixed some CSS from hiding plugins page bar +* moved changelog to it's own file +* added `composer.json` +* added contributors to readme +* clarified license (MIT) + += 0.0.6 - 2015/04/02 = +* version bump for GitHub updater + += 0.0.5 - 2015/04/02 = +* fixed bug in update logic that was preventing checks when disabled (but activated). props @johnbillion + += 0.0.4 - 2015/04/02 = +* added multiple checks for all the various theme and plugin update calls. props @chriscct7 +* added HTTP counter on a per-page basis. props @szepeviktor + += 0.0.3 - 2015/01/23 = +* added `airplane_mode_status_change` hook for functions to fire on status change +* purge update related transients on disable +* added WordPress formatted readme file + += 0.0.2 - 2015/01/21 = +* added GitHub Updater support +* fixed update capabilities when status is disabled + += 0.0.1 - 2014/06/01 = +* lots of stuff. I wasn't keeping a changelog. I apologize. + + +== Upgrade Notice == + += 0.0.1 = +Initial release diff --git a/content/plugins/f-api/inc/events/namespace.php b/content/plugins/f-api/inc/events/namespace.php new file mode 100644 index 0000000..80258fa --- /dev/null +++ b/content/plugins/f-api/inc/events/namespace.php @@ -0,0 +1,121 @@ + WP_REST_Server::READABLE, + 'callback' => __NAMESPACE__ . '\get_events', + 'permission_callback' => '__return_true', + ] ); +} + +/** + * Refresh events data from thewp.world. + * + * This is refreshed hourly, so we always refresh before the cache expires. + */ +function refresh_events() : void { + $response = wp_remote_get( SOURCE_URL, [ + 'user-agent' => 'FAIR Server/1.0', + ] ); + if ( is_wp_error( $response ) ) { + trigger_error( + 'Failed to fetch events from thewp.world: ' . $response->get_error_message(), + E_USER_WARNING + ); + return; + } + + $body = wp_remote_retrieve_body( $response ); + if ( empty( $body ) ) { + trigger_error( + 'Failed to fetch events from thewp.world: Empty response body', + E_USER_WARNING + ); + return; + } + $events = json_decode( $body, true ); + if ( json_last_error() !== JSON_ERROR_NONE ) { + trigger_error( + 'Failed to decode events from thewp.world: ' . json_last_error_msg(), + E_USER_WARNING + ); + return; + } + + wp_cache_set( CACHE_KEY, $events, CACHE_GROUP, CACHE_LIFETIME ); +} + +/** + * Get the latest community events. + * + * @param WP_REST_Request $request The request object. + * @return WP_REST_Response|WP_Error Response object on success or error. + */ +function get_events( WP_REST_Request $request ) { + $data = wp_cache_get( CACHE_KEY, CACHE_GROUP ); + if ( ! $data ) { + return new WP_Error( + 'fairserver.events.not_found', + 'Unable to fetch events.', + [ 'status' => WP_Http::INTERNAL_SERVER_ERROR ] + ); + } + + $response = rest_ensure_response( $data ); + $response->header( + 'Cache-Control', + sprintf( + 'max-age=%d, stale-while-revalidate=%d', + HTTP_CACHE_MAXAGE, + HTTP_CACHE_SWR + ) + ); + return $response; +} diff --git a/content/plugins/f-api/inc/namespace.php b/content/plugins/f-api/inc/namespace.php new file mode 100644 index 0000000..238a57e --- /dev/null +++ b/content/plugins/f-api/inc/namespace.php @@ -0,0 +1,46 @@ + 5 * MINUTE_IN_SECONDS, + 'display' => __( 'FAIR Server - GD Cron', 'fairserver' ), + ]; + + return $schedules; +} + +/** + * Run the cron job on all sites. + * + * GD only runs wp-cron on the main site, so we need to force-spawn it on all + * sites. + */ +function run_cron() : void { + $sites = get_sites( [ + 'number' => MAX_SITES, + 'fields' => 'ids', + ] ); + + foreach ( $sites as $site_id ) { + switch_to_blog( $site_id ); + run_site_cron(); + restore_current_blog(); + } +} + +/** + * Spawn cron for the current site. + * + * @internal Copy of spawn_cron() to allow recursive spawning. + */ +function run_site_cron() : bool { + $gmt_time = microtime( true ); + + /* + * Get the cron lock, which is a Unix timestamp of when the last cron was spawned + * and has not finished running. + * + * Multiple processes on multiple web servers can run this code concurrently, + * this lock attempts to make spawning as atomic as possible. + */ + $lock = (float) get_transient( 'doing_cron' ); + + if ( $lock > $gmt_time + 10 * MINUTE_IN_SECONDS ) { + $lock = 0; + } + + // Don't run if another process is currently running it or more than once every 60 sec. + if ( $lock + WP_CRON_LOCK_TIMEOUT > $gmt_time ) { + return false; + } + + // Confidence check. + $crons = wp_get_ready_cron_jobs(); + if ( empty( $crons ) ) { + return false; + } + + $keys = array_keys( $crons ); + if ( isset( $keys[0] ) && $keys[0] > $gmt_time ) { + return false; + } + + // Set the cron lock with the current unix timestamp, when the cron is being spawned. + $doing_wp_cron = sprintf( '%.22F', $gmt_time ); + set_transient( 'doing_cron', $doing_wp_cron ); + + $cron_request = apply_filters( + 'cron_request', + array( + 'url' => add_query_arg( 'doing_wp_cron', $doing_wp_cron, site_url( 'wp-cron.php' ) ), + 'key' => $doing_wp_cron, + 'args' => array( + 'timeout' => 0.01, + 'blocking' => false, + /** This filter is documented in wp-includes/class-wp-http-streams.php */ + 'sslverify' => apply_filters( 'https_local_ssl_verify', false ), + ), + ), + $doing_wp_cron + ); + + $result = wp_remote_post( $cron_request['url'], $cron_request['args'] ); + return ! is_wp_error( $result ); +} diff --git a/content/plugins/f-gd-cron/plugin.php b/content/plugins/f-gd-cron/plugin.php new file mode 100644 index 0000000..0e849b6 --- /dev/null +++ b/content/plugins/f-gd-cron/plugin.php @@ -0,0 +1,12 @@ + + * : The path to the projects.json file (use glotpress-dump to generate) + * + * @subcommand import + */ + public function import( $args ) { + if ( $args[0] !== '-' ) { + $path = realpath( $args[0] ); + $data = file_get_contents( $path ); + } else { + $data = file_get_contents( 'php://stdin' ); + } + + $items = json_decode( $data ); + + foreach ( $items as $item ) { + // Does this project already exist? + $existing = GP::$project->get( $item->id ); + if ( $existing ) { + // Update the existing project. + $project = $this->sync_project( $item ); + } else { + // Manually create, to ensure the ID matches. + $project = $this->import_project( $item ); + } + } + // var_dump( $projects ); + } + + protected function import_project( object $data ) : GP_Project { + global $wpdb; + + $args = [ + 'name' => $data->name, + 'slug' => $data->slug, + 'description' => $data->description, + 'parent_project_id' => $data->parent_project_id ?? 0, + 'source_url_template' => $data->source_url_template, + 'active' => $data->active, + ]; + $args = GP::$project->prepare_fields_for_save( $args ); + $args = GP::$project->prepare_fields_for_create( $args ); + + // Manually set the ID, to ensure it matches. + // This would otherwise be stripped in prepare_fields_for_save + $args['id'] = $data->id; + + $field_formats = GP::$project->get_db_field_formats( $args ); + + // Let it rip. + $res = $wpdb->insert( GP::$project->table, $args, $field_formats ); + if ( false === $res ) { + throw new Exception( + sprintf( + 'Failed to create project: %s', + $wpdb->last_error + ) + ); + } + + $inserted = new GP_Project( $args ); + $inserted->id = $wpdb->insert_id; + $inserted->after_create(); + + return $inserted; + } + + protected function sync_project( object $data ) : GP_Project { + $project = GP::$project->get( $data->id ); + if ( ! $project ) { + throw new Exception( 'Project not found' ); + } + + $needs_update = false; + $fields = GP::$project->field_names; + foreach ( $fields as $field ) { + if ( in_array( $field, GP::$project->non_updatable_attributes, true ) ) { + continue; + } + + if ( $project->$field !== $data->$field ) { + $needs_update = true; + $project->$field = $data->$field; + } + } + + // Needs update. + if ( $needs_update ) { + WP_CLI::line( sprintf( 'Updating project %d (%s)', $project->id, $project->slug ) ); + // $project->update(); + } + + return $project; + } +} diff --git a/content/plugins/f-translate/inc/class-translationsetcommand.php b/content/plugins/f-translate/inc/class-translationsetcommand.php new file mode 100644 index 0000000..f7f3c1b --- /dev/null +++ b/content/plugins/f-translate/inc/class-translationsetcommand.php @@ -0,0 +1,63 @@ + + * : Project slug. + * + * + * : Locale slug. + * + * [--set=] + * : Translation set slug; default is "default" + * + * [--verbose] + * : Output additional information during execution. + * + * @subcommand ensure + */ + public function ensure_translation_set( $args, $assoc_args ) { + $project = $args[0]; + $locale = $args[1]; + $set = $assoc_args['set'] ?? 'default'; + + $project = GP::$project->by_path( $project ); + if ( ! $project ) { + WP_CLI::error( 'Project not found!', 'glotpress' ); + return; + } + + $gp_locale = GP_Locales::by_slug( $locale ); + if ( ! $gp_locale ) { + WP_CLI::error( 'Locale not found!', 'glotpress' ); + return; + } + + $translation_set = GP::$translation_set->by_project_id_slug_and_locale( $project->id, $set, $gp_locale->slug ); + if ( $translation_set ) { + // Silently exit, unless verbose. + if ( $assoc_args['verbose'] ?? false ) { + WP_CLI::success( 'Already exists.' ); + } + + return; + } + + // Create the translation set. + GP::$translation_set->create( [ + 'name' => $gp_locale->english_name, + 'slug' => $set, + 'project_id' => $project->id, + 'locale' => $gp_locale->slug, + ] ); + WP_CLI::success( 'Translation set created.' ); + } +} diff --git a/content/plugins/f-translate/inc/namespace.php b/content/plugins/f-translate/inc/namespace.php new file mode 100644 index 0000000..77737db --- /dev/null +++ b/content/plugins/f-translate/inc/namespace.php @@ -0,0 +1,24 @@ + $project_id, + 'translation_set' => $translation_set, + 'translation' => $translation, + 'warning' => $warning, + 'user' => $user, + 'timestamp' => gmdate( 'Y-m-d H:i:s' ), + 'status' => 'needs-review' + ); + $format = array( '%d', '%d', '%d', '%s', '%d', '%s', '%s' ); + $wpdb->insert( + $this->table_name, + $warning, + $format + ); + } + + public static function get_schema() : string { + global $gp_table_prefix; + return <<<"END" + CREATE TABLE `{$gp_table_prefix}dotorg_warnings` ( + `ID` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `project_id` bigint(20) unsigned NOT NULL DEFAULT '0', + `translation_set` bigint(20) unsigned NOT NULL DEFAULT '0', + `translation` bigint(20) unsigned NOT NULL DEFAULT '0', + `warning` varchar(20) NOT NULL DEFAULT '', + `user` bigint(20) unsigned NOT NULL DEFAULT '0', + `timestamp` datetime NOT NULL default '0000-00-00 00:00:00', + `status` varchar(20) NOT NULL DEFAULT '', + PRIMARY KEY (`ID`) + ) ENGINE=InnoDB DEFAULT CHARSET=latin1; + END; + } +} diff --git a/content/plugins/f-translate/inc/stats/class-projectstats.php b/content/plugins/f-translate/inc/stats/class-projectstats.php new file mode 100644 index 0000000..a87cf32 --- /dev/null +++ b/content/plugins/f-translate/inc/stats/class-projectstats.php @@ -0,0 +1,235 @@ +project_translation_status = $gp_table_prefix . 'project_translation_status'; + } + + function translation_edited( $translation ) { + /** @var \GP_Translation_Set */ + $set = GP::$translation_set->get( $translation->translation_set_id ); + $this->projects_to_update[ $set->project_id ][ $set->locale . '/' . $set->slug ] = true; + } + + function originals_imported( $project_id, $originals_added, $originals_existing, $originals_obsoleted, $originals_fuzzied ) { + if ( $originals_added || $originals_existing || $originals_obsoleted || $originals_fuzzied ) { + $this->projects_to_update[ $project_id ] = true; + } + } + + // Count up all the strings + function get_project_translation_counts( $project_id, $locale, $locale_slug, &$counts = array() ) { + if ( ! $counts ) { + $counts = array( 'all' => 0, 'current' => 0, 'waiting' => 0, 'fuzzy' => 0, 'warnings' => 0, 'untranslated' => 0 ); + } + + // Not all projects have translation sets + /** @var \GP_Translation_Set */ + $set = GP::$translation_set->by_project_id_slug_and_locale( $project_id, $locale_slug, $locale ); + if ( $set ) { + // Force a refresh of the translation set counts + wp_cache_delete( $set->id, 'translation_set_status_breakdown' ); + + $counts['all'] += $set->all_count(); + $counts['current'] += $set->current_count(); + $counts['waiting'] += $set->waiting_count(); + $counts['fuzzy'] += $set->fuzzy_count(); + $counts['warnings'] += $set->warnings_count(); + $counts['untranslated'] += $set->untranslated_count(); + } + + // Fetch the strings from the sub projects too + /** @var \GP_Project */ + foreach ( GP::$project->get( $project_id )->sub_projects() as $project ) { + if ( ! $project->active ) { + continue; + } + $this->get_project_translation_counts( $project->id, $locale, $locale_slug, $counts ); + } + + return $counts; + } + + /** + * Cron task to cache the string counts for the wp-themes and wp-plugins parent categories. + * + * These don't have any translation sets, but we need to be able to query the waiting strings for them. + */ + public function cache_wp_themes_wp_plugins_strings() { + global $wpdb; + + $cached_projects = [ + GP::$project->by_path( 'wp-plugins' ), + GP::$project->by_path( 'wp-themes' ), + ]; + + // Store the counts for these parent projects as the sum of their children. + $sql = "INSERT INTO {$wpdb->project_translation_status} ( `project_id`, `locale`, `locale_slug`, `all`, `current`, `waiting`, `fuzzy`, `warnings`, `untranslated`, `date_added`, `date_modified`) + SELECT + p.parent_project_id as project_id, + locale, locale_slug, + SUM( stats.all ) as `all`, SUM( stats.current ) as `current`, SUM( stats.waiting ) as `waiting`, + SUM( stats.fuzzy ) as `fuzzy`, SUM( stats.warnings ) as `warnings`, SUM( stats.untranslated ) as `untranslated`, + NOW() as `date_added`, NOW() as `date_modified` + FROM {$wpdb->project_translation_status} stats + LEFT JOIN {$wpdb->gp_projects} p ON stats.project_id = p.id + WHERE + p.parent_project_id = %d + AND p.active = 1 + GROUP BY locale, locale_slug + ON DUPLICATE KEY UPDATE + `all` = VALUES(`all`), `current` = VALUES(`current`), + `waiting` = VALUES(`waiting`), `fuzzy` = VALUES(`fuzzy`), + `warnings` = VALUES(`warnings`), `untranslated` = VALUES(`untranslated`), + `date_modified` = VALUES(`date_modified`); + "; + + foreach ( $cached_projects as $project ) { + $wpdb->query( $wpdb->prepare( $sql, $project->id ) ); + } + + } + + function shutdown() { + global $wpdb; + $values = array(); + + // If a project is `true` then we need to fetch all translation sets for it. + foreach ( $this->projects_to_update as $project_id => $set_data ) { + if ( true === $set_data ) { + $this->projects_to_update[ $project_id ] = array(); + /** @var \GP_Translation_Set */ + foreach ( GP::$translation_set->by_project_id( $project_id ) as $set ) { + $this->projects_to_update[ $project_id ][ $set->locale . '/' . $set->slug ] = true; + } + } + + } + + // Update all parent projects as well. + // This does NOT update a root parent (ie. ! $parent_project_id) as we use those as grouping categories. + $projects = $this->projects_to_update; + foreach ( $projects as $project_id => $data ) { + // Do all parents + /** @var \GP_Project */ + $project = GP::$project->get( $project_id ); + while ( $project ) { + /** @var \GP_Project */ + $project = GP::$project->get( $project->parent_project_id ); + if ( $project->parent_project_id ) { + $projects[ $project->id ] = $data; + } else { + break; + } + } + } + $this->projects_to_update += $projects; + unset( $projects ); + + $now = current_time( 'mysql', 1 ); + + foreach ( $this->projects_to_update as $project_id => $locale_sets ) { + $locale_sets = array_keys( $locale_sets ); + $locale_sets = array_map( function( $set ) { return explode( '/', $set ); }, $locale_sets ); + + foreach ( $locale_sets as $locale_set ) { + list( $locale, $locale_slug ) = $locale_set; + $counts = $this->get_project_translation_counts( $project_id, $locale, $locale_slug ); + + $values[] = $wpdb->prepare( '(%d, %s, %s, %d, %d, %d, %d, %d, %d, %s, %s)', + $project_id, + $locale, + $locale_slug, + $counts['all'], + $counts['current'], + $counts['waiting'], + $counts['fuzzy'], + $counts['warnings'], + $counts['untranslated'], + $now, + $now + ); + } + + // If we're processing a large batch, add them as we go to avoid query lengths & memory limits + if ( count( $values ) > 50 ) { + $wpdb->query( "INSERT INTO {$wpdb->project_translation_status} (`project_id`, `locale`, `locale_slug`, `all`, `current`, `waiting`, `fuzzy`, `warnings`, `untranslated`, `date_added`, `date_modified` ) VALUES " . implode( ', ', $values ) . " ON DUPLICATE KEY UPDATE `all`=VALUES(`all`), `current`=VALUES(`current`), `waiting`=VAlUES(`waiting`), `fuzzy`=VALUES(`fuzzy`), `warnings`=VALUES(`warnings`), `untranslated`=VALUES(`untranslated`), `date_modified`=VALUES(`date_modified`)" ); + $values = array(); + } + } + $this->projects_to_update = array(); + + if ( $values ) { + $wpdb->query( "INSERT INTO {$wpdb->project_translation_status} (`project_id`, `locale`, `locale_slug`, `all`, `current`, `waiting`, `fuzzy`, `warnings`, `untranslated`, `date_added`, `date_modified` ) VALUES " . implode( ', ', $values ) . " ON DUPLICATE KEY UPDATE `all`=VALUES(`all`), `current`=VALUES(`current`), `waiting`=VALUES(`waiting`), `fuzzy`=VALUES(`fuzzy`), `warnings`=VALUES(`warnings`), `untranslated`=VALUES(`untranslated`), `date_modified`=VALUES(`date_modified`)" ); + } + } + + public static function get_schema() : string { + global $gp_table_prefix; + return <<<"END" + CREATE TABLE `{$gp_table_prefix}project_translation_status` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `project_id` int(10) unsigned NOT NULL, + `locale` varchar(10) NOT NULL, + `locale_slug` varchar(255) NOT NULL, + `all` int(10) unsigned NOT NULL DEFAULT '0', + `current` int(10) unsigned NOT NULL DEFAULT '0', + `waiting` int(10) unsigned NOT NULL DEFAULT '0', + `fuzzy` int(10) unsigned NOT NULL DEFAULT '0', + `warnings` int(10) unsigned NOT NULL DEFAULT '0', + `untranslated` int(10) unsigned NOT NULL DEFAULT '0', + PRIMARY KEY (`id`), + UNIQUE KEY `project_locale` (`project_id`,`locale`,`locale_slug`), + KEY `all` (`all`), + KEY `current` (`current`), + KEY `waiting` (`waiting`), + KEY `fuzzy` (`fuzzy`), + KEY `warnings` (`warnings`), + KEY `untranslated` (`untranslated`) + ) ENGINE=InnoDB DEFAULT CHARSET=latin1; + END; + } +} diff --git a/content/plugins/f-translate/inc/stats/class-userstats.php b/content/plugins/f-translate/inc/stats/class-userstats.php new file mode 100644 index 0000000..1ac76d6 --- /dev/null +++ b/content/plugins/f-translate/inc/stats/class-userstats.php @@ -0,0 +1,241 @@ +user_translations_count = $gp_table_prefix . 'user_translations_count'; + $wpdb->user_projects = $gp_table_prefix . 'user_projects'; + } + + public function translation_updated( $translation ) { + if ( ! $translation->user_id ) { + return; + } + + /** @var \GP_Translation_Set */ + $translation_set = GP::$translation_set->get( $translation->translation_set_id ); + + if ( 'waiting' === $translation->status ) { + // New translation suggested + $this->bump_user_stat( $translation->user_id, $translation_set->locale, $translation_set->slug, 1, 0 ); + + } elseif ( 'current' === $translation->status && 'gp_translation_created' === current_filter() ) { + // New translation suggested & approved + $this->bump_user_stat( $translation->user_id, $translation_set->locale, $translation_set->slug, 1, 1 ); + + } elseif ( 'current' === $translation->status ) { + // Translation approved + $this->bump_user_stat( $translation->user_id, $translation_set->locale, $translation_set->slug, 0, 1 ); + + } + + // Record the last time the user submitted a translation for a project/locale. + if ( 'gp_translation_created' == current_filter() ) { + $project = GP::$project->get( $translation_set->project_id ); + + // Find the "root" project ID. + // For projects with sub-projects, we only want to store the "parent" project. + // ie. wp-plugins/plugin-name, wp/dev, or apps/android + $project_path_we_want = implode( '/', array_slice( explode( '/', $project->path ), 0, 2 ) ); + if ( $project_path_we_want != $project->path ) { + $project = GP::$project->by_path( $project_path_we_want ); + } + + $key = "{$translation->user_id},{$project->id},{$translation_set->locale},{$translation_set->slug}"; + if ( ! isset( $this->user_project_stats[ $key ] ) ) { + $this->user_project_stats[ $key ] = 0; + } + $this->user_project_stats[ $key ]++; + } + } + + private function bump_user_stat( $user_id, $locale, $locale_slug, $suggested = 0, $accepted = 0 ) { + $key = "$user_id,$locale,$locale_slug"; + + if ( isset( $this->user_stats[ $key ] ) ) { + $this->user_stats[ $key ]->suggested += $suggested; + $this->user_stats[ $key ]->accepted += $accepted; + } else { + $this->user_stats[ $key ] = (object) array( + 'suggested' => $suggested, + 'accepted' => $accepted, + ); + } + } + + public function write_stats_to_database() { + global $wpdb; + + $now = current_time( 'mysql', 1 ); + + $values = []; + foreach ( $this->user_stats as $key => $stats ) { + list( $user_id, $locale, $locale_slug ) = explode( ',', $key ); + + $values[] = $wpdb->prepare( '(%d, %s, %s, %d, %d, %s, %s)', + $user_id, + $locale, + $locale_slug, + $stats->suggested, + $stats->accepted, + $now, + $now + ); + + // If we're processing a large batch, add them as we go to avoid query lengths & memory limits. + if ( count( $values ) > 50 ) { + $wpdb->query( + "INSERT INTO {$wpdb->user_translations_count} (`user_id`, `locale`, `locale_slug`, `suggested`, `accepted`, `date_added`, `date_modified`) + VALUES " . implode( ', ', $values ) . " + ON DUPLICATE KEY UPDATE `suggested`=`suggested` + VALUES(`suggested`), `accepted`=`accepted` + VALUES(`accepted`), `date_modified`=VALUES(`date_modified`)" + ); + $values = []; + } + } + + if ( $values ) { + $wpdb->query( + "INSERT INTO {$wpdb->user_translations_count} (`user_id`, `locale`, `locale_slug`, `suggested`, `accepted`, `date_added`, `date_modified`) + VALUES " . implode( ', ', $values ) . " + ON DUPLICATE KEY UPDATE `suggested`=`suggested` + VALUES(`suggested`), `accepted`=`accepted` + VALUES(`accepted`), `date_modified`=VALUES(`date_modified`)" + ); + $values = []; + } + + // Process the user project stats too. + $values = []; + foreach ( $this->user_project_stats as $key => $string_count ) { + list( $user_id, $project_id, $locale, $locale_slug ) = explode( ',', $key ); + + // Step 1 - Does this user already have the project listed? Just Bump the date. + if ( $id = $wpdb->get_var( $wpdb->prepare( + "SELECT id FROM {$wpdb->user_projects} + WHERE user_id = %d AND project_id = %d AND locale = %s AND locale_slug = %s", + $user_id, $project_id, $locale, $locale_slug + ) ) ) { + $wpdb->update( + $wpdb->user_projects, + [ 'last_modified' => $now ], + [ 'id' => $id ] + ); + continue; + } + + // Step 2 - More than 5 strings? Import Maybe? Just insert. + if ( $string_count >= 5 ) { + $wpdb->insert( + $wpdb->user_projects, + [ + 'user_id' => $user_id, + 'project_id' => $project_id, + 'locale' => $locale, + 'locale_slug' => $locale_slug, + 'last_modified' => $now + ] + ); + continue; + } + + // Step 3 - If not, find all the sub-project IDs, then all the translation sets, count strings by user. + $this_project = GP::$project->get( $project_id ); + $translation_set_ids = []; + + if ( ! $this_project->active ) { + continue; + } + + if ( $set = GP::$translation_set->by_project_id_slug_and_locale( $project_id, $locale_slug, $locale ) ) { + $translation_set_ids[] = (int) $set->id; + } + + // Fetch the strings from the sub projects too + foreach ( $this_project->sub_projects() as $project ) { + if ( ! $project->active ) { + continue; + } + if ( $set = GP::$translation_set->by_project_id_slug_and_locale( $project->id, $locale_slug, $locale ) ) { + $translation_set_ids[] = (int) $set->id; + } + } + + $user_translations = GP::$translation->find_many_no_map( [ + 'user_id' => $user_id, + 'translation_set_id' => $translation_set_ids + ] ); + + if ( $user_translations && count( $user_translations ) >= 5 ) { + $wpdb->insert( + $wpdb->user_projects, + [ + 'user_id' => $user_id, + 'project_id' => $project_id, + 'locale' => $locale, + 'locale_slug' => $locale_slug, + 'last_modified' => $now + ] + ); + continue; + } + } + } + + public static function get_schema() : string { + global $gp_table_prefix; + // Note: WordPress uses BIGINT(20) for user_id; GlotPress uses int(10) + return <<<"END" + CREATE TABLE `{$gp_table_prefix}user_translations_count` ( + `id` int(10) NOT NULL AUTO_INCREMENT, + `user_id` int(10) unsigned NOT NULL, + `locale` varchar(255) NOT NULL DEFAULT '', + `locale_slug` varchar(255) NOT NULL DEFAULT '', + `suggested` int(10) unsigned NOT NULL DEFAULT '0', + `accepted` int(10) unsigned NOT NULL DEFAULT '0', + `date_added` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', + `date_modified` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', + PRIMARY KEY (`id`), + UNIQUE KEY `user_id` (`user_id`,`locale`,`locale_slug`), + KEY `locale` (`locale`,`locale_slug`) + ) ENGINE=InnoDB DEFAULT CHARSET=latin1; + + CREATE TABLE `{$gp_table_prefix}user_projects` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `user_id` int(10) unsigned NOT NULL, + `project_id` int(11) unsigned NOT NULL, + `locale` varchar(255) NOT NULL, + `locale_slug` varchar(255) NOT NULL DEFAULT 'default', + `last_modified` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', + PRIMARY KEY (`id`), + UNIQUE KEY `user_project_locale` (`user_id`,`project_id`,`locale`,`locale_slug`) + ) ENGINE=InnoDB DEFAULT CHARSET=latin1; + END; + } +} diff --git a/content/plugins/f-translate/inc/stats/class-warningstats.php b/content/plugins/f-translate/inc/stats/class-warningstats.php new file mode 100644 index 0000000..7ccaef2 --- /dev/null +++ b/content/plugins/f-translate/inc/stats/class-warningstats.php @@ -0,0 +1,114 @@ +dotorg_translation_warnings = $gp_table_prefix . 'dotorg_translation_warnings'; + } + + public function translation_updated( $translation ) { + if ( ! $translation->warnings ) { + return; + } + + // We only want to trigger for strings which are live, or are for consideration. + if ( ! in_array( $translation->status, array( 'current', 'waiting' ) ) ) { + return; + } + + /** @var \GP_Original */ + $original = GP::$original->get( $translation->original_id ); + /** @var \GP_Project */ + $project = GP::$project->get( $original->project_id ); + /** @var \GP_Translation_Set */ + $translation_set = GP::$translation_set->get( $translation->translation_set_id ); + + foreach( $translation->warnings as $index => $warnings ) { + foreach ( $warnings as $warning_key => $warning ) { + $key = "{$translation->user_id},{$translation_set->locale},{$translation_set->slug},{$project->path},{$translation->id},{$warning_key}"; + + $this->warning_stats[ $key ] = $warning; + } + } + } + + + public function write_stats_to_database() { + global $wpdb; + + $now = current_time( 'mysql', 1 ); + + $values = array(); + foreach ( $this->warning_stats as $key => $message ) { + list( $user_id, $locale, $locale_slug, $project_path, $translation_id, $warning ) = explode( ',', $key ); + + $values[] = $wpdb->prepare( '(%d, %s, %s, %s, %d, %s, %s, %s)', + $user_id, + $locale, + $locale_slug, + $project_path, + $translation_id, + $warning, + $now, + $message + ); + + // If we're processing a large batch, add them as we go to avoid query lengths & memory limits. + if ( count( $values ) > 50 ) { + $wpdb->query( + "INSERT INTO {$wpdb->dotorg_translation_warnings} (`user_id`, `locale`, `locale_slug`, `project_path`, `translation_id`, `warning`, `timestamp`, `message`) + VALUES " . implode( ', ', $values ) + ); + $values = array(); + } + } + + if ( $values ) { + $wpdb->query( + "INSERT INTO {$wpdb->dotorg_translation_warnings} (`user_id`, `locale`, `locale_slug`, `project_path`, `translation_id`, `warning`, `timestamp`, `message`) + VALUES " . implode( ', ', $values ) + ); + } + } + + public static function get_schema() : string { + global $gp_table_prefix; + return <<<"END" + CREATE TABLE `{$gp_table_prefix}dotorg_translation_warnings` ( + `id` bigint(10) NOT NULL AUTO_INCREMENT, + `user_id` bigint(20) unsigned NOT NULL DEFAULT '0', + `locale` varchar(255) NOT NULL DEFAULT '', + `locale_slug` varchar(255) NOT NULL DEFAULT '', + `project_path` varchar(255) NOT NULL DEFAULT '', + `translation_id` bigint(20) unsigned NOT NULL DEFAULT '0', + `warning` varchar(20) NOT NULL DEFAULT '', + `timestamp` datetime NOT NULL default '0000-00-00 00:00:00', + `message` longtext + PRIMARY KEY (`id`) + ) ENGINE=InnoDB DEFAULT CHARSET=latin1; + END; + } +} diff --git a/content/plugins/f-translate/inc/stats/namespace.php b/content/plugins/f-translate/inc/stats/namespace.php new file mode 100644 index 0000000..5fcf448 --- /dev/null +++ b/content/plugins/f-translate/inc/stats/namespace.php @@ -0,0 +1,54 @@ + new UserStats(), + 'project' => new ProjectStats(), + 'warnings' => new WarningStats(), + 'discarded_warning' => new DiscardedWarningStats(), + ]; +} + +/** + * Initialize the stats system, including database tables. + */ +function init_command( $args, $assoc_args ) { + $schemas = [ + 'user' => UserStats::get_schema(), + 'project' => ProjectStats::get_schema(), + 'warnings' => WarningStats::get_schema(), + 'discarded_warning' => DiscardedWarningStats::get_schema(), + ]; + + if ( ! function_exists( 'dbDelta' ) ) { + require_once ABSPATH . 'wp-admin/includes/upgrade.php'; + } + + foreach ( $schemas as $name => $schema ) { + $res = dbDelta( $schema ); + foreach ( $res as $result ) { + WP_CLI::line( $result ); + } + } + + // Output a success message. + WP_CLI::success( 'Stats tables initialized.' ); +} diff --git a/content/plugins/f-translate/plugin.php b/content/plugins/f-translate/plugin.php new file mode 100644 index 0000000..50e02db --- /dev/null +++ b/content/plugins/f-translate/plugin.php @@ -0,0 +1,24 @@ + + +

Page not found

+ +

The page you were looking for could not be found. I’m sorry, it’s not your fault… probably. Return to the homepage

+ + + +

Analyze translation consistency across projects. The result is limited to 500 translations.

+ + +
+

+ + + + + + + + 'Select a locale', + ]; + $sets_to_hide = array( + 'ca/valencia', + 'nl/formal/default', + 'en/formal', + 'en/default', + 'fr/formal', + 'de/formal/default', + 'de-ch/info/default', + 'pt/ao90/default', + 'sr/latin', + 'sr/latin/latin', + ); + $sets = array_diff_key( $sets, array_flip( $sets_to_hide ) ); + $locale_options = array_merge( $locale_options, $sets ); + echo gp_select( + 'set', + $locale_options, + $set, + [ + 'class' => 'consistency-form-locale', + 'required' => 'required', + ] + ); + ?> + + + + + 'All Projects', + ]; + $project_options = $project_options + $projects; + echo gp_select( + 'project', + $project_options, + $project, + [ + 'class' => 'consistency-form-project', + ] + ); + ?> + +

+ +

+ +

+ +

+ +

+
+ +

No results were found.

'; + +} elseif ( $performed_search && $results ) { + $translations_unique_count = count( $translations_unique ); + $has_different_translations = $translations_unique_count > 1; + if ( ! $has_different_translations ) { + echo '

All originals have the same translations.

'; + } else { + echo '

There are ' . $translations_unique_count . ' different translations. View

'; + echo ''; + echo '
'; + } + + ?> + + + + + + + $translation ) { + $prev_arrow = ''; + $next_arrow = ''; + + $prev_translation = $translations[ $translation_index - 1 ] ?? false; + $next_translation = $translations[ $translation_index + 1 ] ?? false; + + if ( ! $prev_translation ) { + $next_arrow = ''; + } elseif ( ! $next_translation ) { + $prev_arrow = ''; + } else { + $prev_arrow = ''; + $next_arrow = ''; + } + + printf( + '', + esc_attr( 't-' . md5( $translation ) ), + esc_translation( $translation ), + $next_arrow, + $prev_arrow + ); + + foreach ( $results as $result ) { + if ( $result->translation != $translation ) { + continue; + } + + $project_name = $result->project_name; + $parent_project_id = $result->project_parent_id; + $is_active = $result->active; + while ( $parent_project_id ) { + $parent_project = GP::$project->get( $parent_project_id ); + $parent_project_id = $parent_project->parent_project_id; + $project_name = "{$parent_project->name} - {$project_name}"; + $is_active = $is_active && $parent_project->active; + } + + $original_context = ''; + if ( $result->original_context ) { + $original_context = sprintf( + ' %s', + esc_translation( $result->original_context ) + ); + } + + if( $is_active ) { + $active_text = ''; + } else { + $active_text = sprintf( + ' %s', + esc_translation( '(inactive)' ) + ); + } + + printf( + '', + isset( $parent_project->name ) ? sanitize_title( 'project-' . $parent_project->name ) : '', + sprintf( + '
%s%s
+
Project: %s%s
', + esc_translation( $result->original_singular ), + $original_context, + $result->project_path, + $set, + $project_name, + $active_text + ), + sprintf( + '
%s
+
+ Source | + Added: %s +
', + $locale_is_rtl ? ' rtl' : '', + esc_translation( $result->translation ), + $result->project_path, + $set, + $result->original_id, + $result->translation_id, + $result->translation_added + ) + ); + } + } + ?> + +
OriginalTranslation
%s %s %s
%s%s
+ + + + +svg{display:block;position:absolute;top:0;left:0}.ct-minor-second{display:block;position:relative;width:100%}.ct-minor-second:before{display:block;float:left;content:"";width:0;height:0;padding-bottom:93.75%}.ct-minor-second:after{display:table}.ct-minor-second>svg{display:block;position:absolute;top:0;left:0}.ct-major-second{display:block;position:relative;width:100%}.ct-major-second:before{display:block;float:left;content:"";width:0;height:0;padding-bottom:88.8888888889%}.ct-major-second:after{display:table}.ct-major-second>svg{display:block;position:absolute;top:0;left:0}.ct-minor-third{display:block;position:relative;width:100%}.ct-minor-third:before{display:block;float:left;content:"";width:0;height:0;padding-bottom:83.3333333333%}.ct-minor-third:after{display:table}.ct-minor-third>svg{display:block;position:absolute;top:0;left:0}.ct-major-third{display:block;position:relative;width:100%}.ct-major-third:before{display:block;float:left;content:"";width:0;height:0;padding-bottom:80%}.ct-major-third:after{display:table}.ct-major-third>svg{display:block;position:absolute;top:0;left:0}.ct-perfect-fourth{display:block;position:relative;width:100%}.ct-perfect-fourth:before{display:block;float:left;content:"";width:0;height:0;padding-bottom:75%}.ct-perfect-fourth:after{display:table}.ct-perfect-fourth>svg{display:block;position:absolute;top:0;left:0}.ct-perfect-fifth{display:block;position:relative;width:100%}.ct-perfect-fifth:before{display:block;float:left;content:"";width:0;height:0;padding-bottom:66.6666666667%}.ct-perfect-fifth:after{display:table}.ct-perfect-fifth>svg{display:block;position:absolute;top:0;left:0}.ct-minor-sixth{display:block;position:relative;width:100%}.ct-minor-sixth:before{display:block;float:left;content:"";width:0;height:0;padding-bottom:62.5%}.ct-minor-sixth:after{display:table}.ct-minor-sixth>svg{display:block;position:absolute;top:0;left:0}.ct-golden-section{display:block;position:relative;width:100%}.ct-golden-section:before{display:block;float:left;content:"";width:0;height:0;padding-bottom:61.804697157%}.ct-golden-section:after{content:"";display:table;clear:both}.ct-golden-section>svg{display:block;position:absolute;top:0;left:0}.ct-major-sixth{display:block;position:relative;width:100%}.ct-major-sixth:before{display:block;float:left;content:"";width:0;height:0;padding-bottom:60%}.ct-major-sixth:after{display:table}.ct-major-sixth>svg{display:block;position:absolute;top:0;left:0}.ct-minor-seventh{display:block;position:relative;width:100%}.ct-minor-seventh:before{display:block;float:left;content:"";width:0;height:0;padding-bottom:56.25%}.ct-minor-seventh:after{display:table}.ct-minor-seventh>svg{display:block;position:absolute;top:0;left:0}.ct-major-seventh{display:block;position:relative;width:100%}.ct-major-seventh:before{display:block;float:left;content:"";width:0;height:0;padding-bottom:53.3333333333%}.ct-major-seventh:after{display:table}.ct-major-seventh>svg{display:block;position:absolute;top:0;left:0}.ct-octave{display:block;position:relative;width:100%}.ct-octave:before{display:block;float:left;content:"";width:0;height:0;padding-bottom:50%}.ct-octave:after{display:table}.ct-octave>svg{display:block;position:absolute;top:0;left:0}.ct-major-tenth{display:block;position:relative;width:100%}.ct-major-tenth:before{display:block;float:left;content:"";width:0;height:0;padding-bottom:40%}.ct-major-tenth:after{display:table}.ct-major-tenth>svg{display:block;position:absolute;top:0;left:0}.ct-major-eleventh{display:block;position:relative;width:100%}.ct-major-eleventh:before{display:block;float:left;content:"";width:0;height:0;padding-bottom:37.5%}.ct-major-eleventh:after{display:table}.ct-major-eleventh>svg{display:block;position:absolute;top:0;left:0}.ct-major-twelfth{display:block;position:relative;width:100%}.ct-major-twelfth:before{display:block;float:left;content:"";width:0;height:0;padding-bottom:33.3333333333%}.ct-major-twelfth:after{display:table}.ct-major-twelfth>svg{display:block;position:absolute;top:0;left:0}.ct-double-octave{display:block;position:relative;width:100%}.ct-double-octave:before{display:block;float:left;content:"";width:0;height:0;padding-bottom:25%}.ct-double-octave:after{display:table}.ct-double-octave>svg{display:block;position:absolute;top:0;left:0} diff --git a/content/plugins/f-translate/templates/footer.php b/content/plugins/f-translate/templates/footer.php new file mode 100644 index 0000000..1ec10a9 --- /dev/null +++ b/content/plugins/f-translate/templates/footer.php @@ -0,0 +1,5 @@ + + +' ); + +?> + + +
+ +
+
+

Fair Translations

+

+ Contribute to translation WordPress core, themes, and plugins by translating them into your language. +

+
+ +
+ + +
+ +
+ +
+ +
+ wp_create_nonce( 'wporg-editor-settings' ), + ) +); + +wp_register_style( + 'chartist', + plugins_url( 'css/chartist.min.css', __FILE__ ), + [], + '0.9.5' +); +wp_register_script( + 'chartist', + plugins_url( 'js/chartist.min.js', __FILE__ ), + [], + '0.9.5' +); + +if ( isset( $template ) && 'translations' === $template ) { + gp_enqueue_script( 'wporg-translate-editor' ); +} + +// Remove Emoji fallback support +remove_action( 'wp_head', 'print_emoji_detection_script', 7 ); +remove_action( 'wp_print_styles', 'print_emoji_styles' ); + +// Remove output of hreflang tags. +add_action( 'wp_head', function () { + remove_action( 'wp_head', 'WordPressdotorg\Theme\hreflang_link_attributes' ); +}, 1 ); + +/** + * Set the document title to that of GlotPress. + * + * @see https://github.com/GlotPress/GlotPress-WP/issues/8 + */ +add_filter( 'document_title_parts', static function() { + return [ + 'title' => gp_title(), + ]; +}, 1 ); + +/** + * Prints markup for translations help modal in footer. + */ +add_action( 'gp_footer', static function() use ( $template, $args ) { + if ( 'translations' === $template && ! empty( $args['locale_slug'] ) ) { + $locale = GP_Locales::by_slug( $args['locale_slug'] ); + wporg_translation_help_modal( $locale ); + } +} ); + +/** + * Prints markup for the translation help dialog. + * + * @param \GP_Locale $locale Locale of the current translation set. + */ +function wporg_translation_help_modal( $locale ) { + $locale_resources = wporg_get_locale_resources( $locale ) + ?> +
+
+ +
+
+ description ) { + $item_output = str_replace( + $args->link_after . '', + $args->link_after . ': ' . $item->description . '', + $item_output + ); + } + + return $item_output; +} + +/** + * Retrieves the navigation menu from the assigned Rosetta site. + * + * Output is cached for an hour. + * + * @param \GP_Locale $locale + * @return string The HTML markup of the navigation menu. + */ +function wporg_get_locale_resources( $locale ) { + if ( empty( $locale->wp_locale ) ) { + return ''; + } + + $transient_key = 'locale-resources-' . $locale->wp_locale; + $cache = get_transient( $transient_key ); + + if ( false !== $cache ) { + return $cache; + } + + $result = get_sites( [ + 'locale' => $locale->wp_locale, + 'network_id' => WPORG_GLOBAL_NETWORK_ID, + 'path' => '/', + 'fields' => 'ids', + 'number' => '1', + ] ); + $site_id = array_shift( $result ); + if ( ! $site_id ) { + set_transient( $transient_key, '', HOUR_IN_SECONDS ); + return ''; + } + + switch_to_blog( $site_id ); + + add_filter( 'walker_nav_menu_start_el', 'wporg_add_nav_description', 10, 4 ); + + $menu = wp_nav_menu( [ + 'theme_location' => 'rosetta_translation_contributor_resources', + 'fallback_cb' => false, + 'container' => false, + 'menu_id' => 'locale-resources', + 'depth' => 2, + 'echo' => false, + ] ); + + remove_filter( 'walker_nav_menu_start_el', 'wporg_add_nav_description' ); + + restore_current_blog(); + + set_transient( $transient_key, $menu, HOUR_IN_SECONDS ); + + return $menu; +} + +/** + * Adds custom classes to the array of body classes. + * + * @param array $classes An array of body classes. + * @return array Filtered body classes. + */ +function wporg_gp_template_body_classes( $classes ) { + $classes[] = 'no-js'; + return $classes; +} +add_filter( 'body_class', 'wporg_gp_template_body_classes' ); + +add_action( 'gp_tmpl_load_locations', function( $locations, $template, $args, $template_path ) { + $core_templates = GP_PATH . 'gp-templates/'; + require_once $core_templates . 'helper-functions.php'; + $locations[] = $core_templates; + return $locations; +}, 50, 4 ); + +function wporg_gp_is_index() { + return GP::$current_route instanceof \WordPressdotorg\GlotPress\Routes\Routes\Index; +} + +/** + * Prints JavaScript helper for menu toggle. + */ +add_action( 'gp_footer', function() { + ?> + + +
+ warnings[ $index ] ) ) : + $warnings = $entry->warnings[ $index ]; + foreach ( $warnings as $key => $value ) : + ?> +
+ + + + + +
+ + +
+ warnings ) ) { + return $count; + } + + foreach ( $entry->warnings as $warnings ) { + $count += count( $warnings ); + } + + return $count; +} + +/** + * Lists file references for a translation. + * + * @param \GP_Project $project Current project. + * @param object $entry Current translation entry. + */ +function wporg_references( $project, $entry ) { + ?> +
    + references as $reference ) : + list( $file, $line ) = array_pad( explode( ':', $reference ), 2, 0 ); + if ( $source_url = $project->source_url( $file, $line ) ) : + ?> +
  • + +
  • + $file:$line"; + endif; + endforeach; + ?> +
+ path ) { + // wporg-mu-plugins is mu-plugins/ based, but NOT those in mu-plugins/pub + if ( str_starts_with( $file, 'mu-plugins/' ) && ! str_starts_with( $file, 'mu-plugins/pub/' ) ) { + $source_url = "https://github.com/WordPress/wporg-mu-plugins/blob/trunk/{$file}#L{$line}"; + + // wporg-gutenberg theme is pretty unique path.. + } elseif ( str_contains( $file, '/themes/wporg-gutenberg/' ) ) { + $source_url = "https://github.com/WordPress/wporg-gutenberg/blob/trunk/{$file}#L{$line}"; + } + + } elseif ( 'meta/rosetta' === $project->path ) { + + // For Rosetta plugins, they're stored in the WordPress.org svn path. + if ( str_starts_with( $file, 'plugins/' ) && str_contains( $source_url, 'meta.trac.wordpress.org' ) ) { + $source_url = str_replace( '/global.wordpress.org/', '/wordpress.org/', $source_url ); + + // Not all Rosetta mu-plugins are public, don't attempt to link to them. + } elseif( + str_starts_with( $file, 'mu-plugins/' ) && + ! ( + str_starts_with( $file, 'mu-plugins/downloads/' ) || + str_starts_with( $file, 'mu-plugins/roles/' ) || + str_starts_with( $file, 'mu-plugins/showcase/' ) + ) + ) { + $source_url = false; + } + } + + return $source_url; +} +add_filter( 'gp_reference_source_url', 'wporg_references_wordpress_org_github', 10, 4 ); + +/** + * Whether to show the context or not. + * + * Prevents displaying the context if it doesn't provide any new information + * to the translator. + * Especially for mobile projects the context is mostly a duplicate of the singular string. + * + * @param \Translation_Entry $translation Current translation entry. + * @return bool Whether to show the context or not. + */ +function wporg_gp_should_display_original_context( $translation ) { + // No context available. + if ( ! $translation->context ) { + return false; + } + + // Context is the same as the singular. + if ( $translation->singular === $translation->context ) { + return false; + } + + // Context was cut-off due to VARCHAR(255) in the database schema. + if ( 255 === mb_strlen( $translation->context ) && 0 === strpos( $translation->singular, $translation->context ) ) { + return false; + } + + return true; +} diff --git a/content/plugins/f-translate/templates/images/browsehappy.png b/content/plugins/f-translate/templates/images/browsehappy.png new file mode 100644 index 0000000..853b91e Binary files /dev/null and b/content/plugins/f-translate/templates/images/browsehappy.png differ diff --git a/content/plugins/f-translate/templates/images/glotpress.png b/content/plugins/f-translate/templates/images/glotpress.png new file mode 100644 index 0000000..6967017 Binary files /dev/null and b/content/plugins/f-translate/templates/images/glotpress.png differ diff --git a/content/plugins/f-translate/templates/images/openverse.png b/content/plugins/f-translate/templates/images/openverse.png new file mode 100644 index 0000000..f10717a Binary files /dev/null and b/content/plugins/f-translate/templates/images/openverse.png differ diff --git a/content/plugins/f-translate/templates/index-locales.php b/content/plugins/f-translate/templates/index-locales.php new file mode 100644 index 0000000..a38e578 --- /dev/null +++ b/content/plugins/f-translate/templates/index-locales.php @@ -0,0 +1,80 @@ + + +
+ +
+ + +
+
+ +

If your locale isn’t below, follow the steps in the Translator Handbook to contribute a new locale.

+ +
+ slug ] ) ) { + $status = $translation_status[ $locale->slug ]; + $percent_complete = floor( $status->current_count / $status->all_count * 100 ); + } + + $wp_locale = ( isset( $locale->wp_locale ) ) ? $locale->wp_locale : $locale->slug; + ?> +
+
    +
  • slug ), $locale->english_name ) ?>
  • +
  • slug ), $locale->native_name ) ?>
  • +
  • slug ), $wp_locale ) ?>
  • +
+
+
%s', + isset( $contributors_count[ $locale->slug ] ) ? $contributors_count[ $locale->slug ] : 0 + ); + echo gp_link_get( 'https://make.wordpress.org/polyglots/teams/?locale=' . $locale->wp_locale, $contributors ); + ?> +
+
+
+
+
+ slug ), 'Contribute Translation', [ 'class' => 'button contribute-button' ] ); ?> +
+
+ +
+ + + +":">",'"':""","'":"'"},c.serialize=function(a){return null===a||void 0===a?a:("number"==typeof a?a=""+a:"object"==typeof a&&(a=JSON.stringify({data:a})),Object.keys(c.escapingMap).reduce(function(a,b){return c.replaceAll(a,b,c.escapingMap[b])},a))},c.deserialize=function(a){if("string"!=typeof a)return a;a=Object.keys(c.escapingMap).reduce(function(a,b){return c.replaceAll(a,c.escapingMap[b],b)},a);try{a=JSON.parse(a),a=void 0!==a.data?a.data:a}catch(b){}return a},c.createSvg=function(a,b,d,e){var f;return b=b||"100%",d=d||"100%",Array.prototype.slice.call(a.querySelectorAll("svg")).filter(function(a){return a.getAttributeNS("http://www.w3.org/2000/xmlns/",c.xmlNs.prefix)}).forEach(function(b){a.removeChild(b)}),f=new c.Svg("svg").attr({width:b,height:d}).addClass(e).attr({style:"width: "+b+"; height: "+d+";"}),a.appendChild(f._node),f},c.reverseData=function(a){a.labels.reverse(),a.series.reverse();for(var b=0;bf.high&&(f.high=c),h&&ck,m=e?c.rho(j.range):0;if(e&&c.projectLength(a,1,j)>=d)j.step=1;else if(e&&m=d)j.step=m;else for(;;){if(l&&c.projectLength(a,j.step,j)<=d)j.step*=2;else{if(l||!(c.projectLength(a,j.step/2,j)>=d))break;if(j.step/=2,e&&j.step%1!==0){j.step*=2;break}}if(i++>1e3)throw new Error("Exceeded maximum number of iterations while optimizing scale step!")}for(g=j.min,h=j.max;g+j.step<=j.low;)g+=j.step;for(;h-j.step>=j.high;)h-=j.step;for(j.min=g,j.max=h,j.range=j.max-j.min,j.values=[],f=j.min;f<=j.max;f+=j.step)j.values.push(c.roundWithPrecision(f));return j},c.polarToCartesian=function(a,b,c,d){var e=(d-90)*Math.PI/180;return{x:a+c*Math.cos(e),y:b+c*Math.sin(e)}},c.createChartRect=function(a,b,d){var e=!(!b.axisX&&!b.axisY),f=e?b.axisY.offset:0,g=e?b.axisX.offset:0,h=a.width()||c.quantity(b.width).value||0,i=a.height()||c.quantity(b.height).value||0,j=c.normalizePadding(b.chartPadding,d);h=Math.max(h,f+j.left+j.right),i=Math.max(i,g+j.top+j.bottom);var k={padding:j,width:function(){return this.x2-this.x1},height:function(){return this.y1-this.y2}};return e?("start"===b.axisX.position?(k.y2=j.top+g,k.y1=Math.max(i-j.bottom,k.y2+1)):(k.y2=j.top,k.y1=Math.max(i-j.bottom-g,k.y2+1)),"start"===b.axisY.position?(k.x1=j.left+f,k.x2=Math.max(h-j.right,k.x1+1)):(k.x1=j.left,k.x2=Math.max(h-j.right-f,k.x1+1))):(k.x1=j.left,k.x2=Math.max(h-j.right,k.x1+1),k.y2=j.top,k.y1=Math.max(i-j.bottom,k.y2+1)),k},c.createGrid=function(a,b,d,e,f,g,h,i){var j={};j[d.units.pos+"1"]=a,j[d.units.pos+"2"]=a,j[d.counterUnits.pos+"1"]=e,j[d.counterUnits.pos+"2"]=e+f;var k=g.elem("line",j,h.join(" "));i.emit("draw",c.extend({type:"grid",axis:d,index:b,group:g,element:k},j))},c.createLabel=function(a,b,d,e,f,g,h,i,j,k,l){var m,n={};if(n[f.units.pos]=a+h[f.units.pos],n[f.counterUnits.pos]=h[f.counterUnits.pos],n[f.units.len]=b,n[f.counterUnits.len]=g-10,k){var o=''+e[d]+"";m=i.foreignObject(o,c.extend({style:"overflow: visible;"},n))}else m=i.elem("text",n,j.join(" ")).text(e[d]);l.emit("draw",c.extend({type:"label",axis:f,index:d,group:i,element:m,text:e[d]},n))},c.getSeriesOption=function(a,b,c){if(a.name&&b.series&&b.series[a.name]){var d=b.series[a.name];return d.hasOwnProperty(c)?d[c]:b[c]}return b[c]},c.optionsProvider=function(b,d,e){function f(b){var f=h;if(h=c.extend({},j),d)for(i=0;i1){var i=[];return h.forEach(function(a){i.push(g(a.pathCoordinates,a.valueData))}),c.Svg.Path.join(i)}if(a=h[0].pathCoordinates,d=h[0].valueData,a.length<=4)return c.Interpolation.none()(a,d);for(var j,k=(new c.Svg.Path).move(a[0],a[1],!1,d[0]),l=0,m=a.length;m-2*!j>l;l+=2){var n=[{x:+a[l-2],y:+a[l-1]},{x:+a[l],y:+a[l+1]},{x:+a[l+2],y:+a[l+3]},{x:+a[l+4],y:+a[l+5]}];j?l?m-4===l?n[3]={x:+a[0],y:+a[1]}:m-2===l&&(n[2]={x:+a[0],y:+a[1]},n[3]={x:+a[2],y:+a[3]}):n[0]={x:+a[m-2],y:+a[m-1]}:m-4===l?n[3]=n[2]:l||(n[0]={x:+a[l],y:+a[l+1]}),k.curve(e*(-n[0].x+6*n[1].x+n[2].x)/6+f*n[2].x,e*(-n[0].y+6*n[1].y+n[2].y)/6+f*n[2].y,e*(n[1].x+6*n[2].x-n[3].x)/6+f*n[2].x,e*(n[1].y+6*n[2].y-n[3].y)/6+f*n[2].y,n[2].x,n[2].y,!1,d[(l+2)/2])}return k}},c.Interpolation.step=function(a){var b={postpone:!0,fillHoles:!1};return a=c.extend({},b,a),function(b,d){for(var e,f,g,h=new c.Svg.Path,i=0;i1}).map(function(a){var b=a.pathElements[0],c=a.pathElements[a.pathElements.length-1];return a.clone(!0).position(0).remove(1).move(b.x,r).line(b.x,b.y).position(a.pathElements.length+1).line(c.x,r)}).forEach(function(h){var k=i.elem("path",{d:h.stringify()},a.classNames.area,!0).attr({values:b.normalized[g]},c.xmlNs.uri);this.eventEmitter.emit("draw",{type:"area",values:b.normalized[g],path:h.clone(),series:f,seriesIndex:g,axisX:d,axisY:e,chartRect:j,index:g,group:i,element:k})}.bind(this))}}.bind(this)),this.eventEmitter.emit("created",{bounds:e.bounds,chartRect:j,axisX:d,axisY:e,svg:this.svg,options:a})}function e(a,b,d,e){c.Line["super"].constructor.call(this,a,b,f,c.extend({},f,d),e)}var f={axisX:{offset:30,position:"end",labelOffset:{x:0,y:0},showLabel:!0,showGrid:!0,labelInterpolationFnc:c.noop,type:void 0},axisY:{offset:40,position:"start",labelOffset:{x:0,y:0},showLabel:!0,showGrid:!0,labelInterpolationFnc:c.noop,type:void 0,scaleMinSpace:20,onlyInteger:!1},width:void 0,height:void 0,showLine:!0,showPoint:!0,showArea:!1,areaBase:0,lineSmooth:!0,low:void 0,high:void 0,chartPadding:{top:15,right:15,bottom:5,left:10},fullWidth:!1,reverseData:!1,classNames:{chart:"ct-chart-line",label:"ct-label",labelGroup:"ct-labels",series:"ct-series",line:"ct-line",point:"ct-point",area:"ct-area",grid:"ct-grid",gridGroup:"ct-grids",vertical:"ct-vertical",horizontal:"ct-horizontal",start:"ct-start",end:"ct-end"}};c.Line=c.Base.extend({constructor:e,createChart:d})}(window,document,a),function(a,b,c){"use strict";function d(a){var b,d={raw:this.data,normalized:a.distributeSeries?c.getDataArray(this.data,a.reverseData,a.horizontalBars?"x":"y").map(function(a){return[a]}):c.getDataArray(this.data,a.reverseData,a.horizontalBars?"x":"y")};this.svg=c.createSvg(this.container,a.width,a.height,a.classNames.chart+(a.horizontalBars?" "+a.classNames.horizontalBars:""));var e=this.svg.elem("g").addClass(a.classNames.gridGroup),g=this.svg.elem("g"),h=this.svg.elem("g").addClass(a.classNames.labelGroup);if(a.stackBars){var i=c.serialMap(d.normalized,function(){return Array.prototype.slice.call(arguments).map(function(a){return a}).reduce(function(a,b){return{x:a.x+b.x||0,y:a.y+b.y||0}},{x:0,y:0})});b=c.getHighLow([i],c.extend({},a,{referenceValue:0}),a.horizontalBars?"x":"y")}else b=c.getHighLow(d.normalized,c.extend({},a,{referenceValue:0}),a.horizontalBars?"x":"y");b.high=+a.high||(0===a.high?0:b.high),b.low=+a.low||(0===a.low?0:b.low);var j,k,l,m,n,o=c.createChartRect(this.svg,a,f.padding);k=a.distributeSeries&&a.stackBars?d.raw.labels.slice(0,1):d.raw.labels,a.horizontalBars?(j=m=void 0===a.axisX.type?new c.AutoScaleAxis(c.Axis.units.x,d,o,c.extend({},a.axisX,{highLow:b,referenceValue:0})):a.axisX.type.call(c,c.Axis.units.x,d,o,c.extend({},a.axisX,{highLow:b,referenceValue:0})),l=n=void 0===a.axisY.type?new c.StepAxis(c.Axis.units.y,d,o,{ticks:k}):a.axisY.type.call(c,c.Axis.units.y,d,o,a.axisY)):(l=m=void 0===a.axisX.type?new c.StepAxis(c.Axis.units.x,d,o,{ticks:k}):a.axisX.type.call(c,c.Axis.units.x,d,o,a.axisX),j=n=void 0===a.axisY.type?new c.AutoScaleAxis(c.Axis.units.y,d,o,c.extend({},a.axisY,{highLow:b,referenceValue:0})):a.axisY.type.call(c,c.Axis.units.y,d,o,c.extend({},a.axisY,{highLow:b,referenceValue:0})));var p=a.horizontalBars?o.x1+j.projectValue(0):o.y1-j.projectValue(0),q=[];l.createGridAndLabels(e,h,this.supportsForeignObject,a,this.eventEmitter),j.createGridAndLabels(e,h,this.supportsForeignObject,a,this.eventEmitter),d.raw.series.forEach(function(b,e){var f,h,i=e-(d.raw.series.length-1)/2;f=a.distributeSeries&&!a.stackBars?l.axisLength/d.normalized.length/2:a.distributeSeries&&a.stackBars?l.axisLength/2:l.axisLength/d.normalized[e].length/2,h=g.elem("g"),h.attr({"series-name":b.name,meta:c.serialize(b.meta)},c.xmlNs.uri),h.addClass([a.classNames.series,b.className||a.classNames.series+"-"+c.alphaNumerate(e)].join(" ")),d.normalized[e].forEach(function(g,k){var r,s,t,u;if(u=a.distributeSeries&&!a.stackBars?e:a.distributeSeries&&a.stackBars?0:k,r=a.horizontalBars?{x:o.x1+j.projectValue(g&&g.x?g.x:0,k,d.normalized[e]),y:o.y1-l.projectValue(g&&g.y?g.y:0,u,d.normalized[e])}:{x:o.x1+l.projectValue(g&&g.x?g.x:0,u,d.normalized[e]),y:o.y1-j.projectValue(g&&g.y?g.y:0,k,d.normalized[e])},l instanceof c.StepAxis&&(l.options.stretch||(r[l.units.pos]+=f*(a.horizontalBars?-1:1)),r[l.units.pos]+=a.stackBars||a.distributeSeries?0:i*a.seriesBarDistance*(a.horizontalBars?-1:1)),t=q[k]||p,q[k]=t-(p-r[l.counterUnits.pos]),void 0!==g){var v={};v[l.units.pos+"1"]=r[l.units.pos],v[l.units.pos+"2"]=r[l.units.pos],!a.stackBars||"accumulate"!==a.stackMode&&a.stackMode?(v[l.counterUnits.pos+"1"]=p,v[l.counterUnits.pos+"2"]=r[l.counterUnits.pos]):(v[l.counterUnits.pos+"1"]=t,v[l.counterUnits.pos+"2"]=q[k]),v.x1=Math.min(Math.max(v.x1,o.x1),o.x2), +v.x2=Math.min(Math.max(v.x2,o.x1),o.x2),v.y1=Math.min(Math.max(v.y1,o.y2),o.y1),v.y2=Math.min(Math.max(v.y2,o.y2),o.y1),s=h.elem("line",v,a.classNames.bar).attr({value:[g.x,g.y].filter(function(a){return a}).join(","),meta:c.getMetaData(b,k)},c.xmlNs.uri),this.eventEmitter.emit("draw",c.extend({type:"bar",value:g,index:k,meta:c.getMetaData(b,k),series:b,seriesIndex:e,axisX:m,axisY:n,chartRect:o,group:h,element:s},v))}}.bind(this))}.bind(this)),this.eventEmitter.emit("created",{bounds:j.bounds,chartRect:o,axisX:m,axisY:n,svg:this.svg,options:a})}function e(a,b,d,e){c.Bar["super"].constructor.call(this,a,b,f,c.extend({},f,d),e)}var f={axisX:{offset:30,position:"end",labelOffset:{x:0,y:0},showLabel:!0,showGrid:!0,labelInterpolationFnc:c.noop,scaleMinSpace:30,onlyInteger:!1},axisY:{offset:40,position:"start",labelOffset:{x:0,y:0},showLabel:!0,showGrid:!0,labelInterpolationFnc:c.noop,scaleMinSpace:20,onlyInteger:!1},width:void 0,height:void 0,high:void 0,low:void 0,onlyInteger:!1,chartPadding:{top:15,right:15,bottom:5,left:10},seriesBarDistance:15,stackBars:!1,stackMode:"accumulate",horizontalBars:!1,distributeSeries:!1,reverseData:!1,classNames:{chart:"ct-chart-bar",horizontalBars:"ct-horizontal-bars",label:"ct-label",labelGroup:"ct-labels",series:"ct-series",bar:"ct-bar",grid:"ct-grid",gridGroup:"ct-grids",vertical:"ct-vertical",horizontal:"ct-horizontal",start:"ct-start",end:"ct-end"}};c.Bar=c.Base.extend({constructor:e,createChart:d})}(window,document,a),function(a,b,c){"use strict";function d(a,b,c){var d=b.x>a.x;return d&&"explode"===c||!d&&"implode"===c?"start":d&&"implode"===c||!d&&"explode"===c?"end":"middle"}function e(a){var b,e,f,h,i,j=[],k=a.startAngle,l=c.getDataArray(this.data,a.reverseData);this.svg=c.createSvg(this.container,a.width,a.height,a.donut?a.classNames.chartDonut:a.classNames.chartPie),e=c.createChartRect(this.svg,a,g.padding),f=Math.min(e.width()/2,e.height()/2),i=a.total||l.reduce(function(a,b){return a+b},0);var m=c.quantity(a.donutWidth);"%"===m.unit&&(m.value*=f/100),f-=a.donut?m.value/2:0,h="outside"===a.labelPosition||a.donut?f:"center"===a.labelPosition?0:f/2,h+=a.labelOffset;var n={x:e.x1+e.width()/2,y:e.y2+e.height()/2},o=1===this.data.series.filter(function(a){return a.hasOwnProperty("value")?0!==a.value:0!==a}).length;a.showLabel&&(b=this.svg.elem("g",null,null,!0));for(var p=0;p180,0,s.x,s.y);a.donut||u.line(n.x,n.y);var v=j[p].elem("path",{d:u.stringify()},a.donut?a.classNames.sliceDonut:a.classNames.slicePie);if(v.attr({value:l[p],meta:c.serialize(q.meta)},c.xmlNs.uri),a.donut&&v.attr({style:"stroke-width: "+m.value+"px"}),this.eventEmitter.emit("draw",{type:"slice",value:l[p],totalDataSum:i,index:p,meta:q.meta,series:q,group:j[p],element:v,path:u.clone(),center:n,radius:f,startAngle:k,endAngle:r}),a.showLabel){var w=c.polarToCartesian(n.x,n.y,h,k+(r-k)/2),x=a.labelInterpolationFnc(this.data.labels?this.data.labels[p]:l[p],p);if(x||0===x){var y=b.elem("text",{dx:w.x,dy:w.y,"text-anchor":d(n,w,a.labelDirection)},a.classNames.label).text(""+x);this.eventEmitter.emit("draw",{type:"label",index:p,group:b,element:y,text:""+x,x:w.x,y:w.y})}}k=r}this.eventEmitter.emit("created",{chartRect:e,svg:this.svg,options:a})}function f(a,b,d,e){c.Pie["super"].constructor.call(this,a,b,g,c.extend({},g,d),e)}var g={width:void 0,height:void 0,chartPadding:5,classNames:{chartPie:"ct-chart-pie",chartDonut:"ct-chart-donut",series:"ct-series",slicePie:"ct-slice-pie",sliceDonut:"ct-slice-donut",label:"ct-label"},startAngle:0,total:void 0,donut:!1,donutWidth:60,showLabel:!0,labelOffset:0,labelPosition:"inside",labelInterpolationFnc:c.noop,labelDirection:"neutral",reverseData:!1};c.Pie=c.Base.extend({constructor:f,createChart:e,determineAnchorPosition:d})}(window,document,a),a}); + +/* + * Legend plugin for Chartist.js + * https://github.com/CodeYellowBV/chartist-plugin-legend + */ +(function(a,b){if(typeof define==="function"&&define.amd){define(["chartist"],function(c){return(a.returnExportsGlobal=b(c));});}else{if(typeof exports==="object"){module.exports=b(require("chartist"));}else{a["Chartist.plugins.legend"]=b(a.Chartist);}}}(this,function(b){var a={className:"",legendNames:false,clickable:true};b.plugins=b.plugins||{};b.plugins.legend=function(c){c=b.extend({},a,c);return function d(g){var h=g.container.querySelector(".ct-legend");if(h){h.remove();}if(c.clickable){g.data.series.forEach(function(l,k){if(typeof l!=="object"){l={data:l};}l.className=l.className||g.options.classNames.series+"-"+b.alphaNumerate(k);});}var f=document.createElement("ul");f.className="ct-legend";if(g instanceof b.Pie){f.classList.add("ct-legend-inside");}if(typeof c.className==="string"&&c.className.length>0){f.classList.add(c.className);}var j=[],e=g.data.series.slice(0);var i=g.data.series;if(g instanceof b.Pie){i=g.data.labels;}i=c.legendNames||i;i.forEach(function(m,l){var k=document.createElement("li");k.className="ct-series-"+l;k.setAttribute("data-legend",l);k.textContent=m.name||m;f.appendChild(k);});g.container.appendChild(f);if(c.clickable){f.addEventListener("click",function(n){var k=n.target;if(k.parentNode!==f||!k.hasAttribute("data-legend")){return;}n.preventDefault();var l=parseInt(k.getAttribute("data-legend")),o=j.indexOf(l);if(o>-1){j.splice(o,1);k.classList.remove("inactive");}else{if(g.data.series.length>1){j.push(l);k.classList.add("inactive");}}var m=e.slice(0);j.sort().reverse();j.forEach(function(p){m.splice(p,1);});g.data.series=m;g.update();});}};};return b.plugins.legend;})); diff --git a/content/plugins/f-translate/templates/js/details-element-polyfill.min.js b/content/plugins/f-translate/templates/js/details-element-polyfill.min.js new file mode 100644 index 0000000..5e6ad86 --- /dev/null +++ b/content/plugins/f-translate/templates/js/details-element-polyfill.min.js @@ -0,0 +1,5 @@ +/* +Details Element Polyfill 2.3.1 +Copyright © 2019 Javan Makhmali +*/ +!function(){"use strict";var t=document.createElement("details");t.innerHTML="ab",t.setAttribute("style","position: absolute; left: -9999px");var e="open"in t&&function(){(document.body||document.documentElement).appendChild(t);var e=t.offsetHeight;t.open=!0;var n=t.offsetHeight;return t.parentNode.removeChild(t),e!=n}(),n="ontoggle"in t;var r,i,o,a,u='\ndetails, summary {\n display: block;\n}\ndetails:not([open]) > *:not(summary) {\n display: none;\n}\nsummary::before {\n content: "►";\n padding-right: 0.3rem;\n font-size: 0.6rem;\n cursor: default;\n}\n[open] > summary::before {\n content: "▼";\n}\n',s=[],c=s.forEach,d=s.slice;function m(t){(function(t,e){return(t.tagName==e?[t]:[]).concat("function"==typeof t.getElementsByTagName?d.call(t.getElementsByTagName(e)):[])})(t,"SUMMARY").forEach(function(t){var e=b(t,"DETAILS");t.setAttribute("aria-expanded",e.hasAttribute("open")),t.hasAttribute("tabindex")||t.setAttribute("tabindex","0"),t.hasAttribute("role")||t.setAttribute("role","button")})}function l(t){return!(t.defaultPrevented||t.ctrlKey||t.metaKey||t.shiftKey||t.target.isContentEditable)}function f(t){addEventListener("click",function(e){if(l(e)&&e.which<=1){var n=b(e.target,"SUMMARY");n&&n.parentNode&&"DETAILS"==n.parentNode.tagName&&t(n.parentNode)}},!1),addEventListener("keydown",function(e){if(l(e)&&(13==e.keyCode||32==e.keyCode)){var n=b(e.target,"SUMMARY");n&&n.parentNode&&"DETAILS"==n.parentNode.tagName&&(t(n.parentNode),e.preventDefault())}},!1)}function p(t){var e=document.createEvent("Event");e.initEvent("toggle",!1,!1),t.dispatchEvent(e)}function b(t,e){if("function"==typeof t.closest)return t.closest(e);for(;t;){if(t.tagName==e)return t;t=t.parentNode}}e||(document.head.insertAdjacentHTML("afterbegin",""),r=document.createElement("details").constructor.prototype,i=r.setAttribute,o=r.removeAttribute,a=Object.getOwnPropertyDescriptor(r,"open"),Object.defineProperties(r,{open:{get:function(){return"DETAILS"==this.tagName?this.hasAttribute("open"):a&&a.get?a.get.call(this):void 0},set:function(t){return"DETAILS"==this.tagName?t?this.setAttribute("open",""):this.removeAttribute("open"):a&&a.set?a.set.call(this,t):void 0}},setAttribute:{value:function(t,e){var n=this,r=function(){return i.call(n,t,e)};if("open"==t&&"DETAILS"==this.tagName){var o=this.hasAttribute("open"),a=r();if(!o){var u=this.querySelector("summary");u&&u.setAttribute("aria-expanded",!0),p(this)}return a}return r()}},removeAttribute:{value:function(t){var e=this,n=function(){return o.call(e,t)};if("open"==t&&"DETAILS"==this.tagName){var r=this.hasAttribute("open"),i=n();if(r){var a=this.querySelector("summary");a&&a.setAttribute("aria-expanded",!1),p(this)}return i}return n()}}}),f(function(t){t.hasAttribute("open")?t.removeAttribute("open"):t.setAttribute("open","")}),m(document),window.MutationObserver?new MutationObserver(function(t){c.call(t,function(t){c.call(t.addedNodes,m)})}).observe(document.documentElement,{subtree:!0,childList:!0}):document.addEventListener("DOMNodeInserted",function(t){m(t.target)})),e&&!n&&(window.MutationObserver?new MutationObserver(function(t){c.call(t,function(t){var e=t.target,n=t.attributeName;"DETAILS"==e.tagName&&"open"==n&&p(e)})}).observe(document.documentElement,{attributes:!0,subtree:!0}):f(function(t){var e=t.getAttribute("open");setTimeout(function(){var n=t.getAttribute("open");e!=n&&p(t)},1)}))}(); diff --git a/content/plugins/f-translate/templates/js/editor.js b/content/plugins/f-translate/templates/js/editor.js new file mode 100644 index 0000000..46274ee --- /dev/null +++ b/content/plugins/f-translate/templates/js/editor.js @@ -0,0 +1,345 @@ +/* global $gp */ +( function( $ ){ + var $html = $( 'html' ); + var $document = $( document ); + + function checkStorage() { + var test = 'test', + result = false; + + try { + window.localStorage.setItem( 'test', test ); + result = window.localStorage.getItem( 'test' ) === test; + window.localStorage.removeItem( 'test' ); + } catch(e) {} + + hasStorage = result; + return result; + } + + var hasStorage = checkStorage(); + + // Handle tab view for plural forms. + function switchPluralTabs() { + var $tab = $( this ); + if ( $tab.hasClass( 'translation-form-list__tab--active' ) ) { + return; + } + + var $translationWrapper = $gp.editor.current.find( '.translation-wrapper' ); + var $formWrapper = $translationWrapper.find( '.translation-form-wrapper' ); + var $tabList = $formWrapper.find( '.translation-form-list' ); + var $tabs = $translationWrapper.find( '.textareas' ); + + $tabList.find( '.translation-form-list__tab--active' ).removeClass( 'translation-form-list__tab--active' ); + $tab.addClass( 'translation-form-list__tab--active' ); + + $tabs.removeClass( 'active' ); + + var index = $tab.data( 'plural-index' ); + $tabs.filter( '[data-plural-index="' + index + '"]').addClass( 'active' ); + } + + // Open menu for contextual links. + function toggleLinkMenu() { + var $toggle = $( this ); + var $menu = $toggle.parent( '.button-menu' ); + + $menu.toggleClass( 'active' ); + $document.off( 'click.menu-toggle' ); + + if ( $menu.hasClass( 'active' ) ) { + $document.on( 'click.menu-toggle', function( event ) { + if ( ! $menu.is( event.target ) && 0 === $menu.has( event.target ).length ) { + $menu.removeClass( 'active' ); + $document.off( 'click.menu-toggle' ); + } + } ); + } + } + + // Automatically adjust textarea height to fit text. + function textareaAutosize() { + var $textarea = $( this ); + if ( $textarea.hasClass( 'autosize' ) ) { + return; + } + + $textarea.addClass( 'autosize' ); + + autosize( $textarea ); + } + + + //Prefilter ajax requests to add translation_source to the request. + $.ajaxPrefilter( function ( options ) { + let data = Object.fromEntries( new URLSearchParams( options.data ) ); + + if ( 'POST' === options.type && $gp_editor_options.url === options.url ) { + options.data += '&translation_source=frontend'; + + } + }); + + // Override functions to adopt custom markup. + $gp.editor.copy = function() { + var $activeTextarea = $gp.editor.current.find( '.textareas.active textarea' ); + if ( ! $activeTextarea.length ) { + return; + } + + var chunks = $activeTextarea.attr( 'id' ).split( '_' ); + var originalIndex = parseInt( chunks[ chunks.length - 1 ], 10 ); + + var $original; + if ( 0 === originalIndex ) { + $original = $gp.editor.current.find( '.source-string__singular .original-raw' ); + } else { + $original = $gp.editor.current.find( '.source-string__plural .original-raw' ); + } + + if ( ! $original.length ) { + return; + } + + var originalText = $original.text(); + if ( ! originalText ) { + return; + } + + $activeTextarea.val( originalText ).focus(); + + // Trigger input event for autosize(). + var event = new Event( 'input' ); + $activeTextarea[0].dispatchEvent( event ); + }; + $gp.editor.tab = function() { + var text_area = $gp.editor.current.find( '.textareas.active textarea' ); + if ( ! text_area.length ) { + return; + } + + var cursorPos = text_area.prop( 'selectionStart' ); + var v = text_area.val(); + var textBefore = v.substring( 0, cursorPos ); + var textAfter = v.substring( cursorPos, v.length ); + + text_area.val( textBefore + '\t' + textAfter ); + + text_area.focus(); + text_area[0].selectionEnd = cursorPos + 1; + }, + $gp.editor.newline = function() { + var text_area = $gp.editor.current.find( '.textareas.active textarea' ); + if ( ! text_area.length ) { + return; + } + + var cursorPos = text_area.prop( 'selectionStart' ); + var v = text_area.val(); + var textBefore = v.substring( 0, cursorPos ); + var textAfter = v.substring( cursorPos, v.length ); + + text_area.val( textBefore + '\n' + textAfter ); + + text_area.focus(); + text_area[0].selectionEnd = cursorPos + 1; + }; + + function switchTextDirection() { + var direction = $( this ).is( '.translation-actions__ltr') ? 'ltr' : 'rtl'; + + var $wrapper = $gp.editor.current.find( '.translation-wrapper' ); + if ( ! $wrapper.length ) { + return; + } + + $wrapper.removeClass( 'textarea-direction-rtl textarea-direction-ltr' ); + $wrapper.addClass( 'textarea-direction-' + direction ); + } + + // Open the modal for translation help. + function openHelpModal() { + var $modal = $( '#wporg-translation-help-modal' ); + var $closeButton = $modal.find( '.wporg-translate-modal__close' ); + + $html.addClass( 'modal-open' ); + $modal.addClass( 'wporg-translate-modal--open' ); + $closeButton.focus(); + + $document.on( 'keydown.modal', function( event ) { + if ( 27 !== event.which ) { // ESC key. + return; + } + + $modal.removeClass( 'wporg-translate-modal--open' ); + $html.removeClass( 'modal-open' ); + $document.off( 'keydown.modal' ); + } ); + + $closeButton.one( 'click', function() { + $modal.removeClass( 'wporg-translate-modal--open' ); + $html.removeClass( 'modal-open' ); + $document.off( 'keydown.modal' ); + } ); + } + + $gp.editor.keydown = ( function( original ) { + return function( event ) { + // Shift-Enter = Save. + if ( 13 === event.keyCode && event.shiftKey ) { + var $textarea = $( event.target ); + + if ( ! $textarea.val().trim() ) { + $gp.notices.error( 'Translation is empty.' ); + return false; + } + + // Check plural forms. + var $textareas = $gp.editor.current.find( '.textareas:not(.active) textarea' ); + var isValid = true; + $textareas.each( function() { + if ( ! this.value.trim() ) { + isValid = false; + } + } ); + + if ( ! isValid ) { + $gp.notices.error( 'Translation is empty.' ); + return false; + } + + $gp.editor.save( $gp.editor.current.find( 'button.translation-actions__save' ) ); + + // Ctrl-Enter or Ctrl-Shift-B = Copy original. + } else if ( + ( 13 === event.keyCode && event.ctrlKey ) || + ( 66 === event.keyCode && event.shiftKey && event.ctrlKey ) ) + { + var $button = $gp.editor.current.find( 'button.translation-actions__copy' ); + + $button.trigger( 'click' ); + } else { + return original.apply( $gp.editor, arguments ); + } + + return false; + } + })( $gp.editor.keydown ); + + // Store the open/close state of
element in locale storage and apply state when editor is shown. + var DETAILS_STORE_KEY = 'translate-details-state'; + function updateDetailsState( type, state ) { + if ( ! hasStorage ) { + return; + } + + var store = window.localStorage.getItem( DETAILS_STORE_KEY ); + var states = store ? JSON.parse( store ) : {}; + + states[ type ] = state; + + window.localStorage.setItem( DETAILS_STORE_KEY, JSON.stringify( states ) ); + } + + function toggleDetails( event ) { + var $el = $( event.target ).closest( 'details' ); + var isClosed = $el.attr( 'open' ) === 'open'; // Gets closed when open attribute was previously set. + var className = $el.attr( 'class' ).replace( /^(\S*).*/, '$1' ); + + updateDetailsState( className, isClosed ? 'close' : 'open' ); + } + + function applyDetailsState() { + if ( ! hasStorage || ! $gp.editor.current.length ) { + return; + } + + var store = window.localStorage.getItem( DETAILS_STORE_KEY ); + var states = store ? JSON.parse( store ) : {}; + + for ( var type in states ) { + var state = states[ type ]; + + if ( 'open' === state ) { + $gp.editor.current.find( '.' + type ).attr( 'open', 'open' ); + } else { + $gp.editor.current.find( '.' + type ).removeAttr( 'open' ); + } + } + // Click on the last tab opened in the previous row, to show the same tab in the current row. + $gp.editor.current.find( '.' + states['last-tab-type-open'] ).first().click(); + } + + function changeRightTab( event ) { + var tab = $( this ); + var tabType = tab.attr( 'class' ).split(' ')[0]; + var tabId = tab.attr( 'data-tab' ); + var divId = tabId.replace( 'tab', 'div' ); + var originalId = tabId.replace( /[^\d-]/g, '' ).replace( /^-+/g, '' ); + changeVisibleTab( tab ); + changeVisibleDiv( divId, originalId ); + updateDetailsState( 'last-tab-type-open', tabType ); + // Avoid to execute the code from the gp-translation-helpers plugin. + event.stopImmediatePropagation(); + } + + /** + * Hides all tabs and show one of them, the last clicked. + * + * @param {Object} tab The selected tab. + */ + function changeVisibleTab( tab ) { + var tabId = tab.attr( 'data-tab' ); + tab.siblings().removeClass( 'current' ); + tab.parents( '.sidebar-tabs ' ).find( '.helper' ).removeClass( 'current' ); + tab.addClass( 'current' ); + + $( '#' + tabId ).addClass( 'current' ); + } + + + /** + * Hides all divs and show one of them, the last clicked. + * + * @param {string} tabId The select tab id. + * @param {number} originalId The id of the original string to translate. + */ + function changeVisibleDiv( tabId, originalId ) { + $( '#sidebar-div-meta-' + originalId ).hide(); + $( '#sidebar-div-discussion-' + originalId ).hide(); + $( '#sidebar-div-others-' + originalId ).hide(); + $( '#' + tabId ).show(); + } + + $gp.editor.show = ( function( original ) { + return function() { + original.apply( $gp.editor, arguments ); + + applyDetailsState(); + } + })( $gp.editor.show ); + + $gp.editor.install_hooks = ( function( original ) { + return function() { + original.apply( $gp.editor, arguments ); + + $( $gp.editor.table ) + .on( 'click', 'button.translation-form-list__tab', switchPluralTabs ) + .on( 'click', 'button.panel-header-actions__previous', $gp.editor.prev ) + .on( 'click', 'button.panel-header-actions__next', $gp.editor.next ) + .on( 'click', 'button.panel-header-actions__cancel', $gp.editor.hooks.cancel ) + .on( 'click', 'button.translation-actions__copy', $gp.editor.hooks.copy ) + .on( 'click', 'button.translation-actions__insert-tab', $gp.editor.hooks.tab ) + .on( 'click', 'button.translation-actions__save', $gp.editor.hooks.ok ) + .on( 'click', 'button.translation-actions__help', openHelpModal ) + .on( 'click', 'button.translation-actions__ltr', switchTextDirection ) + .on( 'click', 'button.translation-actions__rtl', switchTextDirection ) + .on( 'focus', 'textarea', textareaAutosize ) + .on( 'click', 'summary', toggleDetails ) + .on( 'click', 'button.button-menu__toggle', toggleLinkMenu ) + .on( 'click', '.sidebar-tabs li', changeRightTab ); + } + })( $gp.editor.install_hooks ); + +})( jQuery ); diff --git a/content/plugins/f-translate/templates/locale-project.php b/content/plugins/f-translate/templates/locale-project.php new file mode 100644 index 0000000..bd7396a --- /dev/null +++ b/content/plugins/f-translate/templates/locale-project.php @@ -0,0 +1,486 @@ +english_name ) ) ); + +$breadcrumb = array(); +$breadcrumb[] = gp_link_get( '/', __( 'Locales' ) ); +$breadcrumb[] = gp_link_get( gp_url_join( '/locale', $locale_slug, $set_slug ), esc_html( $locale->english_name ) ); +$breadcrumb[] = gp_link_get( gp_url_join( '/locale', $locale_slug, $set_slug, $project->path ), esc_html( $project->name ) ); +$breadcrumb[] = $sub_project->name; +gp_breadcrumb( $breadcrumb ); +gp_tmpl_header(); +?> + +
+

description, $sub_project ); + + // Localize the links to the currently viewed locale. + $description = WordPressdotorg\GlotPress\Customizations\Plugin::get_instance()->localize_links( $description, $locale->wp_locale ); + + echo $description; + ?>

+ +
+
+
+ +
+ +
    +
  • name; ?>
  • +
  • english_name; ?>
  • + english_name !== $locale->native_name ) : ?> +
  • native_name; ?>
  • + +
  • + wp_locale; + + if ( count( $variants ) > 1 ) { + ?> + + +
  • + +
  • + +
  • + +
  • + +
  • + +
+ +
+ percent_complete . '%'; ?> +
+
+ +
+
+
+ + +
+
+ +active ) : ?> +
+

This project is no longer actively used. Translations remain for archiving purposes.

+
+ + +path ) { + if ( ! in_array( 'dev', $sub_project_slugs ) && ! in_array( 'stable', $sub_project_slugs ) ) { + ?> +
+

This plugin is not properly prepared for localization. If you would like to translate this plugin, please contact the author.

+

Import results are logged on Slack in the #meta-language-packs channel. Please see the handbook for more information about Slack and possible errors.

+
+ +
+

Translations for the readme are published almost immediately. + The initial language pack for the plugin will be generated when 90% of the sub-project strings have been translated (currently percent_complete . '%'; ?>).

+
+ path ) { + ?> +
+

The initial language pack for the theme will be generated when 90% of the project strings have been translated (currently percent_complete . '%'; ?>).

+
+ + +
+ + + + + + + + + + + + + all_count ) { + ?> + + + + + + + + + + + + path ) { + // Ensure consistent order of development and stable projects. + usort( $sub_projects, function( $a, $b ) { + $a_is_dev = ( substr( $a->slug, 0, 3 ) == 'dev' ); + $b_is_dev = ( substr( $b->slug, 0, 3 ) == 'dev' ); + + // Sort same-type projects alphabetically + if ( $a_is_dev === $b_is_dev ) { + return strnatcasecmp( $a->name, $b->name ); + } + + // Sort Stable before Dev. + return $a_is_dev <=> $b_is_dev; + } ); + } + + foreach ( $sub_projects as $sub_project ) { + $status = $sub_project_statuses[ $sub_project->slug ]; + ?> + + + + + + + + + + +
+ path, gp_url_join( $locale->slug, $set_slug ) ), $sub_project->name ); ?> + percent_complete > 90 ) : ?> + percent_complete; ?>% + + percent_complete; ?>% + + + path, gp_url_join( $locale->slug, $set_slug ), array( 'filters[translated]' => 'yes', 'filters[status]' => 'current') ), number_format_i18n( $sub_project_status->current_count ) ); ?> + + path, gp_url_join( $locale->slug, $set_slug ), array( 'filters[translated]' => 'yes', 'filters[status]' => 'fuzzy' ) ), number_format_i18n( $sub_project_status->fuzzy_count ) ); ?> + + path, gp_url_join( $locale->slug, $set_slug ), array( 'filters[status]' => 'untranslated' ) ), number_format_i18n( $sub_project_status->untranslated_count ) ); ?> + + path, gp_url_join( $locale->slug, $set_slug ), array( 'filters[translated]' => 'yes', 'filters[status]' => 'waiting' ) ), number_format_i18n( $sub_project_status->waiting_count ) ); ?> + + path, gp_url_join( $locale->slug, $set_slug ), array( 'filters[changesrequested]' => 'yes', 'filters[status]' => 'changesrequested' ) ), number_format_i18n( $sub_project_status->changesrequested_count ) ); ?> +
+ path, gp_url_join( $locale->slug, $set_slug ) ), $sub_project->name ); ?> + percent_complete > 90 ) : ?> + percent_complete; ?>% + + percent_complete; ?>% + + + path, gp_url_join( $locale->slug, $set_slug ), array( 'filters[translated]' => 'yes', 'filters[status]' => 'current') ), number_format_i18n( $status->current_count ) ); ?> + + path, gp_url_join( $locale->slug, $set_slug ), array( 'filters[translated]' => 'yes', 'filters[status]' => 'fuzzy' ) ), number_format_i18n( $status->fuzzy_count ) ); ?> + + path, gp_url_join( $locale->slug, $set_slug ), array( 'filters[status]' => 'untranslated' ) ), number_format_i18n( $status->untranslated_count ) ); ?> + + path, gp_url_join( $locale->slug, $set_slug ), array( 'filters[translated]' => 'yes', 'filters[status]' => 'waiting' ) ), number_format_i18n( $status->waiting_count ) ); ?> + + path, gp_url_join( $locale->slug, $set_slug ), array( 'filters[changesrequested]' => 'yes', 'filters[status]' => 'changesrequested' ) ), number_format_i18n( $status->changesrequested_count ) ); ?> +
+
+ +
+
+

Translation Contributors

+ + + + + + + + + + path ) { + // Ensure consistent order of development and stable projects. + usort( $contributor->detailed, function( $a, $b ) { + return strnatcasecmp( $a->project->name, $b->project->name ); + } ); + } + + foreach ( $contributor->detailed as $detail_project_id => $detail_data ) { + $detailed .= '' . $detail_data->project->name . ':'; + + if ( $detail_data->total_count > 0 ) { + $total_count = gp_link_get( + gp_url_project( + $detail_data->project->path, + gp_url_join( $locale->slug, $set_slug ), + [ + 'filters[translated]' => 'yes', + 'filters[status]' => 'current_or_waiting_or_fuzzy_or_untranslated', + 'filters[user_login]' => $contributor->login, + ] + ), + number_format_i18n( $detail_data->total_count ) + ); + } else { + $total_count = number_format_i18n( $detail_data->total_count ); + } + + if ( $detail_data->current_count > 0 ) { + $current_count = gp_link_get( + gp_url_project( + $detail_data->project->path, + gp_url_join( $locale->slug, $set_slug ), + [ + 'filters[translated]' => 'yes', + 'filters[status]' => 'current', + 'filters[user_login]' => $contributor->login, + ] + ), + number_format_i18n( $detail_data->current_count ) + ); + } else { + $current_count = number_format_i18n( $detail_data->current_count ); + } + + if ( $detail_data->waiting_count > 0 ) { + $waiting_count = gp_link_get( + gp_url_project( + $detail_data->project->path, + gp_url_join( $locale->slug, $set_slug ), + [ + 'filters[translated]' => 'yes', + 'filters[status]' => 'waiting', + 'filters[user_login]' => $contributor->login, + ] + ), + number_format_i18n( $detail_data->waiting_count ) + ); + } else { + $waiting_count = number_format_i18n( $detail_data->waiting_count ); + } + + if ( $detail_data->fuzzy_count > 0 ) { + $fuzzy_count = gp_link_get( + gp_url_project( + $detail_data->project->path, + gp_url_join( $locale->slug, $set_slug ), + [ + 'filters[translated]' => 'yes', + 'filters[status]' => 'fuzzy', + 'filters[user_login]' => $contributor->login, + ] + ), + number_format_i18n( $detail_data->fuzzy_count ) + ); + } else { + $fuzzy_count = number_format_i18n( $detail_data->fuzzy_count ); + } + + $detailed .= sprintf( + ' +
+

%s

+
+
+

%s

+
+
+

%s

+
+
+

%s

+
+ ', + $total_count, + $current_count, + $waiting_count, + $fuzzy_count + ); + } + + printf( + ' + + + ', + $contributor->nicename, + get_avatar( $contributor->email, 40 ), + $contributor->is_editor ? 'Editor' : '', + $contributor->nicename, + $contributor->display_name ?: $contributor->nicename, + human_time_diff( strtotime( $contributor->last_update ) ), + number_format_i18n( $contributor->total_count ), + number_format_i18n( $contributor->current_count ), + number_format_i18n( $contributor->waiting_count ), + number_format_i18n( $contributor->fuzzy_count ), + $detailed + ); + } + ?> + +
ContributorTranslations
+
+ %s + %s +
+
+ %s + Latest translation: %s ago +
+
+
+ Total +

%s

+
+
+ Translated +

%s

+
+
+ Suggested +

%s

+
+
+ Fuzzy +

%s

+
+
+
+ Per project + %s +
+
+
+ +

None, be the first?

+ +
+ +
+

Translation Editors

+ +

These users can validate and approve your translations for this specific project.

+
    + %s %s', + $editor->nicename, + get_avatar( $editor->email, 40 ), + $editor->nicename, + $editor->display_name ?: $editor->nicename + ); + } + ?> +
+ +

There are no editors for this specific project, yet. Become an editor.

+ +
+

The following users can edit translations for either a parent project or all projects.

+
    + %s %s', + $editor->nicename, + get_avatar( $editor->email, 15 ), + $editor->display_name ? $editor->display_name : $editor->nicename + ); + } + ?> +
+ +
+
+ + + +english_name ) ) ); + +$breadcrumb = array(); +$breadcrumb[] = gp_link_get( '/', __( 'Locales' ) ); +$breadcrumb[] = gp_link_get( gp_url_join( '/locale', $locale_slug, $set_slug ), esc_html( $locale->english_name ) ); +$breadcrumb[] = esc_html( $project->name ); +gp_breadcrumb( $breadcrumb ); +gp_tmpl_header(); +?> + +
+

Translate WordPress, core projects, plugins, and themes into your language. Select your project below to get started.

+ +
+
    +
  • english_name; ?>
  • +
  • native_name; ?>
  • +
  • + wp_locale; + + if ( count( $variants ) > 1 ) { + ?> + + +
  • + +
  • + +
  • + +
  • + +
  • + +
+
+
%s', + isset( $contributors_count[ $locale->slug ] ) ? $contributors_count[ $locale->slug ] : 0 + ); + echo gp_link_get( 'https://make.wordpress.org/polyglots/teams/?locale=' . $locale->wp_locale, $contributors ); + ?> +
+
+
+ +
+ +
+
+ + + + + +
+
+
+
+
+ + + + slug && is_user_logged_in() ) { + $filter_count++; + ?> + > + + + + + + + + + +
+
+ + 1 ) { + echo '
'; + echo gp_pagination( $pages['page'], $pages['per_page'], $pages['results'] ); + echo '
'; +} + +?> +
+ id ] ) ) { + $status = $project_status[ $sub_project->id ]; + $percent_complete = $status->percent_complete; + $waiting = $status->waiting_count; + $fuzzy = $status->fuzzy_count; + $remaining = $status->all_count - $status->current_count; + $sub_projects_count = $status->sub_projects_count; + } + + // Link directly to the Waiting strings if we're in the Waiting view, otherwise link to the project overview + if ( 'waiting' == $project->slug ) { + // TODO: Since we're matching parent projects, we can't link to them as they have no direct translation sets. + //$project_url = gp_url_join( '/projects', $sub_project->path, $locale_slug, $set_slug ) . '?filters[status]=waiting_or_fuzzy'; + $project_url = gp_url_join( '/locale', $locale_slug, $set_slug, $sub_project->path ); + + $project_name = $sub_project->name; + $parent_project_id = $sub_project->parent_project_id; + while ( $parent_project_id ) { + $parent_project = GP::$project->get( $parent_project_id ); + $parent_project_id = $parent_project->parent_project_id; + $project_name = "{$parent_project->name} - {$project_name}"; + } + } elseif ( 'Patterns' == $project->name ) { + $prefix = 'https://translate.wordpress.org/projects/patterns/core'; + if ( 'patterns' == $sub_project->slug ) { + // Remove the URL from the filter for the main Patterns project so that it shows all strings. + $suffix = '?filters%5Bterm%5D=&filters%5Bterm_scope%5D=scope_any&filters%5Bstatus%5D=current_or_waiting_or_fuzzy_or_untranslated_or_rejected_or_changesrequested_or_old&filters%5Buser_login%5D=&filter=Apply+Filters&sort%5Bby%5D=priority&sort%5Bhow%5D=desc'; + } else { + $suffix = '?filters%5Bterm%5D=https%3A%2F%2Fwordpress.org%2Fpatterns%2Fpattern%2F' . $sub_project->slug . '%2F&filters%5Bterm_scope%5D=scope_any&filters%5Bstatus%5D=current_or_waiting_or_fuzzy_or_untranslated_or_rejected_or_changesrequested_or_old&filters%5Buser_login%5D=&filter=Apply+Filters&sort%5Bby%5D=priority&sort%5Bhow%5D=desc'; + } + $project_url = $prefix . '/' . $locale_slug . '/' . $set_slug . '/' . $suffix; + $project_name = $sub_project->name; + } else { + $project_url = gp_url_join( '/locale', $locale_slug, $set_slug, $sub_project->path ); + $project_name = $sub_project->name; + } + + $project_icon = ''; + if ( isset( $project_icons[ $sub_project->id ] ) ) { + $project_icon = $project_icons[ $sub_project->id ]; + } + + $classes = 'project-' . sanitize_title_with_dashes( str_replace( '/', '-', $project->path ) ); + $classes .= ' project-' . sanitize_title_with_dashes( str_replace( '/', '-', $sub_project->path ) ); + $classes .= ' percent-' . $percent_complete; + ?> +
+
+
+ +
+ +
+

+ +

+
+
+

description ); + $description = str_replace( array( 'WordPress.org Plugin Page', 'WordPress.org Theme Page' ), '', $description ); + echo wp_trim_words( $description, 15 ); + ?>

+
+
+ +
+
+ Projects + +
+
+ Waiting/Fuzzy + +
+
+ Remaining + +
+
+ Progress + % +
+
+ +
+
+
+ +
+ 'button contribute-button' ] ); ?> +
+
+ slug ) { + echo '
No projects with strings awaiting approval!
'; + } else { + echo '
No projects found.
'; + } + } + ?> +
+ + 1 ) { + echo '
'; + echo gp_pagination( $pages['page'], $pages['per_page'], $pages['results'] ); + echo '
'; +} +?> + + + + +
+
+ + +
+
+ + +
+ +
+
+ +
+
+ + %file%', + '%line%', + 'https://trac.example.org/browser/%file%#L%line%' + ); ?> +
+ +
+
+ +
active ); ?> />
+ + + diff --git a/content/plugins/f-translate/templates/project-mass-create-sets.php b/content/plugins/f-translate/templates/project-mass-create-sets.php new file mode 100644 index 0000000..03a1b49 --- /dev/null +++ b/content/plugins/f-translate/templates/project-mass-create-sets.php @@ -0,0 +1,19 @@ +name ) ); +gp_breadcrumb_project( $project ); +gp_tmpl_header(); +?> +

+

+
+
+
+
+
+
+

+ id ); ?> +
+name ) ) ); +gp_breadcrumb( array( + gp_project_links_from_root( $project ), + 'Editors & Contributors', +) ); + + +gp_enqueue_script( 'common' ); +gp_enqueue_style( 'chartist' ); +gp_enqueue_script( 'chartist' ); + +gp_tmpl_header(); +?> +
+

description, $project ); ?>

+ +
+
+
+ icon; ?> +
+ +
    +
  • name; ?>
  • +
+
+ + +
+
+ +
+ +

Activity

+

The graph shows the recent activity of your contributors. It’s updated once per day.

+ +
+ +

Teams

+

For each locale a plugin can have translation editors and contributors. If a locale has no editor yet then you should probably make a request.

+ +
+ | + | + + + +
+ '; + foreach ( $contributors_by_locale as $locale_slug => $data ) { + $locale = GP_Locales::by_slug( $locale_slug ); + $has_editors = ! empty ( $data['editors'] ); + + $editors_list = array(); + foreach ( $data['editors'] as $editor ) { + $editors_list[] = sprintf( + '%s', + $editor->nicename, + $editor->display_name ? $editor->display_name : $editor->nicename + ); + } + + if ( ! $editors_list ) { + $editors_list[] = 'None'; + } + + $contributor_list = array(); + foreach ( $data['contributors'] as $contributor ) { + $contributor_list[] = sprintf( + '%s', + $contributor->nicename, + $contributor->display_name ? $contributor->display_name : $contributor->nicename + ); + } + + if ( ! $contributor_list ) { + $contributor_list[] = 'None'; + } + + printf( + '
+

%s %s #%s

+

Editors: %s

+

Contributors: %s

+
', + $has_editors ? ' has-editors' : ' no-editors', + $locale->english_name, + sprintf( _n( '%s person', '%s persons', $data['count'] ), number_format_i18n( $data['count'] ) ), + esc_url( gp_url_join( '/locale', $locale->slug, 'default', $project->path ) ), + $locale->wp_locale, + wp_sprintf( '%l', $editors_list ), + wp_sprintf( '%l', $contributor_list ) + ); + } + echo '
'; + } else { + echo '

The plugin has no contributors, yet.

'; + } + ?> + + + + +name ) ) ); +gp_breadcrumb( array( + gp_project_links_from_root( $project ), + 'Language Packs', +) ); + + +gp_enqueue_script( 'common' ); + +gp_tmpl_header(); +?> + +
+

description, $project ); ?>

+ +
+
+
+ icon; ?> +
+ +
    +
  • name; ?>
  • +
+
+ + +
+
+ +
+

Language Packs

+ +

Language packs are installed automatically if they are available. Once a locale has reached the threshold for a package build it will be listed here. It also means that you don’t have to include this language in your plugin anymore.

+ + translations ) && $language_packs->translations ) { + echo '
    '; + foreach ( $language_packs->translations as $language_pack ) { + printf( + '
  • %s (%s): Last updated %s for version %s (zip)
  • ', + $language_pack->english_name, + $language_pack->language, + $language_pack->updated, + $language_pack->version, + $language_pack->package + ); + } + echo '
'; + } else { + echo '

There are no language packs yet.

'; + } + ?> +
+ + + + 'Locale', + 'dev' => 'Development', + 'dev-readme' => 'Development Readme', + 'stable' => 'Stable', + 'stable-readme' => 'Stable Readme', + 'waiting' => 'Waiting/Fuzzy', +]; + +gp_title( sprintf( __( '%s < GlotPress' ), esc_html( $project->name ) ) ); +gp_breadcrumb_project( $project ); + +gp_enqueue_script( 'common' ); +gp_enqueue_script( 'tablesorter' ); + +gp_tmpl_header(); +?> + +
+

description, $project ); ?>

+ +
+
+
+ icon; ?> +
+ +
    +
  • name; ?>
  • +
+
+ + +
+
+ +active ) : ?> +
+

This plugin is no longer listed in the plugin directory. Translations remain for archiving purposes.

+
+ + + +
+

This plugin is not properly prepared for localization. If you would like to translate this plugin, please contact the author.

+

Import results are logged on Slack in the #meta-language-packs channel. Please see the handbook for details about Slack and possible errors.

+
+ + +
+ + + + $heading ) : ?> + + + + + + $total_complete ) : + $gp_locale = GP_Locales::by_slug( $locale_slug ); + + if ( ! $gp_locale || ! $gp_locale->wp_locale ) { + continue; + } + + list( $locale, $set_slug ) = array_merge( explode( '/', $locale_slug ), [ 'default' ] ); + ?> + + + path ) ); + $link_text = number_format( $percent ); + else : + $percent_class = (int) ( $percent / 10 ) * 10; + $link_url = gp_url_project( $project->path, gp_url_join( $subproject_slug, $locale, $set_slug ) ); + $link_text = "$percent%"; + + endif; + + echo ''; + else : + echo ''; + endif; + endforeach; + else : + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + endif; + ?> + + + +
+ + english_name ); ?> + + '. gp_link_get( $link_url, $link_text ) . '
+
+ + + +name ) ) ); +gp_breadcrumb( array( + gp_project_links_from_root( $project ), + 'Editors & Contributors', +) ); + + +gp_enqueue_script( 'common' ); +gp_enqueue_style( 'chartist' ); +gp_enqueue_script( 'chartist' ); + +gp_tmpl_header(); +?> +
+

description, $project ); ?>

+ +
+
+
+ icon; ?> +
+ +
    +
  • name; ?>
  • +
+
+ + +
+
+ +
+ +

Activity

+

The graph shows the recent activity of your contributors. It’s updated once per day.

+ +
+ +

Teams

+

For each locale a theme can have translation editors and contributors. If a locale has no editor yet then you should probably make a request.

+ +
+ | + | + + + +
+ '; + foreach ( $contributors_by_locale as $locale_slug => $data ) { + $locale = GP_Locales::by_slug( $locale_slug ); + $has_editors = ! empty ( $data['editors'] ); + + $editors_list = array(); + foreach ( $data['editors'] as $editor ) { + $editors_list[] = sprintf( + '%s', + $editor->nicename, + $editor->display_name ? $editor->display_name : $editor->nicename + ); + } + + if ( ! $editors_list ) { + $editors_list[] = 'None'; + } + + $contributor_list = array(); + foreach ( $data['contributors'] as $contributor ) { + $contributor_list[] = sprintf( + '%s', + $contributor->nicename, + $contributor->display_name ? $contributor->display_name : $contributor->nicename + ); + } + + if ( ! $contributor_list ) { + $contributor_list[] = 'None'; + } + + printf( + '
+

%s %s #%s

+

Editors: %s

+

Contributors: %s

+
', + $has_editors ? ' has-editors' : ' no-editors', + $locale->english_name, + sprintf( _n( '%s person', '%s persons', $data['count'] ), number_format_i18n( $data['count'] ) ), + $locale->wp_locale, + wp_sprintf( '%l', $editors_list ), + wp_sprintf( '%l', $contributor_list ) + ); + } + echo '
'; + } else { + echo '

The plugin has no contributors, yet.

'; + } + ?> + + + + +name ) ) ); +gp_breadcrumb( array( + gp_project_links_from_root( $project ), + 'Language Packs', +) ); + + +gp_enqueue_script( 'common' ); + +gp_tmpl_header(); +?> + +
+

description, $project ); ?>

+ +
+
+
+ icon; ?> +
+ +
    +
  • name; ?>
  • +
+
+ + +
+
+ +
+

Language Packs

+ +

Language packs are installed automatically if they are available. Once a locale has reached the threshold for a package build it will be listed here. It also means that you don’t have to include this language in your theme anymore.

+ + translations ) && $language_packs->translations ) { + echo '
    '; + foreach ( $language_packs->translations as $language_pack ) { + printf( + '
  • %s (%s): Last updated %s for version %s (zip)
  • ', + $language_pack->english_name, + $language_pack->language, + $language_pack->updated, + $language_pack->version, + $language_pack->package + ); + } + echo '
'; + } else { + echo '

There are no language packs yet.

'; + } + ?> +
+ + + + 'Locale', + 'stable' => 'Stable', + 'waiting' => 'Waiting/Fuzzy', +]; + +gp_title( sprintf( __( '%s < GlotPress' ), esc_html( $project->name ) ) ); +gp_breadcrumb_project( $project ); + +gp_enqueue_script( 'common' ); +gp_enqueue_script( 'tablesorter' ); + +gp_tmpl_header(); +?> + +
+

description, $project ); ?>

+ +
+
+
+ icon; ?> +
+ +
    +
  • name; ?>
  • +
+
+ + +
+
+ +active ) : ?> +
+

This theme is no longer listed in the theme directory. Translations remain for archiving purposes.

+
+ + +
+ + + + $heading ) : ?> + + + + + + $total_complete ) : + $gp_locale = GP_Locales::by_slug( $locale_slug ); + + if ( ! $gp_locale || ! $gp_locale->wp_locale ) { + continue; + } + + list( $locale, $set_slug ) = array_merge( explode( '/', $locale_slug ), [ 'default' ] ); + ?> + + + path ) ); + $link_text = number_format( $percent ); + else : + $percent_class = (int) ( $percent / 10 ) * 10; + $link_url = gp_url_project( $project->path, gp_url_join( $locale, $set_slug ) ); + $link_text = "$percent%"; + + endif; + + echo ''; + else : + echo ''; + endif; + endforeach; + else : + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + endif; + ?> + + + +
+ + english_name ); ?> + + '. gp_link_get( $link_url, $link_text ) . '
+
+ + + + 'priority', + 'how' => 'desc', + ); +} + +$gp_external_translations = get_user_option( 'gp_external_translations' ); + +$openai_key = trim( gp_array_get( $gp_default_sort, 'openai_api_key' ) ); +$openai_response = null; +if ( $openai_key ) { + $openai_response = wp_remote_get( + 'https://api.openai.com/v1/usage?date=' . gmdate( 'Y-m-d' ), + array( + 'timeout' => 8, + 'headers' => array( + 'Content-Type' => 'application/json', + 'Authorization' => 'Bearer ' . $openai_key, + ), + ) + ); +} +$openai_response_code = wp_remote_retrieve_response_code( $openai_response ); + +$deepl_key = trim( gp_array_get( $gp_default_sort, 'deepl_api_key' ) ); +$deepl_response = null; +$deepl_url_free = 'https://api-free.deepl.com/v2/usage'; +$deepl_url_pro = 'https://api.deepl.com/v2/usage'; +$deepl_url = gp_array_get( $gp_default_sort, 'deepl_use_api_pro', false ) ? $deepl_url_pro : $deepl_url_free; + +if ( $deepl_key ) { + $deepl_response = wp_remote_get( + $deepl_url, + array( + 'timeout' => 4, + 'headers' => array( + 'Content-Type' => 'application/json', + 'Authorization' => 'DeepL-Auth-Key ' . $deepl_key, + ), + ) + ); + $deepl_response_code = wp_remote_retrieve_response_code( $deepl_response ); +} + +?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ __( 'Ascending', 'glotpress' ), + 'desc' => __( 'Descending', 'glotpress' ), + ), + gp_array_get( $gp_default_sort, 'how', 'desc' ) + ); + ?> +
/>
+

+
/>
+

+
+ +
+ 0 ) { + echo '
'; + echo ''; + /* translators: Number of OpenAI translations used. */ + echo esc_html( sprintf( _n( '%s OpenAI translation used:', '%s OpenAI translations used:', 'glotpress' ), number_format_i18n( gp_array_get( $gp_external_translations, 'openai_translations_used', 0 ) ) ) ); + if ( gp_array_get( $gp_external_translations, 'openai_same_translations_used', 0 ) > 0 ) { + echo ' ' . esc_html( + sprintf( + /* translators: 1: Number of OpenAI translations used with modifications. 2: Number of OpenAI translations used without modifications. */ + __( '%1$s with modifications and %2$s without modifications.', 'glotpress' ), + number_format_i18n( gp_array_get( $gp_external_translations, 'openai_translations_used', 0 ) - gp_array_get( $gp_external_translations, 'openai_same_translations_used', 0 ) ), + number_format_i18n( gp_array_get( $gp_external_translations, 'openai_same_translations_used', 0 ) ), + ) + ); + } + echo ''; + } + ?> +
+ + 0 ) { + /* translators: Number of OpenAI tokens used. */ + echo esc_html( sprintf( __( 'OpenAI tokens used: %s', 'glotpress' ), number_format_i18n( $openai_tokens_used ) ) ); + } + ?> + +
+
+
+ + '; + if ( 401 == $openai_response_code ) { + echo ''; + esc_html_e( 'Your OpenAI API Key is not correct.', 'glotpress' ); + } elseif ( 200 != $openai_response_code ) { + echo ''; + esc_html_e( 'We have had a problem with the OpenAI API.', 'glotpress' ); + } else { + echo ''; + esc_html_e( 'Your OpenAI API Key is correct.', 'glotpress' ); + } + echo ''; + } + ?> +
+

+
/>
+ 0 ) { + echo '
'; + echo ''; + /* translators: Number of DeepL translations used. */ + echo esc_html( sprintf( _n( '%s DeepL translation used:', '%s DeepL translations used:', 'glotpress' ), number_format_i18n( gp_array_get( $gp_external_translations, 'deepl_translations_used', 0 ) ) ) ); + if ( gp_array_get( $gp_external_translations, 'deepl_same_translations_used', 0 ) > 0 ) { + echo ' ' . esc_html( + sprintf( + /* translators: 1: Number of DeepL translations used with modifications. 2: Number of DeepL translations used without modifications. */ + __( '%1$s with modifications and %2$s without modifications.', 'glotpress' ), + number_format_i18n( gp_array_get( $gp_external_translations, 'deepl_translations_used', 0 ) - gp_array_get( $gp_external_translations, 'deepl_same_translations_used', 0 ) ), + number_format_i18n( gp_array_get( $gp_external_translations, 'deepl_same_translations_used', 0 ) ), + ) + ); + } + echo ''; + } + ?> +
+ + 0 ) { + /* translators: Number of chars translated with DeepL. */ + echo esc_html( sprintf( __( 'Chars translated with DeepL: %s', 'glotpress' ), number_format_i18n( $deepl_chars_used ) ) ); + } + ?> + +
+ + '; + if ( 200 != $deepl_response_code ) { + echo ''; + esc_html_e( 'Your DeepL API Key is not correct.', 'glotpress' ); + } else { + echo ''; + esc_html_e( 'Your DeepL API Key is correct.', 'glotpress' ); + } + echo ''; + } + ?> +
diff --git a/content/plugins/f-translate/templates/settings.php b/content/plugins/f-translate/templates/settings.php new file mode 100644 index 0000000..70d17ba --- /dev/null +++ b/content/plugins/f-translate/templates/settings.php @@ -0,0 +1,39 @@ + 'priority', + 'how' => 'desc', + ); +} +?> +

+
+ +
+ + +
+ + +
+ + + + + + $project ) : + $name = str_replace( array( 'WordPress.org ', 'WordPress for ', 'WordPress ', 'ectory', ' - Development' ), '', $project->name ); + if ( $slug == 'wp-plugins' || $slug == 'wp-themes' ) { + $name = "Waiting $name"; + } + ?> + + + + + + $total_complete ) : + $gp_locale = GP_Locales::by_slug( $locale_slug ); + + if ( ! $gp_locale || ! $gp_locale->wp_locale ) { + continue; + } + + list( $locale, $set_slug ) = array_merge( explode( '/', $locale_slug ), [ 'default' ] ); + ?> + + + $project ) { + $projecturl = gp_url( gp_url_join( 'locale', $locale, $set_slug, $project->path ) ); + $project_name = str_replace( array( 'WordPress.org ', 'WordPress for ', 'WordPress ', 'ectory' ), '', $project->name ); + + if ( isset( $translation_locale_statuses[ $locale_slug ][ $project->path ] ) ) { + $percent = $translation_locale_statuses[ $locale_slug ][ $project->path ]; + + if ( 'waiting' === $project->path || 'wp-plugins' === $project->path || 'wp-themes' === $project->path ) { + $project_link_title = ''; + if ( 'wp-plugins' === $project->path || 'wp-themes' === $project->path ) { + $project_link_title = "Last Updated {$project->cache_last_updated}"; + + // Filter Plugins/Themes to Waiting (Most first) - Relying upon these being the last items. + $projecturl = add_query_arg( 'filter', 'strings-waiting-and-fuzzy', $projecturl ); + } + + // Color code it on -0~500 waiting strings + $percent_class = 100-min( (int) ( $percent / 50 ) * 10, 100 ); + // It's only 100 if it has 0 strings. + if ( 100 == $percent_class && $percent ) { + $percent_class = 90; + } + $percent_class = 'percent' . $percent_class; + echo ''; + } else { + $percent_class = 'percent' . (int) ( $percent / 10 ) * 10; + echo ''; + } + + } else { + echo ''; + } + } + ?> + + + +
+ + wp_locale ); ?> + + ' . number_format( $percent ) . '' . $percent . '%
+
+ + +english_name ) ); +$breadcrumb[] = trim( ucwords( $view ), 's' ) . ' translation status overview'; +gp_breadcrumb( $breadcrumb ); +gp_tmpl_header(); + +$columns = array( + 'all' => __( 'Translated Percent' ), + 'current' => __( 'Translated' ), + 'untranslated' => __( 'Untranslated' ), + 'fuzzy' => __( 'Fuzzy' ), + 'waiting' => __( 'Waiting' ), +); +$main_column_title = trim( ucwords( $view ), 's' ); + +?> +
+ + + + + %s", $title ); + } + + ?> + + + + $details ) { + $project_link = gp_url( gp_url_join( 'locale', $locale_path, $details->project->path ) ); + // Themes get a shortcut.. + if ( 'themes' == $view ) { + $project_link = gp_url( gp_url_join( 'projects', $details->project->path, $locale_path ) ); + } + + $project_overview_link = gp_url( gp_url_join( 'projects', $details->project->path ) ); + + echo ''; + printf( + '', + esc_attr( sprintf( __( "%s+ Active Installations" ), number_format_i18n( $details->installs ) ) ), + esc_attr( $main_column_title ), + $details->installs, + $project_overview_link, + $details->project->name + ); + + foreach ( $columns as $field => $title ) { + $sort_value = $stat_value = ( $details->stats->{$field} ?? 0 ); + $percent = $stat_value / $details->stats->all * 100; + $link = $project_link; + $cell_text = number_format_i18n( $stat_value ); + + if ( in_array( $field, [ 'fuzzy', 'untranslated', 'waiting' ] ) ) { + $percent = 100 - $percent; + $link = add_query_arg( 'filters[status]', $field, $project_link ); + } elseif ( 'all' == $field ) { + $percent = ($details->stats->current ?? 0) / $details->stats->all * 100; + $sort_value = $percent; + $cell_text = ( $percent > 50 ? floor( $percent ) : ceil( $percent ) ) . '%'; + } + + $percent_class = 'percent' . (int) ( $percent / 10 ) * 10; + + printf( '', + $percent_class, + $title, + $sort_value, + $link, + $cell_text + ); + } + echo ''; + } + ?> + +
%s%s
+
+ + +a, +p a { + text-decoration: underline; + text-decoration-thickness: max(1px,0.063rem); +} + +li>a:hover, +p a:hover { + color: var( --gp-color-accent-fg ); +} + +.gp-content a:active, +.gp-content a:focus, +.gp-content a:hover, +.gp-content .button.is-link:focus, +.gp-content .button.is-link:hover { + text-decoration: underline; + text-decoration-thickness: max(2px,0.125rem); +} + + +.gp-content .button-group > .button { + border-radius: 2px !important; + margin: 0; + display: inline-flex; +} + +.gp-content .button:visited { + color: var( --gp-color-btn-text ); + border: 1px solid var( --gp-color-btn-border ); + box-shadow: none; + background: var( --gp-color-btn-bg ); +} + +.gp-content .openai_api_key, .gp-content .deepl_api_key { + width: auto; +} + +.gp-content .openai_custom_prompt { + width: auto; + border: #7e7e7e thin solid !important; + border-radius: 3px; + height: 8rem; +} + +@media screen and (min-width: 750px) { + .gp-content .openai_api_key, .gp-content .deepl_api_key { + width: 30rem; + } + + .gp-content .openai_custom_prompt { + width: 30rem; + } +} + +select.is-small { + padding-top: 3px; + padding-bottom: 3px; + font-size: 12px; + min-height: 28px; +} + +/** + * GlotPress overrides. + */ + +:root { + --gp-color-fg-default: #000000; + --gp-color-accent-fg: #2271b1; + --gp-color-accent-emphasis: #135e96; + + --gp-color-border-default: #72777c; + --gp-color-border-muted: #b1b8c1; + + --gp-color-btn-text: #2271b1; + --gp-color-btn-border: #2271b1; + --gp-color-btn-hover-text: #135e96; + --gp-color-btn-hover-border: #135e96; + + --gp-color-btn-primary-text: #fff; + --gp-color-btn-primary-bg: #2271b1; + --gp-color-btn-primary-border: #2271b1; + --gp-color-btn-primary-hover-text: #fff; + --gp-color-btn-primary-hover-bg: #135e96; + --gp-color-btn-primary-hover-border: #135e96; + + --gp-color-status-fuzzy-subtle: #f6a983; + --gp-color-status-current-subtle: #b5e1b9; + --gp-color-status-old-subtle: #cdc5e1; + --gp-color-status-waiting-subtle: #ffe399; + --gp-color-status-rejected-subtle: #eb9090; + + --gp-color-tour: #d54e21; +} + +.locale-sub-projects .stats, +.translation-sets .stats { + text-align: left; +} + +table.glossary tr.editor, +table.translations tr.editor, +table.glossary tr.editor:hover, +table.translations tr.editor:hover { + border-left: 0; + box-shadow: none; +} + +.gp-content textarea { + max-width: 100%; +} + +.gp-content summary { + display: list-item; +} + +#gp-js-message { + top: 50px; + left: auto !important; + right: 20px; + font-size: 100%; + padding: 1em 1.5em; + border-radius: 5px; + max-width: 300px; +} + +#gp-js-message:empty { + display: none; +} + +@media screen and (max-width: 500px) { + div#gp-js-message { + top: 5px; + right: 5px; + left: 5px !important; + max-width: 100%; + z-index: 99999; + } +} + +@media screen and (min-width: 1025px) { + div#gp-js-message { + right: 50px; + } +} + +.gp-js-error { + color: #fff; + background-color: #dc3232; +} + +.gp-js-notice { + color: #333; + background-color: #ffb900; +} + +.gp-js-success { + color: #fff; + background-color: #46b450; +} + +.gp-content { + margin: 20px auto; + max-width: 1600px; + padding: 0 20px; +} + +.gp-content h2 { + font-size: 1.5rem; +} + +.gp-content h3 { + font-size: 1.25rem; + margin: 2px 0 .6em; +} + +.gp-content .breadcrumb { + background: none; + border: 0; + padding: 0; + margin: 0 0 1rem; +} + +p.description { + margin: 1em; +} + +a.project-actions { + display: inline-block; + margin-bottom: 1rem; +} + +a.project-actions:not(:hover):not(:focus) { + text-decoration: none; +} + +a.project-actions.open { + display: inline-block; + margin-bottom: .5rem; +} + +small code { + font-size: 1em; +} + +p.actionlist, +div.actionlist, +h2 + .glossary-description, +h2 + .project-description { + margin-top: 1em; + margin-bottom: 1em; +} + +.glossary-description { + font-size: 16px; +} + +.with-sub-projects #translation-sets { + width: auto; +} + +@media screen and (max-width: 960px) { + .with-sub-projects { + margin-left: 0; + } + + #sub-projects, + .with-sub-projects #translation-sets { + float: none; + margin: 0; + } + + #translation-sets { + overflow-x: auto; + } +} + +/* Change some colors (http://codepen.io/hugobaeta/full/RNOzoV/) */ +span.morethan90 { + background: none; + font-size: 90%; + color: #509040; +} + +span.context, +span.priority { + display: inline-block; + color: #1e1e1e; + font-size: 12px; + font-weight: 400; + padding: .1em 0; + margin-left: .2em; + background-color: #a0a5aa; + -webkit-box-decoration-break: clone; + box-decoration-break: clone; + box-shadow: .3em 0 0 #a0a5aa, -.3em 0 0 #a0a5aa; + border-radius: 0; +} + +span.context + span.priority { + margin-left: 1em; +} + +.priority-high span.priority { + color: #fff; + background-color: rgba( 154, 35, 35, 0.65 ); + box-shadow: 0.3em 0 0 rgba( 154, 35, 35, 0.65 ), -0.3em 0 0 rgba( 154, 35, 35, 0.65 ); +} + +.priority-low span.priority { + background-color: rgba( 213, 213, 213, 0.65 ); + box-shadow: 0.3em 0 0 rgba( 213, 213, 213, 0.65 ), -0.3em 0 0 rgba( 213, 213, 213, 0.65 ); +} + + +table.translations td.original ul { + margin: 0; + padding: 0; + list-style-type: none; +} + +table.translations td.original ul li, +table.translations td.translation ul li { + padding-bottom: .2em; + border-bottom: 1px dotted #72777c; +} + +table.translations td.original li:last-child, +table.translations td.translation li:last-child { + padding-bottom: 0; + border-bottom: none; +} + +table.translations td.original small, +table.translations td.translation small { + color: #293139; + font-size: 12px; +} + +.original-tags { + margin-top: .2em; +} + +.original-tags > * { + max-width: 100%; +} + +ul a.edit, +dt a.edit { + background: none; + color: inherit; +} + +/* Glossary editor */ +table.glossary .editor .strings { + width: 100%; + float: none; +} + +table.glossary .editor .strings input[type="text"] { + width: 100%; +} + +table.glossary .editor .meta { + width: 100%; + float: none; + margin: 30px 0 0; + font-size: 14px; +} + +table.glossary .editor .meta h3 { + font-size: 22px; +} + +@media screen and (min-width: 1024px) { + table.glossary .editor .strings { + width: 60%; + float: left; + } + + table.glossary .editor .meta { + width: calc( 40% - 20px ); + float: right; + margin: 0; + } +} + +table.glossary .editor .meta dl { + margin: 5px 0 0; +} + +table.glossary .editor .meta dd { + font-weight: 400; +} + +table.glossary .editor .meta dl:first-child { + margin-top: 0; +} + +table.glossary .editor textarea { + width: 100%; + height: 80px; + resize: vertical; +} + +.invisibles { + -webkit-user-select: none; + -ms-user-select: none; + user-select: none; +} + +span.translation-text, +span.original-text { + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; + white-space: pre-wrap; +} + +.ui-tooltip { + background: #fff; + border: 1px solid #ccc; + box-shadow: 0 2px 10px rgba(0,0,0,.1); + border-radius: 0; + z-index: 20; +} + +.ui-tooltip:after { + border-color: #fff transparent; + top: -9px; +} + +.ui-tooltip:before { + display: block; + content: ""; + border-color: #ccc transparent; + border-style: solid; + border-width: 0 10px 10px; + width: 0; + position: absolute; + top: -10px; + left: 1em; +} + +.ui-tooltip ul { + padding: 0; + margin: 5px; +} + +.ui-tooltip ul li { + font-size: 15px; +} + +.ui-tooltip ul li + li { + margin-top: 5px; +} + +/* custom markup */ +#headline .menu-link { + padding-right: 20px; +} + +/* overrides the global stylesheet: */ +.gp-content blockquote { + border: 0; + background: none; + padding: 0; + margin: 0; +} + +/*.gp-content ul { + padding-left: 0; +}*/ + +/*.gp-content #submit { + font-size: 1em; + margin: 0.4em 0.1em 0 0; +}*/ + +.notice { + background: #e5f5fa; + border-left: 3px solid #00a0d2; + margin-bottom: 10px; +} + +.notice a { + color: #006799; +} + +.notice p { + font-size: 15px; +} + +p.intro { + width: 75%; + margin-bottom: 20px; + font-size: 1.1em; + line-height: 1.5em; +} + +.filter-header { + display: inline-block; + position: relative; + margin: 30px 0; + padding: 0 20px; + width: 100%; + box-shadow: 0 1px 1px rgba(0,0,0,0.04); + border: 1px solid #dfdfdf; + background: #efefef; + color: #555; +} + +ul.filter-header-links { + display: inline-block; + margin: 0; + padding: 0; +} + +.filter-header-links li { + display: inline-block; + margin: 0; +} + +.filter-header-links li > a, +.filter-header-links li > span { + display: inline-block; + margin: 0 10px; + padding: 15px 0; + border-bottom: 4px solid #efefef; + color: #666; + cursor: pointer; + text-decoration: none !important; +} + +.filter-header-links li:hover > a, +.filter-header-links li:hover > span { + border-bottom-color: #666; +} + +.filter-header-links .current { + box-shadow: none; + border-bottom: 4px solid #666; + color: #222; +} + +.filter-header-links li.has-children { + position: relative; +} + +.filter-header-links li.has-children li a { + margin: 0 9px; + padding: 5px 0; +} + +.filter-header-links li.has-children ul { + display: none; +} + +.filter-header-links li.has-children:hover ul { + display: block; + position:absolute; + background: #efefef; + padding: 0; + box-shadow: 0 1px 1px rgba(0,0,0,0.04); + border: 1px solid #dfdfdf; + border-top: 0; + z-index: 1; + margin: 0; +} + +.filter-header-link__sep { + color: #ccc; +} + + +.filter-header .search-form { + float: right; + margin: 12px 0 11px; +} + +.filter-header .filter-search { + margin: 0; + padding: 3px 5px; + width: 280px; + font-size: 16px; + font-weight: 300; + line-height: 1.5; + border: 1px solid #ddd; + box-shadow: inset 0 1px 2px rgba( 0, 0, 0, 0.07 ); + background-color: #fff; + color: #333; + outline: none; + border-radius: 0; + -webkit-appearance: textfield; +} + +@supports (display: flex) and (not (display: grid)) { + .locales { + display: flex; + flex-wrap: wrap; + margin: 0 -15px; + } + + .locales .locale { + flex-grow: 1; + margin: 0 15px 30px; + width: calc( 33% - 30px ); + } +} + +@supports (display: grid) { + .locales { + display: -ms-grid; + display: grid; + -ms-grid-columns: 1fr; + grid-template-columns: 1fr; + grid-gap: 30px; + } + + @media screen and (min-width: 500px) { + .locales { + -ms-grid-columns: 1fr 30px 1fr; + grid-template-columns: repeat(2, 1fr); + } + } + + @media screen and (min-width: 1024px) { + .locales { + -ms-grid-columns: 1fr 30px 1fr 30px 1fr; + grid-template-columns: repeat(3, 1fr); + } + } + + @media screen and (min-width: 1300px) { + .locales { + -ms-grid-columns: 1fr 30px 1fr 30px 1fr; + grid-template-columns: repeat(4, 1fr); + } + } +} + +/* Clearfix */ +.locale-header:before, +.locale-header:after, +.project-box-header:before, +.project-box-header:after, +.project-status:before, +.project-status:after, +.locale-project-contributors:before, +.locale-project-contributors:after { + content: ""; + display: table; +} + +.locale-header:after, +.project-box-header:after, +.project-status:after, +.locale-project-contributors:after { + clear: both; +} + +.locale { + border: 1px solid #72777c; + box-shadow: 0 1px 1px -1px rgba(0,0,0,0.1); + background: #fff; +} + +.locale a { + text-decoration: none; +} + +.locale .contributors a, +.locale-box .contributors a { + text-decoration: none !important +} + +.locale.percent-100 { + border-color: #509040; +} + +.locale-button { + background: #f9f9f9; + text-align: center; + padding: 20px 0; +} + +.locale .name, +.locale-box .name { + display: inline-block; + margin: 0; + padding: 20px 10px 20px 20px; +} + +.locale .name { + max-width: calc( 100% - 100px ); +} + +.locale .name .english { + font-size: 18px; +} + +.locale .name li, +.locale-box .name li { + display: block; +} + +.locale .name li.english a, +.locale-box .name li.english { + font-weight: 600; +} + +.locale-box.project .name li.english { + font-weight: normal; +} + +.locale .name li.code a, +.locale-box .name li.code { + color: #999; +} + +.locale .contributors, +.locale-box .contributors, +.locale-box .project-status { + float: right; + margin-top: 20px; + padding: 10px 20px; + color: #006799; + border-left: 1px solid #72777c; + text-align: center; +} + +.locale-box .project-status { + color: #509040; + font-weight: 600; +} + +.locale .contributors .dashicons, +.locale-box .contributors .dashicons { + font-size: 2em; + padding-bottom: 10px; + display: inline; +} + +.locale-box .contributors .dashicons { + font-size: 1.5em; +} + +.locale .percent, +.project-box .percent, +.project .percent { + width: 100%; + height: 4px; + background-color: #d6d6d6; +} + +.locale .percent-complete, +.project-box .percent-complete, +.project .percent-complete { + height: 4px; + background-color: #509040; +} + +.locale-intro { + float: left; + width: 100%; + max-width: 600px; + margin-top: 20px; + font-family: Georgia, Times, "Times New Roman", serif; + font-size: 16px; + line-height: 1.6em; +} + +.locale-box { + float: right; + width: 250px; + border: 1px solid #72777c; + box-shadow: 0 1px 1px -1px rgba(0,0,0,0.1); + background: #fff; +} + +.projects-paging { + clear: both; + display: flex; + justify-content: flex-end; + margin: 1rem 0; +} + +.projects { + clear: both; + display: grid; + grid-gap: 1rem; + grid-template-columns: minmax( 0, 1fr ); + margin: 1rem 0; +} + +@media screen and (min-width: 799px) { + .projects { + grid-template-columns: repeat( 2, minmax( 0, 1fr ) ); + } +} + +@media screen and (min-width: 1219px) { + .projects { + grid-template-columns: repeat( 3, minmax( 0, 1fr ) ); + } +} + +@media screen and (min-width: 1500px) { + .projects { + grid-template-columns: repeat( 4, minmax( 0, 1fr ) ); + } +} + +.projects .project { + display: flex; + flex-direction: column; + justify-content: flex-end; + border: 1px solid #72777c; + box-shadow: 0 1px 1px -1px rgba(0,0,0,0.1); + background: #fff; +} + +.projects .project.percent-100 { + border-color: #509040; +} + +.projects .project-top { + position: relative; + padding: 20px; + min-height: 140px; + margin-bottom: auto; +} + +.projects .project-name, +.projects .project-description { + margin-left: 120px; + overflow-wrap: break-word; +} + +.projects .project-name h4 { + border: 0; + margin: 0 0 8px; + font-size: 18px; + font-weight: 600; +} + +.projects .project-description { + border-left: 0; + margin-top: 0; + padding: 0; + font-size: .875rem; +} + +.projects .project-description p { + margin: 0; +} + +.projects .project-icon { + position: absolute; + top: 20px; + left: 20px; + width: 100px; + height: 100px; + margin: 0 20px 20px 0; +} + +.projects .project-icon .plugin-icon { + margin: 0 !important; +} + +.projects .project-icon .default-icon, +.projects .project-icon .wordpress-icon { + width: 100px; + height: 100px; + background: #dedede; +} + +.projects .project-icon .plugin-icon { + width: 100px; + height: 100px; + background-size: contain; +} + +.projects .project-icon .default-icon span, +.projects .project-icon .wordpress-icon span { + height: 100px; + width: 100px; + font-size: 85px; + line-height: 100px; + color: #a0a5aa; +} + +.projects .project-icon .wordpress-icon { + background: #464646; +} + +.projects .project-icon .wordpress-icon span { + color: #fff; +} + +.projects .project-icon .icon img { + width: 100px; + height: auto; +} + +.projects .project-status { + font-size: 13px; +} + +.projects .project-status > div { + width: 25%; + float: left; + margin: 0 0 20px; + text-align: center; +} + +.projects .project-status > div:not(:first-child) { + border-left: 1px solid #72777c; +} + +@media screen and (max-width: 500px) { + .projects .project-status > div { + width: 50%; + } + + .projects .project-status > div:nth-child(3) { + border-left: 0; + } +} + +.projects .project-status-title { + display: inline-block; + margin-bottom: 6px; + color: #82878c; +} + +.projects .project-status-value { + display: block; + font-size: 16px; + font-weight: 600; +} + +.projects .project-status-progress .project-status-value { + color: #509040; +} + +.projects .project-bottom { + background: #f9f9f9; + text-align: center; + padding: 20px 0; +} + +/* Project */ +.project-header { + margin-bottom: 30px; + display: flex; +} + +.project-header .project-description { + flex: 1; + margin-top: 20px; + margin-left: 0; + max-width: 100%; + padding: 0; + border: 0; +} + +.project-header .project-box { + position: relative; + width: 350px; + height: 100%; + margin-left: 20px; + border: 1px solid #72777c; + box-shadow: 0 1px 1px -1px rgba(0,0,0,0.1); + background: #fff; + font-size: 14px; +} + +.project-box.percent-100 { + border-color: #509040; +} + +.project-box .project-box-header { + position: relative; + padding: 15px; +} + +.project-box .project-icon { + float: left; + width: 64px; + height: 64px; + margin: 0 20px 20px 0; +} + +.project-box .project-icon .plugin-icon { + width: 64px; + height: 64px; + background-size: contain; +} + +.project-box .project-icon .default-icon, +.project-box .project-icon .wordpress-icon { + width: 64px; + height: 64px; + background: #dedede; +} + +.project-box .project-icon .default-icon span, +.project-box .project-icon .wordpress-icon span { + height: 64px; + width: 64px; + font-size: 42px; + line-height: 64px; + color: #a0a5aa; +} + +.project-box .project-icon .wordpress-icon { + background: #464646; +} + +.project-box .project-icon .wordpress-icon span { + color: #fff; +} + +.project-box .project-icon .icon img { + width: 64px; + height: auto; +} + +.project-box .project-meta { + float: left; + width: 165px; + list-style: none; + margin: 0; + padding: 0; +} + +.project-meta .project-name { + font-weight: 600; +} + +.project-meta .locale-code { + color: #999; +} + +.project-box .project-status { + position: absolute; + top: 50%; + right: 15px; + transform: translateY(-50%); + font-size: 20px; + font-weight: 600; + color: #509040; + padding: 10px 0 10px 15px; + border-left: 1px solid #72777c; +} + +.project-box .project-box-footer { + background: #f9f9f9; +} + +ul.projects-dropdown { + border-top: 1px solid #72777c; +} + +.project-status-progress + .project-box-footer > ul.projects-dropdown { + border-top: 0; +} + +ul.projects-dropdown, +ul.projects-dropdown ul { + margin: 0; + padding: 0; +} + +.projects-dropdown li { + list-style: none; +} + +.projects-dropdown a, +.projects-dropdown a:hover, +.projects-dropdown a:focus { + color: #333; + text-decoration: none; +} + +.projects-dropdown a:hover, +.projects-dropdown a:focus { + background: #ddd; +} + +ul.projects-dropdown ul { + position: absolute; + left: -1px; + right: -1px; + width: inherit; + background: #f9f9f9; + border: 1px solid #72777c; + border-top: 0; + box-shadow: 1px 1px 1px 0 rgba(0,0,0,0.04); + display: none; + z-index: 10; +} + +ul.projects-dropdown.open ul { + display: block; +} + +ul.projects-dropdown li > span, +ul.projects-dropdown li > a { + position: relative; + display: block; + padding: 10px 50px 10px 15px; + cursor: pointer; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +/* Dropdown arrow */ +ul.projects-dropdown > li > span:after { + position: absolute; + top: 5px; + right: 25px; + content: "\f140"; + width: 20px; + height: 30px; + font: 20px/1 "dashicons"; + border-left: 1px solid #72777c; + padding: 5px 0 5px 12px; + box-shadow: inset 1px 0 0 #fff; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +ul.projects-dropdown.open > li > span:after { + content: "\f142"; +} + +/* Percentage */ +ul.projects-dropdown li > a > span { + position: absolute; + right: 15px; +} + +/* Sub Projects table */ +.locale-sub-projects .sub-project-status { + font-size: 90%; + color: #a0a5aa; + padding-left: .5em; +} + +.locale-sub-projects .sub-project-status.percent-90 { + color: #509040; +} + +@media screen and (max-width: 675px) { + .locale-sub-projects th, + .locale-sub-projects td { + display: block; + } + + .locale-sub-projects thead th { + display: none; + } + + .locale-sub-projects thead th:nth-child(1) { + display: block; + width: 97%; + } + + table.locale-sub-projects th:first-child, + table.locale-sub-projects td:first-child { + border-left: none; + border-right: none; + width: 100% !important; + } + + table.locale-sub-projects td.stats { + padding-left: 15px; + border-right :none; + } + + .locale-sub-projects td.stats.translated:before { + content: "Translated:"; + } + + .locale-sub-projects td.stats.fuzzy:before { + content: "Fuzzy:"; + } + + .locale-sub-projects td.stats.untranslated:before { + content: "Untranslated:"; + } + + .locale-sub-projects td.stats.waiting:before { + content: "Waiting:"; + } + + .locale-sub-projects td.stats.changesrequested:before { + content: "Changes requested:"; + } +} + +.projects .no-projects-found { + width: 100%; + float: none; + text-align: center; + margin: 30px 0; + font-size: 1.5em; + color: #999; + min-height: 5em; +} + +.wporg-notice { + background: #fff; + border-left: 4px solid #fff; + margin: 5px 0 15px 0; + padding: 1px 12px; +} + +.wporg-notice p { + margin: 0.5em 0; + padding: 2px; +} + +.wporg-notice-error { + background: #fbeaea; + border-left-color:#dc3232; +} + +.wporg-notice-warning { + background: #fff8e5; + border-left-color:#ffb900; +} + +.wporg-notice-info { + background: #e5f5fa; + border-left-color:#00a0d2; +} + +/* Responsive styles */ +@media screen and (max-width: 1024px) { + #hello { + margin: 25px 10px 15px; + } + + #hello a { + white-space: nowrap; + } + + p.intro { + width: 100%; + } + + .locale-intro { + float: none; + } + + .locale-box { + float: none; + width: 100%; + margin-top: 20px; + } + + .filter-header .search-form { + float: none; + width: 100%; + } + + .filter-header .filter-search { + width: 100%; + } + + .project-header { + display: block; + } + + .project-header .project-box { + margin-top: 20px; + margin-left: 0; + width: 100%; + } + .stats-table table thead th { + display: none; + } + .stats-table table tbody th, + .stats-table table tbody tr, + .stats-table table tbody td { + display: block; + text-align: left; + } + .stats-table table tbody tr { + margin-top: 20px; + } + + .stats-table table tbody td { + padding: 3px 10px; + position: relative; + padding-left: 50%; + } + .stats-table table tbody td:before { + position: absolute; + top: 0; + left: 10px; + width: 45%; + } + + .stats-table td:before { + content: attr(data-column-title); + } +} + +.stats-table table.table { + width: 100%; + text-align: center; + border-collapse: collapse; + table-layout: fixed; +} + +.stats-table table thead { + color: #32373C; + background: white; +} +.stats-table table td, table th { + text-align: unset; /* Override wporg-main. */ +} +.stats-table table thead th { + cursor: pointer; + margin: 0; + margin-right: 0px; + font-weight: bold; + text-align: center; + vertical-align: middle; + padding: 10px 15px 10px 10px; + font-size: .8em; + line-height: 1.2; + border-right: 1px solid #72777C; + border-bottom: 1px solid #72777C; +} + +.stats-table table thead th:last-child { + border-right: none; +} + +.stats-table table th { + overflow-wrap: break-word; +} + +.stats-table table th.col-locale-code { + width: 110px; +} + +.stats-table table th.col-wordpress-org { + width: 60px; +} + +.stats-table table th.col-locale { + width: 180px; +} + +.stats-table .none { + color: #ccc; +} + +.stats-table tbody th { + text-align: left; + padding: 10px; + background: #f9f9f9; + box-shadow: inset 0 1px 0 rgba(0,0,0,.05); +} + +.stats-table tbody tr:hover { + opacity: 0.8; + outline: 1px solid #191E23; + outline-offset: 0; +} + +.stats-table tbody tr th a:link, +.stats-table tbody tr th a:hover, +.stats-table tbody tr th a:visited { + color: #191E23; +} + +.stats-table tbody td { + padding: 10px 0; + box-shadow: inset 0 1px 0 rgba(255,255,255,.15); +} + +.stats-table tbody td.percent100 {background: #46B450; color: white;} +.stats-table tbody td.percent90 {background: #6BC373;} +.stats-table tbody td.percent80 {background: #90D296;} +.stats-table tbody td.percent70 {background: #B5E1B9;} +.stats-table tbody td.percent60 {background: #C7E8CA;} +.stats-table tbody td.percent50 {background: #FFE399;} +.stats-table tbody td.percent40 {background: #FBC5A9;} +.stats-table tbody td.percent30 {background: #F1ADAD;} +.stats-table tbody td.percent20 {background: #EA8484;} +.stats-table tbody td.percent10 {background: #E35B5B;} +.stats-table tbody td.percent0 {background: #DC3232; color: white;} + +.stats-table tbody td a:link, +.stats-table tbody td a:hover, +.stats-table tbody td a:visited { + color: #191E23; + display: inline-block; + width: 100%; + height: 100%; +} + +.stats-table tbody td.percent100 a:link, +.stats-table tbody td.percent0 a:link, +.stats-table tbody td.percent100 a:hover, +.stats-table tbody td.percent0 a:hover, +.stats-table tbody td.percent100 a:visited, +.stats-table tbody td.percent0 a:visited { + color: white; +} + +.stats-table tbody tr td { + vertical-align: middle; +} + +.stats-table th.headerSortUp:after, +.stats-table th.headerSortDown:after { + font-family: "dashicons"; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.stats-table th.headerSortUp:after { + content: "\f140"; +} + +.stats-table th.headerSortDown:after { + content: "\f142"; +} + +.sort-bar { + float: right; + margin: -30px 0 1rem 5px; + background-color: #e2e4e7; + padding: 5px; + border: 1px solid #dfdfdf; + border-top: none; +} + +.sort-bar label { + font-size: 12px; + line-height: 14px; +} + +.sort-bar .filter-sep { + color: #ccc; +} + +.project-sub-page h3 { + margin: 30px 0 10px; + font-size: 1.2em; +} + +.project-sub-page p { + margin-bottom: 1em; +} + +ul.contributors-list, +ul.language-packs-list { + margin: 30px 0; + padding: 0; + list-style: none; +} + +.contributors-list li, +.language-packs-list li { + margin: 10px 0 10px 30px; +} + +.contributors-list li strong, +.language-packs-list li strong { + display: block; + margin-left: -30px; +} + +.language-packs-list li strong .locale-code { + font-size: 11px; + color: #555d66; +} + +.ct-chart-contributors { + position: relative; +} + +.ct-chart-contributors .ct-series-a .ct-area { /* current */ + fill: #b5e1b9; + fill-opacity: .5; +} + +.ct-chart-contributors .ct-series-b .ct-area { /* waiting */ + fill: #ffe399; + fill-opacity: .5; +} + +.ct-chart-contributors .ct-series-c .ct-area { /* rejected */ + fill: #eb9090; + fill-opacity: .5; +} + +ul.ct-legend { + position: absolute; + right: 0; + top: -15px; + padding: 0; + list-style: none; + z-index: 5; + margin: 0; + font-size: 12px; +} + +.ct-legend li { + position: relative; + display: inline-block; + padding-left: 16px; + margin-right: 3px; + cursor: pointer; +} + +.ct-legend li:before { + content: ''; + position: absolute; + top: 4px; + left: 0; + width: 12px; + height: 12px; + border: 3px solid transparent; + border-radius: 2px; +} + +.ct-legend li.inactive:before { + background: transparent; +} + +.ct-legend .ct-series-0:before { /* current */ + background-color: #b5e1b9; + border-color: #b5e1b9; +} + +.ct-legend .ct-series-1:before { /* waiting */ + background-color: #ffe399; + border-color: #ffe399; +} + +.ct-legend .ct-series-2:before { /* rejected */ + background-color: #eb9090; + border-color: #eb9090; +} + +@media screen and (min-width: 600px) { + .contributors-list { + -webkit-column-count: 2; + -webkit-column-gap: 3%; + -moz-column-count: 2; + -moz-column-gap: 3%; + column-count: 2; + column-gap: 3%; + } +} + +.contributors-list-box { + display: inline-block; + width: 100%; + margin-bottom: 20px; + padding-bottom: 10px; + border: 1px solid #ccc; + background: #fff; + page-break-inside: avoid; + break-inside: avoid; +} + +.contributors-list-box h4 { + position: relative; + display: block; + padding: 5px 8px; + margin: 0 0 10px; + background: #f9f9f9; + border-bottom: 1px solid #ccc; + font-size: 14px; +} + +.contributors-list-box .contributors-count { + font-size: 11px; + color: #82878c; + padding-left: 3px; +} + +.contributors-list-box .locale-code { + position: absolute; + top: 1px; + right: 5px; + font-size: 10px; + color: #b4b9be; +} + +.contributors-list-box p { + margin-bottom: .5em; + padding: 0 8px; +} + +.contributors-list-box p:last-child { + margin-bottom: 0; +} + +.contributors-list-filter { + margin: 15px 0 10px; + text-align: right; +} + +.contributors-list-filter .search { + margin: 0 0 0 10px; + padding: 2px 4px; + width: 280px; + font-size: 13px; + font-weight: 300; + border: 1px solid #ddd; + box-shadow: inset 0 1px 2px rgba( 0, 0, 0, 0.07 ); + background-color: #fff; + color: #333; + outline: none; + border-radius: 0; + -webkit-appearance: textfield; +} + +@media screen and (max-width: 600px) { + .contributors-list-filter { + text-align: center; + } + + .contributors-list-filter .search { + display: block; + width: 100%; + margin: 10px 0; + } +} + +/* Buttons that look like links, for a cross of good semantics with the visual */ +.button-link { + margin: 0; + padding: 0; + box-shadow: none; + border: 0; + border-radius: 0; + background: none; + outline: none; + cursor: pointer; + font: inherit; + color: #0073aa; +} + +.button-link:hover { + color: #00a0d2; +} + +.contributors-list-filter .filter.active { + border-bottom: 1px solid #dfdfdf; +} + +.contributors-list[data-current-filter="has-editors"] .no-editors, +.contributors-list[data-current-filter="no-editors"] .has-editors { + display: none !important; +} + +@media screen and (min-width: 600px) { + .locale-project-contributors-group { + float: left; + } + + .locale-project-contributors-contributors { + width: 65%; + margin-right: 5%; + } + + .locale-project-contributors-editors { + width: 30%; + } +} + +.locale-project-contributors-group hr { + margin: 30px 0; + border-color: #72777c; +} + +.locale-project-contributors-group ul { + padding: 0; + margin: 10px 0; + list-style: none; +} + +.locale-project-contributors-group li { + margin: 0 0 10px; +} + +.locale-project-contributors-group.locale-project-contributors-editors .avatar { + vertical-align: middle; + margin-right: 5px; +} + +.locale-project-contributors-group ul.compressed li { + display: inline-block; + margin-right: 8px; + font-size: small; +} + +.locale-project-contributors-group ul.compressed li:not(:last-child):after { + content: ', '; +} + +.locale-project-contributors-group ul.compressed .avatar { + margin-right: 3px; +} + +.locale-project-contributors-table { + width: 100%; +} + +.locale-project-contributors-table .contributor-details { + width: 40%; + overflow: hidden; +} + +.locale-project-contributors-table .contributor-avatar { + float: left; + width: 40px; + display: flex; + flex-direction: column; +} + +.locale-project-contributors-table .contributor-name { + margin-left: 50px; + display: flex; + flex-direction: column; +} + +.locale-project-contributors-table .translation-editor { + width: 40px; + color: #fff; + font-weight: 200; + font-size: 12px; + line-height: 16px; + text-align: center; + background-color: #826eb4; +} + +.locale-project-contributors-table tr { + vertical-align: top; +} + +.locale-project-contributors-table th { + font-weight: bold; +} + +.locale-project-contributors-table th, +.locale-project-contributors-table td { + padding: 10px; + font-size: 14px; + border-bottom: 1px solid #72777c; +} + +.locale-project-contributors-table tr:last-child td { + border-bottom: 0; +} + +.locale-project-contributors-table th.contributor-stats { + text-align: center; +} + +.locale-project-contributors-table td.contributor-stats div { + text-align: center; + width: 25%; + float: left; +} + +.locale-project-contributors-table td.contributor-stats div span { + text-transform: uppercase; + font-size: 12px; +} + +.locale-project-contributors-table td.contributor-stats div.current span { + color: #6bc373; +} + +.locale-project-contributors-table td.contributor-stats div.waiting span { + color: #ffc733; +} + +.locale-project-contributors-table td.contributor-stats div.fuzzy span { + color: #f78b53; +} + +.locale-project-contributors-table td.contributor-stats .detailed { + width: 100%; + clear: left; + float: none; +} + +.detailed summary { + text-align: right; + font-size: 12px; + outline: none; + cursor: pointer; +} + +.detailed__project-name { + display: block; + clear: left; + text-align: left; + font-size: 12px; + padding-top: 5px; +} + +.locale-project-contributors-contributors .stats-hint { + text-align: right; + font-size: 12px; +} + +@media screen and (max-width: 500px) { + .locale-project-contributors-table thead { + display: none; + } + + .locale-project-contributors-table tbody td { + width: 100%; + display: block; + } + + .locale-project-contributors-table .contributor-details, + .locale-project-contributors-table .contributor-stats { + width: 100%; + border-bottom: 0; + } + + .locale-project-contributors-table .contributor-details span { + float: none; + } + + .locale-project-contributors-table .contributor-stats:before, + .locale-project-contributors-table .contributor-stats:after { + content: ""; + display: table; + } + + .locale-project-contributors-table .contributor-stats:after { + clear: both; + } +} + +.consistency-form { + margin: 30px 0; + text-align: center; +} + +.consistency-form p { + margin-bottom: 1em; +} + +.gp-content .consistency-form-search, +.consistency-form-locale, +.consistency-form-project { + vertical-align: middle; +} + +.consistency-form-search { + width: 300px; +} + +.consistency-form-locale { + width: 150px; +} + +.consistency-form-project { + width: 120px; +} + +.consistency-field { + display: inline-block; +} + +.consistency-field label { + display: block; + margin: 0 3px; + font-size: 13px; + text-align: left; +} + +.consistency-table { + width: 100%; + border-collapse: collapse; + table-layout: fixed; + margin: 30px 0; + border: 0; +} + +.consistency-table thead th { + width: 50%; + text-align: center; +} + +.consistency-table td { + vertical-align: top; +} + +.consistency-table tr.new-translation th { + position: -webkit-sticky; + position: sticky; + top: 0; + padding: 10px 7.5px; + background-color: var(--gp-color-canvas-subtle); + border-top-width: 3px; +} + +.consistency-table tbody > tr.new-translation:first-child th { + border-top-width: 0; +} + +/* This is when the admin bar start to stick. */ +@media screen and (min-width: 601px) { + .consistency-table tr.new-translation th { + top: var(--wp-admin--admin-bar--height); + } +} + +/* This is when the global header start to stick. */ +@media screen and (min-width: 890px) { + .consistency-table tr.new-translation th { + top: calc(var(--wp-global-header-height) + var(--wp-admin--admin-bar--height)); + } +} + +.anchor-jumper { + padding: 0 5px; + font-weight: 600; +} + +.consistency-table tr.new-translation th .anchor-jumper { + float: right; +} + +.consistency-table .string.rtl { + direction: rtl; +} + +.consistency-table .meta { + margin-top: 10px; + color: #818181; +} + +.consistency-table .project-wordpress { + background: #E5F5FA !important; +} + +.translations-unique { + margin: 5px; +} + +.translations-unique .space { + background: #cbcdce; + white-space: pre; + opacity: .5; +} + +.paging a { + text-decoration: none !important; +} + +/* Word wraps and fixed table layout for translations */ +.editor .original, +.editor .translation, +span.context, +table.translations td.original, +table.translations td.translation { + word-break: normal; + word-wrap: break-word; + overflow-wrap: break-word; +} + +table.translations th.gp-column-priority, +table.translations td.priority { + display: none; +} + +table.translations tr.preview:not(.has-warnings) > td.priority + td.original { + border-left: none; +} + +table.translations { + table-layout: fixed; +} + +table.translations th.gp-column-original, +table.translations th.gp-column-translation { + width: 50%; +} + +table.translations th.gp-column-actions { + width: 5em; + text-align: center; +} + +table.translations td.translation span.missing { + color: #666; +} + +/* NEW EDITOR */ + +.editor-panel .strings { + float: none; + width: 100%; + min-width: 100%; +} + +.editor-panel .textareas textarea { + width: 100%; + border: 0; + background: #fff !important; + color: #1e1e1e !important; + outline: none; + padding: 15px 0; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; + font-size: 16px; + resize: vertical; + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; +} + +.editor-panel .textareas p, +.editor-panel .textareas blockquote.translation { + display: none; +} + +.editor-panel .original { + max-width: 100%; + font-weight: normal; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; +} + +.editor-panel .original-raw { + display: none; +} + +.editor-panel .meta dt { + margin-right: .25em; +} + +.editor-panel .meta dd { + font-weight: 400; +} + +.editor-panel .meta { + float: none; + width: 100%; + margin: 0; + padding: 0 10px 20px 10px; +} + +.editor-panel .meta .status-actions { + margin-bottom: 15px; +} + +.editor-panel .meta .status-actions button strong { + margin-right: .4em; +} + +/*button.approve strong { + color: #46b450; +}*/ + +button.button.is-primary.approve, +button.button.reject, +button.button.changesrequested, +button.button.fuzzy +{ + margin-bottom: 0.5rem; +} + +button.reject strong { + color: #dc3232; +} + +button.fuzzy strong { + color: #f56e28; +} + +.editor-panel .meta dl { + font-size: 14px; + margin: 5px 0 0; +} + +.editor-panel .meta dl:first-child { + margin-top: 0; +} + +table.translations tr.editor td { + padding: 0; + border-bottom-width: 2px; + border-top: 1px solid #72777c; +} + +@media screen and (min-width: 1024px) { + .editor-panel { + display: flex; + align-items: flex-start; + } +} + +.editor-panel__left { + flex: 1; + border-bottom: 1px solid #72777c; + min-width: 1%; +} + +@media screen and (min-width: 1024px) { + .editor-panel__left { + border-bottom: 0; + border-right: 1px solid #72777c; + } +} + +.editor-panel__right { + flex: 0 0 21rem; + min-width: 1%; +} + +@media screen and (min-width: 1024px) { + .editor-panel__right { + min-width: 40%; + position: -webkit-sticky; + position: sticky; + top: 0; + z-index: 10; + } +} + +.panel-header { + display: flex; + align-items: center; + justify-content: flex-end; + border-bottom: 1px solid #72777c; + background-color: #f3f4f5; + min-height: 40px; +} + +@media screen and (max-width: 1023px) { + .editor-panel__left { + width: 100%; + } + .editor-panel__right { + width: 100%; + } +} + +@media screen and (min-width: 1024px) { + .panel-header { + height: 40px; + } +} + +.editor-panel__left .panel-header, .editor-panel__right { + position: -webkit-sticky; + position: sticky; + top: 0; + z-index: 10; +} + +.admin-bar .editor-panel__left .panel-header, +.admin-bar .editor-panel__right { + top: 32px; +} + +@media screen and (min-width: 890px) { + .admin-bar .editor-panel__left .panel-header, + .admin-bar .editor-panel__right { + top: calc( var(--wp-admin--admin-bar--height) ); + } +} + +@media screen and (max-width: 782px) { + .admin-bar .editor-panel__left .panel-header, + .admin-bar .editor-panel__right { + top: 46px; + } +} + +@media screen and (max-width: 600px) { + .admin-bar .editor-panel__left .panel-header { + top: 0; + } +} + +.panel-header h3 { + flex: 1; + margin: 0 0 0 10px; + font-size: 13px; + line-height: 20px; + font-weight: 400; + letter-spacing: 1px; + text-transform: uppercase; + color: #1e1e1e; +} + +.panel-header__bubble { + display: inline-block; + padding: 2px 4px; + margin: 2px 0; + white-space: nowrap; + font-size: 12px; + font-weight: 600; + text-transform: none; + border: 1px solid #666; +} + +.panel-header__bubble--warning { + color: var(--gp-color-danger-fg); + border-color: var(--gp-color-danger-fg); +} + +.panel-header__bubble--waiting { + color: #FFB900; + border-color: #FFB900; +} + +.panel-header__bubble--fuzzy { + color: #F56E28; + border-color: #F56E28; +} + +.panel-header__bubble--current { + color: #46B450; + border-color: #46B450; +} + +.panel-header__bubble--old { + color: #826EB4; + border-color: #826EB4; +} + +.panel-header-actions { + align-self: flex-start; +} + +.panel-header-actions button { + background: none; + border: none; + height: 40px; + width: 40px; + padding: 0; + margin: 0; + vertical-align: middle; + box-shadow: none; + border-radius: 0; + display: inline-flex; + align-items: center; + justify-content: center; +} + +.panel-header-actions button:hover { + background: #bdbdbd; +} + +table.translations tbody > tr:first-child + tr .panel-header-actions__previous, +table.translations tbody > tr:last-child .panel-header-actions__next { + display: none; +} + +.button-menu { + position: relative; + display: inline-block; +} + +.button-menu__dropdown { + display: none; + list-style: none; + position: absolute; + top: 100%; + right: 0; + z-index: 1000; + min-width: 150px; + background-color: #fff; + white-space: nowrap; + border: 1px solid #ccc; + padding: 6px 12px !important; + box-shadow: 0 2px 10px rgba(0,0,0,.1); +} + +.button-menu.active .button-menu__dropdown { + display: block; +} + +.button-menu__dropdown li a { + padding: 6px 0; + display: inline-block; +} + +.panel-content summary { + cursor: pointer; + outline: 0; +} + +.panel-content summary:focus { + color: #1e1e1e; +} + +.panel-content details[open] summary { + margin-bottom: 5px; +} + +.source-string { + padding: 20px 10px; +} + +.source-string__singular small, +.source-string__plural small { + display: block; + color: #666; + font-size: 12px; +} + +.source-string__plural { + margin-top: 15px; +} + +.source-details { + padding: 0 10px; + font-size: 14px; +} + +.source-details summary { + color: #666; +} + +.source-details details[open] summary { + margin: 0; +} + +.source-details details + details { + margin-top: 5px; +} + +.source-details__references { + word-wrap: break-word; + overflow-wrap: break-word; +} + +.source-details__context .context { + font-size: 100%; + background: transparent; + box-shadow: none; + margin: 0; + padding: 0; +} + +.translation-wrapper { + padding: 0 10px; + margin: 15px -1px; + border: 1px solid; + border-color: #72777c; + background: #fff; +} + +.translation-wrapper:focus-within { + box-shadow: 0 0 2px 1px #33b3db; + border-color: #5b9dd9; +} + +.translation-wrapper .warning { + margin: 15px 0 0; +} + +.translation-wrapper .textareas { + display: none; +} + +.translation-wrapper .textareas.active { + display: block; +} + +.translation-form-wrapper { + border-bottom: 1px solid #72777c; + margin-left: -10px; + margin-right: -10px; + padding: 0 10px; + line-height: 40px; + display: flex; +} + +.translation-form-wrapper span { + font-weight: 400; + letter-spacing: 1px; + text-transform: uppercase; + color: #666; + font-size: 13px; +} + +ul.translation-form-list { + padding: 0; + list-style: none; + flex: 1; + margin: 0 0 0 10px; +} + +ul.translation-form-list li { + display: inline-block; + margin-right: 5px; + cursor: pointer; +} + + +ul.translation-form-list button { + background: none; + border: 0; + box-shadow: none; + vertical-align: top; + height: auto; + font-size: 13px; + color: #333; + line-height: 40px; + margin: 0; + padding: 0 5px; + border-radius: 0; +} + +ul.translation-form-list button:focus, +ul.translation-form-list button:hover { + box-shadow: inset 0 -2px 0 0 #0085ba; + background: none; + border: 0; +} + +ul.translation-form-list button.translation-form-list__tab--active { + font-weight: 600; + box-shadow: inset 0 -2px 0 0 #0085ba; +} + +.translation-actions { + display: flex; + padding: 7px 0; + flex-direction: row-reverse; + align-items: flex-end; +} + +.translation-actions .info { + font-style: italic; +} + +.translation-actions__secondary { + flex: 1; +} + +button.translation-actions__save { + padding: 10px 18px !important; + font-size: 16px !important; + min-height: 45px !important +} + +/*.translation-actions__secondary button { + height: 35px; +} + +button.translation-actions__save { + font-size: 15px; + height: 35px; + line-height: 1; + background: #0085ba; + border-color: #0073aa #006799 #006799; + box-shadow: 0 1px 0 #006799; + color: #fff; + text-decoration: none; + text-shadow: 0 -1px 1px #006799, 1px 0 1px #006799, 0 1px 1px #006799, -1px 0 1px #006799; +} + +button.translation-actions__save:hover { + background: #008ec2; + border-color: #006799; + color: #fff; +} + +button.translation-actions__save:focus { + background: #008ec2; + border-color: #006799; + box-shadow: 0 1px 0 #0073aa, 0 0 2px 1px #33b3db; + color: #fff; +}*/ + +.suggestions-wrapper { + padding: 0 10px; + margin-bottom: 15px; +} + +.suggestions-wrapper details { + margin-bottom: 15px; + color: #666; +} + +.suggestions-wrapper details:last-child { + margin-bottom: 0; +} + +.with-tooltip { + position: relative; +} + +@keyframes show { + 0% { + opacity: 0 + } + + 100% { + opacity: 1 + } +} + +.with-tooltip:active:after, +.with-tooltip:active:before, +.with-tooltip:focus:after, +.with-tooltip:focus:before, +.with-tooltip:hover:after, +.with-tooltip:hover:before { + animation-delay: .3s; + animation-duration: .1s; + animation-fill-mode: forwards; + animation-name: show; + animation-timing-function: ease-in; + display: inline-block; +} + +.with-tooltip:after { + transform: translateX(50%); + bottom: 100%; + margin-bottom: 6px; + right: 50%; + -webkit-font-smoothing: subpixel-antialiased; + background: #23282d; + border-radius: 3px; + color: #fff; + content: attr(aria-label); + display: none; + font: normal normal 11px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; + letter-spacing: normal; + opacity: 0; + padding: .5em .75em; + pointer-events: none; + position: absolute; + text-align: center; + text-decoration: none; + text-shadow: none; + text-transform: none; + white-space: pre; + word-wrap: break-word; + z-index: 100; +} + +.with-tooltip:before { + border: 6px solid transparent; + border-top-color: #23282d; + bottom: auto; + margin-right: -6px; + right: 50%; + top: -7px; + color: #23282d; + content: ""; + display: none; + height: 0; + opacity: 0; + pointer-events: none; + position: absolute; + width: 0; + z-index: 101; +} + +@keyframes loading-indicator { + 0%, 80%, 100% { + opacity: 0; + } + 40% { + opacity: 1; + } +} + +.suggestions__loading-indicator__icon { + font-size: 4px; + margin-left: .5rem; + line-height: 1; + display: inline-block; + vertical-align: middle; +} + +.suggestions__loading-indicator__icon span { + animation-duration: 1s; + animation-delay: 0ms; + animation-iteration-count: infinite; + animation-name: loading-indicator; + animation-timing-function: ease-in-out; + background-color: #666; + border-radius: 50%; + display: inline-block; + width: 1em; + vertical-align: top; + height: 1em; +} + +.suggestions__loading-indicator__icon span:nth-child(2) { + animation-delay: 160ms; + margin-left: 1em; +} + +.suggestions__loading-indicator__icon span:nth-child(3) { + animation-delay: 320ms; + margin-left: 1em; +} + +html.modal-open { + overflow: hidden; +} + +.wporg-translate-modal { + display: none; +} + +.wporg-translate-modal--open { + display: block; +} + +.wporg-translate-modal__overlay { + animation: edit-post__fade-in-animation .2s ease-out 0s; + animation-fill-mode: forwards; + background-color: hsla(0,0%,100%,.4); + bottom: 0; + left: 0; + position: fixed; + right: 0; + top: 0; + z-index: 100000; +} + +.wporg-translate-modal__frame { + background: #fff; + border: 1px solid #ccc; + box-shadow: 0 2px 10px rgba(0,0,0,.1); + margin: 0; + overflow: auto; + position: absolute; + right: 0; + left: 0; + top: 0; + bottom: 0; + z-index: 1000; + font-family: "Open Sans", sans-serif; + padding: 15px; +} + +@media screen and (min-width: 600px) { + .wporg-translate-modal__frame { + bottom: auto; + left: 10%; + right: 10%; + top: 50%; + max-height: calc(100% - 100px); + max-width: 960px; + min-width: 360px; + transform: translate(0,-50%); + margin: 0 auto; + } +} + +.wporg-translate-modal__header { + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-between; + margin-bottom: 15px; + position: -webkit-sticky; + position: sticky; + top: -15px; + background: #fff; + box-shadow: 0 10px 10px #fff; +} + +.wporg-translate-modal__headline { + line-height: 1; + font-weight: 300; + font-size: 22px; + margin: 0; +} + +.wporg-translate-modal__close { + background: none; + height: 40px; + width: 40px; + font-size: 20px; + padding: 0; + line-height: 20px; + color: #555; + border: 1px solid transparent; + cursor: pointer; + border-radius: 3px; +} + +.wporg-translate-modal__close:focus, +.wporg-translate-modal__close:hover { + background: #fafafa; + border-color: #999; + color: #23282d; +} + +.wporg-translate-modal__close:focus { + border-color: #5b9dd9; + box-shadow: 0 0 3px rgba(0, 115, 170, 0.8); + outline: 0; +} + +.wporg-translate-modal__content h2 { + line-height: 1; + font-weight: 300; + font-size: 18px; + margin: 30px 0 10px; + font-family: "Open Sans", sans-serif; +} + +.wporg-translate-modal__content h2:first-child { + margin-top: 0; +} + +.wporg-translate-modal__content ul { + margin-left: 25px; + padding-left: 0; +} + +.wporg-translate-modal__content li > ul, +.wporg-translate-modal__content li + li { + margin-top: 3px; +} + +.wporg-translate-modal__content a { + color: #0073aa; +} + +.wporg-translate-modal__content a:hover, +.wporg-translate-modal__content a:focus { + color: #00a0d2; + text-decoration: underline; +} + +.wporg-translate-modal__content .no-list { + list-style: none; + margin: 0; +} + +.wporg-translate-modal__content_primary { + margin-bottom: 30px; +} + +@media screen and (min-width: 600px) { + .wporg-translate-modal__content { + display: flex; + } + + .wporg-translate-modal__content_primary { + flex: 50%; + margin-right: 15px; + margin-bottom: 0; + } + + .wporg-translate-modal__content_secondary { + flex: 50%; + margin-left: 15px; + } +} + +.textarea-direction-ltr button.translation-actions__rtl, +.translation-sets-rtl button.translation-actions__ltr { + display: inline-flex !important; +} + +.textarea-direction-ltr button.translation-actions__ltr, +button.translation-actions__ltr, +button.translation-actions__rtl { + display: none !important; +} + +table.translations.translation-sets-rtl .textarea-direction-ltr .foreign-text { + direction: ltr; +} + +.tablesorter-wporg-translate .header, +.tablesorter-wporg-translate .tablesorter-header { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 11 9'%3E%3Cg fill='%2332373C' fill-rule='evenodd'%3E%3Cpath d='M5.5 9L9 5H2zM5.5 0L9 4H2z'/%3E%3C/g%3E%3C/svg%3E"); + background-position: right center; + background-repeat: no-repeat; + background-size: 15px 9px; + cursor: pointer; + white-space: normal; +} + +.tablesorter-wporg-translate thead .headerSortUp, +.tablesorter-wporg-translate thead .tablesorter-headerSortUp, +.tablesorter-wporg-translate thead .tablesorter-headerAsc { + background-color: #f9f9f9; + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 11 4'%3E%3Cpath fill='%2332373C' fill-rule='evenodd' d='M5.5 0L9 4H2z'/%3E%3C/svg%3E"); + background-size: 15px 4px; +} + +.tablesorter-wporg-translate thead .headerSortDown, +.tablesorter-wporg-translate thead .tablesorter-headerSortDown, +.tablesorter-wporg-translate thead .tablesorter-headerDesc { + background-color: #f9f9f9; + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 11 4'%3E%3Cpath fill='%2332373C' fill-rule='evenodd' d='M5.5 4L9 0H2z'/%3E%3C/svg%3E"); + background-size: 15px 4px; +} + +/* translate.w.org CSS. Class: .wporg-make */ +ul.sidebar-tabs { + display: inherit; +} + +.editor .nav-sidebar { + width: 100%; + overflow: auto; +} + +.sidebar-tabs > li { + padding: 8px 15px 7px 15px; +} + +.editor .nav-sidebar .meta { + border: 0; + border-top: 1px solid #72777C; +} + +.sidebar-tabs li.current { + border: 1px solid #72777C; + border-bottom: 1px solid #fff; + margin-top: -1px; +} + +.meta, +.meta.discussion, +.meta.others { + padding: 12px; +} + +.meta.discussion .comment-respond:not(.hide-textarea) { + padding: 0; +} + +.meta.discussion .optin-message-for-each-discussion :not(.hide-textarea) { + padding: 1rem 0; +} + +.meta.others .summary-translation-memory { + font-weight: bold; + padding: 1rem 0 0.5rem 0; +} + +.meta.others td:nth-child(1), +.meta.others td:nth-child(3), +.meta.others td:nth-child(4) { + text-align: center; + vertical-align: middle; + overflow: hidden; +} + +.meta.others th, +.meta.others td { + padding: 4px !important; + border: 1px solid #72777C !important; +} + +.meta.others th:nth-child(1) { + width: 20%; + vertical-align: middle; +} + +.meta.others th:nth-child(2) { + width: 50%; + vertical-align: middle; +} + +.meta.others th:nth-child(3), +.meta.others th:nth-child(4) { + width: 15%; + vertical-align: middle; +} + +.meta.others ul { + margin: 0; + padding: 0; +} + +.meta.others ul.suggestions-list, +.meta.others summary { + margin-left: 0; +} + +.meta.others div.translation-suggestion { + margin: 1rem 0; +} + +.meta.others .locale.unique, .meta.others .other-locales .locale { + width: 6rem; + background: #0073aa; + margin-right: 10px !important; +} + +.meta.other-locales ul { + margin: 1rem 0.5rem; +} + +.meta.other-locales .sidebar-other-locales.button.is-small.copy-suggestion { + margin-left: auto; +} + +.meta.other-locales span.locale.unique { + margin-right: 14px; +} + +.meta.other-locales .other-locales .locale { + min-width: 4em; + width: 4em; +} + +.meta.history { + padding-top: 0.5rem; +} + +.meta.history .translations { + border-top: #32373C 1px double; +} + +.meta.translation-memory { + padding-top: 1rem; +} + +.meta.translation-memory ul.suggestions-list:first-of-type { + margin-top: 1rem; +} + +.meta.translation-memory ul.suggestions-list { + margin-bottom: 0; +} + +.meta.translation-memory ul.suggestions-list li { + list-style: none; + margin-left: -1.2rem; +} + +.meta.translation-memory div.translation-suggestion.with-tooltip.translation { + margin-bottom: 0; +} + +.sidebar-div-others-translation-memory-content > summary { + list-style-type: none; +} + +/* GlotPress Tour Overrides */ +a.tour-button { + text-shadow: none; + padding-top: 0; + text-decoration: none; +} +.pulse-wrapper { + margin: 0; +} + +@media screen and (max-width: 530px), (min-width: 1024px) and (max-width: 1450px) { + .editor-panel__right .tab-meta, + .editor-panel__right .tab-discussion, + .editor-panel__right .tab-history, + .editor-panel__right .tab-other-locales, + .editor-panel__right .tab-translation-memory { + white-space: nowrap; + width: 73px; + overflow: hidden; + text-overflow: ellipsis; + vertical-align: top; + } +} + +ul.other-locales li { + display: flex; + margin-bottom: 0.2rem; +} + +.sidebar-div-others-other-locales-content > ul.other-locales > li > span { + min-width: 6rem; +} + +.sidebar-div-others-other-locales-content > ul.other-locales > li > a { + display: flex; + flex: auto; +} + +.sidebar-div-others-other-locales-content > ul.other-locales > li > ul { + display: flex; + flex-direction: column; + flex: auto; +} + +.sidebar-div-others-history-content #translation-history-table > tbody > tr > td { + overflow: hidden; +} + +#translations.table-virtual-pattern { + float: left; + width: 60%; +} + +.preview-virtual-pattern { + max-width: 39%; + float: right; + padding: 1rem 1rem 0 1rem; + margin-top: 0.5rem; + margin-bottom: 0.5rem; + border: 1px solid rgb(114, 119, 124); +} + +.preview-virtual-pattern h2 { + text-align: center; + margin: 0.5rem 0; +} +.preview-virtual-pattern p.link-to-pattern { + text-align: center; + padding: 0 0 1rem 0; + margin: 0 -1rem; + border-bottom: 1px solid rgb(114, 119, 124); +} + +@media screen and (max-width: 1280px) { + #translations.table-virtual-pattern { + float: none; + width: 100%; + } + + .preview-virtual-pattern { + max-width: 100%; + float: none; + } +} \ No newline at end of file diff --git a/content/plugins/f-translate/templates/translation-row-editor.php b/content/plugins/f-translate/templates/translation-row-editor.php new file mode 100644 index 0000000..46b88b8 --- /dev/null +++ b/content/plugins/f-translate/templates/translation-row-editor.php @@ -0,0 +1,398 @@ +translation_status ) { + $translation_permalink = gp_url_project_locale( + $project, + $locale->slug, + $translation_set->slug, + array( + 'filters[status]' => 'either', + 'filters[original_id]' => $translation->original_id, + 'filters[translation_id]' => $translation->id, + ) + ); + $more_links['translation-permalink'] = 'Permalink to translation'; +} else { + $original_permalink = gp_url_project_locale( $project, $locale->slug, $translation_set->slug, array( 'filters[original_id]' => $translation->original_id ) ); + $more_links['original-permalink'] = 'Permalink to original'; +} + +$original_history = gp_url_project_locale( + $project, + $locale->slug, + $translation_set->slug, + array( + 'filters[status]' => 'either', + 'filters[original_id]' => $translation->original_id, + 'sort[by]' => 'translation_date_added', + 'sort[how]' => 'asc', + ) +); +$more_links['history'] = 'Translation History'; + +/** + * Allows to modify the more links in the translation editor. + * + * @since 2.3.0 + * + * @param array $more_links The links to be output. + * @param GP_Project $project Project object. + * @param GP_Locale $locale Locale object. + * @param GP_Translation_Set $translation_set Translation Set object. + * @param GP_Translation $translation Translation object. + */ +$more_links = apply_filters( 'gp_translation_row_template_more_links', $more_links, $project, $locale, $translation_set, $translation ); +?> + + +
+
+
+ %s', + $translation->translation_status ? ' panel-header__bubble--' . $translation->translation_status : '', + display_status( $translation->translation_status ) + ); + + $warnings_count = wporg_gp_count_warnings( $translation ); + $warnings_info = ''; + if ( $warnings_count ) { + $warnings_info = ' ' . sprintf( + _n( '%s warning', '%s warnings', $warnings_count ), + number_format_i18n( $warnings_count ) + ) . ''; + } + ?> +

Original

+
+ + + +
+ +
    + +
  • + +
+
+
+
+
+
+ singular_glossary_markup ?? esc_translation( $translation->singular ); + $plural = $translation->plural_glossary_markup ?? esc_translation( $translation->plural ); + + if ( ! $translation->plural ) : + ?> +
+ + +
+ +
+ Singular: + + +
+
+ Plural: + + +
+ +
+ +
+ +
+ Context + context ); ?> +
+ + extracted_comments ) : + ?> +
+ +

+ extracted_comments, $translation ); + ?> +

+
+ + references ) : ?> +
+ References + +
+ +
+ +
+ plural && $locale->nplurals > 1 ) : ?> +
+ Form: +
    + nplurals && 'n != 1' === $locale->plural_expression ) : ?> +
  • + +
  • +
  • + +
  • + + nplurals - 1 ) as $plural_index ) : + $plural_string = implode( ', ', $locale->numbers_for_index( $plural_index ) ); + ?> +
  • + +
  • + + +
+
+ + + plural ) : ?> + + + nplurals - 1 ) as $plural_index ) : ?> + + + + +
+ +
+ +
+
+ + + + + + +
+ + Sorry, you are not allowed to edit this translation.

', $translation ); ?> + +

+ have to log in to edit this translation.', + esc_url( wp_login_url( gp_url_current() ) ) + ); + ?> +

+ +
+
+ + +
+ +
+ +
+
+ +
+ +
+ + + '; + $sidebar_tabs .= ''; + $sidebar_tabs .= $meta_sidebar; + $sidebar_tabs .= ''; + $sidebar_tabs .= ''; /* meta others */ + $sidebar_tabs .= ''; + + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped + echo $sidebar_tabs; + ?> + + +
+
+
+ + diff --git a/content/plugins/f-translate/templates/translation-row-preview.php b/content/plugins/f-translate/templates/translation-row-preview.php new file mode 100644 index 0000000..972a394 --- /dev/null +++ b/content/plugins/f-translate/templates/translation-row-preview.php @@ -0,0 +1,137 @@ + '×', + '-1' => '↓', + '0' => '', + '1' => '↑', +); + +?> + + + + + + + + + + priority ]; + ?> + + + plural ) : + ?> + + plural_glossary_markup ) ? $translation->plural_glossary_markup : esc_translation( $translation->plural ); + ?> +
    +
  • Singular:
  • +
  • Plural:
  • +
+ + + + priority || '-1' === $translation->priority; + if ( $show_context || $show_priority ) : + ?> +
+ + context ); ?> + + get_static( 'priorities' ), $translation->priority ) ) ); ?> + +
+ + + + have to log in to add a translation.', 'glotpress' ), esc_url( wp_login_url( gp_url_current() ) ) ); + } + + $missing_text = "$edit_text"; + if ( ! count( array_filter( $translation->translations, 'gp_is_not_null' ) ) ) : + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped + echo $missing_text; + elseif ( ! $translation->plural || 1 === $locale->nplurals ) : + echo '' . esc_translation( $translation->translations[0] ) . ''; + elseif ( $translation->plural && 2 === $locale->nplurals && 'n != 1' === $locale->plural_expression ) : + ?> +
    +
  • + Singular:
    + translations[0] ) || gp_is_empty_string( $translation->translations[0] ) ) { + echo $missing_text; + } else { + echo '' . esc_translation( $translation->translations[0] ) . ''; + } + ?> +
  • +
  • + Plural:
    + translations[1] ) || gp_is_empty_string( $translation->translations[1] ) ) { + echo $missing_text; + } else { + echo '' . esc_translation( $translation->translations[1] ) . ''; + } + ?> +
  • +
+ '; + foreach( range( 0, $locale->nplurals - 1 ) as $plural_index ): + $plural_string = implode(', ', $locale->numbers_for_index( $plural_index ) ); + ?> +
  • + + : +
    + translations[ $plural_index ] ) || gp_is_empty_string( $translation->translations[ $plural_index ] ) ) { + echo $missing_text; + } else { + echo '' . esc_translation( $translation->translations[ $plural_index ] ) . ''; + } + ?> +
  • + '; + endif; ?> + + + + + diff --git a/content/plugins/f-translate/templates/translation-set-form.php b/content/plugins/f-translate/templates/translation-set-form.php new file mode 100644 index 0000000..c5f6504 --- /dev/null +++ b/content/plugins/f-translate/templates/translation-set-form.php @@ -0,0 +1,25 @@ +
    +
    +
    + locale ); ?> + +
    + +
    +
    + + +
    +
    + +
    +
    +
    + + diff --git a/content/plugins/f-translate/templates/translations.api.php b/content/plugins/f-translate/templates/translations.api.php new file mode 100644 index 0000000..55433f1 --- /dev/null +++ b/content/plugins/f-translate/templates/translations.api.php @@ -0,0 +1,12 @@ + $translation ) { + foreach ( (array) $translation as $key => $value ) { + if ( $value instanceof WP_User ) { + $translations[ $index ]->$key = (object) array_intersect_key( (array) $value->data, array_flip( array( + 'user_login', + 'display_name', + ) ) ); + } + } +} +echo wp_json_encode( $translations ); diff --git a/content/plugins/f-translate/wporg-gp-routes/inc/class-plugin.php b/content/plugins/f-translate/wporg-gp-routes/inc/class-plugin.php new file mode 100644 index 0000000..9a7d340 --- /dev/null +++ b/content/plugins/f-translate/wporg-gp-routes/inc/class-plugin.php @@ -0,0 +1,271 @@ +request_uri(); + $path = '(.+?)'; + $dir = '([^_/][^/]*)'; + $project = '([^/]*)/?'; + + $locale = '(' . implode( '|', array_map( function( $locale ) { return $locale->slug; }, GP_Locales::locales() ) ) . ')'; + $sets = '(default|formal|informal|ao90|valencia|latin)'; + + if ( gp_startswith( $request_uri, '/' . GP::$router->api_prefix . '/' ) ) { // API requests. + // Delete default routes. + GP::$router->remove( '/languages' ); + GP::$router->remove( "/languages/$locale" ); + GP::$router->remove( '/profile' ); + } else { + // Delete default routes. + GP::$router->remove( "/languages/$locale" ); + GP::$router->remove( "/languages/$locale/$path" ); + GP::$router->remove( "(/languages)/$locale/$dir/glossary" ); + GP::$router->remove( "(/languages)/$locale/$dir/glossary", 'post' ); + GP::$router->remove( "(/languages)/$locale/$dir/glossary/-new", 'post' ); + GP::$router->remove( "(/languages)/$locale/$dir/glossary/-delete", 'post' ); + GP::$router->remove( "(/languages)/$locale/$dir/glossary/-export" ); + GP::$router->remove( "(/languages)/$locale/$dir/glossary/-import" ); + GP::$router->remove( "(/languages)/$locale/$dir/glossary/-import", 'post' ); + + GP::$router->remove( '/profile' ); + GP::$router->remove( "/profile/$path" ); + + // Redirect routes. + GP::$router->prepend( '/languages', array( __NAMESPACE__ . '\Routes\Redirector', 'redirect_languages' ) ); + GP::$router->prepend( "/languages/$path", array( __NAMESPACE__ . '\Routes\Redirector', 'redirect_languages' ) ); + GP::$router->prepend( '/projects/wp-plugins/?', array( __NAMESPACE__ . '\Routes\Redirector', 'redirect_index' ) ); + GP::$router->prepend( '/projects/wp-themes/?', array( __NAMESPACE__ . '\Routes\Redirector', 'redirect_index' ) ); + GP::$router->prepend( "/projects/wp/$path/$locale/$dir/glossary", array( __NAMESPACE__ . '\Routes\Redirector', 'redirect_old_glossary' ) ); + + // Register custom routes. + GP::$router->prepend( '/', array( __NAMESPACE__ . '\Routes\Index', 'get_locales' ) ); + GP::$router->prepend( "/locale/$locale", array( __NAMESPACE__ . '\Routes\Locale', 'get_locale_projects' ) ); + GP::$router->prepend( "/locale/$locale/$sets", array( __NAMESPACE__ . '\Routes\Locale', 'get_locale_projects' ) ); + GP::$router->prepend( "/locale/$locale/$sets/$path", array( __NAMESPACE__ . '\Routes\Locale', 'get_locale_projects' ) ); + GP::$router->prepend( "/locale/$locale/$sets/$path/$path", array( __NAMESPACE__ . '\Routes\Locale', 'get_locale_project' ) ); + GP::$router->prepend( "(/locale)/$locale/$sets/glossary", array( 'GP_Route_Glossary_Entry', 'glossary_entries_get' ) ); + GP::$router->prepend( "(/locale)/$locale/$sets/glossary", array( 'GP_Route_Glossary_Entry', 'glossary_entries_post' ), 'post' ); + GP::$router->prepend( "(/locale)/$locale/$sets/glossary/-new", array( 'GP_Route_Glossary_Entry', 'glossary_entry_add_post' ), 'post' ); + GP::$router->prepend( "(/locale)/$locale/$sets/glossary/-delete", array( 'GP_Route_Glossary_Entry', 'glossary_entry_delete_post' ), 'post' ); + GP::$router->prepend( "(/locale)/$locale/$sets/glossary/-export", array( 'GP_Route_Glossary_Entry', 'export_glossary_entries_get' ) ); + GP::$router->prepend( "(/locale)/$locale/$sets/glossary/-import", array( 'GP_Route_Glossary_Entry', 'import_glossary_entries_get' ) ); + GP::$router->prepend( "(/locale)/$locale/$sets/glossary/-import", array( 'GP_Route_Glossary_Entry', 'import_glossary_entries_post' ), 'post' ); + GP::$router->prepend( "/locale/$locale/$sets/stats(?:/(plugins|themes))?", array( __NAMESPACE__ . '\Routes\Stats', 'get_stats_plugin_theme_overview' ) ); + GP::$router->prepend( '/stats', array( __NAMESPACE__ . '\Routes\Stats', 'get_stats_overview' ) ); + GP::$router->prepend( '/consistency', array( __NAMESPACE__ . '\Routes\Consistency', 'get_search_form' ) ); + + // Project routes. + GP::$router->prepend( "/projects/wp-plugins/$project", array( __NAMESPACE__ . '\Routes\WP_Plugins', 'get_plugin_projects' ) ); + GP::$router->prepend( "/projects/wp-plugins/$project/contributors", array( __NAMESPACE__ . '\Routes\WP_Plugins', 'get_plugin_contributors' ) ); + GP::$router->prepend( "/projects/wp-plugins/$project/language-packs", array( __NAMESPACE__ . '\Routes\WP_Plugins', 'get_plugin_language_packs' ) ); + GP::$router->prepend( "/projects/wp-themes/$project", array( __NAMESPACE__ . '\Routes\WP_Themes', 'get_theme_projects' ) ); + GP::$router->prepend( "/projects/wp-themes/$project/contributors", array( __NAMESPACE__ . '\Routes\WP_Themes', 'get_theme_contributors' ) ); + GP::$router->prepend( "/projects/wp-themes/$project/language-packs", array( __NAMESPACE__ . '\Routes\WP_Themes', 'get_theme_language_packs' ) ); + + // Add Robots.txt support + GP::$router->prepend( '/robots\.txt', 'do_robots' ); + + if ( defined( 'TRANSLATE_MAINTENANCE_ACTIVE' ) ) { + GP::$router->prepend( '.*', array( __NAMESPACE__ . '\Routes\Maintenance', 'show_maintenance_message' ) ); + } + } + } + + /** + * Calculates the translation status of the WordPress project per locale. + */ + public static function get_translation_status() { + global $wpdb; + + if ( ! isset( $wpdb->project_translation_status ) ) { + return; + } + + $cached = wp_cache_get( 'translation-status', self::CACHE_GROUP ); + if ( false !== $cached ) { + return $cached; + } + + $translation_status = $wpdb->get_results( $wpdb->prepare( + "SELECT `locale`, `all` AS `all_count`, `waiting` AS `waiting_count`, `current` AS `current_count`, `fuzzy` AS `fuzzy_count` + FROM {$wpdb->project_translation_status} + WHERE `project_id` = %d AND `locale_slug` = %s", + 2, // 2 = wp/dev + 'default' + ), OBJECT_K ); + + wp_cache_set( 'translation-status', $translation_status, 'wporg-translate', 15 * MINUTE_IN_SECONDS ); + + return $translation_status; + } + + /** + * Updates contributors count per locale. + */ + public static function get_contributors_count() { + global $wpdb; + + $cached = wp_cache_get( 'contributors-count', self::CACHE_GROUP ); + if ( false !== $cached ) { + return $cached; + } + + if ( ! isset( $wpdb->user_translations_count ) ) { + return []; + } + + $locales = self::get_existing_locales(); + $db_counts = $wpdb->get_results( + "SELECT `locale`, COUNT( DISTINCT user_id ) as `count` FROM {$wpdb->user_translations_count} WHERE `accepted` > 0 GROUP BY `locale`", + OBJECT_K + ); + + $counts = array(); + foreach ( $locales as $locale ) { + if ( isset( $db_counts[ $locale ] ) ) { + $counts[ $locale ] = (int) $db_counts[ $locale ]->count; + } else { + $counts[ $locale ] = 0; + } + } + + wp_cache_set( 'contributors-count', $counts, self::CACHE_GROUP, 15 * MINUTE_IN_SECONDS ); + + return $counts; + } + + /** + * Retrieves existing locales of the main wp/dev project. + * + * Much faster alternative to `GP::$translation_set->existing_locales();` since it avoids + * the expensive DISTINCT. + * + * @return array List of GlotPress locales. + */ + public static function get_existing_locales() { + global $wpdb; + + $cached = wp_cache_get( 'existing-locales', self::CACHE_GROUP ); + if ( false !== $cached ) { + return $cached; + } + + $existing_locales = $wpdb->get_col( + $wpdb->prepare( + "SELECT locale FROM {$wpdb->gp_translation_sets} WHERE `project_id` = %d and slug = %s", + 2, // 2 = wp/dev + 'default' + ) + ); + + wp_cache_set( 'existing-locales', $existing_locales, self::CACHE_GROUP, HOUR_IN_SECONDS ); + + return $existing_locales; + } +} diff --git a/content/plugins/f-translate/wporg-gp-routes/inc/routes/class-consistency.php b/content/plugins/f-translate/wporg-gp-routes/inc/routes/class-consistency.php new file mode 100644 index 0000000..3a0a39c --- /dev/null +++ b/content/plugins/f-translate/wporg-gp-routes/inc/routes/class-consistency.php @@ -0,0 +1,187 @@ + 'WordPress', + 523 => 'Themes', + 17 => 'Plugins', + 487 => 'Meta', + 281 => 'Apps', + 473698 => 'Patterns', + ); + + /** + * Prints a search form and the search results for a consistency view. + */ + public function get_search_form() { + $sets = $this->get_translation_sets(); + + $search = $set = $project = ''; + $search_case_sensitive = false; + + if ( isset( $_REQUEST['search'] ) && strlen( $_REQUEST['search'] ) ) { + $search = wp_unslash( $_REQUEST['search'] ); + } + + if ( ! empty( $_REQUEST['set'] ) ) { + $set = wp_unslash( $_REQUEST['set'] ); + if ( ! isset( $sets[ $set ] ) ) { + $set = ''; + } + } + + if ( ! empty( $_REQUEST['search_case_sensitive'] ) ) { + $search_case_sensitive = true; + } + + if ( ! empty( $_REQUEST['project'] ) && isset( self::PROJECTS[ $_REQUEST['project'] ] ) ) { + $project = $_REQUEST['project']; + } + + $locale = ''; + $set_slug = ''; + $locale_is_rtl = false; + + if ( $set ) { + list( $locale, $set_slug ) = explode( '/', $set ); + $locale_is_rtl = 'rtl' === GP_Locales::by_slug( $locale )->text_direction; + } + + $results = []; + $performed_search = false; + if ( strlen( $search ) && $locale && $set_slug ) { + $performed_search = true; + $results = $this->query( [ + 'search' => $search, + 'locale' => $locale, + 'set_slug' => $set_slug, + 'case_sensitive' => $search_case_sensitive, + 'project' => $project, + ] ); + + $translations = wp_list_pluck( $results, 'translation', 'translation_id' ); + $translations_unique = array_values( array_unique( $translations ) ); + $translations_unique_counts = array_count_values( $translations ); + + // Sort the unique translations by highest count first. + arsort( $translations_unique_counts ); + } + + $projects = self::PROJECTS; + + $this->tmpl( 'consistency', get_defined_vars() ); + } + + /** + * Retrieves a list of unique translation sets. + * + * @return array Array of sets. + */ + private function get_translation_sets() { + global $wpdb; + + $sets = wp_cache_get( 'translation-sets', $this->cache_group ); + + if ( empty( $sets ) ) { + $_sets = $wpdb->get_results( "SELECT name, locale, slug FROM {$wpdb->gp_translation_sets} GROUP BY locale, slug ORDER BY name" ); + + $sets = array(); + foreach ( $_sets as $set ) { + $sets[ "{$set->locale}/$set->slug" ] = $set->name; + } + + wp_cache_set( 'translation-sets', $sets, $this->cache_group, DAY_IN_SECONDS ); + } + + return $sets; + } + + /** + * Performs the search query. + * + * @param array $args Query arguments. + * + * @return array The search results. + */ + private function query( $args ) { + global $wpdb; + + if ( $args['case_sensitive'] ) { + $collation = 'BINARY'; + } else { + $collation = ''; + } + + $search = $wpdb->prepare( "= {$collation} %s", $args['search'] ); + $locale = $wpdb->prepare( '%s', $args['locale'] ); + $set_slug = $wpdb->prepare( '%s', $args['set_slug'] ); + + $project_where = ''; + if ( $args['project'] ) { + $project = GP::$project->get( $args['project'] ); + $project_where = $wpdb->prepare( 'AND p.path LIKE %s', $wpdb->esc_like( $project->path ) . '/%' ); + } + + $results = $wpdb->get_results( " + SELECT + p.name AS project_name, + p.id AS project_id, + p.path AS project_path, + p.parent_project_id AS project_parent_id, + p.active AS active, + o.singular AS original_singular, + o.plural AS original_plural, + o.context AS original_context, + o.id AS original_id, + t.translation_0 AS translation, + t.date_added AS translation_added, + t.id AS translation_id + FROM {$wpdb->gp_originals} AS o + JOIN + {$wpdb->gp_projects} AS p ON p.id = o.project_id + JOIN + {$wpdb->gp_translations} AS t ON o.id = t.original_id + JOIN + {$wpdb->gp_translation_sets} as ts on ts.id = t.translation_set_id + WHERE + p.active = 1 + AND t.status = 'current' + AND o.status = '+active' AND o.singular {$search} + AND ts.locale = {$locale} AND ts.slug = {$set_slug} + {$project_where} + LIMIT 0, 500 + " ); + + if ( ! $results ) { + return []; + } + + // Group by translation and project path. Done in PHP because it's faster as in MySQL. + usort( $results, [ $this, '_sort_callback' ] ); + + return $results; + } + + public function _sort_callback( $a, $b ) { + $sort = strnatcmp( $a->translation . $a->original_context, $b->translation . $b->original_context ); + if ( 0 === $sort ) { + $sort = strnatcmp( $a->project_path, $b->project_path ); + } + + return $sort; + } +} diff --git a/content/plugins/f-translate/wporg-gp-routes/inc/routes/class-index.php b/content/plugins/f-translate/wporg-gp-routes/inc/routes/class-index.php new file mode 100644 index 0000000..32e8e3d --- /dev/null +++ b/content/plugins/f-translate/wporg-gp-routes/inc/routes/class-index.php @@ -0,0 +1,38 @@ +tmpl( 'index-locales', get_defined_vars() ); + } + + private function _sort_english_name_callback( $a, $b ) { + return $a->english_name <=> $b->english_name; + } +} diff --git a/content/plugins/f-translate/wporg-gp-routes/inc/routes/class-locale.php b/content/plugins/f-translate/wporg-gp-routes/inc/routes/class-locale.php new file mode 100644 index 0000000..11d9e82 --- /dev/null +++ b/content/plugins/f-translate/wporg-gp-routes/inc/routes/class-locale.php @@ -0,0 +1,1006 @@ +roles_adapter = Rosetta_Roles::get_instance(); + } + } + + /** + * Prints projects/translation sets of a top level project. + * + * @param string $locale_slug Slug of the locale. + * @param string $set_slug Slug of the translation set. + * @param bool|string $project_path Path of a project. + */ + public function get_locale_projects( $locale_slug, $set_slug = 'default', $project_path = false ) { + global $wpdb; + + $per_page = 24; + $page = (int) gp_get( 'page', 1 ); + $search = gp_get( 's', '' ); + $filter = gp_get( 'filter', false ); + $without_editors = (bool) gp_get( 'without-editors', false ); + + if ( $search && ! is_string( $search ) ) { + $search = ''; + } + if ( $filter && ! is_string( $filter ) ) { + $filter = false; + } + + $locale = GP_Locales::by_slug( $locale_slug ); + if ( ! $locale ) { + return $this->die_with_404(); + } + + if ( ! $this->translation_set_slug_exists( $locale, $set_slug ) ) { + return $this->die_with_404(); + } + + // Grab the top level projects to show in the menu first, so as to be able to handle the default Waiting / WP tab selection + $top_level_projects = $this->get_active_top_level_projects(); + + // Default to the Waiting or WordPress tabs + $default_project_tab = 'waiting'; + $user_id = get_current_user_id(); + if ( + ! is_user_logged_in() || + ! $this->roles_adapter || // Rosetta Roles plugin is not enabled + ! ( + $this->roles_adapter->is_global_administrator( $user_id ) || // Not a global admin + $this->roles_adapter->is_approver_for_locale( $user_id, $locale_slug ) // Doesn't have project-level access either + ) + // Add check to see if there are any waiting translations for this locale? + ) { + $default_project_tab = 'wp'; + } + + // Filter out the Waiting Tab if the current user cannot validate strings + if ( 'waiting' != $default_project_tab ) { + foreach ( $top_level_projects as $i => $project ) { + if ( 'waiting' == $project->slug ) { + unset( $top_level_projects[ $i ] ); + break; + } + } + } + + $project_path = $project_path ?: $default_project_tab; + + $project = GP::$project->by_path( $project_path ); + if ( ! $project ) { + return $this->die_with_404(); + } + + $paged_sub_projects = $this->get_paged_active_sub_projects( + $project, + array( + 'page' => $page, + 'per_page' => $per_page, + 'search' => $search, + 'filter' => $filter, + 'without_editors' => $without_editors, + 'set_slug' => $set_slug, + 'locale' => $locale_slug, + ) + ); + + $data['project'] = $project; + $data['sub_projects'] = $paged_sub_projects['projects']; + $data['pages'] = $paged_sub_projects['pages']; + $data = apply_filters( 'gp_subprojects', $data ); + $paged_sub_projects['projects'] = $data['sub_projects']; + $paged_sub_projects['pages'] = $data['pages']; + + if ( ! $paged_sub_projects ) { + return $this->die_with_404(); + } + + $sub_projects = $paged_sub_projects['projects']; + $pages = $paged_sub_projects['pages']; + $filter = $paged_sub_projects['filter']; + unset( $paged_sub_projects ); + + $project_status = $project_icons = array(); + foreach ( $sub_projects as $key => $sub_project ) { + $project_status[ $sub_project->id ] = $this->get_project_status( $sub_project, $locale_slug, $set_slug ); + $project_icons[ $sub_project->id ] = $this->get_project_icon( $project, $sub_project ); + } + + $project_ids = array_keys( $project_status ); + $project_ids[] = $project->id; + $project_ids = array_merge( + $project_ids, + $wpdb->get_col( "SELECT id FROM {$wpdb->gp_projects} WHERE parent_project_id IN( " . implode( ', ', $project_ids ) . ')' ) + ); + + $contributors_count = Plugin::get_contributors_count(); + + $variants = $this->get_locale_variants( $locale_slug ); + // If there were no results for the current variant in the current project branch, it should still show it. + if ( ! in_array( $set_slug, $variants, true ) ) { + $variants[] = $set_slug; + } + + $can_create_locale_glossary = GP::$permission->current_user_can( 'admin' ); + $locale_glossary_translation_set = GP::$translation_set->by_project_id_slug_and_locale( 0, $set_slug, $locale_slug ); + $locale_glossary = false; + if ( $locale_glossary_translation_set ) { + $locale_glossary = GP::$glossary->by_set_id( $locale_glossary_translation_set->id ); + } + + $this->tmpl( 'locale-projects', get_defined_vars() ); + } + + /** + * Prints projects/translation sets of a sub project. + * + * @param string $locale_slug Slug of the locale. + * @param string $set_slug Slug of the translation set. + * @param string $project_path Path of a project. + * @param string $sub_project_path Path of a sub project. + */ + public function get_locale_project( $locale_slug, $set_slug, $project_path, $sub_project_path ) { + $locale = GP_Locales::by_slug( $locale_slug ); + if ( ! $locale ) { + return $this->die_with_404(); + } + + if ( ! $this->translation_set_slug_exists( $locale, $set_slug ) ) { + return $this->die_with_404(); + } + + $project = GP::$project->by_path( $project_path ); + if ( ! $project ) { + return $this->die_with_404(); + } + + $sub_project = GP::$project->by_path( $project_path . '/' . $sub_project_path ); + if ( ! $sub_project ) { + return $this->die_with_404(); + } + + $project_status = $this->get_project_status( $sub_project, $locale_slug, $set_slug ); + $sub_project_status = $this->get_project_status( $sub_project, $locale_slug, $set_slug, null, false ); + + $project_icon = $this->get_project_icon( $project, $sub_project, 64 ); + + $contributors_count = Plugin::get_contributors_count(); + + $sub_project_statuses = array(); + $sub_projects = $this->get_active_sub_projects( $sub_project, true ); + if ( $sub_projects ) { + foreach ( $sub_projects as $key => $_sub_project ) { + $sub_project_statuses[ $_sub_project->slug ] = $this->get_project_status( + $_sub_project, + $locale_slug, + $set_slug, + null, + false + ); + } + } + + $sub_project_slugs = array_keys( $sub_project_statuses ); + + $variants = $this->get_locale_variants( $locale_slug ); + + $locale_contributors = $this->get_locale_contributors( $sub_project, $locale_slug, $set_slug ); + + $can_create_locale_glossary = GP::$permission->current_user_can( 'admin' ); + $locale_glossary_translation_set = GP::$translation_set->by_project_id_slug_and_locale( 0, $set_slug, $locale_slug ); + $locale_glossary = GP::$glossary->by_set_id( $locale_glossary_translation_set->id ); + + $this->tmpl( 'locale-project', get_defined_vars() ); + } + + /** + * Whether a translation set slug exists for a locale. + * + * For performance reasons, this checks the wp/dev project which is the canonical + * source for all available and active locales. + * + * @param \GP_Locale $locale The locale. + * @param string $slug The slug of a translation set. + * @return bool True if slug exists, false if not. + */ + private function translation_set_slug_exists( $locale, $slug ) { + global $wpdb; + + $id = $wpdb->get_var( $wpdb->prepare( + "SELECT id FROM {$wpdb->gp_translation_sets} WHERE locale = %s AND slug = %s AND project_id = %d", + $locale->slug, + $slug, + 2 // wp/dev + ) ); + + return null !== $id; + } + + /** + * Returns markup for project icons. + * + * @param GP_Project $project A GlotPress project. + * @param GP_Project $sub_project A sub project of a GlotPress project. + * @param int $size Size of icon. + * @return string HTML markup of an icon. + */ + private function get_project_icon( $project, $sub_project, $size = 128 ) { + // The Waiting tab will have $sub_project's which are not sub-projects of $project + if ( $sub_project->parent_project_id && $sub_project->parent_project_id !== $project->id ) { + $project = GP::$project->get( $sub_project->parent_project_id ); + // In the case of Plugins, we may need to go up another level yet + if ( $project->parent_project_id ) { + $sub_project = $project; + $project = GP::$project->get( $sub_project->parent_project_id ); + } + } + + switch ( $project->slug ) { + case 'wp': + return '
    '; + case 'meta': + switch ( $sub_project->slug ) { + case 'forums': + return '
    '; + case 'rosetta': + return '
    '; + case 'plugins': + case 'plugins-v3': + return '
    '; + case 'themes': + return '
    '; + case 'wordcamp': + return '
    '; + case 'pattern-directory': + return '
    '; + case 'browsehappy': + return '
    '; + case 'openverse': + return '
    '; + default: + return '
    '; + } + case 'wp-themes': + $screenshot = gp_get_meta( 'wp-themes', $sub_project->id, 'screenshot' ); + if ( $screenshot ) { + return '
    '; + } else { + return '
    '; + } + case 'wp-plugins': + $icon = ''; + + if ( class_exists( 'WordPressdotorg\Plugin_Directory\Template' ) ) { + $directory_post_id = gp_get_meta( 'wp-plugins', $sub_project->id, 'directory-post-id' ); + if ( $directory_post_id ) { + switch_to_blog( WPORG_PLUGIN_DIRECTORY_BLOGID ); + $icon = \WordPressdotorg\Plugin_Directory\Template::get_plugin_icon( $directory_post_id, 'html' ); + restore_current_blog(); + } + } + + if ( $icon ) { + return $icon; + } + + return '
    '; + case 'apps': + return '
    '; + case 'patterns': + return '
    '; + default: + return '
    '; + } + } + + /** + * Retrieves all slugs of translation sets for a locale. + * + * For performance reasons, this checks the wp/dev project which is the canonical + * source for all available and active locales. + * + * @param string $locale Slug of a GlotPress locale. + * @return array List of translation set slugs. + */ + private function get_locale_variants( $locale ) { + global $wpdb; + + return $wpdb->get_col( $wpdb->prepare( + "SELECT slug FROM {$wpdb->gp_translation_sets} WHERE locale = %s AND project_id = %d", + $locale, + 2 // wp/dev + ) ); + } + + /** + * Retrieves translation editors of a project. + * + * Also includes cross-locale editors and editors of parent projects. + * + * @param GP_Project $project A GlotPress project. + * @param string $locale_slug Slug of the locale. + * @return array List of user IDs. + */ + private function get_translation_editors( $project, $locale_slug ) { + global $wpdb; + + $editors = [ + 'project' => [], + 'inherited' => [], + ]; + + // Get the translation editors of the project. + $editors['project'] = (array) $wpdb->get_col( $wpdb->prepare( " + SELECT + `user_id` + FROM {$wpdb->wporg_translation_editors} + WHERE + `project_id` = %d + AND `locale` IN (%s, 'all-locales') + ", $project->id, $locale_slug ) ); + + // Get the translation editors of parent projects. + if ( $project->parent_project_id ) { + $parent_project_id = $project->parent_project_id; + $parent_project = GP::$project->get( $parent_project_id ); + while ( $parent_project_id ) { + $editors['inherited'] = array_merge( $editors['inherited'], (array) $wpdb->get_col( $wpdb->prepare( " + SELECT + `user_id` + FROM {$wpdb->wporg_translation_editors} + WHERE + `project_id` = %d + AND `locale` IN (%s, 'all-locales') + ", $parent_project->id, $locale_slug ) ) ); + + $parent_project = GP::$project->get( $parent_project_id ); + $parent_project_id = $parent_project->parent_project_id; + } + } + + // Get the translation editors for all projects. + $editors['inherited'] = array_merge( $editors['inherited'], (array) $wpdb->get_col( $wpdb->prepare( " + SELECT + `user_id` + FROM {$wpdb->wporg_translation_editors} + WHERE + `project_id` = '0' + AND `locale` = %s + ", $locale_slug ) ) ); + + return $editors; + } + + /** + * Retrieves contributors of a project. + * + * @param GP_Project $project A GlotPress project. + * @param string $locale_slug Slug of the locale. + * @param string $set_slug Slug of the translation set. + * @return array Contributors. + */ + private function get_locale_contributors( $project, $locale_slug, $set_slug ) { + global $wpdb; + + $locale_contributors = [ + 'editors' => [ + 'project' => [], + 'inherited' => [], + ], + 'contributors' => [], + ]; + + // Get the translation editors of the project. + $editors = $this->get_translation_editors( $project, $locale_slug ); + + $editor_ids = []; + + // Get the names of the translation editors. + foreach ( [ 'project', 'inherited'] as $editor_source ) { + foreach ( $editors[ $editor_source ] as $editor_id ) { + $user = get_user_by( 'id', $editor_id ); + if ( ! $user ) { + continue; + } + + $locale_contributors['editors'][ $editor_source ][ $editor_id ] = (object) array( + 'nicename' => $user->user_nicename, + 'display_name' => $this->_encode( $user->display_name ), + 'email' => $user->user_email, + ); + + $editor_ids[] = $editor_id; + } + + uasort( $locale_contributors['editors'][ $editor_source ], function( $a, $b ) { + return strcasecmp( $a->display_name, $b->display_name ); + } ); + } + + unset( $editors ); + + // Get the contributors of the project. + $contributors = array(); + + // In case the project has a translation set, like /wp-themes/twentysixteen. + $translation_set = GP::$translation_set->by_project_id_slug_and_locale( $project->id, $set_slug, $locale_slug ); + if ( $translation_set ) { + $contributors = array_merge( + $contributors, + $this->get_locale_contributors_by_translation_set( $translation_set ) + ); + } + + // Check if the project has sub-projects, like /wp-plugins/wordpress-importer. + $sub_projects = $wpdb->get_col( $wpdb->prepare( " + SELECT id + FROM {$wpdb->gp_projects} + WHERE + parent_project_id = %d + AND active = 1 + ", $project->id ) ); + + foreach ( $sub_projects as $sub_project ) { + $translation_set = GP::$translation_set->by_project_id_slug_and_locale( $sub_project, $set_slug, $locale_slug ); + if ( ! $translation_set ) { + continue; + } + + $contributors = array_merge( + $contributors, + $this->get_locale_contributors_by_translation_set( $translation_set ) + ); + } + + $projects = []; + + // Get the names of the contributors. + foreach ( $contributors as $contributor ) { + if ( isset( $locale_contributors['contributors'][ $contributor->user_id ] ) ) { + // Update last updated and counts per status. + $locale_contributors['contributors'][ $contributor->user_id ]->last_update = max( + $locale_contributors['contributors'][ $contributor->user_id ]->last_update, + $contributor->last_update + ); + + $locale_contributors['contributors'][ $contributor->user_id ]->total_count += $contributor->total_count; + $locale_contributors['contributors'][ $contributor->user_id ]->current_count += $contributor->current_count; + $locale_contributors['contributors'][ $contributor->user_id ]->waiting_count += $contributor->waiting_count; + $locale_contributors['contributors'][ $contributor->user_id ]->fuzzy_count += $contributor->fuzzy_count; + + if ( ! isset( $projects[ $contributor->project_id ] ) ) { + $projects[ $contributor->project_id ] = GP::$project->get( $contributor->project_id ); + } + + $locale_contributors['contributors'][ $contributor->user_id ]->detailed[ $contributor->project_id ] = (object) [ + 'total_count' => $contributor->total_count, + 'current_count' => $contributor->current_count, + 'waiting_count' => $contributor->waiting_count, + 'fuzzy_count' => $contributor->fuzzy_count, + 'project' => $projects[ $contributor->project_id ], + ]; + + continue; + } + + $user = get_user_by( 'id', $contributor->user_id ); + if ( ! $user ) { + continue; + } + + if ( ! isset( $projects[ $contributor->project_id ] ) ) { + $projects[ $contributor->project_id ] = GP::$project->get( $contributor->project_id ); + } + + $locale_contributors['contributors'][ $contributor->user_id ] = (object) array( + 'login' => $user->user_login, + 'nicename' => $user->user_nicename, + 'display_name' => $this->_encode( $user->display_name ), + 'email' => $user->user_email, + 'last_update' => $contributor->last_update, + 'total_count' => $contributor->total_count, + 'current_count' => $contributor->current_count, + 'waiting_count' => $contributor->waiting_count, + 'fuzzy_count' => $contributor->fuzzy_count, + 'detailed' => [ + $contributor->project_id => (object) [ + 'total_count' => $contributor->total_count, + 'current_count' => $contributor->current_count, + 'waiting_count' => $contributor->waiting_count, + 'fuzzy_count' => $contributor->fuzzy_count, + 'project' => $projects[ $contributor->project_id ], + ], + ], + 'is_editor' => in_array( $user->ID, $editor_ids ), + ); + } + unset( $contributors, $editor_ids ); + + uasort( $locale_contributors['contributors'], function( $a, $b ) { + return $a->total_count < $b->total_count; + } ); + + return $locale_contributors; + } + + /** + * Retrieves contributors of a translation set. + * + * @param GP_Translation_Set $translation_set A translation set. + * @return array List of user IDs. + */ + private function get_locale_contributors_by_translation_set( $translation_set ) { + global $wpdb; + + $contributors = $wpdb->get_results( $wpdb->prepare( " + SELECT + `t`.`user_id` as `user_id`, + `o`.`project_id` as `project_id`, + MAX( `t`.`date_added` ) AS `last_update`, + COUNT( * ) as `total_count`, + COUNT( CASE WHEN `t`.`status` = 'current' THEN `t`.`status` END ) AS `current_count`, + COUNT( CASE WHEN `t`.`status` = 'waiting' THEN `t`.`status` END ) AS `waiting_count`, + COUNT( CASE WHEN `t`.`status` = 'fuzzy' THEN `t`.`status` END ) AS `fuzzy_count` + FROM `{$wpdb->gp_translations}` as `t` + JOIN `{$wpdb->gp_originals}` as `o` + ON `t`.`original_id` = `o`.`id` AND `o`.`status` = '+active' + WHERE + `t`.`translation_set_id` = %d + AND `t`.`user_id` IS NOT NULL AND `t`.`user_id` != 0 + AND `t`.`status` IN( 'current', 'waiting', 'fuzzy' ) + GROUP BY `t`.`user_id` + ", $translation_set->id ) ); + + return $contributors; + } + + /** + * Calculates the status of a project. + * + * @param GP_Project $project The GlotPress project. + * @param string $locale Slug of GlotPress locale. + * @param string $set_slug Slug of the translation set. + * @param object $status The status object. + * @param bool $calc_sub_projects Whether sub projects should be calculated too. + * Default true. + * @return object The status of a project. + */ + private function get_project_status( $project, $locale, $set_slug, $status = null, $calc_sub_projects = true ) { + if ( null === $status ) { + $status = new stdClass; + $status->sub_projects_count = 0; + $status->waiting_count = 0; + $status->current_count = 0; + $status->fuzzy_count = 0; + $status->untranslated_count = 0; + $status->changesrequested_count = 0; + $status->all_count = 0; + $status->percent_complete = 0; + } + + $status = apply_filters( 'gp_get_project_status', $status, $project, $locale, $set_slug ); + if ( isset( $status->is_pattern ) && $status->is_pattern ) { + return $status; + } + + $set = GP::$translation_set->by_project_id_slug_and_locale( + $project->id, + $set_slug, + $locale + ); + + if ( $set ) { + $status->sub_projects_count += 1; + $status->waiting_count += (int) $set->waiting_count(); + $status->current_count += (int) $set->current_count(); + $status->fuzzy_count += (int) $set->fuzzy_count(); + $status->untranslated_count += (int) $set->untranslated_count(); + $status->changesrequested_count += (int) $set->changesrequested_count(); + $status->all_count += (int) $set->all_count(); + + if ( $status->all_count ) { + /* + * > 50% round down, so that a project with all strings except 1 translated shows 99%, instead of 100%. + * < 50% round up, so that a project with just a few strings shows 1%, instead of 0%. + */ + $percent_complete = ( $status->current_count / $status->all_count * 100 ); + $status->percent_complete = ( $percent_complete > 50 ) ? floor( $percent_complete ) : ceil( $percent_complete ); + } + } + + if ( $calc_sub_projects ) { + $sub_projects = $this->get_active_sub_projects( $project, true ); + if ( $sub_projects ) { + foreach ( $sub_projects as $sub_project ) { + $this->get_project_status( $sub_project, $locale, $set_slug, $status, false ); + } + } + } + + return $status; + } + + /** + * Retrieves active sub projects. + * + * @param GP_Project $project The parent project + * @param bool $with_sub_projects Whether sub projects should be fetched too. + * Default false. + * @return array List of sub projects. + */ + private function get_active_sub_projects( $project, $with_sub_projects = false ) { + global $wpdb; + + $_projects = $project->many( " + SELECT * + FROM {$wpdb->gp_projects} + WHERE + parent_project_id = %d + AND active = 1 + ORDER BY id ASC + ", $project->id ); + + $projects = array(); + foreach ( $_projects as $project ) { + $projects[ $project->id ] = $project; + + if ( $with_sub_projects ) { + // e.g. wp/dev/admin/network + $sub_projects = $project->many( " + SELECT * + FROM {$wpdb->gp_projects} + WHERE + parent_project_id = %d + AND active = 1 + ORDER BY id ASC + ", $project->id ); + + foreach ( $sub_projects as $sub_project ) { + $projects[ $sub_project->id ] = $sub_project; + } + unset( $sub_projects); + } + } + unset( $_projects ); + + return $projects; + } + + /** + * Retrieves active sub projects with paging. + * + * This method is horribly inefficient when there exists many sub-projects, as it can't use SQL. + * + * @param GP_Project $project The parent project + * @param array $args { + * @type int $per_page Number of items per page. Default 20 + * @type int $page The page of results to view. Default 1. + * @type string $orderby The field to order by, id or name. Default id. + * @type string $order The sorting order, ASC or DESC. Default ASC. + * @type string $search The search string + * @type string $set_slug The translation set to view. + * @type string $locale The locale of the translation set to view. + * } + * @return array List of sub projects. + */ + private function get_paged_active_sub_projects( $project, $args = array() ) { + global $wpdb; + + $defaults = array( + 'per_page' => 20, + 'page' => 1, + 'search' => false, + 'set_slug' => '', + 'locale' => '', + 'filter' => false, + 'without_editors' => false, + ); + $r = wp_parse_args( $args, $defaults ); + extract( $r, EXTR_SKIP ); + + $limit_sql = ''; + if ( $per_page ) { + $limit_sql = $wpdb->prepare( 'LIMIT %d, %d', ( $page - 1 ) * $per_page, $per_page ); + } + + $parent_project_sql = $wpdb->prepare( 'AND tp.parent_project_id = %d', $project->id ); + + $search_sql = ''; + if ( $search ) { + $esc_search = '%%' . $wpdb->esc_like( $search ) . '%%'; + $search_sql = $wpdb->prepare( 'AND ( tp.name LIKE %s OR tp.slug LIKE %s )', $esc_search, $esc_search ); + } + + // Special Waiting Project Tab + // This removes the parent_project_id restriction and replaces it with all-translation-editer-projects + if ( 'waiting' == $project->slug && is_user_logged_in() && $this->roles_adapter ) { + + if ( ! $filter ) { + $filter = 'strings-waiting-and-fuzzy'; + } + + $user_id = get_current_user_id(); + + // Global Admin or Locale-specific admin + $can_approve_for_all = $this->roles_adapter->is_global_administrator( $user_id ); + + // Limit to only showing base-level projects. + $base_level_project_sql = ''; + $base_level_project_ids = $wpdb->get_col( "SELECT id FROM {$wpdb->gp_projects} WHERE parent_project_id IS NULL AND active = 1" ); + if ( $base_level_project_ids ) { + $ids = implode( ', ', array_map( 'intval', $base_level_project_ids ) ); + $base_level_project_sql = " AND tp.parent_project_id IN( $ids )"; + } + + // Check to see if they have any special approval permissions. + $allowed_projects = array(); + $allowed_base_level_projects = array(); + if ( ! $can_approve_for_all && $role = $this->roles_adapter->is_approver_for_locale( $user_id, $locale ) ) { + $allowed_projects = $this->roles_adapter->get_project_id_access_list( $user_id, $locale ); + + $allowed_base_level_projects = array_intersect( $allowed_projects, $base_level_project_ids ); + $allowed_projects = array_diff( $allowed_projects, $base_level_project_ids ); + + // Check to see if they can approve for all projects in this locale. + if ( Rosetta_Roles::LOCALE_MANAGER_ROLE === $role || in_array( 'all', $allowed_projects ) ) { + $can_approve_for_all = true; + $allowed_projects = array(); + } + } + + if ( $can_approve_for_all ) { + // The current user can approve for all projects, so just grab all with any waiting strings. + $parent_project_sql = 'AND ( stats.waiting > 0 OR stats.fuzzy > 0 )'; + $parent_project_sql .= $base_level_project_sql; + } elseif ( $allowed_projects || $allowed_base_level_projects ) { + $parent_project_sql = 'AND ( stats.waiting > 0 OR stats.fuzzy > 0 ) AND ( ('; + + if ( $allowed_projects ) { + /* + * The current user can approve for a small set of projects. + * We only need to check against tp.id and not tp_sub.id in this case as we've overriding the parent_project_id check. + */ + $ids = implode( ', ', array_map( 'intval', $allowed_projects ) ); + $parent_project_sql .= "tp.id IN( $ids )"; + $parent_project_sql .= $base_level_project_sql; + } else { + $parent_project_sql .= '0=1'; + } + + $parent_project_sql .= ") OR ("; + + if ( $allowed_base_level_projects ) { + /* + * The current user can approve all sub-projects of a base level project. + */ + $ids = implode( ', ', array_map( 'intval', $allowed_base_level_projects ) ); + $parent_project_sql .= "tp.parent_project_id IN( $ids )"; + } else { + $parent_project_sql .= '0=1'; + } + + $parent_project_sql .= ") )"; + + } else { + // The current user can't approve for any locale projects, or is logged out. + $parent_project_sql = 'AND 0=1'; + + } + + // Exclude projects which have an assigned editor. + if ( $without_editors ) { + $project_ids_with_editor = $wpdb->get_col( $wpdb->prepare( + "SELECT DISTINCT(project_id) FROM `translate_translation_editors` WHERE (locale = %s OR locale = 'all-locales') AND project_id != 0 AND user_id != %d", + $locale, + $user_id + ) ); + if ( $project_ids_with_editor ) { + $project_ids_with_editor = implode( ', ', array_map( 'intval', $project_ids_with_editor ) ); + $parent_project_sql .= " AND tp.id NOT IN( $project_ids_with_editor )"; + } + } + } + + $filter_order_by = $filter_where = ''; + $sort_order = 'DESC'; + $filter_name = $filter; + if ( $filter && '-asc' == substr( $filter, -4 ) ) { + $sort_order = 'ASC'; + $filter_name = substr( $filter, 0, -4 ); + } + switch ( $filter_name ) { + default: + if ( ! is_user_logged_in() || ! in_array( $project->slug, array( 'waiting', 'wp-themes', 'wp-plugins' ) ) ) { + if ( 'wp' === $project->slug ) { + $filter_order_by = 'stats.untranslated > 0 DESC, stats.untranslated DESC, tp.name DESC'; + } else { + $filter_order_by = 'stats.untranslated > 0 DESC, stats.untranslated DESC, tp.name ASC'; + } + break; + } + case 'special': + // Float favorites to the start, but only if they have untranslated strings + $user_fav_projects = array_map( 'esc_sql', $this->get_user_favorites( $project->slug ) ); + + // Float Favorites to the start, float fully translated to the bottom, order the rest by name + if ( $user_fav_projects ) { + $filter_order_by = 'FIELD( tp.path, "' . implode( '", "', $user_fav_projects ) . '" ) > 0 AND stats.untranslated > 0 DESC, stats.untranslated > 0 DESC, stats.untranslated DESC, tp.name ASC'; + } else { + $filter_order_by = 'stats.untranslated > 0 DESC, stats.untranslated DESC, tp.name ASC'; + } + break; + + case 'favorites': + // Only list favorites + $user_fav_projects = array_map( 'esc_sql', $this->get_user_favorites( $project->slug ) ); + + if ( $user_fav_projects ) { + $filter_where = 'AND tp.path IN( "' . implode( '", "', $user_fav_projects ) . '" )'; + } else { + $filter_where = 'AND 0=1'; + } + $filter_order_by = 'stats.untranslated > 0 DESC, tp.name ASC'; + + break; + + case 'strings-remaining': + $filter_where = 'AND stats.untranslated > 0'; + $filter_order_by = "stats.untranslated $sort_order, tp.name ASC"; + break; + + case 'strings-waiting-and-fuzzy': + $filter_where = 'AND (stats.waiting > 0 OR stats.fuzzy > 0 )'; + $filter_order_by = "tp.path LIKE 'wp/%%' AND (stats.fuzzy + stats.waiting) > 0 DESC, (stats.fuzzy + stats.waiting) $sort_order, tp.name ASC"; + break; + + case 'strings-waiting-and-fuzzy-by-modified-date': + $filter_where = 'AND (stats.waiting > 0 OR stats.fuzzy > 0 ) AND stats.date_modified > "0000-00-00 00:00:00"'; + $filter_order_by = "stats.date_modified $sort_order, tp.name ASC"; + break; + + case 'percent-completed': + $filter_where = 'AND stats.untranslated > 0'; + $filter_order_by = "( stats.current / stats.all ) $sort_order, tp.name ASC"; + break; + + case 'completed': + $filter_where = 'AND stats.all > 0 AND stats.current = stats.all'; + $filter_order_by = "tp.name $sort_order"; + break; + + } + + /* + * Find all child projects with translation sets that match the current locale/slug. + * + * 1. We need to fetch all sub-projects of the current project (so, if we're at wp-plugins, we want akismet, debug bar, importers, etc) + * 2. Next, we fetch the sub-projects of those sub-projects, that gets us things like Development, Readme, etc. + * 3. Next, we fetch the translation sets of both the sub-projects(1), and any sub-sub-projects(2). + * Once we have the sets in 3, we can then check to see if there exists any translation sets for the current (locale, slug) (ie. en-au/default) + * If not, we can simply filter them out, so that paging only has items returned that actually exist. + */ + $_projects = $project->many( " + SELECT SQL_CALC_FOUND_ROWS tp.* + FROM {$wpdb->gp_projects} tp + LEFT JOIN {$wpdb->project_translation_status} stats ON stats.project_id = tp.id AND stats.locale = %s AND stats.locale_slug = %s + WHERE + tp.active = 1 + $parent_project_sql + $search_sql + $filter_where + GROUP BY tp.id + ORDER BY $filter_order_by + $limit_sql + ", $locale, $set_slug ); + + $results = (int) $project->found_rows(); + $pages = (int) ceil( $results / $per_page ); + + $projects = array(); + foreach ( $_projects as $project ) { + $projects[ $project->id ] = $project; + } + + return array( + 'pages' => compact( 'pages', 'page', 'per_page', 'results' ), + 'projects' => $projects, + 'filter' => $filter, + ); + } + + /** + * Retrieves a list of projects which the current user has favorited. + * + * @return array List of favorited items, eg [ 'wp-themes/twentyten', 'wp-themes/twentyeleven' ] + */ + function get_user_favorites( $project_slug = false ) { + global $wpdb; + + if ( ! is_user_logged_in() ) { + return array(); + } + + $user_id = get_current_user_id(); + + switch ( $project_slug ) { + default: + // Fall through to include both Themes and Plugins + case 'wp-themes': + // Theme favorites are stored as theme slugs, these map 1:1 to GlotPress projects. + $theme_favorites = array_map( function( $slug ) { + return "wp-themes/$slug"; + }, (array) get_user_meta( $user_id, 'theme_favorites', true ) ); + + if ( 'wp-themes' === $project_slug ) { + return $theme_favorites; + } + + case 'wp-plugins': + // Plugin favorites are stored as plugin slugs, these map 1:1 to GlotPress projects. + $plugin_favorites = array_map( function( $slug ) { + return "wp-plugins/$slug"; + }, (array) get_user_meta( $user_id, 'plugin_favorites', true ) ); + + if ( 'wp-plugins' === $project_slug ) { + return $plugin_favorites; + } + } + + // Return all favorites, for uses in things like the Waiting tab + return array_merge( $theme_favorites, $plugin_favorites ); + } + + /** + * Retrieves active top level projects. + * + * @return array List of top level projects. + */ + public function get_active_top_level_projects() { + global $wpdb; + + return GP::$project->many( " + SELECT * + FROM {$wpdb->gp_projects} + WHERE + parent_project_id IS NULL + AND active = 1 + ORDER BY FIELD( slug, 'waiting', 'wp', 'wp-themes', 'wp-plugins', 'patterns', 'meta', 'apps' ) + " ); + } + + private function _encode( $raw ) { + if ( 'UTF-8' !== mb_detect_encoding( $raw, 'UTF-8', true ) ) { + $raw = mb_convert_encoding( $raw, 'UTF-8', 'ASCII, JIS, Windows-1252, ISO-8859-1' ); + } + return ent2ncr( htmlspecialchars_decode( htmlentities( $raw, ENT_NOQUOTES, 'UTF-8' ), ENT_NOQUOTES ) ); + } +} diff --git a/content/plugins/f-translate/wporg-gp-routes/inc/routes/class-maintenance.php b/content/plugins/f-translate/wporg-gp-routes/inc/routes/class-maintenance.php new file mode 100644 index 0000000..c8ad8aa --- /dev/null +++ b/content/plugins/f-translate/wporg-gp-routes/inc/routes/class-maintenance.php @@ -0,0 +1,15 @@ + 503 ] ); + } +} diff --git a/content/plugins/f-translate/wporg-gp-routes/inc/routes/class-redirector.php b/content/plugins/f-translate/wporg-gp-routes/inc/routes/class-redirector.php new file mode 100644 index 0000000..49639cd --- /dev/null +++ b/content/plugins/f-translate/wporg-gp-routes/inc/routes/class-redirector.php @@ -0,0 +1,63 @@ +redirect( '/' ); + } else { + $this->redirect( "/locale/$path" ); + } + } + + public function redirect_index() { + $this->redirect( '/' ); + } + + /** + * Redirects previous glossary paths from `/projects/wp/dev/$locale/$slug/glossary` + * to `/locale/$locale/$slug/glossary`. + * + * @param string $project_path Path of a project. + * @param string $locale Locale slug. + * @param string $slug Slug if a translation set. + */ + public function redirect_old_glossary( $project_path = '', $locale = '', $slug = '' ) { + $project_path = "wp/$project_path"; + + $project = GP::$project->by_path( $project_path ); + if ( ! $project ) { + $route_glossary_entry = new GP_Route_Glossary_Entry(); + return $route_glossary_entry->glossary_entries_get( $project_path, $locale, $slug ); + } + + $translation_set = GP::$translation_set->by_project_id_slug_and_locale( $project->id, $slug, $locale ); + if ( ! $translation_set ) { + $route_glossary_entry = new GP_Route_Glossary_Entry(); + return $route_glossary_entry->glossary_entries_get( $project_path, $locale, $slug ); + } + + // If the current project has a glossary stop here and load it. + $glossary = GP::$glossary->by_set_id( $translation_set->id ); + if ( $glossary ) { + $route_glossary_entry = new GP_Route_Glossary_Entry(); + return $route_glossary_entry->glossary_entries_get( $project_path, $locale, $slug ); + } + + // Otherwise redirect to the locale glossary. + $locale_glossary_translation_set = GP::$translation_set->by_project_id_slug_and_locale( 0, $slug, $locale ); + $locale_glossary = GP::$glossary->by_set_id( $locale_glossary_translation_set->id ); + $this->redirect( $locale_glossary->path() ); + } +} diff --git a/content/plugins/f-translate/wporg-gp-routes/inc/routes/class-stats.php b/content/plugins/f-translate/wporg-gp-routes/inc/routes/class-stats.php new file mode 100644 index 0000000..3cb42f2 --- /dev/null +++ b/content/plugins/f-translate/wporg-gp-routes/inc/routes/class-stats.php @@ -0,0 +1,247 @@ + false, + 'meta/wordpress-org' => false, + 'meta/rosetta' => false, + 'meta/browsehappy' => false, + 'meta/themes' => false, + 'meta/plugins-v3' => false, + 'meta/forums' => false, + 'apps/android' => false, + 'apps/ios' => false, + 'waiting' => false, + 'wp-themes' => false, + 'wp-plugins' => false, + ); + + // I'm sure there's somewhere to fetch these from statically defined + $wp_project = GP::$project->by_path( 'wp' ); + $previous_wp_version = WP_CORE_STABLE_BRANCH - 0.1; + foreach ( GP::$project->find_many( array( 'parent_project_id' => $wp_project->id, 'active' => 1 ), 'name ASC' ) as $wp_sub_project ) { + if ( 'dev' === $wp_sub_project->slug || version_compare( $previous_wp_version, (float) $wp_sub_project->name, '<=' ) ) { + // Prefix the WordPress projects... + $wp_sub_project->name = $wp_project->name . ' ' . $wp_sub_project->name; + $projects = array_merge( array( $wp_sub_project->path => $wp_sub_project ), $projects ); + } + } + + // Load the projects for each display item + array_walk( $projects, function( &$project, $project_slug ) { + if ( ! $project ) { + $project = GP::$project->by_path( $project_slug ); + } + } ); + + $all_project_paths_sql = '"' . implode( '", "', array_keys( $projects ) ) . '"'; + $sql = "SELECT + path, locale, locale_slug, + (100 * stats.current/stats.all) as percent_complete, + stats.waiting+stats.fuzzy as waiting_strings, + stats.date_modified as last_modified + FROM {$wpdb->project_translation_status} stats + LEFT JOIN {$wpdb->gp_projects} p ON stats.project_id = p.id + WHERE + p.path IN ( $all_project_paths_sql ) + AND p.active = 1"; + + $rows = $wpdb->get_results( $sql ); + + // Split out into $[Locale][Project] = % + $translation_locale_statuses = array(); + foreach ( $rows as $set ) { + $locale_key = $set->locale; + if ( 'default' !== $set->locale_slug ) { + $locale_key = $set->locale . '/' . $set->locale_slug; + } + + $gp_locale = GP_Locales::by_slug( $locale_key ); + if ( ! $gp_locale || ! $gp_locale->wp_locale ) { + continue; + } + + /* + * > 50% round down, so that a project with all strings except 1 translated shows 99%, instead of 100%. + * < 50% round up, so that a project with just a few strings shows 1%, instead of 0%. + */ + $percent_complete = (float) $set->percent_complete; + $percent_complete = ( $percent_complete > 50 ) ? floor( $percent_complete ) : ceil( $percent_complete ); + $translation_locale_statuses[ $locale_key ][ $set->path ] = $percent_complete; + + // Don't include these in the 'waiting' section, override the value to be waiting strings w/ Date Modified. + if ( 'wp-plugins' === $set->path || 'wp-themes' === $set->path ) { + $translation_locale_statuses[ $locale_key ][ $set->path ] = $set->waiting_strings; + $projects[ $set->path ]->cache_last_updated = $set->last_modified; + continue; + } + + if ( ! isset( $translation_locale_statuses[ $locale_key ]['waiting'] ) ) { + $translation_locale_statuses[ $locale_key ]['waiting'] = 0; + } + $translation_locale_statuses[ $locale_key ]['waiting'] += (int) $set->waiting_strings; + } + unset( $rows, $locale_key, $set ); + + // Calculate a list of [Locale] = % subtotals + $translation_locale_complete = array(); + foreach ( $translation_locale_statuses as $locale => $sets ) { + unset( $sets['waiting'], $sets['wp-plugins'], $sets['wp-themes'] ); + $sets_count = count( $sets ); + if ( $sets_count ) { + $translation_locale_complete[ $locale ] = round( array_sum( $sets ) / $sets_count, 3 ); + } else { + $translation_locale_complete[ $locale ] = 0; + } + } + unset( $locale, $sets ); + + // Sort by translation completeness, least number of waiting strings, and locale slug. + uksort( $translation_locale_complete, function ( $a, $b ) use ( $translation_locale_complete, $translation_locale_statuses ) { + if ( $translation_locale_complete[ $a ] < $translation_locale_complete[ $b ] ) { + return 1; + } elseif ( $translation_locale_complete[ $a ] == $translation_locale_complete[ $b ] ) { + if ( $translation_locale_statuses[ $a ]['waiting'] != $translation_locale_statuses[ $b ]['waiting'] ) { + return strnatcmp( $translation_locale_statuses[ $a ]['waiting'], $translation_locale_statuses[ $b ]['waiting'] ); + } else { + return strnatcmp( $a, $b ); + } + } else { + return -1; + } + } ); + + $this->tmpl( 'stats-overview', get_defined_vars() ); + } + + public function get_stats_plugin_theme_overview( $locale, $locale_slug, $view = false ) { + global $wpdb; + if ( ! $locale || ! $locale_slug || ! $view ) { + wp_redirect( '/stats', 301 ); + exit; + } + + if ( 'default' !== $locale_slug ) { + $gp_locale = GP_Locales::by_slug( $locale . '/' . $locale_slug ); + } else { + $gp_locale = GP_Locales::by_slug( $locale ); + } + + if ( ! $gp_locale ) { + wp_redirect( '/stats', 301 ); + exit; + } + + $locale_path = $locale . '/' . $locale_slug; + + $items = array(); + if ( 'plugins' == $view ) { + // Fetch top ~500 plugins.. + $items = get_transient( __METHOD__ . '_plugin_items' ); + if ( false === $items ) { + $items = array(); + foreach ( range( 1, 2 ) as $page ) { // 2 pages x 250 items per page. + $api = wp_safe_remote_get( 'https://api.wordpress.org/plugins/info/1.2/?action=query_plugins&request[per_page]=250&request[page]=' . $page ); + foreach ( json_decode( wp_remote_retrieve_body( $api ) )->plugins as $plugin ) { + $items[ $plugin->slug ] = (object) [ + 'installs' => $plugin->active_installs, + ]; + } + } + set_transient( __METHOD__ . '_plugin_items', $items, $items ? DAY_IN_SECONDS : 5 * MINUTE_IN_SECONDS ); + } + } elseif ( 'themes' == $view && defined( 'WPORG_THEME_DIRECTORY_BLOGID' ) ) { + $items = get_transient( __METHOD__ . '_theme_items' ); + if ( false === $items ) { + // The Themes API API isn't playing nice.. Easiest way.. + switch_to_blog( WPORG_THEME_DIRECTORY_BLOGID ); + $items = $wpdb->get_results( + "SELECT p.post_name as slug, pm.meta_value as installs + FROM {$wpdb->posts} p + LEFT JOIN {$wpdb->postmeta} pm ON p.ID = pm.post_id AND pm.meta_key = '_active_installs' + WHERE p.post_type = 'repopackage' AND p.post_status = 'publish' + ORDER BY pm.meta_value+0 DESC, p.post_date + LIMIT 500", + OBJECT_K + ); + restore_current_blog(); + foreach ( $items as $slug => $details ) { + unset( $items[$slug]->slug ); + } + set_transient( __METHOD__ . '_theme_items', $items, $items ? DAY_IN_SECONDS : 5 * MINUTE_IN_SECONDS ); + } + } else { + wp_safe_redirect( '/stats' ); + die(); + } + + $project_ids = []; + foreach ( $items as $slug => $details ) { + $items[$slug]->project = GP::$project->by_path( 'wp-' . $view . '/' . $slug ); + if ( ! $items[$slug]->project || ! $items[$slug]->project->active ) { + // Not all top-all-time plugins/themes have translation projects. + unset( $items[ $slug ] ); + continue; + } + + if ( 'plugins' == $view ) { + // For plugins, we're ignoring the Readme projects as they're not immediately useful. + // The display will use the "Code Stable" if present, else "Code Development" + $code_project = + GP::$project->by_path( 'wp-' . $view . '/' . $slug . '/stable' ) ?: + GP::$project->by_path( 'wp-' . $view . '/' . $slug . '/dev' ); + + // No code project? This happens when the plugin isn't translatable. The readme projects still exist though. + if ( ! $code_project ) { + unset( $items[ $slug ] ); + continue; + } + + $project_ids[ $code_project->id ] = $slug; + } else { + $project_ids[ $items[$slug]->project->id ] = $slug; + } + } + + $sql_project_ids = implode( ', ', array_map( 'intval', array_keys( $project_ids ) ) ); + $stats = $wpdb->get_results( $wpdb->prepare( + "SELECT `project_id`, `all`, `current`, `waiting`, `fuzzy`, `untranslated` + FROM {$wpdb->project_translation_status} + WHERE project_id IN ($sql_project_ids) + AND locale = %s AND locale_slug = %s", + $locale, $locale_slug + ) ); + + // Link Projects & Stats + foreach ( $stats as $row ) { + $items[ $project_ids[ $row->project_id ] ]->stats = $row; + } + + // Final sanity check that we have data to display. + foreach ( $items as $slug => $details ) { + if ( + ! isset( $details->stats ) || // Didn't find any cached data for a project + ! $details->stats->all // Project has no strings, not useful for this interface + ) { + unset( $items[ $slug ] ); + } + } + + $this->tmpl( 'stats-plugin-themes-overview', compact( 'locale_path', 'view', 'gp_locale', 'items' ) ); + } +} diff --git a/content/plugins/f-translate/wporg-gp-routes/inc/routes/class-wp-directory.php b/content/plugins/f-translate/wporg-gp-routes/inc/routes/class-wp-directory.php new file mode 100644 index 0000000..63bece9 --- /dev/null +++ b/content/plugins/f-translate/wporg-gp-routes/inc/routes/class-wp-directory.php @@ -0,0 +1,248 @@ + 0, + 'editors' => array(), + 'contributors' => array(), + ); + + $translation_editors = $wpdb->get_results( $wpdb->prepare( " + SELECT + `user_id`, `locale` + FROM {$wpdb->wporg_translation_editors} + WHERE `project_id` = %d AND `locale` != 'all-locales' + ", $project->id ), OBJECT ); + + foreach ( $translation_editors as $translation_editor ) { + if ( ! isset( $contributors_by_locale[ $translation_editor->locale ] ) ) { + $contributors_by_locale[ $translation_editor->locale ] = $default_value; + } + + $user = get_user_by( 'id', $translation_editor->user_id ); + if ( ! $user ) { + continue; + } + + $contributors_by_locale[ $translation_editor->locale ]['editors'][ $translation_editor->user_id ] = (object) array( + 'nicename' => $user->user_nicename, + 'display_name' => $this->_encode( $user->display_name ), + ); + + $contributors_by_locale[ $translation_editor->locale ]['count']++; + } + + unset( $translation_editors ); + + foreach ( $this->get_translation_contributors_by_locale( $project->id ) as $row ) { + if ( ! isset( $contributors_by_locale[ $row->locale ] ) ) { + $contributors_by_locale[ $row->locale ] = $default_value; + } + + if ( isset( $contributors_by_locale[ $row->locale ]['editors'][ $row->user_id ] ) ) { + continue; + } + + if ( isset( $contributors_by_locale[ $row->locale ]['contributors'][ $row->user_id ] ) ) { + continue; + } + + $user = get_user_by( 'id', $row->user_id ); + if ( ! $user ) { + continue; + } + + $contributors_by_locale[ $row->locale ]['contributors'][ $row->user_id ] = (object) array( + 'nicename' => $user->user_nicename, + 'display_name' => $this->_encode( $user->display_name ), + ); + + $contributors_by_locale[ $row->locale ]['count']++; + } + + $sub_projects = $wpdb->get_col( $wpdb->prepare( " + SELECT id + FROM {$wpdb->gp_projects} + WHERE parent_project_id = %d + ", $project->id ) ); + + foreach ( $sub_projects as $sub_project ) { + foreach ( $this->get_translation_contributors_by_locale( $sub_project ) as $row ) { + if ( ! isset( $contributors_by_locale[ $row->locale ] ) ) { + $contributors_by_locale[ $row->locale ] = $default_value; + } + + if ( isset( $contributors_by_locale[ $row->locale ]['editors'][ $row->user_id ] ) ) { + continue; + } + + if ( isset( $contributors_by_locale[ $row->locale ]['contributors'][ $row->user_id ] ) ) { + continue; + } + + $user = get_user_by( 'id', $row->user_id ); + if ( ! $user ) { + continue; + } + + $contributors_by_locale[ $row->locale ]['contributors'][ $row->user_id ] = (object) array( + 'nicename' => $user->user_nicename, + 'display_name' => $this->_encode( $user->display_name ), + ); + + $contributors_by_locale[ $row->locale ]['count']++; + } + } + + return $contributors_by_locale; + } + + /** + * Generates the chart data for contributors activity. + * + * @param \GP_Project $project The project. + * @return array The data to build a chart via Chartist.js. + */ + protected function get_contributors_chart_data( $project ) { + global $wpdb; + + $sub_projects = $wpdb->get_col( $wpdb->prepare( " + SELECT id + FROM {$wpdb->gp_projects} + WHERE parent_project_id = %d + ", $project->id ) ); + + $project_ids = array_merge( array( $project->id ), $sub_projects ); + $translation_set_ids = $wpdb->get_col( " + SELECT `id` FROM {$wpdb->gp_translation_sets} WHERE `project_id` IN ( " . implode( ',', $project_ids ) . ") + " ); + + if ( ! $translation_set_ids ) { + return array(); + } + + $date_begin = new DateTime( '-6 day' ); + $date_end = new DateTime( 'NOW' ); + $date_interval = new DateInterval( 'P1D' ); + $date_range = new DatePeriod( $date_begin, $date_interval, $date_end ); + + $days = array(); + foreach ( $date_range as $date ) { + $days[] = $date->format( 'Y-m-d' ); + } + $days[] = $date_end->format( 'Y-m-d' ); + + $counts = $wpdb->get_results( " + SELECT + DATE(date_modified) AS `day`, COUNT(*) AS `count`, `status` + FROM {$wpdb->gp_translations} + WHERE + `translation_set_id` IN (" . implode( ',', $translation_set_ids ) . ") + AND date_modified >= ( CURDATE() - INTERVAL 7 DAY ) + GROUP BY `status`, `day` + ORDER BY `day` DESC + " ); + + $status = array( 'current', 'waiting', 'rejected' ); + $data = []; + foreach ( $days as $day ) { + $data[ $day ] = array_fill_keys( $status, 0 ); + foreach ( $counts as $count ) { + if ( $count->day !== $day || ! in_array( $count->status, $status ) ) { + continue; + } + + $data[ $day ][ $count->status ] = (int) $count->count; + } + } + + $labels = array_keys( $data ); + array_pop( $labels ); + $labels[] = ''; // Don't show a label for today + + $series = array(); + $series_data = array_values( $data ); + foreach ( $status as $stati ) { + $series[] = (object) array( + 'name' => $stati, + 'data' => wp_list_pluck( $series_data, $stati ), + ); + } + + $chart_data = compact( 'labels', 'series' ); + + return $chart_data; + } + + /** + * Prints stats about language packs of a specific project. + * + * @param string $type Type of the language pack, plugin or theme. + * @param string $slug Slug of a project. + */ + public function get_language_packs( $type, $slug ) { + if ( 'plugin' === $type ) { + $type = 'plugins'; + } else { + $type = 'themes'; + } + + $json = wp_remote_retrieve_body( + wp_safe_remote_get( + "https://api.wordpress.org/translations/$type/1.0/?slug={$slug}", + array( + 'user-agent' => 'WordPress.org Translate', + ) + ) + ); + $language_packs = $json && '{' == $json[0] ? json_decode( $json ) : null; + + return $language_packs; + } + + /** + * Retrieves translators of a specific project. + * + * @param int $project_id Project ID. + * @return object Translators of the project. + */ + private function get_translation_contributors_by_locale( $project_id ) { + global $wpdb; + + $sql = $wpdb->prepare( " + SELECT ts.`locale`, ts.`slug` AS `locale_slug`, t.`user_id` + FROM `{$wpdb->gp_translations}` t, `{$wpdb->gp_translation_sets}` ts + WHERE t.`translation_set_id` = ts.`id` + AND t.`user_id` IS NOT NULL AND t.`user_id` != 0 + AND t.`date_modified` > %s + AND ts.`project_id` = %d + AND t.`status` <> 'rejected' + GROUP BY ts.`locale`, ts.`slug`, t.`user_id` + ", date( 'Y-m-d', time() - YEAR_IN_SECONDS ), $project_id ); + + return $wpdb->get_results( $sql ); + } + + private function _encode( $raw ) { + $raw = mb_convert_encoding( $raw, 'UTF-8', 'ASCII, JIS, UTF-8, Windows-1252, ISO-8859-1' ); + return ent2ncr( htmlspecialchars_decode( htmlentities( $raw, ENT_NOQUOTES, 'UTF-8' ), ENT_NOQUOTES ) ); + } +} diff --git a/content/plugins/f-translate/wporg-gp-routes/inc/routes/class-wp-plugins.php b/content/plugins/f-translate/wporg-gp-routes/inc/routes/class-wp-plugins.php new file mode 100644 index 0000000..89c5529 --- /dev/null +++ b/content/plugins/f-translate/wporg-gp-routes/inc/routes/class-wp-plugins.php @@ -0,0 +1,192 @@ +by_path( $project_path ); + if ( ! $project ) { + return $this->die_with_404(); + } + + $rows = $wpdb->get_results( " + SELECT + path, locale, locale_slug, + (100 * stats.current/stats.all) as percent_complete, + stats.waiting+stats.fuzzy as waiting_strings, + stats.untranslated as untranslated + FROM {$wpdb->project_translation_status} stats + LEFT JOIN {$wpdb->gp_projects} p ON stats.project_id = p.id + WHERE + p.parent_project_id = '{$project->id}' + " ); + + // Split out into $[Locale][Project] = % + $translation_locale_statuses = array(); + $sub_projects = array(); + foreach ( $rows as $set ) { + + // Find unique locale key. + $locale_key = $set->locale; + if ( 'default' != $set->locale_slug ) { + $locale_key = $set->locale . '/' . $set->locale_slug; + } + $sub_project = str_replace( "$project_path/", '', $set->path ); + $sub_projects[ $sub_project ] = true; + + /* + * > 50% round down, so that a project with all strings except 1 translated shows 99%, instead of 100%. + * < 50% round up, so that a project with just a few strings shows 1%, instead of 0%. + */ + $percent_complete = (float) $set->percent_complete; + $translation_locale_statuses[ $locale_key ][ $sub_project ] = ( $percent_complete > 50 ) ? floor( $percent_complete ) : ceil( $percent_complete ); + + // Increment the amount of waiting and untranslated strings. + if ( ! isset( $translation_locale_statuses[ $locale_key ]['waiting'] ) ) { + $translation_locale_statuses[ $locale_key ]['waiting'] = 0; + } + if ( ! isset( $translation_locale_statuses[ $locale_key ]['untranslated'] ) ) { + $translation_locale_statuses[ $locale_key ]['untranslated'] = 0; + } + $translation_locale_statuses[ $locale_key ]['waiting'] += (int) $set->waiting_strings; + $translation_locale_statuses[ $locale_key ]['untranslated'] += (int) $set->untranslated; + + + ksort( $translation_locale_statuses[ $locale_key ], SORT_NATURAL ); + } + + // Check if the plugin has at least one code project. These won't be created if a plugin + // has no text domain defined. + $sub_projects = array_keys( $sub_projects ); + $has_error = ( ! in_array( 'dev', $sub_projects ) && ! in_array( 'stable', $sub_projects ) ); + + unset( $project_path, $locale_key, $rows, $set, $sub_project, $sub_projects ); + + // Calculate a list of [Locale] = % subtotals + $translation_locale_complete = array(); + foreach ( $translation_locale_statuses as $locale => $sets ) { + unset( $sets['waiting'], $sets['untranslated'] ); + $translation_locale_complete[ $locale ] = round( array_sum( $sets ) / count( $sets ), 3 ); + } + unset( $locale, $sets ); + + + // Sort by translation completeness, least number of waiting strings, and locale slug. + uksort( $translation_locale_complete, function ( $a, $b ) use ( $translation_locale_complete, $translation_locale_statuses ) { + if ( $translation_locale_complete[ $a ] < $translation_locale_complete[ $b ] ) { + return 1; + } elseif ( $translation_locale_complete[ $a ] == $translation_locale_complete[ $b ] ) { + if ( $translation_locale_statuses[ $a ]['waiting'] != $translation_locale_statuses[ $b ]['waiting'] ) { + return strnatcmp( $translation_locale_statuses[ $a ]['waiting'], $translation_locale_statuses[ $b ]['waiting'] ); + } else { + return strnatcmp( $a, $b ); + } + } else { + return -1; + } + } ); + + $project->icon = $this->get_plugin_icon( $project, 64 ); + + $this->tmpl( 'projects-wp-plugins', get_defined_vars() ); + } + + /** + * Prints stats about contributors of a specific project. + * + * @param string $project_slug Slug of a project. + */ + public function get_plugin_contributors( $project_slug ) { + $project_path = 'wp-plugins/' . $project_slug; + $project = GP::$project->by_path( $project_path ); + if ( ! $project ) { + return $this->die_with_404(); + } + + $project->icon = $this->get_plugin_icon( $project, 64 ); + + $contributors_by_locale = gp_get_meta( 'wp-plugins', $project->id, 'contributors-by-locale' ); + if ( ! $contributors_by_locale || $contributors_by_locale['last_updated'] + HOUR_IN_SECONDS < time() ) { + $contributors_by_locale = $this->get_contributors( $project ); + $contributors_by_locale['last_updated'] = time(); + gp_update_meta( $project->id, 'contributors-by-locale', $contributors_by_locale, 'wp-plugins' ); + } + + $chart_data = gp_get_meta( 'wp-plugins', $project->id, 'contributors-chart-data' ); + if ( ! $chart_data || $chart_data['last_updated'] + DAY_IN_SECONDS < time() ) { + $chart_data = $this->get_contributors_chart_data( $project ); + $chart_data['last_updated'] = time(); + gp_update_meta( $project->id, 'contributors-chart-data', $chart_data, 'wp-plugins' ); + } + + unset( $contributors_by_locale['last_updated'], $chart_data['last_updated'] ); + + $this->tmpl( 'projects-wp-plugins-contributors', get_defined_vars() ); + } + + /** + * Prints stats about language packs of a specific project. + * + * @param string $project_slug Slug of a project. + */ + public function get_plugin_language_packs( $project_slug ) { + $project_path = 'wp-plugins/' . $project_slug; + $project = GP::$project->by_path( $project_path ); + if ( ! $project ) { + return $this->die_with_404(); + } + + $project->icon = $this->get_plugin_icon( $project, 64 ); + + $json = wp_remote_retrieve_body( + wp_safe_remote_get( + "https://api.wordpress.org/translations/plugins/1.0/?slug={$project_slug}", + array( + 'user-agent' => 'WordPress.org Translate', + ) + ) + ); + $language_packs = $json && '{' == $json[0] ? json_decode( $json ) : null; + + $this->tmpl( 'projects-wp-plugins-language-packs', get_defined_vars() ); + } + + /** + * Retrieves the icon of a plugin. + * + * @param GP_Project $project The plugin project. + * @param int $size Optional. The size of the icon. Default 64. + * @return string HTML markup for the icon. + */ + private function get_plugin_icon( $project, $size = 64 ) { + $default = '
    '; + + $icon = ''; + + if ( class_exists( 'WordPressdotorg\Plugin_Directory\Template' ) ) { + $directory_post_id = gp_get_meta( 'wp-plugins', $project->id, 'directory-post-id' ); + if ( $directory_post_id ) { + switch_to_blog( WPORG_PLUGIN_DIRECTORY_BLOGID ); + $icon = \WordPressdotorg\Plugin_Directory\Template::get_plugin_icon( $directory_post_id, 'html' ); + restore_current_blog(); + } + } + + if ( $icon ) { + return $icon; + } + + return $default; + } +} diff --git a/content/plugins/f-translate/wporg-gp-routes/inc/routes/class-wp-themes.php b/content/plugins/f-translate/wporg-gp-routes/inc/routes/class-wp-themes.php new file mode 100644 index 0000000..2f66114 --- /dev/null +++ b/content/plugins/f-translate/wporg-gp-routes/inc/routes/class-wp-themes.php @@ -0,0 +1,174 @@ +by_path( $project_path ); + if ( ! $project ) { + return $this->die_with_404(); + } + + $rows = $wpdb->get_results( " + SELECT + path, locale, locale_slug, + (100 * stats.current/stats.all) as percent_complete, + stats.waiting+stats.fuzzy as waiting_strings, + stats.untranslated as untranslated + FROM {$wpdb->project_translation_status} stats + LEFT JOIN {$wpdb->gp_projects} p ON stats.project_id = p.id + WHERE + p.id = '{$project->id}' + " ); + + // Split out into $[Locale][Project] = % + $translation_locale_statuses = array(); + $sub_projects = array(); + foreach ( $rows as $set ) { + + // Find unique locale key. + $locale_key = $set->locale; + if ( 'default' != $set->locale_slug ) { + $locale_key = $set->locale . '/' . $set->locale_slug; + } + + /* + * > 50% round down, so that a project with all strings except 1 translated shows 99%, instead of 100%. + * < 50% round up, so that a project with just a few strings shows 1%, instead of 0%. + */ + $percent_complete = (float) $set->percent_complete; + $translation_locale_statuses[ $locale_key ]['stable'] = ( $percent_complete > 50 ) ? floor( $percent_complete ) : ceil( $percent_complete ); + + // Increment the amount of waiting and untranslated strings. + if ( ! isset( $translation_locale_statuses[ $locale_key ]['waiting'] ) ) { + $translation_locale_statuses[ $locale_key ]['waiting'] = 0; + } + if ( ! isset( $translation_locale_statuses[ $locale_key ]['untranslated'] ) ) { + $translation_locale_statuses[ $locale_key ]['untranslated'] = 0; + } + $translation_locale_statuses[ $locale_key ]['waiting'] += (int) $set->waiting_strings; + $translation_locale_statuses[ $locale_key ]['untranslated'] += (int) $set->untranslated; + + + ksort( $translation_locale_statuses[ $locale_key ], SORT_NATURAL ); + } + + unset( $project_path, $locale_key, $rows, $set, $sub_project, $sub_projects ); + + // Calculate a list of [Locale] = % subtotals + $translation_locale_complete = array(); + foreach ( $translation_locale_statuses as $locale => $sets ) { + unset( $sets['waiting'], $sets['untranslated'] ); + $translation_locale_complete[ $locale ] = round( array_sum( $sets ) / count( $sets ), 3 ); + } + unset( $locale, $sets ); + + + // Sort by translation completeness, least number of waiting strings, and locale slug. + uksort( $translation_locale_complete, function ( $a, $b ) use ( $translation_locale_complete, $translation_locale_statuses ) { + if ( $translation_locale_complete[ $a ] < $translation_locale_complete[ $b ] ) { + return 1; + } elseif ( $translation_locale_complete[ $a ] == $translation_locale_complete[ $b ] ) { + if ( $translation_locale_statuses[ $a ]['waiting'] != $translation_locale_statuses[ $b ]['waiting'] ) { + return strnatcmp( $translation_locale_statuses[ $a ]['waiting'], $translation_locale_statuses[ $b ]['waiting'] ); + } else { + return strnatcmp( $a, $b ); + } + } else { + return -1; + } + } ); + + $project->icon = $this->get_theme_icon( $project, 64 ); + + $this->tmpl( 'projects-wp-themes', get_defined_vars() ); + } + + /** + * Prints stats about contributors of a specific project. + * + * @param string $project_slug Slug of a project. + */ + public function get_theme_contributors( $project_slug ) { + global $wpdb; + + $project_path = 'wp-themes/' . $project_slug; + $project = GP::$project->by_path( $project_path ); + if ( ! $project ) { + return $this->die_with_404(); + } + + $project->icon = $this->get_theme_icon( $project, 64 ); + + $contributors_by_locale = gp_get_meta( 'wp-themes', $project->id, 'contributors-by-locale' ); + if ( ! $contributors_by_locale || $contributors_by_locale['last_updated'] + HOUR_IN_SECONDS < time() ) { + $contributors_by_locale = $this->get_contributors( $project ); + $contributors_by_locale['last_updated'] = time(); + gp_update_meta( $project->id, 'contributors-by-locale', $contributors_by_locale, 'wp-themes' ); + } + + $chart_data = gp_get_meta( 'wp-themes', $project->id, 'contributors-chart-data' ); + if ( ! $chart_data || $chart_data['last_updated'] + DAY_IN_SECONDS < time() ) { + $chart_data = $this->get_contributors_chart_data( $project ); + $chart_data['last_updated'] = time(); + gp_update_meta( $project->id, 'contributors-chart-data', $chart_data, 'wp-themes' ); + } + + unset( $contributors_by_locale['last_updated'], $chart_data['last_updated'] ); + + $this->tmpl( 'projects-wp-themes-contributors', get_defined_vars() ); + } + + /** + * Prints stats about language packs of a specific project. + * + * @param string $project_slug Slug of a project. + */ + public function get_theme_language_packs( $project_slug ) { + $project_path = 'wp-themes/' . $project_slug; + $project = GP::$project->by_path( $project_path ); + if ( ! $project ) { + return $this->die_with_404(); + } + + $project->icon = $this->get_theme_icon( $project, 64 ); + + $language_packs = $this->get_language_packs( 'theme', $project_slug ); + + $this->tmpl( 'projects-wp-themes-language-packs', get_defined_vars() ); + } + + /** + * Retrieves the icon of a theme. + * + * @param GP_Project $project The theme project. + * @param int $size Optional. The size of the icon. Default 64. + * @return string HTML markup for the icon. + */ + private function get_theme_icon( $project, $size = 64 ) { + $default = '
    '; + + $screenshot = gp_get_meta( 'wp-themes', $project->id, 'screenshot' ); + if ( $screenshot ) { + return sprintf( + '
    ', + esc_url( 'https://i0.wp.com/' . $screenshot . '?w=' . $size * 2 . '&strip=all' ), + $size, + $size + ); + } + + return $default; + } +} diff --git a/content/plugins/f-translate/wporg-gp-routes/wporg-gp-routes.php b/content/plugins/f-translate/wporg-gp-routes/wporg-gp-routes.php new file mode 100644 index 0000000..26f6551 --- /dev/null +++ b/content/plugins/f-translate/wporg-gp-routes/wporg-gp-routes.php @@ -0,0 +1,26 @@ +/locale or /stats for translate.wordpress.org. + * Version: 2.0 + * Author: WordPress.org + * Author URI: http://wordpress.org/ + * License: GPLv2 or later + */ + +namespace WordPressdotorg\GlotPress\Routes; + +use WordPressdotorg\Autoload; + +// Store the root plugin file for usage with functions which use the plugin basename. +define( __NAMESPACE__ . '\PLUGIN_FILE', __FILE__ ); + +if ( ! class_exists( '\WordPressdotorg\Autoload\Autoloader', false ) ) { + include __DIR__ . '/vendor/wordpressdotorg/autoload/class-autoloader.php'; +} + +// Register an Autoloader for all files. +Autoload\register_class_path( __NAMESPACE__, __DIR__ . '/inc' ); + +// Instantiate the Plugin. +Plugin::get_instance(); diff --git a/content/themes/twentytwentyfive/assets/css/editor-style.css b/content/themes/twentytwentyfive/assets/css/editor-style.css new file mode 100644 index 0000000..13b91ba --- /dev/null +++ b/content/themes/twentytwentyfive/assets/css/editor-style.css @@ -0,0 +1,8 @@ +/* + * Link styles + * https://github.com/WordPress/gutenberg/issues/42319 + */ +a { + text-decoration-thickness: 1px !important; + text-underline-offset: .1em; +} diff --git a/content/themes/twentytwentyfive/assets/fonts/beiruti/Beiruti-VariableFont_wght.woff2 b/content/themes/twentytwentyfive/assets/fonts/beiruti/Beiruti-VariableFont_wght.woff2 new file mode 100644 index 0000000..ddfcab2 Binary files /dev/null and b/content/themes/twentytwentyfive/assets/fonts/beiruti/Beiruti-VariableFont_wght.woff2 differ diff --git a/content/themes/twentytwentyfive/assets/fonts/fira-code/FiraCode-VariableFont_wght.woff2 b/content/themes/twentytwentyfive/assets/fonts/fira-code/FiraCode-VariableFont_wght.woff2 new file mode 100644 index 0000000..f40961f Binary files /dev/null and b/content/themes/twentytwentyfive/assets/fonts/fira-code/FiraCode-VariableFont_wght.woff2 differ diff --git a/content/themes/twentytwentyfive/assets/fonts/fira-sans/FiraSans-Black.woff2 b/content/themes/twentytwentyfive/assets/fonts/fira-sans/FiraSans-Black.woff2 new file mode 100644 index 0000000..bac3ec2 Binary files /dev/null and b/content/themes/twentytwentyfive/assets/fonts/fira-sans/FiraSans-Black.woff2 differ diff --git a/content/themes/twentytwentyfive/assets/fonts/fira-sans/FiraSans-BlackItalic.woff2 b/content/themes/twentytwentyfive/assets/fonts/fira-sans/FiraSans-BlackItalic.woff2 new file mode 100644 index 0000000..a550f65 Binary files /dev/null and b/content/themes/twentytwentyfive/assets/fonts/fira-sans/FiraSans-BlackItalic.woff2 differ diff --git a/content/themes/twentytwentyfive/assets/fonts/fira-sans/FiraSans-Bold.woff2 b/content/themes/twentytwentyfive/assets/fonts/fira-sans/FiraSans-Bold.woff2 new file mode 100644 index 0000000..d67367c Binary files /dev/null and b/content/themes/twentytwentyfive/assets/fonts/fira-sans/FiraSans-Bold.woff2 differ diff --git a/content/themes/twentytwentyfive/assets/fonts/fira-sans/FiraSans-BoldItalic.woff2 b/content/themes/twentytwentyfive/assets/fonts/fira-sans/FiraSans-BoldItalic.woff2 new file mode 100644 index 0000000..0d4ee87 Binary files /dev/null and b/content/themes/twentytwentyfive/assets/fonts/fira-sans/FiraSans-BoldItalic.woff2 differ diff --git a/content/themes/twentytwentyfive/assets/fonts/fira-sans/FiraSans-ExtraBold.woff2 b/content/themes/twentytwentyfive/assets/fonts/fira-sans/FiraSans-ExtraBold.woff2 new file mode 100644 index 0000000..5ba058c Binary files /dev/null and b/content/themes/twentytwentyfive/assets/fonts/fira-sans/FiraSans-ExtraBold.woff2 differ diff --git a/content/themes/twentytwentyfive/assets/fonts/fira-sans/FiraSans-ExtraBoldItalic.woff2 b/content/themes/twentytwentyfive/assets/fonts/fira-sans/FiraSans-ExtraBoldItalic.woff2 new file mode 100644 index 0000000..5e40008 Binary files /dev/null and b/content/themes/twentytwentyfive/assets/fonts/fira-sans/FiraSans-ExtraBoldItalic.woff2 differ diff --git a/content/themes/twentytwentyfive/assets/fonts/fira-sans/FiraSans-ExtraLight.woff2 b/content/themes/twentytwentyfive/assets/fonts/fira-sans/FiraSans-ExtraLight.woff2 new file mode 100644 index 0000000..a06977d Binary files /dev/null and b/content/themes/twentytwentyfive/assets/fonts/fira-sans/FiraSans-ExtraLight.woff2 differ diff --git a/content/themes/twentytwentyfive/assets/fonts/fira-sans/FiraSans-ExtraLightItalic.woff2 b/content/themes/twentytwentyfive/assets/fonts/fira-sans/FiraSans-ExtraLightItalic.woff2 new file mode 100644 index 0000000..ca7c7d7 Binary files /dev/null and b/content/themes/twentytwentyfive/assets/fonts/fira-sans/FiraSans-ExtraLightItalic.woff2 differ diff --git a/content/themes/twentytwentyfive/assets/fonts/fira-sans/FiraSans-Italic.woff2 b/content/themes/twentytwentyfive/assets/fonts/fira-sans/FiraSans-Italic.woff2 new file mode 100644 index 0000000..212cd3b Binary files /dev/null and b/content/themes/twentytwentyfive/assets/fonts/fira-sans/FiraSans-Italic.woff2 differ diff --git a/content/themes/twentytwentyfive/assets/fonts/fira-sans/FiraSans-Light.woff2 b/content/themes/twentytwentyfive/assets/fonts/fira-sans/FiraSans-Light.woff2 new file mode 100644 index 0000000..027c4e4 Binary files /dev/null and b/content/themes/twentytwentyfive/assets/fonts/fira-sans/FiraSans-Light.woff2 differ diff --git a/content/themes/twentytwentyfive/assets/fonts/fira-sans/FiraSans-LightItalic.woff2 b/content/themes/twentytwentyfive/assets/fonts/fira-sans/FiraSans-LightItalic.woff2 new file mode 100644 index 0000000..e16e676 Binary files /dev/null and b/content/themes/twentytwentyfive/assets/fonts/fira-sans/FiraSans-LightItalic.woff2 differ diff --git a/content/themes/twentytwentyfive/assets/fonts/fira-sans/FiraSans-Medium.woff2 b/content/themes/twentytwentyfive/assets/fonts/fira-sans/FiraSans-Medium.woff2 new file mode 100644 index 0000000..00b0ea7 Binary files /dev/null and b/content/themes/twentytwentyfive/assets/fonts/fira-sans/FiraSans-Medium.woff2 differ diff --git a/content/themes/twentytwentyfive/assets/fonts/fira-sans/FiraSans-MediumItalic.woff2 b/content/themes/twentytwentyfive/assets/fonts/fira-sans/FiraSans-MediumItalic.woff2 new file mode 100644 index 0000000..47a5428 Binary files /dev/null and b/content/themes/twentytwentyfive/assets/fonts/fira-sans/FiraSans-MediumItalic.woff2 differ diff --git a/content/themes/twentytwentyfive/assets/fonts/fira-sans/FiraSans-Regular.woff2 b/content/themes/twentytwentyfive/assets/fonts/fira-sans/FiraSans-Regular.woff2 new file mode 100644 index 0000000..d224f4f Binary files /dev/null and b/content/themes/twentytwentyfive/assets/fonts/fira-sans/FiraSans-Regular.woff2 differ diff --git a/content/themes/twentytwentyfive/assets/fonts/fira-sans/FiraSans-SemiBold.woff2 b/content/themes/twentytwentyfive/assets/fonts/fira-sans/FiraSans-SemiBold.woff2 new file mode 100644 index 0000000..ff815c0 Binary files /dev/null and b/content/themes/twentytwentyfive/assets/fonts/fira-sans/FiraSans-SemiBold.woff2 differ diff --git a/content/themes/twentytwentyfive/assets/fonts/fira-sans/FiraSans-SemiBoldItalic.woff2 b/content/themes/twentytwentyfive/assets/fonts/fira-sans/FiraSans-SemiBoldItalic.woff2 new file mode 100644 index 0000000..897a0f6 Binary files /dev/null and b/content/themes/twentytwentyfive/assets/fonts/fira-sans/FiraSans-SemiBoldItalic.woff2 differ diff --git a/content/themes/twentytwentyfive/assets/fonts/fira-sans/FiraSans-Thin.woff2 b/content/themes/twentytwentyfive/assets/fonts/fira-sans/FiraSans-Thin.woff2 new file mode 100644 index 0000000..444b0c7 Binary files /dev/null and b/content/themes/twentytwentyfive/assets/fonts/fira-sans/FiraSans-Thin.woff2 differ diff --git a/content/themes/twentytwentyfive/assets/fonts/fira-sans/FiraSans-ThinItalic.woff2 b/content/themes/twentytwentyfive/assets/fonts/fira-sans/FiraSans-ThinItalic.woff2 new file mode 100644 index 0000000..85da45d Binary files /dev/null and b/content/themes/twentytwentyfive/assets/fonts/fira-sans/FiraSans-ThinItalic.woff2 differ diff --git a/content/themes/twentytwentyfive/assets/fonts/literata/Literata72pt-Black.woff2 b/content/themes/twentytwentyfive/assets/fonts/literata/Literata72pt-Black.woff2 new file mode 100644 index 0000000..2fefc2e Binary files /dev/null and b/content/themes/twentytwentyfive/assets/fonts/literata/Literata72pt-Black.woff2 differ diff --git a/content/themes/twentytwentyfive/assets/fonts/literata/Literata72pt-BlackItalic.woff2 b/content/themes/twentytwentyfive/assets/fonts/literata/Literata72pt-BlackItalic.woff2 new file mode 100644 index 0000000..aa9ab25 Binary files /dev/null and b/content/themes/twentytwentyfive/assets/fonts/literata/Literata72pt-BlackItalic.woff2 differ diff --git a/content/themes/twentytwentyfive/assets/fonts/literata/Literata72pt-Bold.woff2 b/content/themes/twentytwentyfive/assets/fonts/literata/Literata72pt-Bold.woff2 new file mode 100644 index 0000000..218a007 Binary files /dev/null and b/content/themes/twentytwentyfive/assets/fonts/literata/Literata72pt-Bold.woff2 differ diff --git a/content/themes/twentytwentyfive/assets/fonts/literata/Literata72pt-BoldItalic.woff2 b/content/themes/twentytwentyfive/assets/fonts/literata/Literata72pt-BoldItalic.woff2 new file mode 100644 index 0000000..e32f031 Binary files /dev/null and b/content/themes/twentytwentyfive/assets/fonts/literata/Literata72pt-BoldItalic.woff2 differ diff --git a/content/themes/twentytwentyfive/assets/fonts/literata/Literata72pt-ExtraBold.woff2 b/content/themes/twentytwentyfive/assets/fonts/literata/Literata72pt-ExtraBold.woff2 new file mode 100644 index 0000000..0d3efcd Binary files /dev/null and b/content/themes/twentytwentyfive/assets/fonts/literata/Literata72pt-ExtraBold.woff2 differ diff --git a/content/themes/twentytwentyfive/assets/fonts/literata/Literata72pt-ExtraBoldItalic.woff2 b/content/themes/twentytwentyfive/assets/fonts/literata/Literata72pt-ExtraBoldItalic.woff2 new file mode 100644 index 0000000..4665bfd Binary files /dev/null and b/content/themes/twentytwentyfive/assets/fonts/literata/Literata72pt-ExtraBoldItalic.woff2 differ diff --git a/content/themes/twentytwentyfive/assets/fonts/literata/Literata72pt-ExtraLight.woff2 b/content/themes/twentytwentyfive/assets/fonts/literata/Literata72pt-ExtraLight.woff2 new file mode 100644 index 0000000..bc7f2ae Binary files /dev/null and b/content/themes/twentytwentyfive/assets/fonts/literata/Literata72pt-ExtraLight.woff2 differ diff --git a/content/themes/twentytwentyfive/assets/fonts/literata/Literata72pt-ExtraLightItalic.woff2 b/content/themes/twentytwentyfive/assets/fonts/literata/Literata72pt-ExtraLightItalic.woff2 new file mode 100644 index 0000000..9e7bd16 Binary files /dev/null and b/content/themes/twentytwentyfive/assets/fonts/literata/Literata72pt-ExtraLightItalic.woff2 differ diff --git a/content/themes/twentytwentyfive/assets/fonts/literata/Literata72pt-Light.woff2 b/content/themes/twentytwentyfive/assets/fonts/literata/Literata72pt-Light.woff2 new file mode 100644 index 0000000..0d00850 Binary files /dev/null and b/content/themes/twentytwentyfive/assets/fonts/literata/Literata72pt-Light.woff2 differ diff --git a/content/themes/twentytwentyfive/assets/fonts/literata/Literata72pt-LightItalic.woff2 b/content/themes/twentytwentyfive/assets/fonts/literata/Literata72pt-LightItalic.woff2 new file mode 100644 index 0000000..2ab7591 Binary files /dev/null and b/content/themes/twentytwentyfive/assets/fonts/literata/Literata72pt-LightItalic.woff2 differ diff --git a/content/themes/twentytwentyfive/assets/fonts/literata/Literata72pt-Medium.woff2 b/content/themes/twentytwentyfive/assets/fonts/literata/Literata72pt-Medium.woff2 new file mode 100644 index 0000000..fe4b21a Binary files /dev/null and b/content/themes/twentytwentyfive/assets/fonts/literata/Literata72pt-Medium.woff2 differ diff --git a/content/themes/twentytwentyfive/assets/fonts/literata/Literata72pt-MediumItalic.woff2 b/content/themes/twentytwentyfive/assets/fonts/literata/Literata72pt-MediumItalic.woff2 new file mode 100644 index 0000000..da06424 Binary files /dev/null and b/content/themes/twentytwentyfive/assets/fonts/literata/Literata72pt-MediumItalic.woff2 differ diff --git a/content/themes/twentytwentyfive/assets/fonts/literata/Literata72pt-Regular.woff2 b/content/themes/twentytwentyfive/assets/fonts/literata/Literata72pt-Regular.woff2 new file mode 100644 index 0000000..043102e Binary files /dev/null and b/content/themes/twentytwentyfive/assets/fonts/literata/Literata72pt-Regular.woff2 differ diff --git a/content/themes/twentytwentyfive/assets/fonts/literata/Literata72pt-RegularItalic.woff2 b/content/themes/twentytwentyfive/assets/fonts/literata/Literata72pt-RegularItalic.woff2 new file mode 100644 index 0000000..dd072f4 Binary files /dev/null and b/content/themes/twentytwentyfive/assets/fonts/literata/Literata72pt-RegularItalic.woff2 differ diff --git a/content/themes/twentytwentyfive/assets/fonts/literata/Literata72pt-SemiBold.woff2 b/content/themes/twentytwentyfive/assets/fonts/literata/Literata72pt-SemiBold.woff2 new file mode 100644 index 0000000..d00879a Binary files /dev/null and b/content/themes/twentytwentyfive/assets/fonts/literata/Literata72pt-SemiBold.woff2 differ diff --git a/content/themes/twentytwentyfive/assets/fonts/literata/Literata72pt-SemiBoldItalic.woff2 b/content/themes/twentytwentyfive/assets/fonts/literata/Literata72pt-SemiBoldItalic.woff2 new file mode 100644 index 0000000..8d5628b Binary files /dev/null and b/content/themes/twentytwentyfive/assets/fonts/literata/Literata72pt-SemiBoldItalic.woff2 differ diff --git a/content/themes/twentytwentyfive/assets/fonts/manrope/Manrope-VariableFont_wght.woff2 b/content/themes/twentytwentyfive/assets/fonts/manrope/Manrope-VariableFont_wght.woff2 new file mode 100644 index 0000000..44f81dc Binary files /dev/null and b/content/themes/twentytwentyfive/assets/fonts/manrope/Manrope-VariableFont_wght.woff2 differ diff --git a/content/themes/twentytwentyfive/assets/fonts/platypi/Platypi-Italic-VariableFont_wght.woff2 b/content/themes/twentytwentyfive/assets/fonts/platypi/Platypi-Italic-VariableFont_wght.woff2 new file mode 100644 index 0000000..c9e4e2e Binary files /dev/null and b/content/themes/twentytwentyfive/assets/fonts/platypi/Platypi-Italic-VariableFont_wght.woff2 differ diff --git a/content/themes/twentytwentyfive/assets/fonts/platypi/Platypi-VariableFont_wght.woff2 b/content/themes/twentytwentyfive/assets/fonts/platypi/Platypi-VariableFont_wght.woff2 new file mode 100644 index 0000000..f86f871 Binary files /dev/null and b/content/themes/twentytwentyfive/assets/fonts/platypi/Platypi-VariableFont_wght.woff2 differ diff --git a/content/themes/twentytwentyfive/assets/fonts/roboto-slab/RobotoSlab-VariableFont_wght.woff2 b/content/themes/twentytwentyfive/assets/fonts/roboto-slab/RobotoSlab-VariableFont_wght.woff2 new file mode 100644 index 0000000..8484d4f Binary files /dev/null and b/content/themes/twentytwentyfive/assets/fonts/roboto-slab/RobotoSlab-VariableFont_wght.woff2 differ diff --git a/content/themes/twentytwentyfive/assets/fonts/vollkorn/Vollkorn-Italic-VariableFont_wght.woff2 b/content/themes/twentytwentyfive/assets/fonts/vollkorn/Vollkorn-Italic-VariableFont_wght.woff2 new file mode 100644 index 0000000..67ccfbc Binary files /dev/null and b/content/themes/twentytwentyfive/assets/fonts/vollkorn/Vollkorn-Italic-VariableFont_wght.woff2 differ diff --git a/content/themes/twentytwentyfive/assets/fonts/vollkorn/Vollkorn-VariableFont_wght.woff2 b/content/themes/twentytwentyfive/assets/fonts/vollkorn/Vollkorn-VariableFont_wght.woff2 new file mode 100644 index 0000000..6f93056 Binary files /dev/null and b/content/themes/twentytwentyfive/assets/fonts/vollkorn/Vollkorn-VariableFont_wght.woff2 differ diff --git a/content/themes/twentytwentyfive/assets/fonts/ysabeau-office/YsabeauOffice-Italic-VariableFont_wght.woff2 b/content/themes/twentytwentyfive/assets/fonts/ysabeau-office/YsabeauOffice-Italic-VariableFont_wght.woff2 new file mode 100644 index 0000000..761f2e8 Binary files /dev/null and b/content/themes/twentytwentyfive/assets/fonts/ysabeau-office/YsabeauOffice-Italic-VariableFont_wght.woff2 differ diff --git a/content/themes/twentytwentyfive/assets/fonts/ysabeau-office/YsabeauOffice-VariableFont_wght.woff2 b/content/themes/twentytwentyfive/assets/fonts/ysabeau-office/YsabeauOffice-VariableFont_wght.woff2 new file mode 100644 index 0000000..562680d Binary files /dev/null and b/content/themes/twentytwentyfive/assets/fonts/ysabeau-office/YsabeauOffice-VariableFont_wght.woff2 differ diff --git a/content/themes/twentytwentyfive/assets/images/404-image.webp b/content/themes/twentytwentyfive/assets/images/404-image.webp new file mode 100644 index 0000000..5b33a9e Binary files /dev/null and b/content/themes/twentytwentyfive/assets/images/404-image.webp differ diff --git a/content/themes/twentytwentyfive/assets/images/agenda-img-4.webp b/content/themes/twentytwentyfive/assets/images/agenda-img-4.webp new file mode 100644 index 0000000..d7a00dc Binary files /dev/null and b/content/themes/twentytwentyfive/assets/images/agenda-img-4.webp differ diff --git a/content/themes/twentytwentyfive/assets/images/akaka-falls-state-park-flora.webp b/content/themes/twentytwentyfive/assets/images/akaka-falls-state-park-flora.webp new file mode 100644 index 0000000..f4eabf2 Binary files /dev/null and b/content/themes/twentytwentyfive/assets/images/akaka-falls-state-park-flora.webp differ diff --git a/content/themes/twentytwentyfive/assets/images/book-image-landing.webp b/content/themes/twentytwentyfive/assets/images/book-image-landing.webp new file mode 100644 index 0000000..f30065c Binary files /dev/null and b/content/themes/twentytwentyfive/assets/images/book-image-landing.webp differ diff --git a/content/themes/twentytwentyfive/assets/images/book-image.webp b/content/themes/twentytwentyfive/assets/images/book-image.webp new file mode 100644 index 0000000..92beb78 Binary files /dev/null and b/content/themes/twentytwentyfive/assets/images/book-image.webp differ diff --git a/content/themes/twentytwentyfive/assets/images/botany-flowers-closeup.webp b/content/themes/twentytwentyfive/assets/images/botany-flowers-closeup.webp new file mode 100644 index 0000000..427db85 Binary files /dev/null and b/content/themes/twentytwentyfive/assets/images/botany-flowers-closeup.webp differ diff --git a/content/themes/twentytwentyfive/assets/images/botany-flowers.webp b/content/themes/twentytwentyfive/assets/images/botany-flowers.webp new file mode 100644 index 0000000..bb34c39 Binary files /dev/null and b/content/themes/twentytwentyfive/assets/images/botany-flowers.webp differ diff --git a/content/themes/twentytwentyfive/assets/images/campanula-alliariifolia-flower.webp b/content/themes/twentytwentyfive/assets/images/campanula-alliariifolia-flower.webp new file mode 100644 index 0000000..c2ad28b Binary files /dev/null and b/content/themes/twentytwentyfive/assets/images/campanula-alliariifolia-flower.webp differ diff --git a/content/themes/twentytwentyfive/assets/images/category-anthuriums.webp b/content/themes/twentytwentyfive/assets/images/category-anthuriums.webp new file mode 100644 index 0000000..0f1d2fa Binary files /dev/null and b/content/themes/twentytwentyfive/assets/images/category-anthuriums.webp differ diff --git a/content/themes/twentytwentyfive/assets/images/category-cactus.webp b/content/themes/twentytwentyfive/assets/images/category-cactus.webp new file mode 100644 index 0000000..9c90905 Binary files /dev/null and b/content/themes/twentytwentyfive/assets/images/category-cactus.webp differ diff --git a/content/themes/twentytwentyfive/assets/images/category-sunflowers.webp b/content/themes/twentytwentyfive/assets/images/category-sunflowers.webp new file mode 100644 index 0000000..eced76d Binary files /dev/null and b/content/themes/twentytwentyfive/assets/images/category-sunflowers.webp differ diff --git a/content/themes/twentytwentyfive/assets/images/coming-soon-bg-image.webp b/content/themes/twentytwentyfive/assets/images/coming-soon-bg-image.webp new file mode 100644 index 0000000..ac96d52 Binary files /dev/null and b/content/themes/twentytwentyfive/assets/images/coming-soon-bg-image.webp differ diff --git a/content/themes/twentytwentyfive/assets/images/coral-square.webp b/content/themes/twentytwentyfive/assets/images/coral-square.webp new file mode 100644 index 0000000..73c068f Binary files /dev/null and b/content/themes/twentytwentyfive/assets/images/coral-square.webp differ diff --git a/content/themes/twentytwentyfive/assets/images/dallas-creek-square.webp b/content/themes/twentytwentyfive/assets/images/dallas-creek-square.webp new file mode 100644 index 0000000..d363401 Binary files /dev/null and b/content/themes/twentytwentyfive/assets/images/dallas-creek-square.webp differ diff --git a/content/themes/twentytwentyfive/assets/images/delphinium-flowers.webp b/content/themes/twentytwentyfive/assets/images/delphinium-flowers.webp new file mode 100644 index 0000000..dc5a84a Binary files /dev/null and b/content/themes/twentytwentyfive/assets/images/delphinium-flowers.webp differ diff --git a/content/themes/twentytwentyfive/assets/images/flower-meadow-square.webp b/content/themes/twentytwentyfive/assets/images/flower-meadow-square.webp new file mode 100644 index 0000000..4b9cd30 Binary files /dev/null and b/content/themes/twentytwentyfive/assets/images/flower-meadow-square.webp differ diff --git a/content/themes/twentytwentyfive/assets/images/grid-flower-1.webp b/content/themes/twentytwentyfive/assets/images/grid-flower-1.webp new file mode 100644 index 0000000..4fadf2e Binary files /dev/null and b/content/themes/twentytwentyfive/assets/images/grid-flower-1.webp differ diff --git a/content/themes/twentytwentyfive/assets/images/grid-flower-2.webp b/content/themes/twentytwentyfive/assets/images/grid-flower-2.webp new file mode 100644 index 0000000..2bebf05 Binary files /dev/null and b/content/themes/twentytwentyfive/assets/images/grid-flower-2.webp differ diff --git a/content/themes/twentytwentyfive/assets/images/hero-podcast.webp b/content/themes/twentytwentyfive/assets/images/hero-podcast.webp new file mode 100644 index 0000000..1a79e97 Binary files /dev/null and b/content/themes/twentytwentyfive/assets/images/hero-podcast.webp differ diff --git a/content/themes/twentytwentyfive/assets/images/link-in-bio-background.webp b/content/themes/twentytwentyfive/assets/images/link-in-bio-background.webp new file mode 100644 index 0000000..0f31d5b Binary files /dev/null and b/content/themes/twentytwentyfive/assets/images/link-in-bio-background.webp differ diff --git a/content/themes/twentytwentyfive/assets/images/link-in-bio-image.webp b/content/themes/twentytwentyfive/assets/images/link-in-bio-image.webp new file mode 100644 index 0000000..ace36ca Binary files /dev/null and b/content/themes/twentytwentyfive/assets/images/link-in-bio-image.webp differ diff --git a/content/themes/twentytwentyfive/assets/images/location.webp b/content/themes/twentytwentyfive/assets/images/location.webp new file mode 100644 index 0000000..4f7ea3c Binary files /dev/null and b/content/themes/twentytwentyfive/assets/images/location.webp differ diff --git a/content/themes/twentytwentyfive/assets/images/malibu-plantlife.webp b/content/themes/twentytwentyfive/assets/images/malibu-plantlife.webp new file mode 100644 index 0000000..74f54e6 Binary files /dev/null and b/content/themes/twentytwentyfive/assets/images/malibu-plantlife.webp differ diff --git a/content/themes/twentytwentyfive/assets/images/man-in-hat.webp b/content/themes/twentytwentyfive/assets/images/man-in-hat.webp new file mode 100644 index 0000000..5090ff2 Binary files /dev/null and b/content/themes/twentytwentyfive/assets/images/man-in-hat.webp differ diff --git a/content/themes/twentytwentyfive/assets/images/marshland-birds-square.webp b/content/themes/twentytwentyfive/assets/images/marshland-birds-square.webp new file mode 100644 index 0000000..5b2bc76 Binary files /dev/null and b/content/themes/twentytwentyfive/assets/images/marshland-birds-square.webp differ diff --git a/content/themes/twentytwentyfive/assets/images/northern-buttercups-flowers.webp b/content/themes/twentytwentyfive/assets/images/northern-buttercups-flowers.webp new file mode 100644 index 0000000..d75c1d3 Binary files /dev/null and b/content/themes/twentytwentyfive/assets/images/northern-buttercups-flowers.webp differ diff --git a/content/themes/twentytwentyfive/assets/images/nurse.webp b/content/themes/twentytwentyfive/assets/images/nurse.webp new file mode 100644 index 0000000..606552f Binary files /dev/null and b/content/themes/twentytwentyfive/assets/images/nurse.webp differ diff --git a/content/themes/twentytwentyfive/assets/images/parthenon-square.webp b/content/themes/twentytwentyfive/assets/images/parthenon-square.webp new file mode 100644 index 0000000..039281d Binary files /dev/null and b/content/themes/twentytwentyfive/assets/images/parthenon-square.webp differ diff --git a/content/themes/twentytwentyfive/assets/images/poster-image-background.webp b/content/themes/twentytwentyfive/assets/images/poster-image-background.webp new file mode 100644 index 0000000..00bc0b7 Binary files /dev/null and b/content/themes/twentytwentyfive/assets/images/poster-image-background.webp differ diff --git a/content/themes/twentytwentyfive/assets/images/red-hibiscus-closeup.webp b/content/themes/twentytwentyfive/assets/images/red-hibiscus-closeup.webp new file mode 100644 index 0000000..3435a3b Binary files /dev/null and b/content/themes/twentytwentyfive/assets/images/red-hibiscus-closeup.webp differ diff --git a/content/themes/twentytwentyfive/assets/images/ruins-image.webp b/content/themes/twentytwentyfive/assets/images/ruins-image.webp new file mode 100644 index 0000000..d407de2 Binary files /dev/null and b/content/themes/twentytwentyfive/assets/images/ruins-image.webp differ diff --git a/content/themes/twentytwentyfive/assets/images/services-subscriber-photo.webp b/content/themes/twentytwentyfive/assets/images/services-subscriber-photo.webp new file mode 100644 index 0000000..785147d Binary files /dev/null and b/content/themes/twentytwentyfive/assets/images/services-subscriber-photo.webp differ diff --git a/content/themes/twentytwentyfive/assets/images/star-thristle-flower.webp b/content/themes/twentytwentyfive/assets/images/star-thristle-flower.webp new file mode 100644 index 0000000..f5ccb93 Binary files /dev/null and b/content/themes/twentytwentyfive/assets/images/star-thristle-flower.webp differ diff --git a/content/themes/twentytwentyfive/assets/images/typewriter.webp b/content/themes/twentytwentyfive/assets/images/typewriter.webp new file mode 100644 index 0000000..d386d23 Binary files /dev/null and b/content/themes/twentytwentyfive/assets/images/typewriter.webp differ diff --git a/content/themes/twentytwentyfive/assets/images/vash-gon-square.webp b/content/themes/twentytwentyfive/assets/images/vash-gon-square.webp new file mode 100644 index 0000000..a9b8d17 Binary files /dev/null and b/content/themes/twentytwentyfive/assets/images/vash-gon-square.webp differ diff --git a/content/themes/twentytwentyfive/assets/images/woman-splashing-water.webp b/content/themes/twentytwentyfive/assets/images/woman-splashing-water.webp new file mode 100644 index 0000000..187c016 Binary files /dev/null and b/content/themes/twentytwentyfive/assets/images/woman-splashing-water.webp differ diff --git a/content/themes/twentytwentyfive/functions.php b/content/themes/twentytwentyfive/functions.php new file mode 100644 index 0000000..ddb42a8 --- /dev/null +++ b/content/themes/twentytwentyfive/functions.php @@ -0,0 +1,158 @@ +get( 'Version' ) + ); + } +endif; +add_action( 'wp_enqueue_scripts', 'twentytwentyfive_enqueue_styles' ); + +// Registers custom block styles. +if ( ! function_exists( 'twentytwentyfive_block_styles' ) ) : + /** + * Registers custom block styles. + * + * @since Twenty Twenty-Five 1.0 + * + * @return void + */ + function twentytwentyfive_block_styles() { + register_block_style( + 'core/list', + array( + 'name' => 'checkmark-list', + 'label' => __( 'Checkmark', 'twentytwentyfive' ), + 'inline_style' => ' + ul.is-style-checkmark-list { + list-style-type: "\2713"; + } + + ul.is-style-checkmark-list li { + padding-inline-start: 1ch; + }', + ) + ); + } +endif; +add_action( 'init', 'twentytwentyfive_block_styles' ); + +// Registers pattern categories. +if ( ! function_exists( 'twentytwentyfive_pattern_categories' ) ) : + /** + * Registers pattern categories. + * + * @since Twenty Twenty-Five 1.0 + * + * @return void + */ + function twentytwentyfive_pattern_categories() { + + register_block_pattern_category( + 'twentytwentyfive_page', + array( + 'label' => __( 'Pages', 'twentytwentyfive' ), + 'description' => __( 'A collection of full page layouts.', 'twentytwentyfive' ), + ) + ); + + register_block_pattern_category( + 'twentytwentyfive_post-format', + array( + 'label' => __( 'Post formats', 'twentytwentyfive' ), + 'description' => __( 'A collection of post format patterns.', 'twentytwentyfive' ), + ) + ); + } +endif; +add_action( 'init', 'twentytwentyfive_pattern_categories' ); + +// Registers block binding sources. +if ( ! function_exists( 'twentytwentyfive_register_block_bindings' ) ) : + /** + * Registers the post format block binding source. + * + * @since Twenty Twenty-Five 1.0 + * + * @return void + */ + function twentytwentyfive_register_block_bindings() { + register_block_bindings_source( + 'twentytwentyfive/format', + array( + 'label' => _x( 'Post format name', 'Label for the block binding placeholder in the editor', 'twentytwentyfive' ), + 'get_value_callback' => 'twentytwentyfive_format_binding', + ) + ); + } +endif; +add_action( 'init', 'twentytwentyfive_register_block_bindings' ); + +// Registers block binding callback function for the post format name. +if ( ! function_exists( 'twentytwentyfive_format_binding' ) ) : + /** + * Callback function for the post format name block binding source. + * + * @since Twenty Twenty-Five 1.0 + * + * @return string|void Post format name, or nothing if the format is 'standard'. + */ + function twentytwentyfive_format_binding() { + $post_format_slug = get_post_format(); + + if ( $post_format_slug && 'standard' !== $post_format_slug ) { + return get_post_format_string( $post_format_slug ); + } + } +endif; diff --git a/content/themes/twentytwentyfive/parts/footer-columns.html b/content/themes/twentytwentyfive/parts/footer-columns.html new file mode 100644 index 0000000..00ca2ec --- /dev/null +++ b/content/themes/twentytwentyfive/parts/footer-columns.html @@ -0,0 +1 @@ + diff --git a/content/themes/twentytwentyfive/parts/footer-newsletter.html b/content/themes/twentytwentyfive/parts/footer-newsletter.html new file mode 100644 index 0000000..8e16988 --- /dev/null +++ b/content/themes/twentytwentyfive/parts/footer-newsletter.html @@ -0,0 +1 @@ + diff --git a/content/themes/twentytwentyfive/parts/footer.html b/content/themes/twentytwentyfive/parts/footer.html new file mode 100644 index 0000000..c2ea07c --- /dev/null +++ b/content/themes/twentytwentyfive/parts/footer.html @@ -0,0 +1 @@ + diff --git a/content/themes/twentytwentyfive/parts/header-large-title.html b/content/themes/twentytwentyfive/parts/header-large-title.html new file mode 100644 index 0000000..2c7ccf8 --- /dev/null +++ b/content/themes/twentytwentyfive/parts/header-large-title.html @@ -0,0 +1 @@ + diff --git a/content/themes/twentytwentyfive/parts/header.html b/content/themes/twentytwentyfive/parts/header.html new file mode 100644 index 0000000..7e3e990 --- /dev/null +++ b/content/themes/twentytwentyfive/parts/header.html @@ -0,0 +1 @@ + diff --git a/content/themes/twentytwentyfive/parts/sidebar.html b/content/themes/twentytwentyfive/parts/sidebar.html new file mode 100644 index 0000000..a29f829 --- /dev/null +++ b/content/themes/twentytwentyfive/parts/sidebar.html @@ -0,0 +1 @@ + diff --git a/content/themes/twentytwentyfive/parts/vertical-header.html b/content/themes/twentytwentyfive/parts/vertical-header.html new file mode 100644 index 0000000..e102cc7 --- /dev/null +++ b/content/themes/twentytwentyfive/parts/vertical-header.html @@ -0,0 +1 @@ + diff --git a/content/themes/twentytwentyfive/patterns/banner-about-book.php b/content/themes/twentytwentyfive/patterns/banner-about-book.php new file mode 100644 index 0000000..dc06f30 --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/banner-about-book.php @@ -0,0 +1,41 @@ + + + +
    + +
    + +
    + +

    + + + +

    + +
    + + + +
    + +
    <?php esc_attr_e( 'Image of a book', 'twentytwentyfive' ); ?>
    + +
    + +
    + +
    + diff --git a/content/themes/twentytwentyfive/patterns/banner-cover-big-heading.php b/content/themes/twentytwentyfive/patterns/banner-cover-big-heading.php new file mode 100644 index 0000000..1b00c3a --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/banner-cover-big-heading.php @@ -0,0 +1,35 @@ + + +
    + +
    + +
    + <?php esc_attr_e( 'Photo of a field full of flowers, a blue sky and a tree.', 'twentytwentyfive' ); ?> +
    + + + +
    + +

    + + +
    + +
    + +
    + diff --git a/content/themes/twentytwentyfive/patterns/banner-intro-image.php b/content/themes/twentytwentyfive/patterns/banner-intro-image.php new file mode 100644 index 0000000..ea70d00 --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/banner-intro-image.php @@ -0,0 +1,52 @@ + + +
    + +
    + +
    + +
    + <?php echo esc_attr_x( 'Picture of a flower', 'Alt text for intro picture.', 'twentytwentyfive' ); ?> +
    + +
    + + + +
    + +

    + + + +

    + + + +
    + +
    + +
    + +
    + +
    + +
    + +
    + diff --git a/content/themes/twentytwentyfive/patterns/banner-intro.php b/content/themes/twentytwentyfive/patterns/banner-intro.php new file mode 100644 index 0000000..48a816a --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/banner-intro.php @@ -0,0 +1,28 @@ + + +
    + +

    + ' . esc_html_x( 'Fleurs', 'Example brand name.', 'twentytwentyfive' ) . '' + ); + ?> +

    + +
    + diff --git a/content/themes/twentytwentyfive/patterns/banner-poster.php b/content/themes/twentytwentyfive/patterns/banner-poster.php new file mode 100644 index 0000000..3c78fe3 --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/banner-poster.php @@ -0,0 +1,69 @@ + + + + diff --git a/content/themes/twentytwentyfive/patterns/banner-with-description-and-images-grid.php b/content/themes/twentytwentyfive/patterns/banner-with-description-and-images-grid.php new file mode 100644 index 0000000..8fc3369 --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/banner-with-description-and-images-grid.php @@ -0,0 +1,53 @@ + + +
    + +
    + +
    + +
    + +

    + + + +

    + ' . esc_html_x( 'Fleurs', 'Example brand name.', 'twentytwentyfive' ) . '' + ); + ?> +

    + + +
    + + + +
    <?php esc_attr_e( 'Photography close up of a red flower.', 'twentytwentyfive' ); ?>
    + +
    + + + +
    <?php esc_attr_e( 'Black and white photography close up of a flower.', 'twentytwentyfive' ); ?>
    + +
    + +
    + diff --git a/content/themes/twentytwentyfive/patterns/binding-format.php b/content/themes/twentytwentyfive/patterns/binding-format.php new file mode 100644 index 0000000..a2ca92d --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/binding-format.php @@ -0,0 +1,16 @@ + + +

    + diff --git a/content/themes/twentytwentyfive/patterns/comments.php b/content/themes/twentytwentyfive/patterns/comments.php new file mode 100644 index 0000000..08c500f --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/comments.php @@ -0,0 +1,53 @@ + + +
    + +

    + + + + +
    + +
    + + +
    + + + + +
    + + +
    + +
    + +
    + +
    + + + + + + + + + +
    + diff --git a/content/themes/twentytwentyfive/patterns/contact-centered-social-link.php b/content/themes/twentytwentyfive/patterns/contact-centered-social-link.php new file mode 100644 index 0000000..7fad89b --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/contact-centered-social-link.php @@ -0,0 +1,39 @@ + + + +
    + +
    + +

    Feel free to reach out.', 'Heading of the Contact social link pattern', 'twentytwentyfive' ) ); ?>

    + + + + + + + + + +
    + +
    + diff --git a/content/themes/twentytwentyfive/patterns/contact-info-locations.php b/content/themes/twentytwentyfive/patterns/contact-info-locations.php new file mode 100644 index 0000000..393d0a7 --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/contact-info-locations.php @@ -0,0 +1,101 @@ + + +
    + +
    + +

    + + + +
    + +
    + +

    + + + + + + + + +

    + + +

    + +
    + + + +
    + +
    + +

    + + +

    + +
    + + + +
    + +

    + + + +

    + +
    + + + +
    + +

    + + + +

    + +
    + + + +
    + +

    + + + +

    + +
    + +
    + +
    + +
    + +
    + diff --git a/content/themes/twentytwentyfive/patterns/contact-location-and-link.php b/content/themes/twentytwentyfive/patterns/contact-location-and-link.php new file mode 100644 index 0000000..95cbbe3 --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/contact-location-and-link.php @@ -0,0 +1,43 @@ + + +
    + +
    + +
    + +
    +

    + + + +

    + +
    + +
    + + + +
    + +
    <?php esc_attr_e( 'The business location', 'twentytwentyfive' ); ?>
    + +
    + +
    + +
    + diff --git a/content/themes/twentytwentyfive/patterns/cta-book-links.php b/content/themes/twentytwentyfive/patterns/cta-book-links.php new file mode 100644 index 0000000..b142d08 --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/cta-book-links.php @@ -0,0 +1,60 @@ + + +
    + +

    + + + +
    + +
    + + + +
    + + + +
    + + + +
    + + + +
    + + + +
    + + + +
    + + + +
    + +
    + + + +

    international editions.', 'Pattern placeholder text with link.', 'twentytwentyfive' ) ); ?>

    + +
    + diff --git a/content/themes/twentytwentyfive/patterns/cta-book-locations.php b/content/themes/twentytwentyfive/patterns/cta-book-locations.php new file mode 100644 index 0000000..37e6419 --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/cta-book-locations.php @@ -0,0 +1,148 @@ + + +
    + +
    + +
    + +
    + +

    + + + +

    + +
    + +
    + + + +
    + +
    + +
    + +
    + +

    + + + +

    + +
    + + + +
    + +

    + + + +

    + +
    + + + +
    + +

    + + + +

    + +
    + + + +
    + +

    + + + +

    + +
    + +
    + + + +
    + +
    + +

    + + + +

    + +
    + + + +
    + +

    + + + +

    + +
    + + + +
    + +

    + + + +

    + +
    + + + +
    + +

    + + + +

    + +
    + +
    + +
    + +
    + +
    + +
    + diff --git a/content/themes/twentytwentyfive/patterns/cta-centered-heading.php b/content/themes/twentytwentyfive/patterns/cta-centered-heading.php new file mode 100644 index 0000000..e1c8d7e --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/cta-centered-heading.php @@ -0,0 +1,34 @@ + + +
    + +
    + +

    + + +

    + + + +
    + +
    +
    + +
    + +
    + diff --git a/content/themes/twentytwentyfive/patterns/cta-events-list.php b/content/themes/twentytwentyfive/patterns/cta-events-list.php new file mode 100644 index 0000000..5cdd050 --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/cta-events-list.php @@ -0,0 +1,171 @@ + + +
    + +
    + +

    + + + +

    + + + +
    + +
    + +
    + +

    + + + +

    + +
    + + + +
    + +

    + + + +
    + +
    + +
    + +
    + +
    + + + +
    +
    + +

    + historias, iсторії, iστορίες”', 'Placeholder heading in four languages.', 'twentytwentyfive' ) + ); + ?> +

    + + + +

    + +
    + + + +
    + +

    + + + +
    + +
    + +
    + +
    + +
    + + + +
    +
    + +

    + + + +

    + +
    + + + +
    + +

    + + + +
    + +
    + +
    + +
    + +
    + + + +
    +
    + +

    + historias, iсторії, iστορίες”', 'Placeholder heading in four languages.', 'twentytwentyfive' ) + ); + ?> +

    + + + +

    + +
    + + + +
    + +

    + + + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + diff --git a/content/themes/twentytwentyfive/patterns/cta-grid-products-link.php b/content/themes/twentytwentyfive/patterns/cta-grid-products-link.php new file mode 100644 index 0000000..87851b4 --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/cta-grid-products-link.php @@ -0,0 +1,141 @@ + + +
    + +
    + +

    + + + +
    + +
    <?php esc_attr_e( 'Black and white flower', 'twentytwentyfive' ); ?>
    + + + + + + + +
    <?php esc_attr_e( 'Closeup of plantlife in the Malibu Canyon area', 'twentytwentyfive' ); ?>
    + + + +
    + + + +
    + + + + + + + +
    <?php esc_attr_e( 'Flora of Akaka Falls State Park', 'twentytwentyfive' ); ?>
    + + + + + + + + + + + +
    + + + +
    + + + + + + + +
    + + + +
    + + + +
    <?php esc_attr_e( 'Botany flowers', 'twentytwentyfive' ); ?>
    + + + +
    + + + +
    + + + +
    <?php esc_attr_e( 'Black and white flower', 'twentytwentyfive' ); ?>
    + +
    + + + +
    + +
    + +
    + +
    + +
    + diff --git a/content/themes/twentytwentyfive/patterns/cta-heading-search.php b/content/themes/twentytwentyfive/patterns/cta-heading-search.php new file mode 100644 index 0000000..00dffc2 --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/cta-heading-search.php @@ -0,0 +1,25 @@ + + +
    +
    + +

    + + + +
    + +
    + diff --git a/content/themes/twentytwentyfive/patterns/cta-newsletter.php b/content/themes/twentytwentyfive/patterns/cta-newsletter.php new file mode 100644 index 0000000..679e1e0 --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/cta-newsletter.php @@ -0,0 +1,38 @@ + + + + diff --git a/content/themes/twentytwentyfive/patterns/event-3-col.php b/content/themes/twentytwentyfive/patterns/event-3-col.php new file mode 100644 index 0000000..08a7d7a --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/event-3-col.php @@ -0,0 +1,105 @@ + + +
    + +
    + +

    + + + +

    + +
    + + + +
    + +
    + +
    <?php esc_attr_e( 'Event image', 'twentytwentyfive' ); ?>
    + + + +
    + +

    + + + + + +
    + + + +

    + +
    + + + +
    + +
    <?php esc_attr_e( 'Event image', 'twentytwentyfive' ); ?>
    + + + +
    + +

    + + + + + +
    + + + +

    + +
    + + + +
    + +
    <?php esc_attr_e( 'Event image', 'twentytwentyfive' ); ?>
    + + + +
    + +

    + + + + + +
    + + + +

    + +
    + +
    + +
    + diff --git a/content/themes/twentytwentyfive/patterns/event-rsvp.php b/content/themes/twentytwentyfive/patterns/event-rsvp.php new file mode 100644 index 0000000..1ba58e5 --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/event-rsvp.php @@ -0,0 +1,103 @@ + + +
    + +
    + +
    + +
    + +

    + historias, iсторії, iστορίες”', 'Placeholder heading in four languages.', 'twentytwentyfive' ) + ); + ?> +

    + + + +

    + + + + + +
    + +
    + + + +
    + + + +
    + +
    + +

    + +
    + +
    + +
    + + + +
    + +
    + +
    + +

    + + + + + + + +

    + +
    + +
    + + + +
    + +
    <?php esc_attr_e( 'Close up photo of white flowers on a grey background', 'twentytwentyfive' ); ?> +
    + + + +
    + +
    + +
    + +
    + diff --git a/content/themes/twentytwentyfive/patterns/event-schedule.php b/content/themes/twentytwentyfive/patterns/event-schedule.php new file mode 100644 index 0000000..ba5156d --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/event-schedule.php @@ -0,0 +1,199 @@ + + +
    + +
    + +

    + + +

    + + + + + +
    + +
    + +
    + +

    + +
    + + +
    + +
    + +
    + +
    <?php esc_attr_e( 'Birds on a lake.', 'twentytwentyfive' ); ?>
    + +
    + + +
    + +
    + +
    + +

    + + +

    + +
    + + +

    Prof. Fiona Presley', 'Pattern placeholder text with link.', 'twentytwentyfive' ) ); ?>

    + +
    + +
    + +
    + + +
    + +
    + +
    <?php esc_attr_e( 'View of the deep ocean.', 'twentytwentyfive' ); ?>
    + +
    + + +
    + +
    + +
    + +

    + + +

    + +
    + + +

    Prof. Fiona Presley', 'Pattern placeholder text with link.', 'twentytwentyfive' ) ); ?>

    + +
    + +
    + +
    + +
    + +
    + +
    + + + + + +
    + +
    + +
    + +

    + +
    + + +
    + +
    + +
    + +
    <?php esc_attr_e( 'The Acropolis of Athens.', 'twentytwentyfive' ); ?>
    + +
    + + +
    +
    + +
    + +

    + + +

    + +
    + + +

    Prof. Fiona Presley', 'Pattern placeholder text with link.', 'twentytwentyfive' ) ); ?>

    + +
    + +
    + +
    + + +
    + +
    + +
    <?php esc_attr_e( 'Black and white photo of an African woman.', 'twentytwentyfive' ); ?>
    + +
    + + +
    + +
    + +
    + +

    + + +

    + +
    + + +

    Prof. Fiona Presley', 'Pattern placeholder text with link.', 'twentytwentyfive' ) ); ?>

    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + +
    + diff --git a/content/themes/twentytwentyfive/patterns/footer-centered.php b/content/themes/twentytwentyfive/patterns/footer-centered.php new file mode 100644 index 0000000..be82e0f --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/footer-centered.php @@ -0,0 +1,40 @@ + + +
    + +
    + + +
    + + + + + + + +

    + WordPress' + ); + ?> +

    + +
    + diff --git a/content/themes/twentytwentyfive/patterns/footer-columns.php b/content/themes/twentytwentyfive/patterns/footer-columns.php new file mode 100644 index 0000000..6b12c32 --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/footer-columns.php @@ -0,0 +1,84 @@ + + +
    + +
    + +
    + +
    + + +
    + + + +
    + +
    + +

    + + + + + + + +
    + + +
    + +

    + + + + + + + +
    + +
    + +
    + + + + + +
    + +

    + + +

    + WordPress' + ); + ?> +

    + +
    + +
    + +
    + diff --git a/content/themes/twentytwentyfive/patterns/footer-newsletter.php b/content/themes/twentytwentyfive/patterns/footer-newsletter.php new file mode 100644 index 0000000..1c88efc --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/footer-newsletter.php @@ -0,0 +1,60 @@ + + +
    + +
    + +

    + + + +

    + + + +
    + +
    + +
    + + + + + + + +
    + +

    + + +

    + WordPress' + ); + ?> +

    + +
    + +
    + +
    + diff --git a/content/themes/twentytwentyfive/patterns/footer-social.php b/content/themes/twentytwentyfive/patterns/footer-social.php new file mode 100644 index 0000000..006cb83 --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/footer-social.php @@ -0,0 +1,42 @@ + + +
    + +
    + + + + + + +
    + + + + + +

    + WordPress' + ); + ?> +

    + +
    + diff --git a/content/themes/twentytwentyfive/patterns/footer.php b/content/themes/twentytwentyfive/patterns/footer.php new file mode 100644 index 0000000..4dec2cc --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/footer.php @@ -0,0 +1,93 @@ + + +
    + +
    + + + +
    + +
    + +
    + + +
    + + + +
    + + + +
    + +
    + + + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + + + + + + + +
    + +

    + + +

    + WordPress' + ); + ?> +

    + +
    + +
    + +
    + diff --git a/content/themes/twentytwentyfive/patterns/format-audio.php b/content/themes/twentytwentyfive/patterns/format-audio.php new file mode 100644 index 0000000..852f1d4 --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/format-audio.php @@ -0,0 +1,38 @@ + + +
    + +
    + +
    +
    <?php esc_attr_e( 'Event image', 'twentytwentyfive' ); ?>
    +
    + + + +
    +

    + + + +

    + + + +
    +
    +
    +
    + diff --git a/content/themes/twentytwentyfive/patterns/format-link.php b/content/themes/twentytwentyfive/patterns/format-link.php new file mode 100644 index 0000000..2605a89 --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/format-link.php @@ -0,0 +1,28 @@ + + +
    + +

    + + + +
    + +

    + +
    + +
    + diff --git a/content/themes/twentytwentyfive/patterns/grid-videos.php b/content/themes/twentytwentyfive/patterns/grid-videos.php new file mode 100644 index 0000000..56f54c2 --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/grid-videos.php @@ -0,0 +1,56 @@ + + +
    + +
    + +

    + + + +

    + +
    + + + +
    + +
    + + + +
    + + + +
    + + + +
    + + + +
    + + + +
    + +
    + +
    + diff --git a/content/themes/twentytwentyfive/patterns/grid-with-categories.php b/content/themes/twentytwentyfive/patterns/grid-with-categories.php new file mode 100644 index 0000000..f0762aa --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/grid-with-categories.php @@ -0,0 +1,71 @@ + + +
    + +
    + +
    + +

    + +
    + + +
    + +
    <?php esc_attr_e( 'Close up of a red anthurium.', 'twentytwentyfive' ); ?>
    + + + +
    + + +

    + +
    + + +
    + +
    + + + +
    + + +

    + +
    + + +
    + +
    + + + +
    + + +

    + +
    + +
    + +
    + diff --git a/content/themes/twentytwentyfive/patterns/header-centered.php b/content/themes/twentytwentyfive/patterns/header-centered.php new file mode 100644 index 0000000..4468001 --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/header-centered.php @@ -0,0 +1,28 @@ + + +
    + +
    + + +
    + +
    + +
    + +
    + diff --git a/content/themes/twentytwentyfive/patterns/header-columns.php b/content/themes/twentytwentyfive/patterns/header-columns.php new file mode 100644 index 0000000..7cb8eab --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/header-columns.php @@ -0,0 +1,34 @@ + + +
    + +
    + +
    + + +
    + + +
    + +
    + + +
    + +
    + diff --git a/content/themes/twentytwentyfive/patterns/header-large-title.php b/content/themes/twentytwentyfive/patterns/header-large-title.php new file mode 100644 index 0000000..8a4cd38 --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/header-large-title.php @@ -0,0 +1,28 @@ + + +
    + +
    + + +
    + +
    + +
    + +
    + diff --git a/content/themes/twentytwentyfive/patterns/header.php b/content/themes/twentytwentyfive/patterns/header.php new file mode 100644 index 0000000..8cccb6c --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/header.php @@ -0,0 +1,32 @@ + + +
    + +
    + +
    + + +
    + +
    + +
    + +
    + +
    + diff --git a/content/themes/twentytwentyfive/patterns/heading-and-paragraph-with-image.php b/content/themes/twentytwentyfive/patterns/heading-and-paragraph-with-image.php new file mode 100644 index 0000000..6ece41c --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/heading-and-paragraph-with-image.php @@ -0,0 +1,44 @@ + + + +
    + +
    + +
    + +

    + +

    + + +

    + +
    + + + +
    + +
    + <?php echo esc_attr_x( 'Cliff Palace, Colorado', 'Alt text for Overview picture.', 'twentytwentyfive' ); ?> +
    + +
    + +
    + +
    + diff --git a/content/themes/twentytwentyfive/patterns/hero-book.php b/content/themes/twentytwentyfive/patterns/hero-book.php new file mode 100644 index 0000000..31d3465 --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/hero-book.php @@ -0,0 +1,50 @@ + + +
    + +
    + +
    + +
    + + <?php esc_attr_e( 'Image of the book', 'twentytwentyfive' ); ?> +
    + + + +
    +
    + +
    + + + +
    + +

    + + + +

    + + + +

    +
    +
    +
    + diff --git a/content/themes/twentytwentyfive/patterns/hero-full-width-image.php b/content/themes/twentytwentyfive/patterns/hero-full-width-image.php new file mode 100644 index 0000000..9507971 --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/hero-full-width-image.php @@ -0,0 +1,41 @@ + + + +
    + + <?php echo esc_attr_x( 'Picture of a flower', 'Alt text for cover image.', 'twentytwentyfive' ); ?> +
    + +
    + +

    + + + +

    + + + +
    + +
    + +
    + +
    + +
    +
    + diff --git a/content/themes/twentytwentyfive/patterns/hero-overlapped-book-cover-with-links.php b/content/themes/twentytwentyfive/patterns/hero-overlapped-book-cover-with-links.php new file mode 100644 index 0000000..677e992 --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/hero-overlapped-book-cover-with-links.php @@ -0,0 +1,123 @@ + + +
    + +
    + +
    + +
    + +
    + +
    + +

    + +

    + + + +

    + +

    + +
    + + + +
    + + + + + +
    + +
    + +
    + +
    + + + +
    + + +
    + + + +
    + +
    + +
    + + +
    + +
    + +
    + + + +
    + + +
    + + + +
    + +
    + +
    + +
    + + + + + + + +

    international editions.', 'Pattern placeholder text with link.', 'twentytwentyfive' ) ); ?>

    + +
    + +
    + +
    + + + +
    + +
    + <?php echo esc_attr__( 'Book Image', 'twentytwentyfive' ); ?> +
    + +
    + +
    + +
    + +
    + diff --git a/content/themes/twentytwentyfive/patterns/hero-podcast.php b/content/themes/twentytwentyfive/patterns/hero-podcast.php new file mode 100644 index 0000000..43610a4 --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/hero-podcast.php @@ -0,0 +1,78 @@ + + +
    + +
    + +
    + +
    + <?php echo esc_attr_x( 'Picture of a person', 'Alt text for hero image.', 'twentytwentyfive' ); ?> +
    + +
    + + + + +
    + +

    + + + +

    + + + +
    + + +

    + + + +
    + +

    + + + +

    + + + +

    + + + +

    + + + +

    + +
    + + +
    + + +
    + +
    + +
    + diff --git a/content/themes/twentytwentyfive/patterns/hidden-404.php b/content/themes/twentytwentyfive/patterns/hidden-404.php new file mode 100644 index 0000000..b548067 --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/hidden-404.php @@ -0,0 +1,46 @@ + + +
    + +
    + +
    + +
    + <?php echo esc_attr_x( 'Small totara tree on ridge above Long Point', 'image description', 'twentytwentyfive' ); ?> +
    + +
    + + +
    + +
    + +

    + +

    + + +

    + + +
    + +
    + +
    + +
    + diff --git a/content/themes/twentytwentyfive/patterns/hidden-blog-heading.php b/content/themes/twentytwentyfive/patterns/hidden-blog-heading.php new file mode 100644 index 0000000..a632a2b --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/hidden-blog-heading.php @@ -0,0 +1,16 @@ + + +

    + diff --git a/content/themes/twentytwentyfive/patterns/hidden-search.php b/content/themes/twentytwentyfive/patterns/hidden-search.php new file mode 100644 index 0000000..d4a7090 --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/hidden-search.php @@ -0,0 +1,14 @@ + + + diff --git a/content/themes/twentytwentyfive/patterns/hidden-sidebar.php b/content/themes/twentytwentyfive/patterns/hidden-sidebar.php new file mode 100644 index 0000000..1b6dccb --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/hidden-sidebar.php @@ -0,0 +1,42 @@ + + +

    + + + + + + + +
    + + +
    + + +
    + + + + + + + + + +

    + + +
    + diff --git a/content/themes/twentytwentyfive/patterns/hidden-written-by.php b/content/themes/twentytwentyfive/patterns/hidden-written-by.php new file mode 100644 index 0000000..a8ffce6 --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/hidden-written-by.php @@ -0,0 +1,24 @@ + + + + diff --git a/content/themes/twentytwentyfive/patterns/logos.php b/content/themes/twentytwentyfive/patterns/logos.php new file mode 100644 index 0000000..7d16329 --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/logos.php @@ -0,0 +1,48 @@ + + +
    + +

    + + + + + + + +
    + +
    + + + +
    + + + +
    + + + +
    + + + +
    + +
    + +
    + diff --git a/content/themes/twentytwentyfive/patterns/media-instagram-grid.php b/content/themes/twentytwentyfive/patterns/media-instagram-grid.php new file mode 100644 index 0000000..f064293 --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/media-instagram-grid.php @@ -0,0 +1,65 @@ + + +
    + +
    + +
    + +
    + +

    + + + +

    + +
    + +
    + + + +
    <?php esc_attr_e( 'Photo of a field full of flowers, a blue sky and a tree.', 'twentytwentyfive' ); ?>
    + + + +
    <?php esc_attr_e( 'Profile portrait of a native person.', 'twentytwentyfive' ); ?>
    + + + +
    <?php esc_attr_e( 'View of the deep ocean.', 'twentytwentyfive' ); ?>
    + + + +
    <?php esc_attr_e( 'Portrait of an African Woman dressed in traditional costume, wearing decorative jewelry.', 'twentytwentyfive' ); ?>
    + + + +
    <?php esc_attr_e( 'The Acropolis of Athens.', 'twentytwentyfive' ); ?>
    + + + +
    <?php esc_attr_e( 'Close up of two flowers on a dark background.', 'twentytwentyfive' ); ?>
    + + + +
    <?php esc_attr_e( 'Birds on a lake.', 'twentytwentyfive' ); ?>
    + +
    + +
    + diff --git a/content/themes/twentytwentyfive/patterns/more-posts.php b/content/themes/twentytwentyfive/patterns/more-posts.php new file mode 100644 index 0000000..6dd8f82 --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/more-posts.php @@ -0,0 +1,34 @@ + + +
    + +

    + + + +
    + + +
    + + +
    + + +
    + +
    + diff --git a/content/themes/twentytwentyfive/patterns/overlapped-images.php b/content/themes/twentytwentyfive/patterns/overlapped-images.php new file mode 100644 index 0000000..f7e8215 --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/overlapped-images.php @@ -0,0 +1,58 @@ + + +
    + +
    + +
    + +
    <?php esc_attr_e( 'Photography close up of a red flower.', 'twentytwentyfive' ); ?>
    + + +
    + +
    <?php esc_attr_e( 'Black and white photography close up of a flower.', 'twentytwentyfive' ); ?>
    + +
    + +
    + + +
    + +
    + +

    + +
    + + + +

    + ' . esc_html_x( 'Fleurs', 'Example brand name.', 'twentytwentyfive' ) . '' + ); + ?> +

    + +
    + +
    + +
    + diff --git a/content/themes/twentytwentyfive/patterns/page-business-home.php b/content/themes/twentytwentyfive/patterns/page-business-home.php new file mode 100644 index 0000000..e94cf50 --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/page-business-home.php @@ -0,0 +1,24 @@ + + + + + + + + diff --git a/content/themes/twentytwentyfive/patterns/page-coming-soon.php b/content/themes/twentytwentyfive/patterns/page-coming-soon.php new file mode 100644 index 0000000..baab759 --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/page-coming-soon.php @@ -0,0 +1,45 @@ + + + + diff --git a/content/themes/twentytwentyfive/patterns/page-cv-bio.php b/content/themes/twentytwentyfive/patterns/page-cv-bio.php new file mode 100644 index 0000000..13dc4f3 --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/page-cv-bio.php @@ -0,0 +1,57 @@ + + + + diff --git a/content/themes/twentytwentyfive/patterns/page-landing-book.php b/content/themes/twentytwentyfive/patterns/page-landing-book.php new file mode 100644 index 0000000..3874c78 --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/page-landing-book.php @@ -0,0 +1,24 @@ + + + + + + + + diff --git a/content/themes/twentytwentyfive/patterns/page-landing-event.php b/content/themes/twentytwentyfive/patterns/page-landing-event.php new file mode 100644 index 0000000..9915e20 --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/page-landing-event.php @@ -0,0 +1,23 @@ + + + + + + + diff --git a/content/themes/twentytwentyfive/patterns/page-landing-podcast.php b/content/themes/twentytwentyfive/patterns/page-landing-podcast.php new file mode 100644 index 0000000..48ac731 --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/page-landing-podcast.php @@ -0,0 +1,23 @@ + + + + + + + diff --git a/content/themes/twentytwentyfive/patterns/page-link-in-bio-heading-paragraph-links-image.php b/content/themes/twentytwentyfive/patterns/page-link-in-bio-heading-paragraph-links-image.php new file mode 100644 index 0000000..7d5e1ef --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/page-link-in-bio-heading-paragraph-links-image.php @@ -0,0 +1,68 @@ + + +
    + +
    + +
    + +
    + +

    + + + +

    + + + +
    + +

    + + + +

    + + + +

    + +
    + +
    + +
    + + + +
    + +
    + <?php esc_attr_e( 'Photo of a woman worker.', 'twentytwentyfive' ); ?>
    + + + +
    + +
    + +
    + +
    + diff --git a/content/themes/twentytwentyfive/patterns/page-link-in-bio-wide-margins.php b/content/themes/twentytwentyfive/patterns/page-link-in-bio-wide-margins.php new file mode 100644 index 0000000..3f095cc --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/page-link-in-bio-wide-margins.php @@ -0,0 +1,57 @@ + + +
    + +
    + +
    + +
    <?php esc_attr_e( 'Woman on beach, splashing water.', 'twentytwentyfive' ); ?>
    + +
    + + + +
    + +
    + +

    + + + +

    + + + + + +
    + +
    + +
    + +
    + diff --git a/content/themes/twentytwentyfive/patterns/page-link-in-bio-with-tight-margins.php b/content/themes/twentytwentyfive/patterns/page-link-in-bio-with-tight-margins.php new file mode 100644 index 0000000..264ce63 --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/page-link-in-bio-with-tight-margins.php @@ -0,0 +1,67 @@ + + +
    + +
    + +
    + +
    + + <?php esc_attr_e( 'Black and white photo focusing on a woman and a child from afar.', 'twentytwentyfive' ); ?>
    + + + + +
    + +
    + + + +
    + +
    + +

    + + + +
    + +

    + + + +

    + + + +

    + +
    + +
    + +
    + +
    + +
    + diff --git a/content/themes/twentytwentyfive/patterns/page-portfolio-home.php b/content/themes/twentytwentyfive/patterns/page-portfolio-home.php new file mode 100644 index 0000000..7a2a5b3 --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/page-portfolio-home.php @@ -0,0 +1,236 @@ + + +
    + +
    + +
    + +
    + +

    + +
    + + + +
    + + + +
    + +
    + +
    + +
    + + + +
    + +
    + +
    + +
    + + +
    + + + +
    + + + + +

    + + +
    + +
    + + +
    + +
    + + +
    + + + +
    + + + + +

    + + +
    + +
    + +
    + + + + + +
    + + + +
    + + + + +
    + + +
    + + + +
    + + + + +

    + + +
    + + + + +
    + + + +
    + + + + +
    + +
    + +
    + + +
    + + + +
    + + + + +

    + + +
    + +
    + + +
    + +
    + + +
    + + + +
    + + + + +

    + + +
    + +
    + +
    + + + + + + + +
    + + +
    + + + +
    + + + + +

    + + +
    + + + +
    + + + + + +
    + + + +
    + +
    + +
    + +

    + + +


    + +
    + +
    + +
    + diff --git a/content/themes/twentytwentyfive/patterns/page-shop-home.php b/content/themes/twentytwentyfive/patterns/page-shop-home.php new file mode 100644 index 0000000..ce87caf --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/page-shop-home.php @@ -0,0 +1,21 @@ + + + + + diff --git a/content/themes/twentytwentyfive/patterns/post-navigation.php b/content/themes/twentytwentyfive/patterns/post-navigation.php new file mode 100644 index 0000000..22852b2 --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/post-navigation.php @@ -0,0 +1,24 @@ + + +
    + + + +
    + diff --git a/content/themes/twentytwentyfive/patterns/pricing-2-col.php b/content/themes/twentytwentyfive/patterns/pricing-2-col.php new file mode 100644 index 0000000..c1ac80b --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/pricing-2-col.php @@ -0,0 +1,121 @@ + + +
    + +

    + + + +

    + + + + + + + +
    + +
    + +

    + + + +

    + + + +
      + +
    • + + + +
    • + + + +
    • + + + +
    • + + + +
    • + +
    + + + +
    + +
    + +
    + +
    + + + +
    + +

    + + + +

    + + + +
      + +
    • + + + +
    • + + + +
    • + + + +
    • + + + +
    • + +
    + + + +
    + +
    + +
    + +
    + +
    + +
    + diff --git a/content/themes/twentytwentyfive/patterns/pricing-3-col.php b/content/themes/twentytwentyfive/patterns/pricing-3-col.php new file mode 100644 index 0000000..ff66c8b --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/pricing-3-col.php @@ -0,0 +1,148 @@ + + +
    + +
    + +

    + + + +

    + +
    + + + +
    + +
    + +
    + +
    + +

    + + + +

    + +
    + + + +
    + +

    + +
    + +
    + + + +
    + +
    + +
    + +
    + + + +
    + +
    + +
    + +

    + + + +

    + +
    + + + +
    + +

    + + + +

    + +
    + +
    + + + +
    + +
    + +
    + +
    + + + +
    + +
    + +
    + +

    + + + +

    + +
    + + + +
    + +

    + + + +

    + +
    + +
    + + + +
    + +
    + +
    + +
    + +
    + +
    + diff --git a/content/themes/twentytwentyfive/patterns/services-3-col.php b/content/themes/twentytwentyfive/patterns/services-3-col.php new file mode 100644 index 0000000..44a4bc0 --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/services-3-col.php @@ -0,0 +1,79 @@ + + +
    + +

    + + + +
    + +
    + + +
    + <?php esc_attr_e( 'Image for service', 'twentytwentyfive' ); ?> +
    + + + +

    + + + +

    + +
    + + + +
    + +
    + <?php esc_attr_e( 'Image for service', 'twentytwentyfive' ); ?> +
    + + + +

    + + + +

    + +
    + + + +
    + +
    + <?php esc_attr_e( 'Image for service', 'twentytwentyfive' ); ?> +
    + + + +

    + + + +

    + +
    + +
    + +
    + diff --git a/content/themes/twentytwentyfive/patterns/services-subscriber-only-section.php b/content/themes/twentytwentyfive/patterns/services-subscriber-only-section.php new file mode 100644 index 0000000..713103c --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/services-subscriber-only-section.php @@ -0,0 +1,76 @@ + + +
    + +
    + +
    + +

    + + + +
      + +
    • + + + +
    • + + + +
    • + + + +
    • + + + +
    • + +
    + + + +
    + +
    + + + +
    + +
    + + + +

    + +
    + + + +
    + +
    <?php esc_attr_e( 'Smartphones capturing a scenic wildflower meadow with trees', 'twentytwentyfive' ); ?>
    + +
    + +
    + +
    + diff --git a/content/themes/twentytwentyfive/patterns/services-team-photos.php b/content/themes/twentytwentyfive/patterns/services-team-photos.php new file mode 100644 index 0000000..865438c --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/services-team-photos.php @@ -0,0 +1,60 @@ + + +
    + +
    + +
    + +

    + +
    + + + +
    + +
    + +
    + <?php esc_attr_e( 'Woman on beach, splashing water.', 'twentytwentyfive' ); ?> +
    + + + +
    + <?php esc_attr_e( 'Portrait of a nurse', 'twentytwentyfive' ); ?> +
    + + + +
    + <?php esc_attr_e( 'Picture of a person typing on a typewriter.', 'twentytwentyfive' ); ?> +
    + + + +
    + <?php esc_attr_e( 'Man in hat, standing in front of a building.', 'twentytwentyfive' ); ?> +
    + +
    + +
    + +
    + +
    + diff --git a/content/themes/twentytwentyfive/patterns/template-404-vertical-header-blog.php b/content/themes/twentytwentyfive/patterns/template-404-vertical-header-blog.php new file mode 100644 index 0000000..5506cb4 --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/template-404-vertical-header-blog.php @@ -0,0 +1,41 @@ + + +
    + +
    + +
    + + +
    + +
    + + + + + + + + + +
    + +
    + +
    + + + diff --git a/content/themes/twentytwentyfive/patterns/template-archive-news-blog.php b/content/themes/twentytwentyfive/patterns/template-archive-news-blog.php new file mode 100644 index 0000000..8ad1942 --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/template-archive-news-blog.php @@ -0,0 +1,39 @@ + + + + +
    + +
    + + + + + + + + +
    + + +
    + +
    + +
    + + + diff --git a/content/themes/twentytwentyfive/patterns/template-archive-photo-blog.php b/content/themes/twentytwentyfive/patterns/template-archive-photo-blog.php new file mode 100644 index 0000000..e94b245 --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/template-archive-photo-blog.php @@ -0,0 +1,26 @@ + + + + + +
    + + + +
    + + + diff --git a/content/themes/twentytwentyfive/patterns/template-archive-text-blog.php b/content/themes/twentytwentyfive/patterns/template-archive-text-blog.php new file mode 100644 index 0000000..7efe1b4 --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/template-archive-text-blog.php @@ -0,0 +1,28 @@ + + + + +
    + + + + + + +
    + + + diff --git a/content/themes/twentytwentyfive/patterns/template-archive-vertical-header-blog.php b/content/themes/twentytwentyfive/patterns/template-archive-vertical-header-blog.php new file mode 100644 index 0000000..9a25fe3 --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/template-archive-vertical-header-blog.php @@ -0,0 +1,48 @@ + + +
    + +
    + +
    + + + +
    + +
    + + + + + + + + + + + + + + +
    + +
    + +
    + + + diff --git a/content/themes/twentytwentyfive/patterns/template-home-news-blog.php b/content/themes/twentytwentyfive/patterns/template-home-news-blog.php new file mode 100644 index 0000000..7dea528 --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/template-home-news-blog.php @@ -0,0 +1,166 @@ + + + + +
    + +
    + +
    + +
    + +
    + +
    + + +
    + + + +
    + + + + +

    + + +
    + + +
    + + +
    + + + +
    + + +
    + +
    + +
    + + +
    + +
    + + +
    + + + + +
    + + +
    + +
    + + +
    + +
    + +
    + + +
    + + + +
    + + +
    + + +
    + + +
    + + + +
    + + +
    + +
    + +
    + +
    + +
    + + + +
    + +
    + + +
    + + + +
    + + +
    + +
    + + + +
    + +
    + + +
    + + + +
    + + + +
    + + + + + +
    + +
    + +
    + +
    + + + diff --git a/content/themes/twentytwentyfive/patterns/template-home-photo-blog.php b/content/themes/twentytwentyfive/patterns/template-home-photo-blog.php new file mode 100644 index 0000000..29ed376 --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/template-home-photo-blog.php @@ -0,0 +1,33 @@ + + + + +
    + +
    + +

    + +
    + + +

    + + +
    + + + diff --git a/content/themes/twentytwentyfive/patterns/template-home-posts-grid-news-blog.php b/content/themes/twentytwentyfive/patterns/template-home-posts-grid-news-blog.php new file mode 100644 index 0000000..167f0a0 --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/template-home-posts-grid-news-blog.php @@ -0,0 +1,136 @@ + + + + +
    + + +
    + +
    + + + +
    + + + +
    + + + + +

    + + +
    + +
    + + + +
    + +
    + +
    + + +
    + + + +
    + + + + +

    + + +
    + + +
    + + +
    + + + +
    + + + + +

    + + +
    + +
    + +
    + + + +
    + +
    + + +
    + + + +
    + + + + +

    + + +
    + +
    + + + +
    + +

    + + +
    + + +
    + + +
    + + +
    + +
    + + +
    + + + + + diff --git a/content/themes/twentytwentyfive/patterns/template-home-text-blog.php b/content/themes/twentytwentyfive/patterns/template-home-text-blog.php new file mode 100644 index 0000000..81e482e --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/template-home-text-blog.php @@ -0,0 +1,29 @@ + + + + +
    + +

    + + + + + +
    + + + diff --git a/content/themes/twentytwentyfive/patterns/template-home-vertical-header-blog.php b/content/themes/twentytwentyfive/patterns/template-home-vertical-header-blog.php new file mode 100644 index 0000000..b44b5dd --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/template-home-vertical-header-blog.php @@ -0,0 +1,47 @@ + + +
    + +
    + +
    + + + +
    + +
    + + + + + + + + + + + + + +
    + +
    + +
    + + + diff --git a/content/themes/twentytwentyfive/patterns/template-home-with-sidebar-news-blog.php b/content/themes/twentytwentyfive/patterns/template-home-with-sidebar-news-blog.php new file mode 100644 index 0000000..ee67322 --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/template-home-with-sidebar-news-blog.php @@ -0,0 +1,127 @@ + + + + +
    + +
    + +
    + +
    + + + +
    + + + +
    + + +
    + +
    + + +
    + +

    + + + + + +
    + + +
    + + +
    + + + + + + + +

    + + +
    + +
    + +
    + + + + + +
    + + +
    + +
    + +
    + + +
    + + +

    + + +
    + +
    + +
    + + +
    + + +
    + +
    + +
    + + + +
    + + + + + +
    + + + +

    + + +
    + +
    + + + diff --git a/content/themes/twentytwentyfive/patterns/template-page-photo-blog.php b/content/themes/twentytwentyfive/patterns/template-page-photo-blog.php new file mode 100644 index 0000000..54ccb20 --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/template-page-photo-blog.php @@ -0,0 +1,28 @@ + + + + +
    + +
    + + + +
    + +
    + + + diff --git a/content/themes/twentytwentyfive/patterns/template-page-vertical-header-blog.php b/content/themes/twentytwentyfive/patterns/template-page-vertical-header-blog.php new file mode 100644 index 0000000..1c23770 --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/template-page-vertical-header-blog.php @@ -0,0 +1,63 @@ + + +
    + +
    + +
    + + +
    + +
    + + +
    + + + + +
    + +
    + + + + + + +
    + +
    + +
    + + +
    + +
    + +
    + +
    + +
    + +
    + +
    + + + diff --git a/content/themes/twentytwentyfive/patterns/template-query-loop-news-blog.php b/content/themes/twentytwentyfive/patterns/template-query-loop-news-blog.php new file mode 100644 index 0000000..c55b337 --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/template-query-loop-news-blog.php @@ -0,0 +1,62 @@ + + +
    + +
    +
    + + + +
    + + + + + + +
    + + + + +
    +
    + + + +
    +
    + + + + +
    + + + + + +
    + + + + +

    + + + + + +
    + diff --git a/content/themes/twentytwentyfive/patterns/template-query-loop-photo-blog.php b/content/themes/twentytwentyfive/patterns/template-query-loop-photo-blog.php new file mode 100644 index 0000000..c9f150c --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/template-query-loop-photo-blog.php @@ -0,0 +1,46 @@ + + +
    + +
    + + +

    + + +
    + + + +
    + + + +
    + + + +
    + + + + + +
    + +
    + diff --git a/content/themes/twentytwentyfive/patterns/template-query-loop-text-blog.php b/content/themes/twentytwentyfive/patterns/template-query-loop-text-blog.php new file mode 100644 index 0000000..e90e480 --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/template-query-loop-text-blog.php @@ -0,0 +1,47 @@ + + +
    + +
    + + +

    + + +
    + + + +
    + + +
    + + + + + + + + +
    + + + + + +
    + +
    + diff --git a/content/themes/twentytwentyfive/patterns/template-query-loop-vertical-header-blog.php b/content/themes/twentytwentyfive/patterns/template-query-loop-vertical-header-blog.php new file mode 100644 index 0000000..b572e93 --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/template-query-loop-vertical-header-blog.php @@ -0,0 +1,51 @@ + + +
    + + +
    + + +
    + + + + + +
    +
    + + + +
    +
    + + + + + + + + + + + + + + +

    + + +
    + diff --git a/content/themes/twentytwentyfive/patterns/template-query-loop.php b/content/themes/twentytwentyfive/patterns/template-query-loop.php new file mode 100644 index 0000000..82dc4de --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/template-query-loop.php @@ -0,0 +1,46 @@ + + +
    + + +
    + + + + +
    + + + +
    + + +

    + + +
    + + +
    + + + + + +
    + +
    + diff --git a/content/themes/twentytwentyfive/patterns/template-search-news-blog.php b/content/themes/twentytwentyfive/patterns/template-search-news-blog.php new file mode 100644 index 0000000..e4ff042 --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/template-search-news-blog.php @@ -0,0 +1,39 @@ + + + + +
    + +
    + + + + + + + + +
    + + +
    + +
    + +
    + + + diff --git a/content/themes/twentytwentyfive/patterns/template-search-photo-blog.php b/content/themes/twentytwentyfive/patterns/template-search-photo-blog.php new file mode 100644 index 0000000..c08992c --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/template-search-photo-blog.php @@ -0,0 +1,29 @@ + + + + +
    + + +
    + +
    + + +
    + + + diff --git a/content/themes/twentytwentyfive/patterns/template-search-text-blog.php b/content/themes/twentytwentyfive/patterns/template-search-text-blog.php new file mode 100644 index 0000000..124af4a --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/template-search-text-blog.php @@ -0,0 +1,32 @@ + + + + +
    + +
    + + +
    + + + + + +
    + + + diff --git a/content/themes/twentytwentyfive/patterns/template-search-vertical-header-blog.php b/content/themes/twentytwentyfive/patterns/template-search-vertical-header-blog.php new file mode 100644 index 0000000..3121358 --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/template-search-vertical-header-blog.php @@ -0,0 +1,45 @@ + + +
    + +
    + +
    + + +
    + +
    + + + + + + + + + + + + +
    + +
    + +
    + + + diff --git a/content/themes/twentytwentyfive/patterns/template-single-left-aligned-content.php b/content/themes/twentytwentyfive/patterns/template-single-left-aligned-content.php new file mode 100644 index 0000000..9f86084 --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/template-single-left-aligned-content.php @@ -0,0 +1,112 @@ + + + + +
    + +
    + +
    + +
    + +
    + + +
    + +

    + + +
    + +
    + +
    + + +
    + +
    + +
    + + + +
    + +
    + +
    + + +

    + + +
    + +
    + +
    + +
    + + + +
    + +
    + + + +
    + +
    + + + +
    + +
    + + + +
    + +
    + +
    + + + +
    + + +
    + +
    + +
    + +
    + +
    + + + diff --git a/content/themes/twentytwentyfive/patterns/template-single-news-blog.php b/content/themes/twentytwentyfive/patterns/template-single-news-blog.php new file mode 100644 index 0000000..86ebd9c --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/template-single-news-blog.php @@ -0,0 +1,141 @@ + + + + +
    + + +
    + +
    + + + + + + + + +
    + +
    + +
    + + +

    + + +
    + + +
    + + +
    + +
    + +
    + +
    + +
    + + + +
    + + + +
    + +
    + +
    + + +
    + + + + + +
    + + +
    + + +
    + + +
    + +
    + +
    + + + +
    + + + +
    + + + +
    + +
    + +
    + + + +
    + +
    + +
    + +
    + + + +
    + + + +
    + + + +
    + + +
    + +
    + +
    + + + diff --git a/content/themes/twentytwentyfive/patterns/template-single-offset.php b/content/themes/twentytwentyfive/patterns/template-single-offset.php new file mode 100644 index 0000000..bc71fa2 --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/template-single-offset.php @@ -0,0 +1,93 @@ + + + + +
    + +
    + +
    + + +
    + +
    + + + +
    + +
    + +
    + +
    + +
    +

    + +
    + +
    + + + +
    + +
    + +
    + +
    + +
    + + + +
    + + + +
    + + + +
    + +
    + +
    + + + +
    + + +
    + +
    + +
    + +
    + +
    + + + diff --git a/content/themes/twentytwentyfive/patterns/template-single-photo-blog.php b/content/themes/twentytwentyfive/patterns/template-single-photo-blog.php new file mode 100644 index 0000000..884259b --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/template-single-photo-blog.php @@ -0,0 +1,97 @@ + + + + +
    + +
    + +
    + +
    + +
    + + +
    + +
    + +
    + +
    +

    + +
    + + +
    +

    + +
    + +
    + + +
    + +
    + +

    + + +
    + + +
    + +

    + + +
    + +
    + +
    + +
    + +
    + + +
    + + + +
    + + +
    + + + + + +
    + +
    + +
    + + diff --git a/content/themes/twentytwentyfive/patterns/template-single-text-blog.php b/content/themes/twentytwentyfive/patterns/template-single-text-blog.php new file mode 100644 index 0000000..2b60f96 --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/template-single-text-blog.php @@ -0,0 +1,49 @@ + + + + +
    + +
    + + + + + + + + +
    + +
    + + + +
    + + + +
    + + +
    + +
    + + diff --git a/content/themes/twentytwentyfive/patterns/template-single-vertical-header-blog.php b/content/themes/twentytwentyfive/patterns/template-single-vertical-header-blog.php new file mode 100644 index 0000000..9d8c310 --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/template-single-vertical-header-blog.php @@ -0,0 +1,100 @@ + + +
    + +
    + +
    + + +
    + +
    + +
    + + + + +
    + + +
    + + + + + +
    + + + +
    + +
    + +
    + + +
    + + +
    + + + + + + + +
    + +
    + +
    + + +
    + +
    + +
    + + + + + +
    + + + + +
    + + + + +
    + +
    + + + diff --git a/content/themes/twentytwentyfive/patterns/testimonials-2-col.php b/content/themes/twentytwentyfive/patterns/testimonials-2-col.php new file mode 100644 index 0000000..7f33f2c --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/testimonials-2-col.php @@ -0,0 +1,79 @@ + + +
    + +
    + +
    + +
    + +
    + +
    <?php echo esc_attr_x( 'Picture of a person', 'Alt text for testimonial image.', 'twentytwentyfive' ); ?>
    + +
    + + + +
    + +
    + +

    + + Atlanta, GA', 'Sample testimonial citation.', 'twentytwentyfive' ) ); ?> +
    + +
    + +
    + +
    + + + +
    + +
    + +
    + +
    <?php echo esc_attr_x( 'Picture of a person', 'Alt text for testimonial image.', 'twentytwentyfive' ); ?>
    + +
    + + + +
    + +
    + +

    + + Springfield, IL', 'Sample testimonial citation.', 'twentytwentyfive' ) ); ?> +
    + +
    + +
    + +
    + +
    + +
    + diff --git a/content/themes/twentytwentyfive/patterns/testimonials-6-col.php b/content/themes/twentytwentyfive/patterns/testimonials-6-col.php new file mode 100644 index 0000000..e3bb055 --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/testimonials-6-col.php @@ -0,0 +1,127 @@ + + +
    + +

    + + + +
    + +
    + +
    + +
    + +

    + +
    + + Springfield, IL', 'Sample testimonial citation.', 'twentytwentyfive' ) ); ?> +
    + +
    + + + +
    + +
    + +
    + +

    + +
    + + Springfield, IL', 'Sample testimonial citation.', 'twentytwentyfive' ) ); ?> +
    + +
    + + + +
    + +
    + +
    + +

    + +
    + + Springfield, IL', 'Sample testimonial citation.', 'twentytwentyfive' ) ); ?> +
    + +
    + +
    + + + +
    + +
    + +
    + +
    + +

    + +
    + + Springfield, IL', 'Sample testimonial citation.', 'twentytwentyfive' ) ); ?> +
    + +
    + + + +
    +
    + +
    + +

    + +
    + Springfield, IL', 'Sample testimonial citation.', 'twentytwentyfive' ) ); ?> +
    + +
    + + + +
    +
    + +
    + +

    + +
    + Springfield, IL', 'Sample testimonial citation.', 'twentytwentyfive' ) ); ?> +
    + +
    + +
    + +
    + diff --git a/content/themes/twentytwentyfive/patterns/testimonials-large.php b/content/themes/twentytwentyfive/patterns/testimonials-large.php new file mode 100644 index 0000000..b9d727c --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/testimonials-large.php @@ -0,0 +1,54 @@ + + +
    + +
    + +
    + +
    + +

    + + + +
    + +
    + +

    + +
    + + Atlanta, GA', 'Sample testimonial citation.', 'twentytwentyfive' ) ); ?> +
    + +
    + +
    + + + +
    + +
    <?php echo esc_attr_x( 'Picture of a person typing on a typewriter.', 'Alt text for testimonial image.', 'twentytwentyfive' ); ?>
    + +
    + +
    + +
    + diff --git a/content/themes/twentytwentyfive/patterns/text-faqs.php b/content/themes/twentytwentyfive/patterns/text-faqs.php new file mode 100644 index 0000000..fd8397b --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/text-faqs.php @@ -0,0 +1,98 @@ + + +
    + +
    + +

    + + + +
    + +
    + +
    + +

    + + + +

    + +
    + +
    + + + +
    + +
    + +

    + + + +

    + +
    + +
    + +
    + + + +
    + +
    + +
    + +

    + + + +

    + +
    + +
    + + + +
    + +
    + +

    + + + +

    + +
    + +
    + +
    + +
    + +
    + diff --git a/content/themes/twentytwentyfive/patterns/vertical-header.php b/content/themes/twentytwentyfive/patterns/vertical-header.php new file mode 100644 index 0000000..52cbf9a --- /dev/null +++ b/content/themes/twentytwentyfive/patterns/vertical-header.php @@ -0,0 +1,29 @@ + + +
    + +
    + +
    + + +
    + +
    + +
    + diff --git a/content/themes/twentytwentyfive/readme.txt b/content/themes/twentytwentyfive/readme.txt new file mode 100644 index 0000000..7f2be9b --- /dev/null +++ b/content/themes/twentytwentyfive/readme.txt @@ -0,0 +1,267 @@ +=== Twenty Twenty-Five === +Contributors: wordpressdotorg +Requires at least: 6.7 +Tested up to: 6.8 +Requires PHP: 7.2 +Stable tag: 1.2 +License: GPLv2 or later +License URI: http://www.gnu.org/licenses/gpl-2.0.html + +== Description == + +Twenty Twenty-Five emphasizes simplicity and adaptability. It offers flexible design options, supported by a variety of patterns for different page types, such as services and landing pages, making it ideal for building personal blogs, professional portfolios, online magazines, or business websites. Its templates cater to various blog styles, from text-focused to image-heavy layouts. Additionally, it supports international typography and diverse color palettes, ensuring accessibility and customization for users worldwide. + + +== Changelog == + += 1.2 = +* Released: April 15, 2025 + +https://wordpress.org/documentation/article/twenty-twenty-five-changelog/#Version_1.2 + += 1.1 = +* Released: February 11, 2025 + +https://wordpress.org/documentation/article/twenty-twenty-five-changelog/#Version_1.1 + += 1.0 = +* Released: November 13, 2024 + +https://wordpress.org/documentation/article/twenty-twenty-five-changelog/#Version_1.0 + +== Copyright == + +Twenty Twenty-Five WordPress Theme, (C) 2024-2025 WordPress.org and contributors. +Twenty Twenty-Five is distributed under the terms of the GNU GPL. + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +This theme incorporates code from: + +Twenty Twenty-Four WordPress Theme, (C) 2023 WordPress.org +License: GPLv2 or later. License URI: http://www.gnu.org/licenses/gpl-2.0.html + + +This theme bundles the following third-party resources: + +=== Fonts === +.ttf files downloaded from fonts.google.com have been converted to .woff2 using +https://github.com/google/woff2 + + +Fira Code Font +Copyright (c) 2014, The Fira Code Project Authors +License: SIL Open Font License, 1.1, https://opensource.org/licenses/OFL-1.1 +Reference: https://github.com/tonsky/FiraCode +Source: https://fonts.google.com/specimen/Fira+Code + +Manrope Font +Copyright (c) 2018 The Manrope Project Authors +License: SIL Open Font License, 1.1, https://opensource.org/licenses/OFL-1.1 +Reference: https://github.com/sharanda/manrope +Source: https://fonts.google.com/specimen/Manrope + +Vollkorn Font +Copyright (c) 2005–2018, Friedrich Althausen +License: SIL Open Font License, 1.1, https://opensource.org/licenses/OFL-1.1 +Reference: https://github.com/FAlthausen/Vollkorn-Typeface +Source: https://fonts.google.com/specimen/Vollkorn + +Fira Sans Font +Digitized data copyright (c) 2012-2015, The Mozilla Foundation and Telefonica S.A. +License: SIL Open Font License, 1.1, https://opensource.org/licenses/OFL-1.1 +Reference: https://github.com/mozilla/Fira +Source: https://fonts.google.com/specimen/Fira+Sans + +Platypi Font +License: SIL Open Font License, 1.1, https://opensource.org/licenses/OFL-1.1 +Reference: https://github.com/d-sargent/platypi +Source: https://fonts.google.com/specimen/Platypi + +Ysabeau Office Font +License: SIL Open Font License, 1.1, https://opensource.org/licenses/OFL-1.1 +Reference: https://github.com/CatharsisFonts/Ysabeau +Source: https://fonts.google.com/specimen/Ysabeau+Office + +Literata Font +License: SIL Open Font License, 1.1, https://opensource.org/licenses/OFL-1.1 +Reference: https://github.com/googlefonts/literata +Source: https://fonts.google.com/specimen/Literata + +Roboto Slab Font +License: SIL Open Font License, 1.1, https://opensource.org/licenses/OFL-1.1 +Reference: hhttps://github.com/googlefonts/robotoslab +Source: https://fonts.google.com/specimen/Roboto+Slab + +Beiruti Font +License: SIL Open Font License, 1.1, https://opensource.org/licenses/OFL-1.1 +Reference: https://github.com/googlefonts/beiruti +Source: https://fonts.google.com/specimen/Beiruti + +=== Images === + +Northern Buttercups. +Free public domain CC0 image. +northern-buttercups-flowers.webp +https://www.rawpixel.com/image/8802603 + +License: CC0 https://creativecommons.org/publicdomain/zero/1.0/ +Small totara tree on ridge above Long Point, Porirua Harbour, by Leslie Adkin. +Free public domain CC0 image. +404-image.webp +https://www.rawpixel.com/image/13029755 + +Old gray paris map. +Free public domain CC0 image. +location.webp +https://www.rawpixel.com/image/6033837 + +Delphinium (Larkspur). +Free public domain CC0 image. +delphinium-flowers.webp +https://www.rawpixel.com/image/2224378 + +Campanula Alliariifolia (Cornish Bellflower). +Free public domain CC0 image. +campanula-alliariifolia-flower.webp +https://www.rawpixel.com/image/2222755 + +Centaurea Ruthenica(Star Thristle). +Free public domain CC0 image. +star-thristle-flower.webp +https://www.rawpixel.com/image/2211732 + +Botany flowers. +Free public domain CC0 image. +botany-flowers.webp +botany-flowers-closeup.webp +https://www.rawpixel.com/image/8812207 + +Person typing on a typewriter. +Free public domain CC0 image. +typewriter.webp +https://www.rawpixel.com/image/12240004/photo-image-face-person-technology + +Woman wearing a traditional nurse's cap, photographed from behind. +nurse.webp +Free public domain CC0 image. +https://www.rawpixel.com/image/8782633/photo-image-person-white + +Woman splashing water, at Lake George. +woman-splashing-water.webp +Free public domain CC0 image. +https://www.rawpixel.com/image/9758986/photo-image-people-art-vintage + +Man in hat, standing in front of a building. +man-in-hat.webp +Free public domain CC0 image. +https://www.slam.org/collection/objects/62642/ + +African Woman by Pascal Sébah and Jean Pascal Sébah +Free public domain CC0 image. +agenda-img-4.webp +https://www.rawpixel.com/image/14263497 + +Two Girls, Mill Workers by Lewis W Hine. +Free public domain CC0 image. +link-in-bio-background.webp +https://www.rawpixel.com/image/14265869 + +Cliff Palace, Mesa Verde National Park, Colorado (vertical orientation) +Free public domain CC0 image. +poster-image-background.webp +ruins-image.webp +https://www.rawpixel.com/image/8802835 + +Flower meadow in Llano, Texas. +Free public domain CC0 image. +coming-soon-bg-image.webp +flower-meadow-square.webp +services-subscriber-photo.webp +https://www.rawpixel.com/image/8800058 + +Hibiscus flower. +Free public domain CC0 image. +grid-flower-1.webp +red-hibiscus-closeup.webp +https://www.rawpixel.com/image/8799471 + +Phacelia tanacetifolia (Lacy Phacelia) enlarged 4 times from Urformen der Kunst (1928) by Karl Blossfeldt. +Free public domain CC0 image. +grid-flower-2.webp +https://www.rawpixel.com/image/2222743 + +At Hawaiian Greenhouse, Inc, near Pahoa, anthuriums grow under a sun screen. +Free public domain CC0 image. +category-anthuriums.webp +https://www.rawpixel.com/image/8799473 + +Sunflower +Free public domain CC0 image. +category-sunflowers.webp +https://www.rawpixel.com/image/8799614 + +Detail of cactus "Saguaros, Saguro National Monument," Arizona. Photographer: Adams, Ansel, 1902-1984 +Free public domain CC0 image. +category-cactus.webp +https://www.rawpixel.com/image/8799351 + +Vash Gon - Jicarilla by Edward S Curtis. +Free public domain CC0 image. +vash-gon-square.webp +https://www.rawpixel.com/image/14262822 + +One of the 40 Or More Species of Coral at John Pennekamp Coral Reef State Park, a Few Miles Off Key Largo. +Free public domain CC0 image. +coral-square.webp +https://www.rawpixel.com/image/8799931 + +Parthenon op de Akropolis in Athene (westzijde) (c. 1880 - c. 1890) by Rhomaides Frères. +Free public domain CC0 image. +parthenon-square.webp +https://www.rawpixel.com/image/13759051 + +Near East Dallas Creek, 05/1972. Photographer: Norton, Boyd. +Free public domain CC0 image. +dallas-creek-square.webp +https://www.rawpixel.com/image/8802688 + +Marshland birds at the Lake Havasu National Wildlife Refuge. +Free public domain CC0 image. +marshland-birds-square.webp +https://www.rawpixel.com/image/8799403 + +Photograph - New York [Portrait - Washington Square] by Paul Strand. +Free public domain CC0 image. +hero-podcast.webp +https://www.rawpixel.com/image/14264288 + +Evening Breeze by Asahachi Kono. +Free public domain CC0 image. +link-in-bio-image +https://www.rawpixel.com/image/14262995 + +Bust by Mathew brady. +Free public domain CC0 image. +book-image-landing.webp +book-image.webp +https://www.rawpixel.com/image/8799536 +Book template by Beatriz Fialho, public domain. + +Flora of Akaka Falls State Park. +Free public domain CC0 image. +akaka-falls-state-park-flora.webp +https://www.rawpixel.com/image/8802845 + +Closeup of plantlife in the Malibu Canyon area of the Santa Monica Mountains. +Free public domain CC0 image. +malibu-plantlife.webp +https://www.rawpixel.com/image/8799918 diff --git a/content/themes/twentytwentyfive/screenshot.png b/content/themes/twentytwentyfive/screenshot.png new file mode 100644 index 0000000..2dd45d3 Binary files /dev/null and b/content/themes/twentytwentyfive/screenshot.png differ diff --git a/content/themes/twentytwentyfive/style.css b/content/themes/twentytwentyfive/style.css new file mode 100644 index 0000000..dbec2fe --- /dev/null +++ b/content/themes/twentytwentyfive/style.css @@ -0,0 +1,61 @@ +/* +Theme Name: Twenty Twenty-Five +Theme URI: https://wordpress.org/themes/twentytwentyfive/ +Author: the WordPress team +Author URI: https://wordpress.org +Description: Twenty Twenty-Five emphasizes simplicity and adaptability. It offers flexible design options, supported by a variety of patterns for different page types, such as services and landing pages, making it ideal for building personal blogs, professional portfolios, online magazines, or business websites. Its templates cater to various blog styles, from text-focused to image-heavy layouts. Additionally, it supports international typography and diverse color palettes, ensuring accessibility and customization for users worldwide. +Requires at least: 6.7 +Tested up to: 6.8 +Requires PHP: 7.2 +Version: 1.2 +License: GNU General Public License v2 or later +License URI: http://www.gnu.org/licenses/gpl-2.0.html +Text Domain: twentytwentyfive +Tags: one-column, custom-colors, custom-menu, custom-logo, editor-style, featured-images, full-site-editing, block-patterns, rtl-language-support, sticky-post, threaded-comments, translation-ready, wide-blocks, block-styles, style-variations, accessibility-ready, blog, portfolio, news +*/ + +/* + * Link styles + * https://github.com/WordPress/gutenberg/issues/42319 + */ +a { + text-decoration-thickness: 1px !important; + text-underline-offset: .1em; +} + +/* Focus styles */ +:where(.wp-site-blocks *:focus) { + outline-width: 2px; + outline-style: solid; +} + +/* Increase the bottom margin on submenus, so that the outline is visible. */ +.wp-block-navigation .wp-block-navigation-submenu .wp-block-navigation-item:not(:last-child) { + margin-bottom: 3px; +} + +/* Increase the outline offset on the parent menu items, so that the outline does not touch the text. */ +.wp-block-navigation .wp-block-navigation-item .wp-block-navigation-item__content { + outline-offset: 4px; +} + +/* Remove outline offset from the submenus, otherwise the outline is visible outside the submenu container. */ +.wp-block-navigation .wp-block-navigation-item ul.wp-block-navigation__submenu-container .wp-block-navigation-item__content { + outline-offset: 0; +} + +/* + * Progressive enhancement to reduce widows and orphans + * https://github.com/WordPress/gutenberg/issues/55190 + */ +h1, h2, h3, h4, h5, h6, blockquote, caption, figcaption, p { + text-wrap: pretty; +} + +/* + * Change the position of the more block on the front, by making it a block level element. + * https://github.com/WordPress/gutenberg/issues/65934 +*/ +.more-link { + display: block; +} diff --git a/content/themes/twentytwentyfive/styles/01-evening.json b/content/themes/twentytwentyfive/styles/01-evening.json new file mode 100644 index 0000000..6b9a11a --- /dev/null +++ b/content/themes/twentytwentyfive/styles/01-evening.json @@ -0,0 +1,126 @@ +{ + "$schema": "https://schemas.wp.org/wp/6.7/theme.json", + "version": 3, + "title": "Evening", + "settings": { + "color": { + "palette": [ + { + "color": "#1B1B1B", + "name": "Base", + "slug": "base" + }, + { + "color": "#F0F0F0", + "name": "Contrast", + "slug": "contrast" + }, + { + "color": "#786D0A", + "name": "Accent 1", + "slug": "accent-1" + }, + { + "color": "#442369", + "name": "Accent 2", + "slug": "accent-2" + }, + { + "color": "#D1D0EA", + "name": "Accent 3", + "slug": "accent-3" + }, + { + "color": "#CBCBCB", + "name": "Accent 4", + "slug": "accent-4" + }, + { + "color": "#353535", + "name": "Accent 5", + "slug": "accent-5" + }, + { + "color": "#FFFFFF33", + "name": "Accent 6", + "slug": "accent-6" + } + ] + } + }, + "styles": { + "color": { + "text": "var:preset|color|accent-4" + }, + "blocks": { + "core/button": { + "variations": { + "outline": { + "spacing": { + "padding": { + "bottom": "0.6rem", + "left": "1.6rem", + "right": "1.6rem", + "top": "0.6rem" + } + } + } + } + } + }, + "elements": { + "button": { + "color": { + "background": "var:preset|color|contrast", + "text": "var:preset|color|base" + }, + ":hover": { + "color": { + "background": "color-mix(in srgb, var(--wp--preset--color--contrast) 85%, transparent)", + "text": "var:preset|color|base" + } + }, + "spacing": { + "padding": { + "bottom": "0.6rem", + "left": "1.6rem", + "right": "1.6rem", + "top": "0.6rem" + } + } + } + }, + "variations": { + "section-2": { + "elements": { + "button": { + "color": { + "background": "var:preset|color|base", + "text": "var:preset|color|contrast" + }, + ":hover": { + "color": { + "background": "color-mix(in srgb, var(--wp--preset--color--base) 85%, transparent)" + } + } + } + } + }, + "section-4": { + "elements": { + "button": { + "color": { + "background": "var:preset|color|accent-2", + "text": "var:preset|color|contrast" + }, + ":hover": { + "color": { + "background": "color-mix(in srgb, var(--wp--preset--color--accent-2) 85%, transparent)" + } + } + } + } + } + } + } +} diff --git a/content/themes/twentytwentyfive/styles/02-noon.json b/content/themes/twentytwentyfive/styles/02-noon.json new file mode 100644 index 0000000..32bed51 --- /dev/null +++ b/content/themes/twentytwentyfive/styles/02-noon.json @@ -0,0 +1,461 @@ +{ + "$schema": "https://schemas.wp.org/wp/6.7/theme.json", + "version": 3, + "title": "Noon", + "settings": { + "color": { + "palette": [ + { + "color": "#F8F7F5", + "name": "Base", + "slug": "base" + }, + { + "color": "#191919", + "name": "Contrast", + "slug": "contrast" + }, + { + "color": "#FFFFFF", + "name": "Accent 1", + "slug": "accent-1" + }, + { + "color": "#F5B684", + "name": "Accent 2", + "slug": "accent-2" + }, + { + "color": "#191919", + "name": "Accent 3", + "slug": "accent-3" + }, + { + "color": "#5F5F5F", + "name": "Accent 4", + "slug": "accent-4" + }, + { + "color": "#F1EEE9", + "name": "Accent 5", + "slug": "accent-5" + }, + { + "color": "#19191933", + "name": "Accent 6", + "slug": "accent-6" + } + ] + }, + "typography": { + "fontFamilies": [ + { + "name": "Beiruti", + "slug": "beiruti", + "fontFamily": "Beiruti, sans-serif", + "fontFace": [ + { + "fontFamily": "Beiruti", + "fontStyle": "normal", + "fontWeight": "200 900", + "src": [ + "file:./assets/fonts/beiruti/Beiruti-VariableFont_wght.woff2" + ] + } + ] + }, + { + "name": "Literata", + "slug": "literata", + "fontFamily": "Literata, serif", + "fontFace": [ + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-ExtraLight.woff2" + ], + "fontWeight": "200", + "fontStyle": "normal", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-ExtraLightItalic.woff2" + ], + "fontWeight": "200", + "fontStyle": "italic", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-Light.woff2" + ], + "fontWeight": "300", + "fontStyle": "normal", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-LightItalic.woff2" + ], + "fontWeight": "300", + "fontStyle": "italic", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-Regular.woff2" + ], + "fontWeight": "400", + "fontStyle": "normal", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-RegularItalic.woff2" + ], + "fontWeight": "400", + "fontStyle": "italic", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-Medium.woff2" + ], + "fontWeight": "500", + "fontStyle": "normal", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-MediumItalic.woff2" + ], + "fontWeight": "500", + "fontStyle": "italic", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-SemiBold.woff2" + ], + "fontWeight": "600", + "fontStyle": "normal", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-SemiBoldItalic.woff2" + ], + "fontWeight": "600", + "fontStyle": "italic", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-Bold.woff2" + ], + "fontWeight": "700", + "fontStyle": "normal", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-BoldItalic.woff2" + ], + "fontWeight": "700", + "fontStyle": "italic", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-ExtraBold.woff2" + ], + "fontWeight": "800", + "fontStyle": "normal", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-ExtraBoldItalic.woff2" + ], + "fontWeight": "800", + "fontStyle": "italic", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-Black.woff2" + ], + "fontWeight": "900", + "fontStyle": "normal", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-BlackItalic.woff2" + ], + "fontWeight": "900", + "fontStyle": "italic", + "fontFamily": "Literata" + } + ] + } + ], + "fontSizes": [ + { + "fluid": false, + "name": "Small", + "size": "0.9rem", + "slug": "small" + }, + { + "fluid": { + "max": "1.2rem", + "min": "1rem" + }, + "name": "Medium", + "size": "1rem", + "slug": "medium" + }, + { + "fluid": { + "max": "1.8rem", + "min": "1.6rem" + }, + "name": "Large", + "size": "1.6rem", + "slug": "large" + }, + { + "fluid": { + "max": "2.2rem", + "min": "1.8em" + }, + "name": "Extra Large", + "size": "1.8rem", + "slug": "x-large" + }, + { + "fluid": { + "max": "2.8rem", + "min": "2rem" + }, + "name": "Extra Extra Large", + "size": "2rem", + "slug": "xx-large" + } + ] + } + }, + "styles": { + "color": { + "text": "var:preset|color|accent-4" + }, + "typography": { + "fontFamily": "var:preset|font-family|literata", + "fontSize": "var:preset|font-size|medium", + "letterSpacing": "-0.01em", + "lineHeight": "1.6" + }, + "blocks": { + "core/button": { + "border": { + "color": "var:preset|color|contrast" + }, + "shadow": "var:preset|shadow|natural", + "spacing": { + "padding": { + "bottom": "0.6rem", + "left": "1.6rem", + "right": "1.6rem", + "top": "0.6rem" + } + }, + "typography": { + "fontFamily": "var:preset|font-family|beiruti" + }, + "variations": { + "outline": { + "shadow": "none", + "spacing": { + "padding": { + "bottom": "0.6rem", + "left": "1.6rem", + "right": "1.6rem", + "top": "0.6rem" + } + } + } + } + }, + "core/list": { + "typography": { + "lineHeight": "1.3" + } + }, + "core/loginout": { + "typography": { + "fontSize": "var:preset|font-size|medium" + } + }, + "core/post-terms": { + "typography": { + "fontWeight": "300" + } + }, + "core/post-title": { + "color": { + "text": "var:preset|color|accent-3" + }, + "elements": { + "link": { + "color": { + "text": "currentColor" + } + } + } + }, + "core/pullquote": { + "color": { + "text": "var:preset|color|accent-3" + }, + "elements": { + "link": { + "color": { + "text": "currentColor" + } + } + }, + "typography": { + "fontFamily": "var:preset|font-family|beiruti", + "fontWeight": "500", + "lineHeight": "1" + } + }, + "core/quote": { + "typography": { + "fontSize": "var:preset|font-size|medium" + } + }, + "core/query-pagination": { + "typography": { + "fontWeight": "300" + } + }, + "core/query-title": { + "color": { + "text": "var:preset|color|accent-3" + }, + "elements": { + "link": { + "color": { + "text": "currentColor" + } + } + } + }, + "core/site-tagline": { + "typography": { + "fontSize": "var:preset|font-size|small" + } + }, + "core/site-title": { + "typography": { + "fontFamily": "var:preset|font-family|beiruti", + "fontWeight": "600", + "letterSpacing": "2.4px", + "textTransform": "uppercase" + } + } + }, + "elements": { + "button": { + "color": { + "background": "var:preset|color|contrast", + "text": "var:preset|color|base" + } + }, + "h4": { + "typography": { + "fontSize": "var:preset|font-size|large" + } + }, + "h5": { + "typography": { + "fontSize": "var:preset|font-size|medium", + "letterSpacing": "0px" + } + }, + "h6": { + "typography": { + "fontSize": "var:preset|font-size|small" + } + }, + "heading": { + "color": { + "text": "var:preset|color|accent-3" + }, + "typography": { + "fontFamily": "var:preset|font-family|beiruti", + "fontWeight": "500", + "letterSpacing": "-0.02em", + "lineHeight": "1.02" + } + }, + "link": { + "color": { + "text": "currentColor" + } + } + }, + "variations": { + "section-4": { + "color": { + "text": "var:preset|color|accent-2" + }, + "elements": { + "button": { + ":hover": { + "color": { + "background": "color-mix(in srgb, var(--wp--preset--color--accent-2) 85%, transparent)" + } + } + }, + "heading": { + "color": { + "text": "currentColor" + } + }, + "link": { + "color": { + "text": "currentColor" + } + } + } + }, + "section-5": { + "color": { + "text": "var:preset|color|base" + }, + "elements": { + "button": { + ":hover": { + "color": { + "background": "color-mix(in srgb, var(--wp--preset--color--base) 85%, transparent)" + } + } + }, + "heading": { + "color": { + "text": "var:preset|color|base" + } + }, + "link": { + "color": { + "text": "currentColor" + } + } + } + } + } + } +} diff --git a/content/themes/twentytwentyfive/styles/03-dusk.json b/content/themes/twentytwentyfive/styles/03-dusk.json new file mode 100644 index 0000000..bbcdf63 --- /dev/null +++ b/content/themes/twentytwentyfive/styles/03-dusk.json @@ -0,0 +1,396 @@ +{ + "$schema": "https://schemas.wp.org/wp/6.7/theme.json", + "version": 3, + "title": "Dusk", + "settings": { + "color": { + "palette": [ + { + "color": "#E2E2E2", + "name": "Base", + "slug": "base" + }, + { + "color": "#3B3B3B", + "name": "Contrast", + "slug": "contrast" + }, + { + "color": "#F5EDFF", + "name": "Accent 1", + "slug": "accent-1" + }, + { + "color": "#650DD4", + "name": "Accent 2", + "slug": "accent-2" + }, + { + "color": "#191919", + "name": "Accent 3", + "slug": "accent-3" + }, + { + "color": "#5F5F5F", + "name": "Accent 4", + "slug": "accent-4" + }, + { + "color": "#DBDBDB", + "name": "Accent 5", + "slug": "accent-5" + }, + { + "color": "#3B3B3B33", + "name": "Accent 6", + "slug": "accent-6" + } + ] + }, + "custom": { + "color": { + "accent-2-opacity-20": "#650DD433" + } + }, + "typography": { + "fontFamilies": [ + { + "name": "Vollkorn", + "slug": "vollkorn", + "fontFamily": "Vollkorn, serif", + "fontFace": [ + { + "src": [ + "file:./assets/fonts/vollkorn/Vollkorn-Italic-VariableFont_wght.woff2" + ], + "fontWeight": "400 900", + "fontStyle": "italic", + "fontFamily": "Vollkorn" + }, + { + "src": [ + "file:./assets/fonts/vollkorn/Vollkorn-VariableFont_wght.woff2" + ], + "fontWeight": "400 900", + "fontStyle": "normal", + "fontFamily": "Vollkorn" + } + ] + }, + { + "name": "Fira Code", + "slug": "fira-code", + "fontFamily": "\"Fira Code\", monospace", + "fontFace": [ + { + "src": [ + "file:./assets/fonts/fira-code/FiraCode-VariableFont_wght.woff2" + ], + "fontWeight": "300 700", + "fontStyle": "normal", + "fontFamily": "\"Fira Code\"" + } + ] + } + ] + } + }, + "styles": { + "typography": { + "fontFamily": "var:preset|font-family|fira-code", + "fontSize": "var:preset|font-size|medium", + "letterSpacing": "-0.18px", + "lineHeight": "1.5" + }, + "blocks": { + "core/code": { + "color": { + "text": "var:preset|color|black", + "background": "var:preset|color|accent-5" + } + }, + "core/paragraph": { + "elements": { + "link": { + "color": { + "text": "var:preset|color|accent-2" + } + } + } + }, + "core/post-author-name": { + "typography": { + "fontWeight": "300" + }, + "color": { + "text": "var:preset|color|accent-2" + }, + "elements": { + "link": { + "color": { + "text": "currentColor" + } + } + } + }, + "core/post-terms": { + "typography": { + "fontWeight": "300" + }, + "color": { + "text": "var:preset|color|accent-2" + }, + "elements": { + "link": { + "color": { + "text": "currentColor" + } + } + } + }, + "core/post-title": { + "typography": { + "fontWeight": "400", + "letterSpacing": "-0.96px" + }, + "elements": { + "link": { + "color": { + "text": "var:preset|color|accent-3" + } + } + } + }, + "core/pullquote": { + "color": { + "text": "var:preset|color|black" + }, + "typography": { + "fontFamily": "var:preset|font-family|vollkorn", + "fontSize": "var:preset|font-size|x-large", + "fontWeight": "400" + }, + "elements": { + "cite": { + "typography": { + "fontFamily": "var:preset|font-family|fira-code", + "fontWeight": "300", + "letterSpacing": "-0.14px" + }, + "color": { + "text": "var:preset|color|contrast" + } + } + } + }, + "core/quote": { + "color": { + "text": "var:preset|color|black" + }, + "typography": { + "fontFamily": "var:preset|font-family|fira-code", + "fontWeight": "500", + "letterSpacing": "-0.18px" + } + }, + "core/site-title": { + "color": { + "text": "var:preset|color|accent-3" + }, + "typography": { + "fontFamily": "var:preset|font-family|vollkorn", + "fontSize": "var:preset|font-size|x-large" + }, + "elements": { + "link": { + "color": { + "text": "var:preset|color|accent-3" + } + } + } + } + }, + "elements": { + "button": { + "typography": { + "fontFamily": "var:preset|font-family|fira-code", + "fontSize": "var:preset|font-size|medium", + "fontWeight": "400", + "letterSpacing": "-0.36px" + }, + "color": { + "text": "var:preset|color|base", + "background": "var:preset|color|accent-2" + }, + "border": { + "radius": "4px", + "color": "transparent" + }, + ":hover": { + "color": { + "background": "color-mix(in srgb, var(--wp--preset--color--accent-2) 85%, transparent)" + } + } + }, + "heading": { + "color": { + "text": "var:preset|color|accent-3" + }, + "typography": { + "fontFamily": "var:preset|font-family|vollkorn" + } + }, + "h1": { + "typography": { + "fontSize": "48px", + "letterSpacing": "-0.96px;" + } + }, + "h2": { + "typography": { + "fontSize": "38px", + "letterSpacing": "-0.96px" + } + }, + "h3": { + "typography": { + "fontSize": "32px", + "letterSpacing": "-0.64px" + } + }, + "h4": { + "typography": { + "fontSize": "28px", + "letterSpacing": "-0.56px" + } + }, + "h5": { + "typography": { + "fontSize": "24px", + "letterSpacing": "-0.48px" + } + }, + "link": { + "color": { + "text": "var:preset|color|accent-3" + } + } + }, + "variations": { + "post-terms-1": { + "elements": { + "link": { + "border": { + "color": "var:custom|color|accent-2-opacity-20", + "radius": "4px", + "width": "0.8px", + "style": "solid" + } + } + } + }, + "section-1": { + "elements": { + "link": { + "color": { + "text": "var:preset|color|accent-3" + } + } + } + }, + "section-2": { + "color": { + "text": "var:preset|color|base" + }, + "elements": { + "button": { + "color": { + "background": "var:preset|color|accent-3", + "text": "var:preset|color|base" + }, + ":hover": { + "color": { + "background": "color-mix(in srgb, var(--wp--preset--color--accent-3) 85%, transparent)" + } + } + }, + "link": { + "color": { + "text": "currentColor" + } + }, + "heading": { + "color": { + "text": "currentColor" + } + } + } + }, + "section-3": { + "color": { + "text": "var:preset|color|accent-2" + }, + "elements": { + "heading": { + "color": { + "text": "currentColor" + } + } + } + }, + "section-4": { + "color": { + "text": "var:preset|color|base" + }, + "elements": { + "button": { + "color": { + "text": "var:preset|color|base" + }, + ":hover": { + "color": { + "text": "var:preset|color|base" + } + } + }, + "link": { + "color": { + "text": "currentColor" + } + }, + "heading": { + "color": { + "text": "currentColor" + } + } + } + }, + "section-5": { + "elements": { + "button": { + "color": { + "background": "var:preset|color|accent-2", + "text": "var:preset|color|base" + }, + ":hover": { + "color": { + "background": "color-mix(in srgb, var(--wp--preset--color--accent-2) 85%, transparent)", + "text": "var:preset|color|base" + } + } + }, + "heading": { + "color": { + "text": "var:preset|color|base" + } + }, + "link": { + "color": { + "text": "var:preset|color|base" + } + } + } + } + } + } +} diff --git a/content/themes/twentytwentyfive/styles/04-afternoon.json b/content/themes/twentytwentyfive/styles/04-afternoon.json new file mode 100644 index 0000000..d1edf01 --- /dev/null +++ b/content/themes/twentytwentyfive/styles/04-afternoon.json @@ -0,0 +1,302 @@ +{ + "$schema": "https://schemas.wp.org/wp/6.7/theme.json", + "version": 3, + "title": "Afternoon", + "settings": { + "color": { + "palette": [ + { + "color": "#DAE7BD", + "name": "Base", + "slug": "base" + }, + { + "color": "#516028", + "name": "Contrast", + "slug": "contrast" + }, + { + "color": "#C7F642", + "name": "Accent 1", + "slug": "accent-1" + }, + { + "color": "#EBF6D3", + "name": "Accent 2", + "slug": "accent-2" + }, + { + "color": "#303D10", + "name": "Accent 3", + "slug": "accent-3" + }, + { + "color": "#516028", + "name": "Accent 4", + "slug": "accent-4" + }, + { + "color": "#EBF6D3", + "name": "Accent 5", + "slug": "accent-5" + }, + { + "color": "#51602833", + "name": "Accent 6", + "slug": "accent-6" + } + ] + }, + "typography": { + "fontFamilies": [ + { + "name": "Platypi", + "slug": "platypi", + "fontFamily": "Platypi", + "fontFace": [ + { + "fontFamily": "Platypi", + "fontStyle": "normal", + "fontWeight": "300 800", + "src": [ + "file:./assets/fonts/platypi/Platypi-VariableFont_wght.woff2" + ] + }, + { + "fontFamily": "Platypi", + "fontStyle": "italic", + "fontWeight": "300 800", + "src": [ + "file:./assets/fonts/platypi/Platypi-Italic-VariableFont_wght.woff2" + ] + } + ] + }, + { + "name": "Ysabeau Office", + "slug": "ysabeau-office", + "fontFamily": "\"Ysabeau Office\", sans-serif", + "fontFace": [ + { + "src": [ + "file:./assets/fonts/ysabeau-office/YsabeauOffice-VariableFont_wght.woff2" + ], + "fontWeight": "100 900", + "fontStyle": "normal", + "fontFamily": "\"Ysabeau Office\"" + }, + { + "src": [ + "file:./assets/fonts/ysabeau-office/YsabeauOffice-Italic-VariableFont_wght.woff2" + ], + "fontWeight": "100 900", + "fontStyle": "italic", + "fontFamily": "\"Ysabeau Office\"" + } + ] + } + ], + "fontSizes": [ + { + "fluid": false, + "name": "Small", + "size": "0.875rem", + "slug": "small" + }, + { + "fluid": { + "max": "1.125rem", + "min": "1rem" + }, + "name": "Medium", + "size": "1rem", + "slug": "medium" + }, + { + "fluid": { + "max": "1.375rem", + "min": "1.125rem" + }, + "name": "Large", + "size": "1.38rem", + "slug": "large" + }, + { + "fluid": { + "max": "1.8rem", + "min": "1.4rem" + }, + "name": "Extra Large", + "size": "1.4rem", + "slug": "x-large" + }, + { + "fluid": { + "max": "2.6rem", + "min": "2rem" + }, + "name": "Extra Extra Large", + "size": "2rem", + "slug": "xx-large" + } + ] + } + }, + "styles": { + "typography": { + "fontFamily": "var:preset|font-family|ysabeau-office", + "letterSpacing": "-0.22px", + "lineHeight": "1.5" + }, + "blocks": { + "core/button": { + "border": { + "radius": "0px" + }, + "spacing": { + "padding": { + "bottom": "1rem", + "left": "1.6rem", + "right": "1.6rem", + "top": "1rem" + } + }, + "variations": { + "outline": { + "spacing": { + "padding": { + "bottom": "1rem", + "left": "1.6rem", + "right": "1.6rem", + "top": "1rem" + } + } + } + } + }, + "core/code": { + "typography": { + "letterSpacing": "0px" + } + }, + "core/heading": { + "typography": { + "lineHeight": "1.2" + } + }, + "core/list": { + "typography": { + "lineHeight": "1.3" + } + }, + "core/loginout": { + "typography": { + "fontSize": "var:preset|font-size|medium" + } + }, + "core/post-terms": { + "typography": { + "fontWeight": "400" + } + }, + "core/pullquote": { + "typography": { + "fontFamily": "var:preset|font-family|platypi", + "letterSpacing": "-0.01em", + "lineHeight": "1.1" + } + }, + "core/quote": { + "typography": { + "fontWeight": "300" + } + }, + "core/site-title": { + "typography": { + "fontFamily": "var:preset|font-family|ysabeau-office", + "fontSize": "var:preset|font-size|large", + "letterSpacing": "1.44px", + "textTransform": "uppercase" + } + } + }, + "elements": { + "button": { + "typography": { + "fontFamily": "var:preset|font-family|ysabeau-office", + "fontWeight": "600", + "letterSpacing": "1.44px", + "textTransform": "uppercase" + }, + ":hover": { + "color": { + "background": "color-mix(in srgb, var(--wp--preset--color--contrast) 85%, black)" + } + } + }, + "heading": { + "typography": { + "fontFamily": "var:preset|font-family|platypi" + } + }, + "h5": { + "typography": { + "fontSize": "var:preset|font-size|medium", + "letterSpacing": "normal" + } + }, + "h6": { + "typography": { + "fontSize": "var:preset|font-size|small", + "fontWeight": "400", + "fontStyle": "initial", + "letterSpacing": "initial", + "textTransform": "initial" + } + } + }, + "variations": { + "section-2": { + "color": { + "background": "var:preset|color|accent-3", + "text": "var:preset|color|accent-1" + }, + "elements": { + "button": { + "color": { + "background": "var:preset|color|accent-1", + "text": "var:preset|color|accent-3" + }, + ":hover": { + "color": { + "background": "color-mix(in srgb, var(--wp--preset--color--accent-1) 85%, transparent)" + } + } + } + } + }, + "section-4": { + "elements": { + "button": { + ":hover": { + "color": { + "background": "color-mix(in srgb, var(--wp--preset--color--accent-2) 85%, transparent)" + } + } + } + } + }, + "section-5": { + "elements": { + "button": { + ":hover": { + "color": { + "background": "color-mix(in srgb, var(--wp--preset--color--base) 90%, transparent)" + } + } + } + } + } + } + } +} diff --git a/content/themes/twentytwentyfive/styles/05-twilight.json b/content/themes/twentytwentyfive/styles/05-twilight.json new file mode 100644 index 0000000..833b4f3 --- /dev/null +++ b/content/themes/twentytwentyfive/styles/05-twilight.json @@ -0,0 +1,254 @@ +{ + "$schema": "https://schemas.wp.org/wp/6.7/theme.json", + "version": 3, + "title": "Twilight", + "settings": { + "color": { + "palette": [ + { + "color": "#131313", + "name": "Base", + "slug": "base" + }, + { + "color": "#FFFFFF", + "name": "Contrast", + "slug": "contrast" + }, + { + "color": "#4B52FF", + "name": "Accent 1", + "slug": "accent-1" + }, + { + "color": "#FF7A5C", + "name": "Accent 2", + "slug": "accent-2" + }, + { + "color": "#252525", + "name": "Accent 3", + "slug": "accent-3" + }, + { + "color": "#FFFFFF", + "name": "Accent 4", + "slug": "accent-4" + }, + { + "color": "#252525", + "name": "Accent 5", + "slug": "accent-5" + }, + { + "color": "#FFFFFF33", + "name": "Accent 6", + "slug": "accent-6" + } + ] + }, + "typography": { + "fontFamilies": [ + { + "name": "Roboto Slab", + "slug": "roboto-slab", + "fontFamily": "\"Roboto Slab\", serif", + "fontFace": [ + { + "fontFamily": "\"Roboto Slab\"", + "fontStyle": "normal", + "fontWeight": "100 900", + "src": [ + "file:./assets/fonts/roboto-slab/RobotoSlab-VariableFont_wght.woff2" + ] + } + ] + }, + { + "name": "Manrope", + "slug": "manrope", + "fontFamily": "Manrope, sans-serif", + "fontFace": [ + { + "src": [ + "file:./assets/fonts/manrope/Manrope-VariableFont_wght.woff2" + ], + "fontWeight": "200 800", + "fontStyle": "normal", + "fontFamily": "Manrope" + } + ] + } + ], + "fontSizes": [ + { + "fluid": false, + "name": "Small", + "size": "0.875rem", + "slug": "small" + }, + { + "fluid": { + "max": "1.125rem", + "min": "1rem" + }, + "name": "Medium", + "size": "1rem", + "slug": "medium" + }, + { + "fluid": { + "max": "1.375rem", + "min": "1.125rem" + }, + "name": "Large", + "size": "1.38rem", + "slug": "large" + }, + { + "fluid": { + "max": "2rem", + "min": "1.75rem" + }, + "name": "Extra Large", + "size": "1.75rem", + "slug": "x-large" + }, + { + "fluid": { + "max": "2.4rem", + "min": "2.15rem" + }, + "name": "Extra Extra Large", + "size": "2.15rem", + "slug": "xx-large" + } + ] + } + }, + "styles": { + "typography": { + "letterSpacing": "0" + }, + "blocks": { + "core/button": { + "variations": { + "outline": { + "spacing": { + "padding": { + "bottom": "0.625rem", + "left": "1.375rem", + "right": "1.375rem", + "top": "0.625rem" + } + } + } + } + }, + "core/navigation": { + "typography": { + "fontSize": "var:preset|font-size|large", + "letterSpacing": "-0.28px", + "textTransform": "uppercase" + } + }, + "core/post-author": { + "typography": { + "fontSize": "var:preset|font-size|small" + } + }, + "core/post-author-name": { + "typography": { + "fontSize": "var:preset|font-size|small" + } + }, + "core/post-terms": { + "typography": { + "fontWeight": "500" + } + }, + "core/pullquote": { + "typography": { + "fontFamily": "var:preset|font-family|roboto-slab", + "fontSize": "var:preset|font-size|xx-large", + "fontWeight": "200" + } + }, + "core/search": { + "typography": { + "textTransform": "uppercase" + } + }, + "core/site-tagline": { + "typography": { + "fontSize": "var:preset|font-size|large" + } + }, + "core/site-title": { + "typography": { + "textTransform": "uppercase" + } + } + }, + "elements": { + "button": { + "spacing": { + "padding": { + "bottom": "0.625rem", + "left": "1.375rem", + "right": "1.375rem", + "top": "0.625rem" + } + }, + "typography": { + "fontWeight": "500", + "letterSpacing": "-0.36px", + "textTransform": "uppercase" + } + }, + "heading": { + "typography": { + "fontFamily": "var:preset|font-family|roboto-slab", + "fontWeight": "300", + "letterSpacing": "-0.5px", + "lineHeight": "1.2" + } + } + }, + "variations": { + "section-2": { + "color": { + "text": "var:preset|color|base" + }, + "elements": { + "button": { + "color": { + "background": "var:preset|color|base", + "text": "var:preset|color|accent-2" + }, + ":hover": { + "color": { + "text": "var:preset|color|accent-2" + } + } + }, + "link": { + "color": { + "text": "currentColor" + } + } + } + }, + "section-5": { + "blocks": { + "core/post-comments-form": { + "css": "& textarea, input:not([type=submit]){border-radius:.25rem; border-color: color-mix(in srgb, currentColor 20%, transparent) !important;} & input[type=checkbox]{margin:0 .2rem 0 0 !important;} & label {font-size: var(--wp--preset--font-size--small); }" + }, + "core/search": { + "css": "& .wp-block-search__input{border-color: color-mix(in srgb, currentColor 20%, transparent);}" + } + } + } + } + } +} diff --git a/content/themes/twentytwentyfive/styles/06-morning.json b/content/themes/twentytwentyfive/styles/06-morning.json new file mode 100644 index 0000000..60d1173 --- /dev/null +++ b/content/themes/twentytwentyfive/styles/06-morning.json @@ -0,0 +1,505 @@ +{ + "$schema": "https://schemas.wp.org/wp/6.7/theme.json", + "version": 3, + "title": "Morning", + "settings": { + "color": { + "palette": [ + { + "color": "#DFDCD7", + "name": "Base", + "slug": "base" + }, + { + "color": "#191919", + "name": "Contrast", + "slug": "contrast" + }, + { + "color": "#7A9BDB", + "name": "Accent 1", + "slug": "accent-1" + }, + { + "color": "#F7E6FF", + "name": "Accent 2", + "slug": "accent-2" + }, + { + "color": "#182949", + "name": "Accent 3", + "slug": "accent-3" + }, + { + "color": "#5F5F5F", + "name": "Accent 4", + "slug": "accent-4" + }, + { + "color": "#D7D3CC", + "name": "Accent 5", + "slug": "accent-5" + }, + { + "color": "#19191933", + "name": "Accent 6", + "slug": "accent-6" + } + ] + }, + "typography": { + "fontFamilies": [ + { + "name": "Literata", + "slug": "literata", + "fontFamily": "Literata, serif", + "fontFace": [ + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-ExtraLight.woff2" + ], + "fontWeight": "200", + "fontStyle": "normal", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-ExtraLightItalic.woff2" + ], + "fontWeight": "200", + "fontStyle": "italic", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-Light.woff2" + ], + "fontWeight": "300", + "fontStyle": "normal", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-LightItalic.woff2" + ], + "fontWeight": "300", + "fontStyle": "italic", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-Regular.woff2" + ], + "fontWeight": "400", + "fontStyle": "normal", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-RegularItalic.woff2" + ], + "fontWeight": "400", + "fontStyle": "italic", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-Medium.woff2" + ], + "fontWeight": "500", + "fontStyle": "normal", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-MediumItalic.woff2" + ], + "fontWeight": "500", + "fontStyle": "italic", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-SemiBold.woff2" + ], + "fontWeight": "600", + "fontStyle": "normal", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-SemiBoldItalic.woff2" + ], + "fontWeight": "600", + "fontStyle": "italic", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-Bold.woff2" + ], + "fontWeight": "700", + "fontStyle": "normal", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-BoldItalic.woff2" + ], + "fontWeight": "700", + "fontStyle": "italic", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-ExtraBold.woff2" + ], + "fontWeight": "800", + "fontStyle": "normal", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-ExtraBoldItalic.woff2" + ], + "fontWeight": "800", + "fontStyle": "italic", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-Black.woff2" + ], + "fontWeight": "900", + "fontStyle": "normal", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-BlackItalic.woff2" + ], + "fontWeight": "900", + "fontStyle": "italic", + "fontFamily": "Literata" + } + ] + }, + { + "name": "Ysabeau Office", + "slug": "ysabeau-office", + "fontFamily": "\"Ysabeau Office\", sans-serif", + "fontFace": [ + { + "src": [ + "file:./assets/fonts/ysabeau-office/YsabeauOffice-VariableFont_wght.woff2" + ], + "fontWeight": "100 900", + "fontStyle": "normal", + "fontFamily": "\"Ysabeau Office\"" + }, + { + "src": [ + "file:./assets/fonts/ysabeau-office/YsabeauOffice-Italic-VariableFont_wght.woff2" + ], + "fontWeight": "100 900", + "fontStyle": "italic", + "fontFamily": "\"Ysabeau Office\"" + } + ] + } + ], + "fontSizes": [ + { + "fluid": false, + "name": "Small", + "size": "0.875rem", + "slug": "small" + }, + { + "fluid": { + "max": "1.125rem", + "min": "1rem" + }, + "name": "Medium", + "size": "1rem", + "slug": "medium" + }, + { + "fluid": { + "max": "1.375rem", + "min": "1.125rem" + }, + "name": "Large", + "size": "1.38rem", + "slug": "large" + }, + { + "fluid": { + "max": "2rem", + "min": "1.75rem" + }, + "name": "Extra Large", + "size": "1.75rem", + "slug": "x-large" + }, + { + "fluid": { + "max": "2.6rem", + "min": "1.4rem" + }, + "name": "Extra Extra Large", + "size": "2.6rem", + "slug": "xx-large" + } + ] + } + }, + "styles": { + "color": { + "text": "var:preset|color|accent-4" + }, + "typography": { + "fontFamily": "var:preset|font-family|ysabeau-office", + "letterSpacing": "-0.24px" + }, + "blocks": { + "core/code": { + "color": { + "text": "var:preset|color|contrast", + "background": "var:preset|color|accent-5" + } + }, + "core/navigation": { + "typography": { + "fontSize": "1.25rem" + } + }, + "core/paragraph": { + "elements": { + "link": { + "color": { + "text": "var:preset|color|contrast" + } + } + } + }, + "core/post-author-name": { + "elements": { + "link": { + "color": { + "text": "var:preset|color|contrast" + } + } + } + }, + "core/post-title": { + "typography": { + "fontWeight": "900", + "letterSpacing": "-0.96px" + }, + "elements": { + "link": { + "color": { + "text": "var:preset|color|contrast" + } + } + } + }, + "core/pullquote": { + "color": { + "text": "var:preset|color|contrast" + }, + "typography": { + "fontSize": "var:preset|font-size|xx-large" + }, + "elements": { + "cite": { + "typography": { + "fontSize": "var:preset|font-size|medium", + "letterSpacing": "-0.14px" + }, + "color": { + "text": "var:preset|color|accent-4" + } + } + } + }, + "core/quote": { + "elements": { + "cite": { + "typography": { + "fontSize": "var:preset|font-size|medium", + "letterSpacing": "-0.14px" + }, + "color": { + "text": "var:preset|color|accent-4" + } + } + } + }, + "core/query-title": { + "typography": { + "fontWeight": "900" + } + }, + "core/site-title": { + "typography": { + "fontFamily": "var:preset|font-family|ysabeau-office", + "textTransform": "uppercase", + "letterSpacing": "1.6px" + } + } + }, + "elements": { + "button": { + "typography": { + "fontFamily": "var:preset|font-family|literata", + "fontSize": "var:preset|font-size|medium", + "fontWeight": "900", + "letterSpacing": "-0.36px" + }, + "color": { + "text": "var:preset|color|contrast", + "background": "var:preset|color|accent-1" + }, + "border": { + "radius": "0px" + }, + ":hover": { + "color": { + "background": "color-mix(in srgb, var(--wp--preset--color--accent-1) 85%, transparent)", + "text": "var:preset|color|contrast" + } + } + }, + "heading": { + "color": { + "text": "var:preset|color|contrast" + }, + "typography": { + "fontFamily": "var:preset|font-family|literata", + "fontWeight": "900", + "lineHeight": "1.2" + } + }, + "h5": { + "typography": { + "letterSpacing": "0px" + } + }, + "h6": { + "typography": { + "fontWeight": "900", + "letterSpacing": "0px" + } + }, + "link": { + "color": { + "text": "currentColor" + } + } + }, + "variations": { + "post-terms-1": { + "typography": { + "fontSize": "var:preset|font-size|medium" + }, + "elements": { + "link": { + "color": { + "background": "var:preset|color|accent-5" + }, + "border": { + "radius": "100px", + "color": "var:preset|color|accent-5" + } + } + } + }, + "section-2": { + "elements": { + "button": { + "color": { + "background": "var:preset|color|accent-1", + "text": "var:preset|color|contrast" + }, + ":hover": { + "color": { + "background": "color-mix(in srgb, var(--wp--preset--color--accent-1) 85%, transparent)" + } + } + } + } + }, + "section-3": { + "elements": { + "button": { + "color": { + "background": "var:preset|color|contrast", + "text": "var:preset|color|base" + }, + ":hover": { + "color": { + "background": "color-mix(in srgb, var(--wp--preset--color--contrast) 85%, transparent)" + } + } + } + } + }, + "section-4": { + "color": { + "text": "var:preset|color|base" + }, + "elements": { + "heading": { + "color": { + "text": "currentColor" + } + }, + "button": { + "color": { + "background": "var:preset|color|accent-1", + "text": "var:preset|color|contrast" + }, + ":hover": { + "color": { + "background": "color-mix(in srgb, var(--wp--preset--color--accent-1) 85%, transparent)", + "text": "var:preset|color|contrast" + } + } + }, + "link": { + "color": { + "text": "currentColor" + } + } + } + }, + "section-5": { + "elements": { + "heading": { + "color": { + "text": "var:preset|color|base" + } + }, + "button": { + "color": { + "background": "var:preset|color|accent-1", + "text": "var:preset|color|contrast" + }, + ":hover": { + "color": { + "background": "color-mix(in srgb, var(--wp--preset--color--accent-1) 85%, transparent)" + } + } + }, + "link": { + "color": { + "text": "currentColor" + } + } + } + } + } + } +} diff --git a/content/themes/twentytwentyfive/styles/07-sunrise.json b/content/themes/twentytwentyfive/styles/07-sunrise.json new file mode 100644 index 0000000..fa5b100 --- /dev/null +++ b/content/themes/twentytwentyfive/styles/07-sunrise.json @@ -0,0 +1,508 @@ +{ + "$schema": "https://schemas.wp.org/wp/6.7/theme.json", + "version": 3, + "title": "Sunrise", + "settings": { + "color": { + "palette": [ + { + "color": "#330616", + "name": "Base", + "slug": "base" + }, + { + "color": "#FFFFFF", + "name": "Contrast", + "slug": "contrast" + }, + { + "color": "#F0FDA6", + "name": "Accent 1", + "slug": "accent-1" + }, + { + "color": "#DB9AB1", + "name": "Accent 2", + "slug": "accent-2" + }, + { + "color": "#C1E4E7", + "name": "Accent 3", + "slug": "accent-3" + }, + { + "color": "#DB9AB1", + "name": "Accent 4", + "slug": "accent-4" + }, + { + "color": "#4A1628", + "name": "Accent 5", + "slug": "accent-5" + }, + { + "color": "#DB9AB133", + "name": "Accent 6", + "slug": "accent-6" + } + ] + }, + "typography": { + "fontFamilies": [ + { + "name": "Platypi", + "slug": "platypi", + "fontFamily": "Platypi", + "fontFace": [ + { + "fontFamily": "Platypi", + "fontStyle": "normal", + "fontWeight": "300 800", + "src": [ + "file:./assets/fonts/platypi/Platypi-VariableFont_wght.woff2" + ] + }, + { + "fontFamily": "Platypi", + "fontStyle": "italic", + "fontWeight": "300 800", + "src": [ + "file:./assets/fonts/platypi/Platypi-Italic-VariableFont_wght.woff2" + ] + } + ] + }, + { + "name": "Literata", + "slug": "literata", + "fontFamily": "Literata, serif", + "fontFace": [ + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-ExtraLight.woff2" + ], + "fontWeight": "200", + "fontStyle": "normal", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-ExtraLightItalic.woff2" + ], + "fontWeight": "200", + "fontStyle": "italic", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-Light.woff2" + ], + "fontWeight": "300", + "fontStyle": "normal", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-LightItalic.woff2" + ], + "fontWeight": "300", + "fontStyle": "italic", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-Regular.woff2" + ], + "fontWeight": "400", + "fontStyle": "normal", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-RegularItalic.woff2" + ], + "fontWeight": "400", + "fontStyle": "italic", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-Medium.woff2" + ], + "fontWeight": "500", + "fontStyle": "normal", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-MediumItalic.woff2" + ], + "fontWeight": "500", + "fontStyle": "italic", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-SemiBold.woff2" + ], + "fontWeight": "600", + "fontStyle": "normal", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-SemiBoldItalic.woff2" + ], + "fontWeight": "600", + "fontStyle": "italic", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-Bold.woff2" + ], + "fontWeight": "700", + "fontStyle": "normal", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-BoldItalic.woff2" + ], + "fontWeight": "700", + "fontStyle": "italic", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-ExtraBold.woff2" + ], + "fontWeight": "800", + "fontStyle": "normal", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-ExtraBoldItalic.woff2" + ], + "fontWeight": "800", + "fontStyle": "italic", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-Black.woff2" + ], + "fontWeight": "900", + "fontStyle": "normal", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-BlackItalic.woff2" + ], + "fontWeight": "900", + "fontStyle": "italic", + "fontFamily": "Literata" + } + ] + } + ] + } + }, + "styles": { + "color": { + "text": "var:preset|color|accent-2" + }, + "typography": { + "fontFamily": "var:preset|font-family|literata", + "fontSize": "1.5rem", + "letterSpacing": "-0.24px", + "lineHeight": "1.3" + }, + "blocks": { + "core/code": { + "color": { + "text": "var:preset|color|accent-2", + "background": "var:preset|color|accent-5" + } + }, + "core/navigation": { + "typography": { + "fontSize": "1.25rem" + } + }, + "core/post-author-name": { + "color": { + "text": "var:preset|color|contrast" + }, + "elements": { + "link": { + "color": { + "text": "var:preset|color|contrast" + } + } + } + }, + "core/post-terms": { + "typography": { + "fontWeight": "400" + }, + "color": { + "text": "var:preset|color|contrast" + }, + "elements": { + "link": { + "color": { + "text": "var:preset|color|contrast" + } + } + } + }, + "core/post-title": { + "typography": { + "fontWeight": "800", + "letterSpacing": "-0.96px" + }, + "elements": { + "link": { + "color": { + "text": "var:preset|color|accent-2" + } + } + } + }, + "core/pullquote": { + "color": { + "text": "var:preset|color|accent-2" + }, + "typography": { + "fontFamily": "var:preset|font-family|platypi", + "fontSize": "var:preset|font-size|x-large", + "letterSpacing": "-0.76px", + "fontWeight": "800" + }, + "elements": { + "cite": { + "typography": { + "fontFamily": "var:preset|font-family|literata", + "fontWeight": "400", + "letterSpacing": "-0.14px" + }, + "color": { + "text": "var:preset|color|accent-2" + } + } + } + }, + "core/quote": { + "color": { + "text": "var:preset|color|accent-2" + }, + "typography": { + "fontSize": "1.5rem", + "fontWeight": "600", + "letterSpacing": "-0.24px" + }, + "elements": { + "cite": { + "typography": { + "letterSpacing": "-0.14px" + }, + "color": { + "text": "var:preset|color|accent-2" + } + } + } + }, + "core/site-title": { + "typography": { + "fontFamily": "var:preset|font-family|platypi", + "fontSize": "30px", + "fontWeight": "800", + "letterSpacing": "-0.6px" + }, + "elements": { + "link": { + "color": { + "text": "var:preset|color|accent-2" + } + } + } + } + }, + "elements": { + "button": { + "color": { + "text": "var:preset|color|base", + "background": "var:preset|color|accent-2" + }, + "border": { + "radius": "0px" + }, + ":hover": { + "color": { + "background": "color-mix(in srgb, var(--wp--preset--color--accent-2) 85%, transparent)" + } + }, + "typography": { + "fontFamily": "var:preset|font-family|platypi", + "fontSize": "1.5rem", + "fontWeight": "800" + } + }, + "heading": { + "typography": { + "fontFamily": "var:preset|font-family|platypi", + "fontWeight": "800" + } + }, + "link": { + "color": { + "text": "var:preset|color|contrast" + } + } + }, + "variations": { + "post-terms-1": { + "typography": { + "fontSize": "16px" + }, + "elements": { + "link": { + "color": { + "background": "var:preset|color|accent-5" + }, + "border": { + "radius": "100px", + "color": "var:preset|color|accent-5" + } + } + } + }, + "section-1": { + "color": { + "text": "var:preset|color|accent-5", + "background": "var:preset|color|contrast" + }, + "elements": { + "link": { + "color": { + "text": "currentColor" + } + }, + "button": { + "color": { + "background": "var:preset|color|base", + "text": "var:preset|color|contrast" + }, + ":hover": { + "color": { + "background": "color-mix(in srgb, var(--wp--preset--color--base) 85%, transparent)" + } + } + } + } + }, + "section-2": { + "color": { + "text": "var:preset|color|base" + }, + "elements": { + "link": { + "color": { + "text": "currentColor" + } + }, + "button": { + "color": { + "background": "var:preset|color|base", + "text": "var:preset|color|contrast" + }, + ":hover": { + "color": { + "background": "color-mix(in srgb, var(--wp--preset--color--base) 85%, transparent)" + } + } + } + } + }, + "section-3": { + "color": { + "text": "var:preset|color|base" + }, + "elements": { + "link": { + "color": { + "text": "currentColor" + } + }, + "button": { + "color": { + "background": "var:preset|color|base", + "text": "var:preset|color|contrast" + }, + ":hover": { + "color": { + "background": "color-mix(in srgb, var(--wp--preset--color--base) 85%, transparent)" + } + } + } + } + }, + "section-4": { + "color": { + "text": "var:preset|color|base" + }, + "elements": { + "link": { + "color": { + "text": "currentColor" + } + }, + "button": { + "color": { + "background": "var:preset|color|base", + "text": "var:preset|color|contrast" + }, + ":hover": { + "color": { + "background": "color-mix(in srgb, var(--wp--preset--color--base) 85%, transparent)" + } + } + } + } + }, + "section-5": { + "color": { + "text": "var:preset|color|contrast", + "background": "var:preset|color|accent-5" + }, + "elements": { + "heading": { + "color": { + "text": "currentColor" + } + }, + "link": { + "color": { + "text": "currentColor" + } + }, + "button": { + "color": { + "background": "var:preset|color|contrast", + "text": "var:preset|color|base" + }, + ":hover": { + "color": { + "background": "color-mix(in srgb, var(--wp--preset--color--contrast) 85%, transparent)", + "text": "var:preset|color|base" + } + } + } + } + } + } + } +} diff --git a/content/themes/twentytwentyfive/styles/08-midnight.json b/content/themes/twentytwentyfive/styles/08-midnight.json new file mode 100644 index 0000000..9272d14 --- /dev/null +++ b/content/themes/twentytwentyfive/styles/08-midnight.json @@ -0,0 +1,612 @@ +{ + "$schema": "https://schemas.wp.org/wp/6.7/theme.json", + "version": 3, + "title": "Midnight", + "settings": { + "color": { + "duotone": [ + { + "colors": [ + "#4433A6", + "#79F3B1" + ], + "name": "Midnight filter", + "slug": "midnight-filter" + } + ], + "palette": [ + { + "color": "#4433A6", + "name": "Base", + "slug": "base" + }, + { + "color": "#79F3B1", + "name": "Contrast", + "slug": "contrast" + }, + { + "color": "#5644BC", + "name": "Accent 1", + "slug": "accent-1" + }, + { + "color": "#372696", + "name": "Accent 2", + "slug": "accent-2" + }, + { + "color": "#251D51", + "name": "Accent 3", + "slug": "accent-3" + }, + { + "color": "#79F3B1", + "name": "Accent 4", + "slug": "accent-4" + }, + { + "color": "#E8B7FF", + "name": "Accent 5", + "slug": "accent-5" + }, + { + "color": "#79F3B133", + "name": "Accent 6", + "slug": "accent-6" + } + ] + }, + "typography": { + "fontSizes": [ + { + "fluid": false, + "name": "Small", + "size": "0.9rem", + "slug": "small" + }, + { + "fluid": { + "max": "1.2rem", + "min": "0.9rem" + }, + "name": "Medium", + "size": "1rem", + "slug": "medium" + }, + { + "fluid": { + "max": "1.8rem", + "min": "1.2rem" + }, + "name": "Large", + "size": "1.2rem", + "slug": "large" + }, + { + "fluid": { + "max": "2.2rem", + "min": "1.8rem" + }, + "name": "Extra Large", + "size": "1.8rem", + "slug": "x-large" + }, + { + "fluid": { + "max": "2.8rem", + "min": "2rem" + }, + "name": "Extra Extra Large", + "size": "2rem", + "slug": "xx-large" + } + ], + "fontFamilies": [ + { + "name": "Literata", + "slug": "literata", + "fontFamily": "Literata, serif", + "fontFace": [ + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-ExtraLight.woff2" + ], + "fontWeight": "200", + "fontStyle": "normal", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-ExtraLightItalic.woff2" + ], + "fontWeight": "200", + "fontStyle": "italic", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-Light.woff2" + ], + "fontWeight": "300", + "fontStyle": "normal", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-LightItalic.woff2" + ], + "fontWeight": "300", + "fontStyle": "italic", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-Regular.woff2" + ], + "fontWeight": "400", + "fontStyle": "normal", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-RegularItalic.woff2" + ], + "fontWeight": "400", + "fontStyle": "italic", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-Medium.woff2" + ], + "fontWeight": "500", + "fontStyle": "normal", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-MediumItalic.woff2" + ], + "fontWeight": "500", + "fontStyle": "italic", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-SemiBold.woff2" + ], + "fontWeight": "600", + "fontStyle": "normal", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-SemiBoldItalic.woff2" + ], + "fontWeight": "600", + "fontStyle": "italic", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-Bold.woff2" + ], + "fontWeight": "700", + "fontStyle": "normal", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-BoldItalic.woff2" + ], + "fontWeight": "700", + "fontStyle": "italic", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-ExtraBold.woff2" + ], + "fontWeight": "800", + "fontStyle": "normal", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-ExtraBoldItalic.woff2" + ], + "fontWeight": "800", + "fontStyle": "italic", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-Black.woff2" + ], + "fontWeight": "900", + "fontStyle": "normal", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-BlackItalic.woff2" + ], + "fontWeight": "900", + "fontStyle": "italic", + "fontFamily": "Literata" + } + ] + }, + { + "name": "Fira Sans", + "slug": "fira-sans", + "fontFamily": "\"Fira Sans\", sans-serif", + "fontFace": [ + { + "src": [ + "file:./assets/fonts/fira-sans/FiraSans-Thin.woff2" + ], + "fontWeight": "100", + "fontStyle": "normal", + "fontFamily": "\"Fira Sans\"" + }, + { + "src": [ + "file:./assets/fonts/fira-sans/FiraSans-ThinItalic.woff2" + ], + "fontWeight": "100", + "fontStyle": "italic", + "fontFamily": "\"Fira Sans\"" + }, + { + "src": [ + "file:./assets/fonts/fira-sans/FiraSans-ExtraLight.woff2" + ], + "fontWeight": "200", + "fontStyle": "normal", + "fontFamily": "\"Fira Sans\"" + }, + { + "src": [ + "file:./assets/fonts/fira-sans/FiraSans-ExtraLightItalic.woff2" + ], + "fontWeight": "200", + "fontStyle": "italic", + "fontFamily": "\"Fira Sans\"" + }, + { + "src": [ + "file:./assets/fonts/fira-sans/FiraSans-Light.woff2" + ], + "fontWeight": "300", + "fontStyle": "normal", + "fontFamily": "\"Fira Sans\"" + }, + { + "src": [ + "file:./assets/fonts/fira-sans/FiraSans-LightItalic.woff2" + ], + "fontWeight": "300", + "fontStyle": "italic", + "fontFamily": "\"Fira Sans\"" + }, + { + "src": [ + "file:./assets/fonts/fira-sans/FiraSans-Italic.woff2" + ], + "fontWeight": "400", + "fontStyle": "italic", + "fontFamily": "\"Fira Sans\"" + }, + { + "src": [ + "file:./assets/fonts/fira-sans/FiraSans-Regular.woff2" + ], + "fontWeight": "400", + "fontStyle": "normal", + "fontFamily": "\"Fira Sans\"" + }, + { + "src": [ + "file:./assets/fonts/fira-sans/FiraSans-Medium.woff2" + ], + "fontWeight": "500", + "fontStyle": "normal", + "fontFamily": "\"Fira Sans\"" + }, + { + "src": [ + "file:./assets/fonts/fira-sans/FiraSans-MediumItalic.woff2" + ], + "fontWeight": "500", + "fontStyle": "italic", + "fontFamily": "\"Fira Sans\"" + }, + { + "src": [ + "file:./assets/fonts/fira-sans/FiraSans-SemiBold.woff2" + ], + "fontWeight": "600", + "fontStyle": "normal", + "fontFamily": "\"Fira Sans\"" + }, + { + "src": [ + "file:./assets/fonts/fira-sans/FiraSans-SemiBoldItalic.woff2" + ], + "fontWeight": "600", + "fontStyle": "italic", + "fontFamily": "\"Fira Sans\"" + }, + { + "src": [ + "file:./assets/fonts/fira-sans/FiraSans-Bold.woff2" + ], + "fontWeight": "700", + "fontStyle": "normal", + "fontFamily": "\"Fira Sans\"" + }, + { + "src": [ + "file:./assets/fonts/fira-sans/FiraSans-BoldItalic.woff2" + ], + "fontWeight": "700", + "fontStyle": "italic", + "fontFamily": "\"Fira Sans\"" + }, + { + "src": [ + "file:./assets/fonts/fira-sans/FiraSans-ExtraBold.woff2" + ], + "fontWeight": "800", + "fontStyle": "normal", + "fontFamily": "\"Fira Sans\"" + }, + { + "src": [ + "file:./assets/fonts/fira-sans/FiraSans-ExtraBoldItalic.woff2" + ], + "fontWeight": "800", + "fontStyle": "italic", + "fontFamily": "\"Fira Sans\"" + }, + { + "src": [ + "file:./assets/fonts/fira-sans/FiraSans-Black.woff2" + ], + "fontWeight": "900", + "fontStyle": "normal", + "fontFamily": "\"Fira Sans\"" + }, + { + "src": [ + "file:./assets/fonts/fira-sans/FiraSans-BlackItalic.woff2" + ], + "fontWeight": "900", + "fontStyle": "italic", + "fontFamily": "\"Fira Sans\"" + } + ] + } + ] + } + }, + "styles": { + "typography": { + "fontSize": "var:preset|font-size|medium", + "fontFamily": "var:preset|font-family|fira-sans", + "letterSpacing": "-0.01em", + "lineHeight": "1.5" + }, + "blocks": { + "core/avatar": { + "filter": { + "duotone": "var:preset|duotone|midnight-filter" + } + }, + "core/button": { + "variations": { + "outline": { + "spacing": { + "padding": { + "bottom": "1rem", + "left": "1rem", + "right": "1rem", + "top": "1rem" + } + } + } + } + }, + "core/code": { + "color": { + "background": "var:preset|color|accent-2", + "text": "var:preset|color|contrast" + } + }, + "core/cover": { + "filter": { + "duotone": "var:preset|duotone|midnight-filter" + } + }, + "core/image": { + "filter": { + "duotone": "var:preset|duotone|midnight-filter" + } + }, + "core/post-date": { + "color": { + "text": "var:preset|color|contrast" + }, + "elements": { + "link": { + "color": { + "text": "var:preset|color|contrast" + } + } + } + }, + "core/post-featured-image": { + "filter": { + "duotone": "var:preset|duotone|midnight-filter" + } + }, + "core/post-title": { + "typography": { + "fontWeight": "200" + } + }, + "core/pullquote": { + "border": { + "bottom": { + "style": "none", + "width": "0px" + }, + "left": { + "style": "none", + "width": "0px" + }, + "right": { + "style": "none", + "width": "0px" + }, + "top": { + "style": "none", + "width": "0px" + } + }, + "typography": { + "fontFamily": "var:preset|font-family|literata", + "fontWeight": "200", + "letterSpacing": "0em" + } + }, + "core/query-pagination": { + "typography": { + "fontWeight": "300", + "letterSpacing": "0px" + } + }, + "core/quote": { + "typography": { + "fontSize": "var:preset|font-size|medium", + "letterSpacing": "-0.01em", + "lineHeight": "1.5", + "fontWeight": "300" + } + }, + "core/search": { + "border": { + "radius": "0px" + } + }, + "core/site-logo": { + "filter": { + "duotone": "var:preset|duotone|midnight-filter" + } + }, + "core/site-title": { + "typography": { + "fontFamily": "var:preset|font-family|literata", + "fontSize": "var:preset|font-size|x-large", + "fontWeight": "300", + "letterSpacing": "-0.56px", + "textTransform": "uppercase" + } + } + }, + "elements": { + "button": { + "border": { + "radius": "0px" + }, + "color": { + "background": "var:preset|color|contrast", + "text": "var:preset|color|base" + }, + "spacing": { + "padding": { + "bottom": "1rem", + "left": "1rem", + "right": "1rem", + "top": "1rem" + } + }, + "typography": { + "fontFamily": "var:preset|font-family|literata", + "fontSize": "var:preset|font-size|medium", + "fontWeight": "400", + "letterSpacing": "-0.01em", + "textTransform": "uppercase" + }, + ":hover": { + "color": { + "background": "color-mix(in srgb, var(--wp--preset--color--contrast) 85%, transparent)" + } + } + }, + "heading": { + "typography": { + "fontFamily": "var:preset|font-family|literata", + "fontWeight": "200", + "letterSpacing": "-0.02em", + "lineHeight": "1.24" + } + }, + "h6": { + "typography": { + "fontWeight": "200" + } + } + }, + "variations": { + "section-1": { + "color": { + "text": "var:preset|color|accent-3" + }, + "elements": { + "button": { + "color": { + "background": "var:preset|color|accent-3", + "text": "var:preset|color|accent-5" + }, + ":hover": { + "color": { + "background": "color-mix(in srgb, var(--wp--preset--color--accent-3) 85%, transparent)" + } + } + }, + "link": { + "color": { + "text": "currentColor" + } + } + } + }, + "section-4": { + "color": { + "text": "var:preset|color|accent-5" + }, + "elements": { + "button": { + "color": { + "background": "var:preset|color|accent-5", + "text": "var:preset|color|accent-3" + }, + ":hover": { + "color": { + "background": "color-mix(in srgb, var(--wp--preset--color--accent-5) 85%, transparent)" + } + } + }, + "link": { + "color": { + "text": "currentColor" + } + } + } + } + } + } +} diff --git a/content/themes/twentytwentyfive/styles/blocks/01-display.json b/content/themes/twentytwentyfive/styles/blocks/01-display.json new file mode 100644 index 0000000..ff8eaae --- /dev/null +++ b/content/themes/twentytwentyfive/styles/blocks/01-display.json @@ -0,0 +1,13 @@ +{ + "$schema": "https://schemas.wp.org/wp/6.7/theme.json", + "version": 3, + "title": "Display", + "slug": "text-display", + "blockTypes": ["core/heading", "core/paragraph"], + "styles": { + "typography": { + "fontSize": "clamp(2.2rem, 2.2rem + ((1vw - 0.2rem) * 1.333), 3.5rem)", + "lineHeight": "1.2" + } + } +} diff --git a/content/themes/twentytwentyfive/styles/blocks/02-subtitle.json b/content/themes/twentytwentyfive/styles/blocks/02-subtitle.json new file mode 100644 index 0000000..bd9640c --- /dev/null +++ b/content/themes/twentytwentyfive/styles/blocks/02-subtitle.json @@ -0,0 +1,13 @@ +{ + "$schema": "https://schemas.wp.org/wp/6.7/theme.json", + "version": 3, + "title": "Subtitle", + "slug": "text-subtitle", + "blockTypes": ["core/heading", "core/paragraph"], + "styles": { + "typography": { + "fontSize": "clamp(1.5rem, 1.5rem + ((1vw - 0.2rem) * 0.392), 1.75rem)", + "lineHeight": "1.2" + } + } +} diff --git a/content/themes/twentytwentyfive/styles/blocks/03-annotation.json b/content/themes/twentytwentyfive/styles/blocks/03-annotation.json new file mode 100644 index 0000000..41391e3 --- /dev/null +++ b/content/themes/twentytwentyfive/styles/blocks/03-annotation.json @@ -0,0 +1,36 @@ +{ + "$schema": "https://schemas.wp.org/wp/6.7/theme.json", + "version": 3, + "title": "Annotation", + "slug": "text-annotation", + "blockTypes": ["core/heading", "core/paragraph"], + "styles": { + "css": "width: fit-content", + "typography": { + "fontSize": "var:preset|font-size|small", + "lineHeight": "1.5", + "letterSpacing": "normal" + }, + "border": { + "color": "currentColor", + "style": "solid", + "width": "1px", + "radius": "16px" + }, + "spacing": { + "padding": { + "top": "0.2rem", + "right": "0.6rem", + "bottom": "0.25rem", + "left": "0.6rem" + } + }, + "elements": { + "link": { + "typography": { + "textDecoration": "none" + } + } + } + } +} diff --git a/content/themes/twentytwentyfive/styles/blocks/post-terms-1.json b/content/themes/twentytwentyfive/styles/blocks/post-terms-1.json new file mode 100644 index 0000000..5995fbb --- /dev/null +++ b/content/themes/twentytwentyfive/styles/blocks/post-terms-1.json @@ -0,0 +1,37 @@ +{ + "version": 3, + "$schema": "https://schemas.wp.org/wp/6.7/theme.json", + "title": "Pill shaped", + "slug": "post-terms-1", + "blockTypes": ["core/post-terms"], + "styles": { + "elements": { + "link": { + "border": { + "color": "var:preset|color|accent-6", + "radius": "20px", + "width": "0.8px", + "style": "solid" + }, + "spacing": { + "padding": { + "top": "5px", + "right": "10px", + "bottom": "5px", + "left": "10px" + } + }, + "typography": { + "fontWeight": "400", + "lineHeight": "2.8", + "textDecoration": "none" + }, + ":hover": { + "typography": { + "textDecoration": "underline" + } + } + } + } + } +} diff --git a/content/themes/twentytwentyfive/styles/colors/01-evening.json b/content/themes/twentytwentyfive/styles/colors/01-evening.json new file mode 100644 index 0000000..56c88fb --- /dev/null +++ b/content/themes/twentytwentyfive/styles/colors/01-evening.json @@ -0,0 +1,102 @@ +{ + "$schema": "https://schemas.wp.org/wp/6.7/theme.json", + "version": 3, + "title": "Evening", + "settings": { + "color": { + "palette": [ + { + "color": "#1B1B1B", + "name": "Base", + "slug": "base" + }, + { + "color": "#F0F0F0", + "name": "Contrast", + "slug": "contrast" + }, + { + "color": "#786D0A", + "name": "Accent 1", + "slug": "accent-1" + }, + { + "color": "#442369", + "name": "Accent 2", + "slug": "accent-2" + }, + { + "color": "#D1D0EA", + "name": "Accent 3", + "slug": "accent-3" + }, + { + "color": "#CBCBCB", + "name": "Accent 4", + "slug": "accent-4" + }, + { + "color": "#353535", + "name": "Accent 5", + "slug": "accent-5" + }, + { + "color": "#FFFFFF33", + "name": "Accent 6", + "slug": "accent-6" + } + ] + } + }, + "styles": { + "color": { + "text": "var:preset|color|accent-4" + }, + "elements": { + "button": { + "color": { + "background": "var:preset|color|contrast", + "text": "var:preset|color|base" + }, + ":hover": { + "color": { + "background": "color-mix(in srgb, var(--wp--preset--color--contrast) 85%, transparent)", + "text": "var:preset|color|base" + } + } + } + }, + "variations": { + "section-2": { + "elements": { + "button": { + "color": { + "background": "var:preset|color|base", + "text": "var:preset|color|contrast" + }, + ":hover": { + "color": { + "background": "color-mix(in srgb, var(--wp--preset--color--base) 85%, transparent)" + } + } + } + } + }, + "section-4": { + "elements": { + "button": { + "color": { + "background": "var:preset|color|accent-2", + "text": "var:preset|color|contrast" + }, + ":hover": { + "color": { + "background": "color-mix(in srgb, var(--wp--preset--color--accent-2) 85%, transparent)" + } + } + } + } + } + } + } +} diff --git a/content/themes/twentytwentyfive/styles/colors/02-noon.json b/content/themes/twentytwentyfive/styles/colors/02-noon.json new file mode 100644 index 0000000..97b12a5 --- /dev/null +++ b/content/themes/twentytwentyfive/styles/colors/02-noon.json @@ -0,0 +1,167 @@ +{ + "$schema": "https://schemas.wp.org/wp/6.7/theme.json", + "version": 3, + "title": "Noon", + "settings": { + "color": { + "palette": [ + { + "color": "#F8F7F5", + "name": "Base", + "slug": "base" + }, + { + "color": "#191919", + "name": "Contrast", + "slug": "contrast" + }, + { + "color": "#FFFFFF", + "name": "Accent 1", + "slug": "accent-1" + }, + { + "color": "#F5B684", + "name": "Accent 2", + "slug": "accent-2" + }, + { + "color": "#191919", + "name": "Accent 3", + "slug": "accent-3" + }, + { + "color": "#5F5F5F", + "name": "Accent 4", + "slug": "accent-4" + }, + { + "color": "#F1EEE9", + "name": "Accent 5", + "slug": "accent-5" + }, + { + "color": "#19191933", + "name": "Accent 6", + "slug": "accent-6" + } + ] + } + }, + "styles": { + "color": { + "text": "var:preset|color|accent-4" + }, + "blocks": { + "core/button": { + "border": { + "color": "var:preset|color|contrast" + } + }, + "core/post-title": { + "color": { + "text": "var:preset|color|accent-3" + }, + "elements": { + "link": { + "color": { + "text": "currentColor" + } + } + } + }, + "core/pullquote": { + "color": { + "text": "var:preset|color|accent-3" + }, + "elements": { + "link": { + "color": { + "text": "currentColor" + } + } + } + }, + "core/query-title": { + "color": { + "text": "var:preset|color|accent-3" + }, + "elements": { + "link": { + "color": { + "text": "currentColor" + } + } + } + } + }, + "elements": { + "button": { + "color": { + "background": "var:preset|color|contrast", + "text": "var:preset|color|base" + } + }, + "heading": { + "color": { + "text": "var:preset|color|accent-3" + } + }, + "link": { + "color": { + "text": "currentColor" + } + } + }, + "variations": { + "section-4": { + "color": { + "text": "var:preset|color|accent-2" + }, + "elements": { + "button": { + ":hover": { + "color": { + "background": "color-mix(in srgb, var(--wp--preset--color--accent-2) 85%, transparent)" + } + } + }, + "heading": { + "color": { + "text": "currentColor" + } + }, + "link": { + "color": { + "text": "currentColor" + } + } + } + }, + "section-5": { + "color": { + "text": "var:preset|color|base" + }, + "elements": { + "button": { + ":hover": { + "color": { + "background": "color-mix(in srgb, var(--wp--preset--color--base) 85%, transparent)" + } + } + }, + "heading": { + "color": { + "text": "var:preset|color|base" + } + }, + "link": { + "color": { + "text": "currentColor" + } + } + } + } + } + } +} diff --git a/content/themes/twentytwentyfive/styles/colors/03-dusk.json b/content/themes/twentytwentyfive/styles/colors/03-dusk.json new file mode 100644 index 0000000..705c827 --- /dev/null +++ b/content/themes/twentytwentyfive/styles/colors/03-dusk.json @@ -0,0 +1,276 @@ +{ + "$schema": "https://schemas.wp.org/wp/6.7/theme.json", + "version": 3, + "title": "Dusk", + "settings": { + "color": { + "palette": [ + { + "color": "#E2E2E2", + "name": "Base", + "slug": "base" + }, + { + "color": "#3B3B3B", + "name": "Contrast", + "slug": "contrast" + }, + { + "color": "#F5EDFF", + "name": "Accent 1", + "slug": "accent-1" + }, + { + "color": "#650DD4", + "name": "Accent 2", + "slug": "accent-2" + }, + { + "color": "#191919", + "name": "Accent 3", + "slug": "accent-3" + }, + { + "color": "#5F5F5F", + "name": "Accent 4", + "slug": "accent-4" + }, + { + "color": "#DBDBDB", + "name": "Accent 5", + "slug": "accent-5" + }, + { + "color": "#3B3B3B33", + "name": "Accent 6", + "slug": "accent-6" + } + ] + }, + "custom": { + "color": { + "accent-2-opacity-20": "#650DD433" + } + } + }, + "styles": { + "blocks": { + "core/code": { + "color": { + "text": "var:preset|color|black", + "background": "var:preset|color|accent-5" + } + }, + "core/paragraph": { + "elements": { + "link": { + "color": { + "text": "var:preset|color|accent-2" + } + } + } + }, + "core/post-author-name": { + "color": { + "text": "var:preset|color|accent-2" + }, + "elements": { + "link": { + "color": { + "text": "currentColor" + } + } + } + }, + "core/post-terms": { + "color": { + "text": "var:preset|color|accent-2" + }, + "elements": { + "link": { + "color": { + "text": "currentColor" + } + } + } + }, + "core/post-title": { + "elements": { + "link": { + "color": { + "text": "var:preset|color|accent-3" + } + } + } + }, + "core/pullquote": { + "color": { + "text": "var:preset|color|black" + }, + "elements": { + "cite": { + "color": { + "text": "var:preset|color|contrast" + } + } + } + }, + "core/quote": { + "color": { + "text": "var:preset|color|black" + } + }, + "core/site-title": { + "color": { + "text": "var:preset|color|accent-3" + }, + "elements": { + "link": { + "color": { + "text": "var:preset|color|accent-3" + } + } + } + } + }, + "elements": { + "button": { + "color": { + "text": "var:preset|color|base", + "background": "var:preset|color|accent-2" + }, + "border": { + "color": "transparent" + }, + ":hover": { + "color": { + "background": "color-mix(in srgb, var(--wp--preset--color--accent-2) 85%, transparent)" + } + } + }, + "heading": { + "color": { + "text": "var:preset|color|accent-3" + } + }, + "link": { + "color": { + "text": "var:preset|color|accent-3" + } + } + }, + "variations": { + "post-terms-1": { + "elements": { + "link": { + "border": { + "color": "var:custom|color|accent-2-opacity-20" + } + } + } + }, + "section-1": { + "elements": { + "link": { + "color": { + "text": "var:preset|color|accent-3" + } + } + } + }, + "section-2": { + "color": { + "text": "var:preset|color|base" + }, + "elements": { + "button": { + "color": { + "background": "var:preset|color|accent-3", + "text": "var:preset|color|base" + }, + ":hover": { + "color": { + "background": "color-mix(in srgb, var(--wp--preset--color--accent-3) 85%, transparent)" + } + } + }, + "link": { + "color": { + "text": "currentColor" + } + }, + "heading": { + "color": { + "text": "currentColor" + } + } + } + }, + "section-3": { + "color": { + "text": "var:preset|color|accent-2" + }, + "elements": { + "heading": { + "color": { + "text": "currentColor" + } + } + } + }, + "section-4": { + "color": { + "text": "var:preset|color|base" + }, + "elements": { + "button": { + "color": { + "text": "var:preset|color|base" + }, + ":hover": { + "color": { + "text": "var:preset|color|base" + } + } + }, + "link": { + "color": { + "text": "currentColor" + } + }, + "heading": { + "color": { + "text": "currentColor" + } + } + } + }, + "section-5": { + "elements": { + "button": { + "color": { + "background": "var:preset|color|accent-2", + "text": "var:preset|color|base" + }, + ":hover": { + "color": { + "background": "color-mix(in srgb, var(--wp--preset--color--accent-2) 85%, transparent)", + "text": "var:preset|color|base" + } + } + }, + "heading": { + "color": { + "text": "var:preset|color|base" + } + }, + "link": { + "color": { + "text": "var:preset|color|base" + } + } + } + } + } + } +} diff --git a/content/themes/twentytwentyfive/styles/colors/04-afternoon.json b/content/themes/twentytwentyfive/styles/colors/04-afternoon.json new file mode 100644 index 0000000..60da749 --- /dev/null +++ b/content/themes/twentytwentyfive/styles/colors/04-afternoon.json @@ -0,0 +1,105 @@ +{ + "$schema": "https://schemas.wp.org/wp/6.7/theme.json", + "version": 3, + "title": "Afternoon", + "settings": { + "color": { + "palette": [ + { + "color": "#DAE7BD", + "name": "Base", + "slug": "base" + }, + { + "color": "#516028", + "name": "Contrast", + "slug": "contrast" + }, + { + "color": "#C7F642", + "name": "Accent 1", + "slug": "accent-1" + }, + { + "color": "#EBF6D3", + "name": "Accent 2", + "slug": "accent-2" + }, + { + "color": "#303D10", + "name": "Accent 3", + "slug": "accent-3" + }, + { + "color": "#516028", + "name": "Accent 4", + "slug": "accent-4" + }, + { + "color": "#EBF6D3", + "name": "Accent 5", + "slug": "accent-5" + }, + { + "color": "#51602833", + "name": "Accent 6", + "slug": "accent-6" + } + ] + } + }, + "styles": { + "elements": { + "button": { + ":hover": { + "color": { + "background": "color-mix(in srgb, var(--wp--preset--color--contrast) 85%, black)" + } + } + } + }, + "variations": { + "section-2": { + "color": { + "background": "var:preset|color|accent-3", + "text": "var:preset|color|accent-1" + }, + "elements": { + "button": { + "color": { + "background": "var:preset|color|accent-1", + "text": "var:preset|color|accent-3" + }, + ":hover": { + "color": { + "background": "color-mix(in srgb, var(--wp--preset--color--accent-1) 85%, transparent)" + } + } + } + } + }, + "section-4": { + "elements": { + "button": { + ":hover": { + "color": { + "background": "color-mix(in srgb, var(--wp--preset--color--accent-2) 85%, transparent)" + } + } + } + } + }, + "section-5": { + "elements": { + "button": { + ":hover": { + "color": { + "background": "color-mix(in srgb, var(--wp--preset--color--base) 90%, transparent)" + } + } + } + } + } + } + } +} diff --git a/content/themes/twentytwentyfive/styles/colors/05-twilight.json b/content/themes/twentytwentyfive/styles/colors/05-twilight.json new file mode 100644 index 0000000..329164d --- /dev/null +++ b/content/themes/twentytwentyfive/styles/colors/05-twilight.json @@ -0,0 +1,78 @@ +{ + "$schema": "https://schemas.wp.org/wp/6.7/theme.json", + "version": 3, + "title": "Twilight", + "settings": { + "color": { + "palette": [ + { + "color": "#131313", + "name": "Base", + "slug": "base" + }, + { + "color": "#FFFFFF", + "name": "Contrast", + "slug": "contrast" + }, + { + "color": "#4B52FF", + "name": "Accent 1", + "slug": "accent-1" + }, + { + "color": "#FF7A5C", + "name": "Accent 2", + "slug": "accent-2" + }, + { + "color": "#252525", + "name": "Accent 3", + "slug": "accent-3" + }, + { + "color": "#FFFFFF", + "name": "Accent 4", + "slug": "accent-4" + }, + { + "color": "#252525", + "name": "Accent 5", + "slug": "accent-5" + }, + { + "color": "#FFFFFF33", + "name": "Accent 6", + "slug": "accent-6" + } + ] + } + }, + "styles": { + "variations": { + "section-2": { + "color": { + "text": "var:preset|color|base" + }, + "elements": { + "button": { + "color": { + "background": "var:preset|color|base", + "text": "var:preset|color|accent-2" + }, + ":hover": { + "color": { + "text": "var:preset|color|accent-2" + } + } + }, + "link": { + "color": { + "text": "currentColor" + } + } + } + } + } + } +} diff --git a/content/themes/twentytwentyfive/styles/colors/06-morning.json b/content/themes/twentytwentyfive/styles/colors/06-morning.json new file mode 100644 index 0000000..4330045 --- /dev/null +++ b/content/themes/twentytwentyfive/styles/colors/06-morning.json @@ -0,0 +1,234 @@ +{ + "$schema": "https://schemas.wp.org/wp/6.7/theme.json", + "version": 3, + "title": "Morning", + "settings": { + "color": { + "palette": [ + { + "color": "#DFDCD7", + "name": "Base", + "slug": "base" + }, + { + "color": "#191919", + "name": "Contrast", + "slug": "contrast" + }, + { + "color": "#7A9BDB", + "name": "Accent 1", + "slug": "accent-1" + }, + { + "color": "#F7E6FF", + "name": "Accent 2", + "slug": "accent-2" + }, + { + "color": "#182949", + "name": "Accent 3", + "slug": "accent-3" + }, + { + "color": "#5F5F5F", + "name": "Accent 4", + "slug": "accent-4" + }, + { + "color": "#D7D3CC", + "name": "Accent 5", + "slug": "accent-5" + }, + { + "color": "#19191933", + "name": "Accent 6", + "slug": "accent-6" + } + ] + } + }, + "styles": { + "color": { + "text": "var:preset|color|accent-4" + }, + "blocks": { + "core/code": { + "color": { + "text": "var:preset|color|contrast", + "background": "var:preset|color|accent-5" + } + }, + "core/paragraph": { + "elements": { + "link": { + "color": { + "text": "var:preset|color|contrast" + } + } + } + }, + "core/post-author-name": { + "elements": { + "link": { + "color": { + "text": "var:preset|color|contrast" + } + } + } + }, + "core/post-title": { + "elements": { + "link": { + "color": { + "text": "var:preset|color|contrast" + } + } + } + }, + "core/pullquote": { + "color": { + "text": "var:preset|color|contrast" + }, + "elements": { + "cite": { + "color": { + "text": "var:preset|color|accent-4" + } + } + } + }, + "core/quote": { + "elements": { + "cite": { + "color": { + "text": "var:preset|color|accent-4" + } + } + } + } + }, + "elements": { + "button": { + "color": { + "text": "var:preset|color|contrast", + "background": "var:preset|color|accent-1" + }, + ":hover": { + "color": { + "background": "color-mix(in srgb, var(--wp--preset--color--accent-1) 85%, transparent)", + "text": "var:preset|color|contrast" + } + } + }, + "heading": { + "color": { + "text": "var:preset|color|contrast" + } + }, + "link": { + "color": { + "text": "currentColor" + } + } + }, + "variations": { + "post-terms-1": { + "elements": { + "link": { + "color": { + "background": "var:preset|color|accent-5" + }, + "border": { + "color": "var:preset|color|accent-5" + } + } + } + }, + "section-2": { + "elements": { + "button": { + "color": { + "background": "var:preset|color|accent-1", + "text": "var:preset|color|contrast" + }, + ":hover": { + "color": { + "background": "color-mix(in srgb, var(--wp--preset--color--accent-1) 85%, transparent)" + } + } + } + } + }, + "section-3": { + "elements": { + "button": { + "color": { + "background": "var:preset|color|contrast", + "text": "var:preset|color|base" + }, + ":hover": { + "color": { + "background": "color-mix(in srgb, var(--wp--preset--color--contrast) 85%, transparent)" + } + } + } + } + }, + "section-4": { + "color": { + "text": "var:preset|color|base" + }, + "elements": { + "heading": { + "color": { + "text": "currentColor" + } + }, + "button": { + "color": { + "background": "var:preset|color|accent-1", + "text": "var:preset|color|contrast" + }, + ":hover": { + "color": { + "background": "color-mix(in srgb, var(--wp--preset--color--accent-1) 85%, transparent)", + "text": "var:preset|color|contrast" + } + } + }, + "link": { + "color": { + "text": "currentColor" + } + } + } + }, + "section-5": { + "elements": { + "heading": { + "color": { + "text": "var:preset|color|base" + } + }, + "button": { + "color": { + "background": "var:preset|color|accent-1", + "text": "var:preset|color|contrast" + }, + ":hover": { + "color": { + "background": "color-mix(in srgb, var(--wp--preset--color--accent-1) 85%, transparent)" + } + } + }, + "link": { + "color": { + "text": "currentColor" + } + } + } + } + } + } +} diff --git a/content/themes/twentytwentyfive/styles/colors/07-sunrise.json b/content/themes/twentytwentyfive/styles/colors/07-sunrise.json new file mode 100644 index 0000000..ee39df9 --- /dev/null +++ b/content/themes/twentytwentyfive/styles/colors/07-sunrise.json @@ -0,0 +1,285 @@ +{ + "$schema": "https://schemas.wp.org/wp/6.7/theme.json", + "version": 3, + "title": "Sunrise", + "settings": { + "color": { + "palette": [ + { + "color": "#330616", + "name": "Base", + "slug": "base" + }, + { + "color": "#FFFFFF", + "name": "Contrast", + "slug": "contrast" + }, + { + "color": "#F0FDA6", + "name": "Accent 1", + "slug": "accent-1" + }, + { + "color": "#DB9AB1", + "name": "Accent 2", + "slug": "accent-2" + }, + { + "color": "#C1E4E7", + "name": "Accent 3", + "slug": "accent-3" + }, + { + "color": "#DB9AB1", + "name": "Accent 4", + "slug": "accent-4" + }, + { + "color": "#4A1628", + "name": "Accent 5", + "slug": "accent-5" + }, + { + "color": "#DB9AB133", + "name": "Accent 6", + "slug": "accent-6" + } + ] + } + }, + "styles": { + "color": { + "text": "var:preset|color|accent-2" + }, + "blocks": { + "core/code": { + "color": { + "text": "var:preset|color|accent-2", + "background": "var:preset|color|accent-5" + } + }, + "core/post-author-name": { + "color": { + "text": "var:preset|color|contrast" + }, + "elements": { + "link": { + "color": { + "text": "var:preset|color|contrast" + } + } + } + }, + "core/post-terms": { + "color": { + "text": "var:preset|color|contrast" + }, + "elements": { + "link": { + "color": { + "text": "var:preset|color|contrast" + } + } + } + }, + "core/post-title": { + "elements": { + "link": { + "color": { + "text": "var:preset|color|accent-2" + } + } + } + }, + "core/pullquote": { + "color": { + "text": "var:preset|color|accent-2" + }, + "elements": { + "cite": { + "color": { + "text": "var:preset|color|accent-2" + } + } + } + }, + "core/quote": { + "color": { + "text": "var:preset|color|accent-2" + }, + "elements": { + "cite": { + "color": { + "text": "var:preset|color|accent-2" + } + } + } + }, + "core/site-title": { + "elements": { + "link": { + "color": { + "text": "var:preset|color|accent-2" + } + } + } + } + }, + "elements": { + "button": { + "color": { + "text": "var:preset|color|base", + "background": "var:preset|color|accent-2" + }, + ":hover": { + "color": { + "background": "color-mix(in srgb, var(--wp--preset--color--accent-2) 85%, transparent)" + } + } + }, + "link": { + "color": { + "text": "var:preset|color|contrast" + } + } + }, + "variations": { + "post-terms-1": { + "elements": { + "link": { + "color": { + "background": "var:preset|color|accent-5" + }, + "border": { + "color": "var:preset|color|accent-5" + } + } + } + }, + "section-1": { + "color": { + "text": "var:preset|color|accent-5", + "background": "var:preset|color|contrast" + }, + "elements": { + "link": { + "color": { + "text": "currentColor" + } + }, + "button": { + "color": { + "background": "var:preset|color|base", + "text": "var:preset|color|contrast" + }, + ":hover": { + "color": { + "background": "color-mix(in srgb, var(--wp--preset--color--base) 85%, transparent)" + } + } + } + } + }, + "section-2": { + "color": { + "text": "var:preset|color|base" + }, + "elements": { + "link": { + "color": { + "text": "currentColor" + } + }, + "button": { + "color": { + "background": "var:preset|color|base", + "text": "var:preset|color|contrast" + }, + ":hover": { + "color": { + "background": "color-mix(in srgb, var(--wp--preset--color--base) 85%, transparent)" + } + } + } + } + }, + "section-3": { + "color": { + "text": "var:preset|color|base" + }, + "elements": { + "link": { + "color": { + "text": "currentColor" + } + }, + "button": { + "color": { + "background": "var:preset|color|base", + "text": "var:preset|color|contrast" + }, + ":hover": { + "color": { + "background": "color-mix(in srgb, var(--wp--preset--color--base) 85%, transparent)" + } + } + } + } + }, + "section-4": { + "color": { + "text": "var:preset|color|base" + }, + "elements": { + "link": { + "color": { + "text": "currentColor" + } + }, + "button": { + "color": { + "background": "var:preset|color|base", + "text": "var:preset|color|contrast" + }, + ":hover": { + "color": { + "background": "color-mix(in srgb, var(--wp--preset--color--base) 85%, transparent)" + } + } + } + } + }, + "section-5": { + "color": { + "text": "var:preset|color|contrast", + "background": "var:preset|color|accent-5" + }, + "elements": { + "heading": { + "color": { + "text": "currentColor" + } + }, + "link": { + "color": { + "text": "currentColor" + } + }, + "button": { + "color": { + "background": "var:preset|color|contrast", + "text": "var:preset|color|base" + }, + ":hover": { + "color": { + "background": "color-mix(in srgb, var(--wp--preset--color--contrast) 85%, transparent)", + "text": "var:preset|color|base" + } + } + } + } + } + } + } +} diff --git a/content/themes/twentytwentyfive/styles/colors/08-midnight.json b/content/themes/twentytwentyfive/styles/colors/08-midnight.json new file mode 100644 index 0000000..c995e2e --- /dev/null +++ b/content/themes/twentytwentyfive/styles/colors/08-midnight.json @@ -0,0 +1,144 @@ +{ + "$schema": "https://schemas.wp.org/wp/6.7/theme.json", + "version": 3, + "title": "Midnight", + "settings": { + "color": { + "duotone": [ + { + "colors": [ + "#4433A6", + "#79F3B1" + ], + "name": "Midnight filter", + "slug": "midnight-filter" + } + ], + "palette": [ + { + "color": "#4433A6", + "name": "Base", + "slug": "base" + }, + { + "color": "#79F3B1", + "name": "Contrast", + "slug": "contrast" + }, + { + "color": "#5644BC", + "name": "Accent 1", + "slug": "accent-1" + }, + { + "color": "#372696", + "name": "Accent 2", + "slug": "accent-2" + }, + { + "color": "#251D51", + "name": "Accent 3", + "slug": "accent-3" + }, + { + "color": "#79F3B1", + "name": "Accent 4", + "slug": "accent-4" + }, + { + "color": "#E8B7FF", + "name": "Accent 5", + "slug": "accent-5" + }, + { + "color": "#79F3B133", + "name": "Accent 6", + "slug": "accent-6" + } + ] + } + }, + "styles": { + "blocks": { + "core/code": { + "color": { + "background": "var:preset|color|accent-2", + "text": "var:preset|color|contrast" + } + }, + "core/post-date": { + "color": { + "text": "var:preset|color|contrast" + }, + "elements": { + "link": { + "color": { + "text": "var:preset|color|contrast" + } + } + } + } + }, + "elements": { + "button": { + "color": { + "background": "var:preset|color|contrast", + "text": "var:preset|color|base" + }, + ":hover": { + "color": { + "background": "color-mix(in srgb, var(--wp--preset--color--contrast) 85%, transparent)" + } + } + } + }, + "variations": { + "section-1": { + "color": { + "text": "var:preset|color|accent-3" + }, + "elements": { + "button": { + "color": { + "background": "var:preset|color|accent-3", + "text": "var:preset|color|accent-5" + }, + ":hover": { + "color": { + "background": "color-mix(in srgb, var(--wp--preset--color--accent-3) 85%, transparent)" + } + } + }, + "link": { + "color": { + "text": "currentColor" + } + } + } + }, + "section-4": { + "color": { + "text": "var:preset|color|accent-5" + }, + "elements": { + "button": { + "color": { + "background": "var:preset|color|accent-5", + "text": "var:preset|color|accent-3" + }, + ":hover": { + "color": { + "background": "color-mix(in srgb, var(--wp--preset--color--accent-5) 85%, transparent)" + } + } + }, + "link": { + "color": { + "text": "currentColor" + } + } + } + } + } + } +} diff --git a/content/themes/twentytwentyfive/styles/sections/section-1.json b/content/themes/twentytwentyfive/styles/sections/section-1.json new file mode 100644 index 0000000..642f3b2 --- /dev/null +++ b/content/themes/twentytwentyfive/styles/sections/section-1.json @@ -0,0 +1,130 @@ +{ + "$schema": "https://schemas.wp.org/wp/6.7/theme.json", + "version": 3, + "slug": "section-1", + "title": "Style 1", + "blockTypes": [ + "core/group", + "core/columns", + "core/column" + ], + "styles": { + "color": { + "background": "var:preset|color|accent-5", + "text": "var:preset|color|contrast" + }, + "blocks": { + "core/separator": { + "color": { + "text": "color-mix(in srgb, currentColor 25%, transparent)" + } + }, + "core/site-title": { + "color": { + "text": "currentColor" + }, + "elements": { + "link": { + "color": { + "text": "currentColor" + } + } + } + }, + "core/post-author-name": { + "color": { + "text": "currentColor" + }, + "elements": { + "link": { + "color": { + "text": "currentColor" + } + } + } + }, + "core/post-date": { + "color":{ + "text": "color-mix(in srgb, currentColor 85%, transparent)" + }, + "elements": { + "link": { + "color" : { + "text": "color-mix(in srgb, currentColor 85%, transparent)" + } + } + } + }, + "core/post-terms": { + "color": { + "text": "currentColor" + }, + "elements": { + "link": { + "color": { + "text": "currentColor" + } + } + } + }, + "core/comment-author-name": { + "color": { + "text": "currentColor" + }, + "elements": { + "link": { + "color": { + "text": "currentColor" + } + } + } + }, + "core/comment-date": { + "color": { + "text": "currentColor" + }, + "elements": { + "link": { + "color": { + "text": "currentColor" + } + } + } + }, + "core/comment-edit-link": { + "color": { + "text": "currentColor" + }, + "elements": { + "link": { + "color": { + "text": "currentColor" + } + } + } + }, + "core/comment-reply-link": { + "color": { + "text": "currentColor" + }, + "elements": { + "link": { + "color": { + "text": "currentColor" + } + } + } + }, + "core/pullquote": { + "color": { + "text": "currentColor" + } + }, + "core/quote": { + "color": { + "text": "currentColor" + } + } + } + } +} diff --git a/content/themes/twentytwentyfive/styles/sections/section-2.json b/content/themes/twentytwentyfive/styles/sections/section-2.json new file mode 100644 index 0000000..81459c0 --- /dev/null +++ b/content/themes/twentytwentyfive/styles/sections/section-2.json @@ -0,0 +1,118 @@ +{ + "$schema": "https://schemas.wp.org/wp/6.7/theme.json", + "version": 3, + "slug": "section-2", + "title": "Style 2", + "blockTypes": [ + "core/group", + "core/columns", + "core/column" + ], + "styles": { + "color": { + "background": "var:preset|color|accent-2", + "text": "var:preset|color|contrast" + }, + "blocks": { + "core/separator": { + "color": { + "text": "color-mix(in srgb, currentColor 25%, transparent)" + } + }, + "core/post-author-name": { + "color": { + "text": "currentColor" + }, + "elements": { + "link": { + "color": { + "text": "currentColor" + } + } + } + }, + "core/post-date": { + "color":{ + "text": "color-mix(in srgb, currentColor 85%, transparent)" + }, + "elements": { + "link": { + "color" : { + "text": "color-mix(in srgb, currentColor 85%, transparent)" + } + } + } + }, + "core/post-terms": { + "color": { + "text": "currentColor" + }, + "elements": { + "link": { + "color": { + "text": "currentColor" + } + } + } + }, + "core/comment-author-name": { + "color": { + "text": "currentColor" + }, + "elements": { + "link": { + "color": { + "text": "currentColor" + } + } + } + }, + "core/comment-date": { + "color": { + "text": "currentColor" + }, + "elements": { + "link": { + "color": { + "text": "currentColor" + } + } + } + }, + "core/comment-edit-link": { + "color": { + "text": "currentColor" + }, + "elements": { + "link": { + "color": { + "text": "currentColor" + } + } + } + }, + "core/comment-reply-link": { + "color": { + "text": "currentColor" + }, + "elements": { + "link": { + "color": { + "text": "currentColor" + } + } + } + }, + "core/pullquote": { + "color": { + "text": "currentColor" + } + }, + "core/quote": { + "color": { + "text": "currentColor" + } + } + } + } +} diff --git a/content/themes/twentytwentyfive/styles/sections/section-3.json b/content/themes/twentytwentyfive/styles/sections/section-3.json new file mode 100644 index 0000000..3d1c0a6 --- /dev/null +++ b/content/themes/twentytwentyfive/styles/sections/section-3.json @@ -0,0 +1,118 @@ +{ + "$schema": "https://schemas.wp.org/wp/6.7/theme.json", + "version": 3, + "slug": "section-3", + "title": "Style 3", + "blockTypes": [ + "core/group", + "core/columns", + "core/column" + ], + "styles": { + "color": { + "background": "var:preset|color|accent-1", + "text": "var:preset|color|contrast" + }, + "blocks": { + "core/separator": { + "color": { + "text": "color-mix(in srgb, currentColor 25%, transparent)" + } + }, + "core/post-author-name": { + "color": { + "text": "currentColor" + }, + "elements": { + "link": { + "color": { + "text": "currentColor" + } + } + } + }, + "core/post-date": { + "color":{ + "text": "color-mix(in srgb, currentColor 85%, transparent)" + }, + "elements": { + "link": { + "color" : { + "text": "color-mix(in srgb, currentColor 85%, transparent)" + } + } + } + }, + "core/post-terms": { + "color": { + "text": "currentColor" + }, + "elements": { + "link": { + "color": { + "text": "currentColor" + } + } + } + }, + "core/comment-author-name": { + "color": { + "text": "currentColor" + }, + "elements": { + "link": { + "color": { + "text": "currentColor" + } + } + } + }, + "core/comment-date": { + "color": { + "text": "currentColor" + }, + "elements": { + "link": { + "color": { + "text": "currentColor" + } + } + } + }, + "core/comment-edit-link": { + "color": { + "text": "currentColor" + }, + "elements": { + "link": { + "color": { + "text": "currentColor" + } + } + } + }, + "core/comment-reply-link": { + "color": { + "text": "currentColor" + }, + "elements": { + "link": { + "color": { + "text": "currentColor" + } + } + } + }, + "core/pullquote": { + "color": { + "text": "currentColor" + } + }, + "core/quote": { + "color": { + "text": "currentColor" + } + } + } + } +} diff --git a/content/themes/twentytwentyfive/styles/sections/section-4.json b/content/themes/twentytwentyfive/styles/sections/section-4.json new file mode 100644 index 0000000..226779b --- /dev/null +++ b/content/themes/twentytwentyfive/styles/sections/section-4.json @@ -0,0 +1,132 @@ +{ + "$schema": "https://schemas.wp.org/wp/6.7/theme.json", + "version": 3, + "slug": "section-4", + "title": "Style 4", + "blockTypes": [ + "core/group", + "core/columns", + "core/column" + ], + "styles": { + "color": { + "background": "var:preset|color|accent-3", + "text": "var:preset|color|accent-2" + }, + "blocks": { + "core/separator": { + "color": { + "text": "color-mix(in srgb, currentColor 25%, transparent)" + } + }, + "core/post-author-name": { + "color": { + "text": "currentColor" + }, + "elements": { + "link": { + "color": { + "text": "currentColor" + } + } + } + }, + "core/post-date": { + "color":{ + "text": "color-mix(in srgb, currentColor 85%, transparent)" + }, + "elements": { + "link": { + "color" : { + "text": "color-mix(in srgb, currentColor 85%, transparent)" + } + } + } + }, + "core/post-terms": { + "color": { + "text": "currentColor" + }, + "elements": { + "link": { + "color": { + "text": "currentColor" + } + } + } + }, + "core/comment-author-name": { + "color": { + "text": "currentColor" + }, + "elements": { + "link": { + "color": { + "text": "currentColor" + } + } + } + }, + "core/comment-date": { + "color": { + "text": "currentColor" + }, + "elements": { + "link": { + "color": { + "text": "currentColor" + } + } + } + }, + "core/comment-edit-link": { + "color": { + "text": "currentColor" + }, + "elements": { + "link": { + "color": { + "text": "currentColor" + } + } + } + }, + "core/comment-reply-link": { + "color": { + "text": "currentColor" + }, + "elements": { + "link": { + "color": { + "text": "currentColor" + } + } + } + }, + "core/pullquote": { + "color": { + "text": "currentColor" + } + }, + "core/quote": { + "color": { + "text": "currentColor" + } + } + }, + "elements": { + "button": { + "color": { + "background": "var:preset|color|accent-2", + "text": "var:preset|color|accent-3" + }, + ":hover": { + "color": { + "background": "color-mix(in srgb, var(--wp--preset--color--accent-2) 85%, transparent)", + "text": "var:preset|color|accent-3" + } + } + } + } + } +} diff --git a/content/themes/twentytwentyfive/styles/sections/section-5.json b/content/themes/twentytwentyfive/styles/sections/section-5.json new file mode 100644 index 0000000..c9b37a8 --- /dev/null +++ b/content/themes/twentytwentyfive/styles/sections/section-5.json @@ -0,0 +1,132 @@ +{ + "$schema": "https://schemas.wp.org/wp/6.7/theme.json", + "version": 3, + "slug": "section-5", + "title": "Style 5", + "blockTypes": [ + "core/group", + "core/columns", + "core/column" + ], + "styles": { + "color": { + "background": "var:preset|color|contrast", + "text": "var:preset|color|base" + }, + "blocks": { + "core/separator": { + "color": { + "text": "color-mix(in srgb, currentColor 25%, transparent)" + } + }, + "core/post-author-name": { + "color": { + "text": "currentColor" + }, + "elements": { + "link": { + "color": { + "text": "currentColor" + } + } + } + }, + "core/post-date": { + "color":{ + "text": "color-mix(in srgb, currentColor 85%, transparent)" + }, + "elements": { + "link": { + "color" : { + "text": "color-mix(in srgb, currentColor 85%, transparent)" + } + } + } + }, + "core/post-terms": { + "color": { + "text": "currentColor" + }, + "elements": { + "link": { + "color": { + "text": "currentColor" + } + } + } + }, + "core/comment-author-name": { + "color": { + "text": "currentColor" + }, + "elements": { + "link": { + "color": { + "text": "currentColor" + } + } + } + }, + "core/comment-date": { + "color": { + "text": "currentColor" + }, + "elements": { + "link": { + "color": { + "text": "currentColor" + } + } + } + }, + "core/comment-edit-link": { + "color": { + "text": "currentColor" + }, + "elements": { + "link": { + "color": { + "text": "currentColor" + } + } + } + }, + "core/comment-reply-link": { + "color": { + "text": "currentColor" + }, + "elements": { + "link": { + "color": { + "text": "currentColor" + } + } + } + }, + "core/pullquote": { + "color": { + "text": "currentColor" + } + }, + "core/quote": { + "color": { + "text": "currentColor" + } + } + }, + "elements": { + "button": { + "color": { + "background": "var:preset|color|base", + "text": "var:preset|color|contrast" + }, + ":hover": { + "color": { + "background": "color-mix(in srgb, var(--wp--preset--color--base) 80%, transparent)", + "text": "var:preset|color|contrast" + } + } + } + } + } +} diff --git a/content/themes/twentytwentyfive/styles/typography/typography-preset-1.json b/content/themes/twentytwentyfive/styles/typography/typography-preset-1.json new file mode 100644 index 0000000..ad6c6cd --- /dev/null +++ b/content/themes/twentytwentyfive/styles/typography/typography-preset-1.json @@ -0,0 +1,292 @@ +{ + "version": 3, + "$schema": "https://schemas.wp.org/wp/6.7/theme.json", + "title": "Beiruti & Literata", + "slug": "typography-preset-1", + "settings": { + "typography": { + "fontFamilies": [ + { + "name": "Beiruti", + "slug": "beiruti", + "fontFamily": "Beiruti, sans-serif", + "fontFace": [ + { + "fontFamily": "Beiruti", + "fontStyle": "normal", + "fontWeight": "200 900", + "src": [ + "file:./assets/fonts/beiruti/Beiruti-VariableFont_wght.woff2" + ] + } + ] + }, + { + "name": "Literata", + "slug": "literata", + "fontFamily": "Literata, serif", + "fontFace": [ + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-ExtraLight.woff2" + ], + "fontWeight": "200", + "fontStyle": "normal", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-ExtraLightItalic.woff2" + ], + "fontWeight": "200", + "fontStyle": "italic", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-Light.woff2" + ], + "fontWeight": "300", + "fontStyle": "normal", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-LightItalic.woff2" + ], + "fontWeight": "300", + "fontStyle": "italic", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-Regular.woff2" + ], + "fontWeight": "400", + "fontStyle": "normal", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-RegularItalic.woff2" + ], + "fontWeight": "400", + "fontStyle": "italic", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-Medium.woff2" + ], + "fontWeight": "500", + "fontStyle": "normal", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-MediumItalic.woff2" + ], + "fontWeight": "500", + "fontStyle": "italic", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-SemiBold.woff2" + ], + "fontWeight": "600", + "fontStyle": "normal", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-SemiBoldItalic.woff2" + ], + "fontWeight": "600", + "fontStyle": "italic", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-Bold.woff2" + ], + "fontWeight": "700", + "fontStyle": "normal", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-BoldItalic.woff2" + ], + "fontWeight": "700", + "fontStyle": "italic", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-ExtraBold.woff2" + ], + "fontWeight": "800", + "fontStyle": "normal", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-ExtraBoldItalic.woff2" + ], + "fontWeight": "800", + "fontStyle": "italic", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-Black.woff2" + ], + "fontWeight": "900", + "fontStyle": "normal", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-BlackItalic.woff2" + ], + "fontWeight": "900", + "fontStyle": "italic", + "fontFamily": "Literata" + } + ] + } + ], + "fontSizes": [ + { + "fluid": false, + "name": "Small", + "size": "0.9rem", + "slug": "small" + }, + { + "fluid": { + "max": "1.2rem", + "min": "1rem" + }, + "name": "Medium", + "size": "1rem", + "slug": "medium" + }, + { + "fluid": { + "max": "1.8rem", + "min": "1.6rem" + }, + "name": "Large", + "size": "1.6rem", + "slug": "large" + }, + { + "fluid": { + "max": "2.2rem", + "min": "1.8em" + }, + "name": "Extra Large", + "size": "1.8rem", + "slug": "x-large" + }, + { + "fluid": { + "max": "2.8rem", + "min": "2rem" + }, + "name": "Extra Extra Large", + "size": "2rem", + "slug": "xx-large" + } + ] + } + }, + "styles": { + "typography": { + "fontFamily": "var:preset|font-family|literata", + "fontSize": "var:preset|font-size|medium", + "letterSpacing": "-0.01em", + "lineHeight": "1.6" + }, + "blocks": { + "core/button": { + "typography": { + "fontFamily": "var:preset|font-family|beiruti" + } + }, + "core/list": { + "typography": { + "lineHeight": "1.3" + } + }, + "core/loginout": { + "typography": { + "fontSize": "var:preset|font-size|medium" + } + }, + "core/post-terms": { + "typography": { + "fontWeight": "300" + } + }, + "core/pullquote": { + "typography": { + "fontFamily": "var:preset|font-family|beiruti", + "fontWeight": "500", + "lineHeight": "1" + } + }, + "core/quote": { + "typography": { + "fontSize": "var:preset|font-size|medium" + } + }, + "core/query-pagination": { + "typography": { + "fontWeight": "300" + } + }, + "core/site-tagline": { + "typography": { + "fontSize": "var:preset|font-size|small" + } + }, + "core/site-title": { + "typography": { + "fontFamily": "var:preset|font-family|beiruti", + "fontWeight": "600", + "letterSpacing": "2.4px", + "textTransform": "uppercase" + } + } + }, + "elements": { + "h4": { + "typography": { + "fontSize": "var:preset|font-size|large" + } + }, + "h5": { + "typography": { + "fontSize": "var:preset|font-size|medium", + "letterSpacing": "0px" + } + }, + "h6": { + "typography": { + "fontSize": "var:preset|font-size|small" + } + }, + "heading": { + "typography": { + "fontFamily": "var:preset|font-family|beiruti", + "fontWeight": "500", + "letterSpacing": "-0.02em", + "lineHeight": "1.02" + } + } + } + } +} diff --git a/content/themes/twentytwentyfive/styles/typography/typography-preset-2.json b/content/themes/twentytwentyfive/styles/typography/typography-preset-2.json new file mode 100644 index 0000000..e3e26b3 --- /dev/null +++ b/content/themes/twentytwentyfive/styles/typography/typography-preset-2.json @@ -0,0 +1,150 @@ +{ + "version": 3, + "$schema": "https://schemas.wp.org/wp/6.7/theme.json", + "title": "Vollkorn & Fira Code", + "slug": "typography-preset-2", + "settings": { + "typography": { + "fontFamilies": [ + { + "name": "Vollkorn", + "slug": "vollkorn", + "fontFamily": "Vollkorn, serif", + "fontFace": [ + { + "src": [ + "file:./assets/fonts/vollkorn/Vollkorn-Italic-VariableFont_wght.woff2" + ], + "fontWeight": "400 900", + "fontStyle": "italic", + "fontFamily": "Vollkorn" + }, + { + "src": [ + "file:./assets/fonts/vollkorn/Vollkorn-VariableFont_wght.woff2" + ], + "fontWeight": "400 900", + "fontStyle": "normal", + "fontFamily": "Vollkorn" + } + ] + }, + { + "name": "Fira Code", + "slug": "fira-code", + "fontFamily": "\"Fira Code\", monospace", + "fontFace": [ + { + "src": [ + "file:./assets/fonts/fira-code/FiraCode-VariableFont_wght.woff2" + ], + "fontWeight": "300 700", + "fontStyle": "normal", + "fontFamily": "\"Fira Code\"" + } + ] + } + ] + } + }, + "styles": { + "typography": { + "fontFamily": "var:preset|font-family|fira-code", + "fontSize": "var:preset|font-size|medium", + "letterSpacing": "-0.18px", + "lineHeight": "1.5" + }, + "blocks": { + "core/post-author-name": { + "typography": { + "fontWeight": "300" + } + }, + "core/post-terms": { + "typography": { + "fontWeight": "300" + } + }, + "core/post-title": { + "typography": { + "fontWeight": "400", + "letterSpacing": "-0.96px" + } + }, + "core/pullquote": { + "typography": { + "fontFamily": "var:preset|font-family|vollkorn", + "fontSize": "var:preset|font-size|x-large", + "fontWeight": "400" + }, + "elements": { + "cite": { + "typography": { + "fontFamily": "var:preset|font-family|fira-code", + "fontWeight": "300", + "letterSpacing": "-0.14px" + } + } + } + }, + "core/quote": { + "typography": { + "fontFamily": "var:preset|font-family|fira-code", + "fontWeight": "500", + "letterSpacing": "-0.18px" + } + }, + "core/site-title": { + "typography": { + "fontFamily": "var:preset|font-family|vollkorn", + "fontSize": "var:preset|font-size|x-large" + } + } + }, + "elements": { + "button": { + "typography": { + "fontFamily": "var:preset|font-family|fira-code", + "fontSize": "var:preset|font-size|medium", + "fontWeight": "400", + "letterSpacing": "-0.36px" + } + }, + "heading": { + "typography": { + "fontFamily": "var:preset|font-family|vollkorn" + } + }, + "h1": { + "typography": { + "fontSize": "48px", + "letterSpacing": "-0.96px;" + } + }, + "h2": { + "typography": { + "fontSize": "38px", + "letterSpacing": "-0.96px" + } + }, + "h3": { + "typography": { + "fontSize": "32px", + "letterSpacing": "-0.64px" + } + }, + "h4": { + "typography": { + "fontSize": "28px", + "letterSpacing": "-0.56px" + } + }, + "h5": { + "typography": { + "fontSize": "24px", + "letterSpacing": "-0.48px" + } + } + } + } +} diff --git a/content/themes/twentytwentyfive/styles/typography/typography-preset-3.json b/content/themes/twentytwentyfive/styles/typography/typography-preset-3.json new file mode 100644 index 0000000..6d64153 --- /dev/null +++ b/content/themes/twentytwentyfive/styles/typography/typography-preset-3.json @@ -0,0 +1,186 @@ +{ + "version": 3, + "$schema": "https://schemas.wp.org/wp/6.7/theme.json", + "title": "Platypi & Ysabeau Office", + "slug": "typography-preset-3", + "settings": { + "typography": { + "fontFamilies": [ + { + "name": "Platypi", + "slug": "platypi", + "fontFamily": "Platypi", + "fontFace": [ + { + "fontFamily": "Platypi", + "fontStyle": "normal", + "fontWeight": "300 800", + "src": [ + "file:./assets/fonts/platypi/Platypi-VariableFont_wght.woff2" + ] + }, + { + "fontFamily": "Platypi", + "fontStyle": "italic", + "fontWeight": "300 800", + "src": [ + "file:./assets/fonts/platypi/Platypi-Italic-VariableFont_wght.woff2" + ] + } + ] + }, + { + "name": "Ysabeau Office", + "slug": "ysabeau-office", + "fontFamily": "\"Ysabeau Office\", sans-serif", + "fontFace": [ + { + "src": [ + "file:./assets/fonts/ysabeau-office/YsabeauOffice-VariableFont_wght.woff2" + ], + "fontWeight": "100 900", + "fontStyle": "normal", + "fontFamily": "\"Ysabeau Office\"" + }, + { + "src": [ + "file:./assets/fonts/ysabeau-office/YsabeauOffice-Italic-VariableFont_wght.woff2" + ], + "fontWeight": "100 900", + "fontStyle": "italic", + "fontFamily": "\"Ysabeau Office\"" + } + ] + } + ], + "fontSizes": [ + { + "fluid": false, + "name": "Small", + "size": "0.875rem", + "slug": "small" + }, + { + "fluid": { + "max": "1.125rem", + "min": "1rem" + }, + "name": "Medium", + "size": "1rem", + "slug": "medium" + }, + { + "fluid": { + "max": "1.375rem", + "min": "1.125rem" + }, + "name": "Large", + "size": "1.38rem", + "slug": "large" + }, + { + "fluid": { + "max": "1.8rem", + "min": "1.4rem" + }, + "name": "Extra Large", + "size": "1.4rem", + "slug": "x-large" + }, + { + "fluid": { + "max": "2.6rem", + "min": "2rem" + }, + "name": "Extra Extra Large", + "size": "2rem", + "slug": "xx-large" + } + ] + } + }, + "styles": { + "typography": { + "fontFamily": "var:preset|font-family|ysabeau-office", + "letterSpacing": "-0.22px", + "lineHeight": "1.5" + }, + "blocks":{ + "core/code": { + "typography": { + "letterSpacing": "0px" + } + }, + "core/heading": { + "typography": { + "lineHeight": "1.2" + } + }, + "core/list": { + "typography": { + "lineHeight": "1.3" + } + }, + "core/loginout": { + "typography": { + "fontSize": "var:preset|font-size|medium" + } + }, + "core/post-terms": { + "typography": { + "fontWeight": "400" + } + }, + "core/pullquote": { + "typography": { + "fontFamily": "var:preset|font-family|platypi", + "letterSpacing": "-0.01em", + "lineHeight": "1.1" + } + }, + "core/quote": { + "typography": { + "fontWeight": "300" + } + }, + "core/site-title": { + "typography": { + "fontFamily": "var:preset|font-family|ysabeau-office", + "fontSize": "var:preset|font-size|large", + "letterSpacing": "1.44px", + "textTransform": "uppercase" + } + } + }, + "elements": { + "button": { + "typography": { + "fontFamily": "var:preset|font-family|ysabeau-office", + "fontWeight": "600", + "letterSpacing": "1.44px", + "textTransform": "uppercase" + } + }, + "heading": { + "typography": { + "fontFamily": "var:preset|font-family|platypi" + } + }, + "h5": { + "typography": { + "fontSize": "var:preset|font-size|medium", + "letterSpacing": "normal" + } + }, + "h6": { + "typography": { + "fontSize": "var:preset|font-size|small", + "fontWeight": "400", + "fontStyle": "initial", + "letterSpacing": "initial", + "textTransform": "initial" + } + } + } + } +} diff --git a/content/themes/twentytwentyfive/styles/typography/typography-preset-4.json b/content/themes/twentytwentyfive/styles/typography/typography-preset-4.json new file mode 100644 index 0000000..62a6362 --- /dev/null +++ b/content/themes/twentytwentyfive/styles/typography/typography-preset-4.json @@ -0,0 +1,154 @@ +{ + "version": 3, + "$schema": "https://schemas.wp.org/wp/6.7/theme.json", + "title": "Roboto Slab & Manrope", + "slug": "typography-preset-4", + "settings": { + "typography": { + "fontFamilies": [ + { + "name": "Roboto Slab", + "slug": "roboto-slab", + "fontFamily": "\"Roboto Slab\", serif", + "fontFace": [ + { + "fontFamily": "\"Roboto Slab\"", + "fontStyle": "normal", + "fontWeight": "100 900", + "src": [ + "file:./assets/fonts/roboto-slab/RobotoSlab-VariableFont_wght.woff2" + ] + } + ] + }, + { + "name": "Manrope", + "slug": "manrope", + "fontFamily": "Manrope, sans-serif", + "fontFace": [ + { + "src": [ + "file:./assets/fonts/manrope/Manrope-VariableFont_wght.woff2" + ], + "fontWeight": "200 800", + "fontStyle": "normal", + "fontFamily": "Manrope" + } + ] + } + ], + "fontSizes": [ + { + "fluid": false, + "name": "Small", + "size": "0.875rem", + "slug": "small" + }, + { + "fluid": { + "max": "1.125rem", + "min": "1rem" + }, + "name": "Medium", + "size": "1rem", + "slug": "medium" + }, + { + "fluid": { + "max": "1.375rem", + "min": "1.125rem" + }, + "name": "Large", + "size": "1.38rem", + "slug": "large" + }, + { + "fluid": { + "max": "2rem", + "min": "1.75rem" + }, + "name": "Extra Large", + "size": "1.75rem", + "slug": "x-large" + }, + { + "fluid": { + "max": "2.4rem", + "min": "2.15rem" + }, + "name": "Extra Extra Large", + "size": "2.15rem", + "slug": "xx-large" + } + ] + } + }, + "styles": { + "typography": { + "letterSpacing": "0" + }, + "blocks": { + "core/navigation": { + "typography": { + "fontSize": "var:preset|font-size|large", + "letterSpacing": "-0.28px", + "textTransform": "uppercase" + } + }, + "core/post-author": { + "typography": { + "fontSize": "var:preset|font-size|small" + } + }, + "core/post-author-name": { + "typography": { + "fontSize": "var:preset|font-size|small" + } + }, + "core/post-terms": { + "typography": { + "fontWeight": "500" + } + }, + "core/pullquote": { + "typography": { + "fontFamily": "var:preset|font-family|roboto-slab", + "fontSize": "var:preset|font-size|xx-large", + "fontWeight": "200" + } + }, + "core/search": { + "typography": { + "textTransform": "uppercase" + } + }, + "core/site-tagline": { + "typography": { + "fontSize": "var:preset|font-size|large" + } + }, + "core/site-title": { + "typography": { + "textTransform": "uppercase" + } + } + }, + "elements": { + "button": { + "typography": { + "fontWeight": "500", + "letterSpacing": "-0.36px", + "textTransform": "uppercase" + } + }, + "heading": { + "typography": { + "fontFamily": "var:preset|font-family|roboto-slab", + "fontWeight": "300", + "letterSpacing": "-0.5px", + "lineHeight": "1.2" + } + } + } + } +} diff --git a/content/themes/twentytwentyfive/styles/typography/typography-preset-5.json b/content/themes/twentytwentyfive/styles/typography/typography-preset-5.json new file mode 100644 index 0000000..e30d03e --- /dev/null +++ b/content/themes/twentytwentyfive/styles/typography/typography-preset-5.json @@ -0,0 +1,303 @@ +{ + "version": 3, + "$schema": "https://schemas.wp.org/wp/6.7/theme.json", + "title": "Literata & Ysabeau Office", + "slug": "typography-preset-5", + "settings": { + "typography": { + "fontFamilies": [ + { + "name": "Literata", + "slug": "literata", + "fontFamily": "Literata, serif", + "fontFace": [ + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-ExtraLight.woff2" + ], + "fontWeight": "200", + "fontStyle": "normal", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-ExtraLightItalic.woff2" + ], + "fontWeight": "200", + "fontStyle": "italic", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-Light.woff2" + ], + "fontWeight": "300", + "fontStyle": "normal", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-LightItalic.woff2" + ], + "fontWeight": "300", + "fontStyle": "italic", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-Regular.woff2" + ], + "fontWeight": "400", + "fontStyle": "normal", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-RegularItalic.woff2" + ], + "fontWeight": "400", + "fontStyle": "italic", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-Medium.woff2" + ], + "fontWeight": "500", + "fontStyle": "normal", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-MediumItalic.woff2" + ], + "fontWeight": "500", + "fontStyle": "italic", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-SemiBold.woff2" + ], + "fontWeight": "600", + "fontStyle": "normal", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-SemiBoldItalic.woff2" + ], + "fontWeight": "600", + "fontStyle": "italic", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-Bold.woff2" + ], + "fontWeight": "700", + "fontStyle": "normal", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-BoldItalic.woff2" + ], + "fontWeight": "700", + "fontStyle": "italic", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-ExtraBold.woff2" + ], + "fontWeight": "800", + "fontStyle": "normal", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-ExtraBoldItalic.woff2" + ], + "fontWeight": "800", + "fontStyle": "italic", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-Black.woff2" + ], + "fontWeight": "900", + "fontStyle": "normal", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-BlackItalic.woff2" + ], + "fontWeight": "900", + "fontStyle": "italic", + "fontFamily": "Literata" + } + ] + }, + { + "name": "Ysabeau Office", + "slug": "ysabeau-office", + "fontFamily": "\"Ysabeau Office\", sans-serif", + "fontFace": [ + { + "src": [ + "file:./assets/fonts/ysabeau-office/YsabeauOffice-VariableFont_wght.woff2" + ], + "fontWeight": "100 900", + "fontStyle": "normal", + "fontFamily": "\"Ysabeau Office\"" + }, + { + "src": [ + "file:./assets/fonts/ysabeau-office/YsabeauOffice-Italic-VariableFont_wght.woff2" + ], + "fontWeight": "100 900", + "fontStyle": "italic", + "fontFamily": "\"Ysabeau Office\"" + } + ] + } + ], + "fontSizes": [ + { + "fluid": false, + "name": "Small", + "size": "0.875rem", + "slug": "small" + }, + { + "fluid": { + "max": "1.125rem", + "min": "1rem" + }, + "name": "Medium", + "size": "1rem", + "slug": "medium" + }, + { + "fluid": { + "max": "1.375rem", + "min": "1.125rem" + }, + "name": "Large", + "size": "1.38rem", + "slug": "large" + }, + { + "fluid": { + "max": "2rem", + "min": "1.75rem" + }, + "name": "Extra Large", + "size": "1.75rem", + "slug": "x-large" + }, + { + "fluid": { + "max": "2.6rem", + "min": "1.4rem" + }, + "name": "Extra Extra Large", + "size": "2.6rem", + "slug": "xx-large" + } + ] + } + }, + "styles": { + "typography": { + "fontFamily": "var:preset|font-family|ysabeau-office", + "letterSpacing": "-0.24px" + }, + "blocks": { + "core/navigation": { + "typography": { + "fontSize": "1.25rem" + } + }, + "core/post-title": { + "typography": { + "fontWeight": "900", + "letterSpacing": "-0.96px" + } + }, + "core/pullquote": { + "typography": { + "fontSize": "var:preset|font-size|xx-large" + }, + "elements": { + "cite": { + "typography": { + "fontSize": "var:preset|font-size|medium", + "letterSpacing": "-0.14px" + } + } + } + }, + "core/quote": { + "elements": { + "cite": { + "typography": { + "fontSize": "var:preset|font-size|medium", + "letterSpacing": "-0.14px" + } + } + } + }, + "core/query-title": { + "typography": { + "fontWeight": "900" + } + }, + "core/site-title": { + "typography": { + "fontFamily": "var:preset|font-family|ysabeau-office", + "textTransform": "uppercase", + "letterSpacing": "1.6px" + } + } + }, + "elements": { + "button": { + "typography": { + "fontFamily": "var:preset|font-family|literata", + "fontSize": "var:preset|font-size|medium", + "fontWeight": "900", + "letterSpacing": "-0.36px" + } + }, + "heading": { + "typography": { + "fontFamily": "var:preset|font-family|literata", + "fontWeight": "900", + "lineHeight": "1.2" + } + }, + "h5": { + "typography": { + "letterSpacing": "0px" + } + }, + "h6": { + "typography": { + "fontWeight": "900", + "letterSpacing": "0px" + } + } + }, + "variations": { + "post-terms-1": { + "typography": { + "fontSize": "var:preset|font-size|medium" + } + } + } + } +} diff --git a/content/themes/twentytwentyfive/styles/typography/typography-preset-6.json b/content/themes/twentytwentyfive/styles/typography/typography-preset-6.json new file mode 100644 index 0000000..d9eb663 --- /dev/null +++ b/content/themes/twentytwentyfive/styles/typography/typography-preset-6.json @@ -0,0 +1,257 @@ +{ + "version": 3, + "$schema": "https://schemas.wp.org/wp/6.7/theme.json", + "title": "Platypi & Literata", + "slug": "typography-preset-6", + "settings": { + "typography": { + "fontFamilies": [ + { + "name": "Platypi", + "slug": "platypi", + "fontFamily": "Platypi", + "fontFace": [ + { + "fontFamily": "Platypi", + "fontStyle": "normal", + "fontWeight": "300 800", + "src": [ + "file:./assets/fonts/platypi/Platypi-VariableFont_wght.woff2" + ] + }, + { + "fontFamily": "Platypi", + "fontStyle": "italic", + "fontWeight": "300 800", + "src": [ + "file:./assets/fonts/platypi/Platypi-Italic-VariableFont_wght.woff2" + ] + } + ] + }, + { + "name": "Literata", + "slug": "literata", + "fontFamily": "Literata, serif", + "fontFace": [ + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-ExtraLight.woff2" + ], + "fontWeight": "200", + "fontStyle": "normal", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-ExtraLightItalic.woff2" + ], + "fontWeight": "200", + "fontStyle": "italic", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-Light.woff2" + ], + "fontWeight": "300", + "fontStyle": "normal", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-LightItalic.woff2" + ], + "fontWeight": "300", + "fontStyle": "italic", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-Regular.woff2" + ], + "fontWeight": "400", + "fontStyle": "normal", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-RegularItalic.woff2" + ], + "fontWeight": "400", + "fontStyle": "italic", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-Medium.woff2" + ], + "fontWeight": "500", + "fontStyle": "normal", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-MediumItalic.woff2" + ], + "fontWeight": "500", + "fontStyle": "italic", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-SemiBold.woff2" + ], + "fontWeight": "600", + "fontStyle": "normal", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-SemiBoldItalic.woff2" + ], + "fontWeight": "600", + "fontStyle": "italic", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-Bold.woff2" + ], + "fontWeight": "700", + "fontStyle": "normal", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-BoldItalic.woff2" + ], + "fontWeight": "700", + "fontStyle": "italic", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-ExtraBold.woff2" + ], + "fontWeight": "800", + "fontStyle": "normal", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-ExtraBoldItalic.woff2" + ], + "fontWeight": "800", + "fontStyle": "italic", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-Black.woff2" + ], + "fontWeight": "900", + "fontStyle": "normal", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-BlackItalic.woff2" + ], + "fontWeight": "900", + "fontStyle": "italic", + "fontFamily": "Literata" + } + ] + } + ] + } + }, + "styles": { + "typography": { + "fontFamily": "var:preset|font-family|literata", + "fontSize": "1.5rem", + "letterSpacing": "-0.24px", + "lineHeight": "1.3" + }, + "blocks": { + "core/navigation": { + "typography": { + "fontSize": "1.25rem" + } + }, + "core/post-terms": { + "typography": { + "fontWeight": "400" + } + }, + "core/post-title": { + "typography": { + "fontWeight": "800", + "letterSpacing": "-0.96px" + } + }, + "core/pullquote": { + "typography": { + "fontFamily": "var:preset|font-family|platypi", + "fontSize": "var:preset|font-size|x-large", + "letterSpacing": "-0.76px", + "fontWeight": "800" + }, + "elements": { + "cite": { + "typography": { + "fontFamily": "var:preset|font-family|literata", + "fontWeight": "400", + "letterSpacing": "-0.14px" + } + } + } + }, + "core/quote": { + "typography": { + "fontSize": "1.5rem", + "fontWeight": "600", + "letterSpacing": "-0.24px" + }, + "elements": { + "cite": { + "typography": { + "letterSpacing": "-0.14px" + } + } + } + }, + "core/site-title": { + "typography": { + "fontFamily": "var:preset|font-family|platypi", + "fontSize": "30px", + "fontWeight": "800", + "letterSpacing": "-0.6px" + } + } + }, + "elements": { + "button": { + "typography": { + "fontFamily": "var:preset|font-family|platypi", + "fontSize": "1.5rem", + "fontWeight": "800" + } + }, + "heading": { + "typography": { + "fontFamily": "var:preset|font-family|platypi", + "fontWeight": "800" + } + } + }, + "variations": { + "post-terms-1": { + "typography": { + "fontSize": "16px" + } + } + } + } +} diff --git a/content/themes/twentytwentyfive/styles/typography/typography-preset-7.json b/content/themes/twentytwentyfive/styles/typography/typography-preset-7.json new file mode 100644 index 0000000..69b1740 --- /dev/null +++ b/content/themes/twentytwentyfive/styles/typography/typography-preset-7.json @@ -0,0 +1,411 @@ +{ + "version": 3, + "$schema": "https://schemas.wp.org/wp/6.7/theme.json", + "title": "Literata & Fira Sans", + "slug": "typography-preset-7", + "settings": { + "typography": { + "fontFamilies": [ + { + "name": "Literata", + "slug": "literata", + "fontFamily": "Literata, serif", + "fontFace": [ + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-ExtraLight.woff2" + ], + "fontWeight": "200", + "fontStyle": "normal", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-ExtraLightItalic.woff2" + ], + "fontWeight": "200", + "fontStyle": "italic", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-Light.woff2" + ], + "fontWeight": "300", + "fontStyle": "normal", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-LightItalic.woff2" + ], + "fontWeight": "300", + "fontStyle": "italic", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-Regular.woff2" + ], + "fontWeight": "400", + "fontStyle": "normal", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-RegularItalic.woff2" + ], + "fontWeight": "400", + "fontStyle": "italic", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-Medium.woff2" + ], + "fontWeight": "500", + "fontStyle": "normal", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-MediumItalic.woff2" + ], + "fontWeight": "500", + "fontStyle": "italic", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-SemiBold.woff2" + ], + "fontWeight": "600", + "fontStyle": "normal", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-SemiBoldItalic.woff2" + ], + "fontWeight": "600", + "fontStyle": "italic", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-Bold.woff2" + ], + "fontWeight": "700", + "fontStyle": "normal", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-BoldItalic.woff2" + ], + "fontWeight": "700", + "fontStyle": "italic", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-ExtraBold.woff2" + ], + "fontWeight": "800", + "fontStyle": "normal", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-ExtraBoldItalic.woff2" + ], + "fontWeight": "800", + "fontStyle": "italic", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-Black.woff2" + ], + "fontWeight": "900", + "fontStyle": "normal", + "fontFamily": "Literata" + }, + { + "src": [ + "file:./assets/fonts/literata/Literata72pt-BlackItalic.woff2" + ], + "fontWeight": "900", + "fontStyle": "italic", + "fontFamily": "Literata" + } + ] + }, + { + "name": "Fira Sans", + "slug": "fira-sans", + "fontFamily": "\"Fira Sans\", sans-serif", + "fontFace": [ + { + "src": [ + "file:./assets/fonts/fira-sans/FiraSans-Thin.woff2" + ], + "fontWeight": "100", + "fontStyle": "normal", + "fontFamily": "\"Fira Sans\"" + }, + { + "src": [ + "file:./assets/fonts/fira-sans/FiraSans-ThinItalic.woff2" + ], + "fontWeight": "100", + "fontStyle": "italic", + "fontFamily": "\"Fira Sans\"" + }, + { + "src": [ + "file:./assets/fonts/fira-sans/FiraSans-ExtraLight.woff2" + ], + "fontWeight": "200", + "fontStyle": "normal", + "fontFamily": "\"Fira Sans\"" + }, + { + "src": [ + "file:./assets/fonts/fira-sans/FiraSans-ExtraLightItalic.woff2" + ], + "fontWeight": "200", + "fontStyle": "italic", + "fontFamily": "\"Fira Sans\"" + }, + { + "src": [ + "file:./assets/fonts/fira-sans/FiraSans-Light.woff2" + ], + "fontWeight": "300", + "fontStyle": "normal", + "fontFamily": "\"Fira Sans\"" + }, + { + "src": [ + "file:./assets/fonts/fira-sans/FiraSans-LightItalic.woff2" + ], + "fontWeight": "300", + "fontStyle": "italic", + "fontFamily": "\"Fira Sans\"" + }, + { + "src": [ + "file:./assets/fonts/fira-sans/FiraSans-Italic.woff2" + ], + "fontWeight": "400", + "fontStyle": "italic", + "fontFamily": "\"Fira Sans\"" + }, + { + "src": [ + "file:./assets/fonts/fira-sans/FiraSans-Regular.woff2" + ], + "fontWeight": "400", + "fontStyle": "normal", + "fontFamily": "\"Fira Sans\"" + }, + { + "src": [ + "file:./assets/fonts/fira-sans/FiraSans-Medium.woff2" + ], + "fontWeight": "500", + "fontStyle": "normal", + "fontFamily": "\"Fira Sans\"" + }, + { + "src": [ + "file:./assets/fonts/fira-sans/FiraSans-MediumItalic.woff2" + ], + "fontWeight": "500", + "fontStyle": "italic", + "fontFamily": "\"Fira Sans\"" + }, + { + "src": [ + "file:./assets/fonts/fira-sans/FiraSans-SemiBold.woff2" + ], + "fontWeight": "600", + "fontStyle": "normal", + "fontFamily": "\"Fira Sans\"" + }, + { + "src": [ + "file:./assets/fonts/fira-sans/FiraSans-SemiBoldItalic.woff2" + ], + "fontWeight": "600", + "fontStyle": "italic", + "fontFamily": "\"Fira Sans\"" + }, + { + "src": [ + "file:./assets/fonts/fira-sans/FiraSans-Bold.woff2" + ], + "fontWeight": "700", + "fontStyle": "normal", + "fontFamily": "\"Fira Sans\"" + }, + { + "src": [ + "file:./assets/fonts/fira-sans/FiraSans-BoldItalic.woff2" + ], + "fontWeight": "700", + "fontStyle": "italic", + "fontFamily": "\"Fira Sans\"" + }, + { + "src": [ + "file:./assets/fonts/fira-sans/FiraSans-ExtraBold.woff2" + ], + "fontWeight": "800", + "fontStyle": "normal", + "fontFamily": "\"Fira Sans\"" + }, + { + "src": [ + "file:./assets/fonts/fira-sans/FiraSans-ExtraBoldItalic.woff2" + ], + "fontWeight": "800", + "fontStyle": "italic", + "fontFamily": "\"Fira Sans\"" + }, + { + "src": [ + "file:./assets/fonts/fira-sans/FiraSans-Black.woff2" + ], + "fontWeight": "900", + "fontStyle": "normal", + "fontFamily": "\"Fira Sans\"" + }, + { + "src": [ + "file:./assets/fonts/fira-sans/FiraSans-BlackItalic.woff2" + ], + "fontWeight": "900", + "fontStyle": "italic", + "fontFamily": "\"Fira Sans\"" + } + ] + } + ], + "fontSizes": [ + { + "fluid": false, + "name": "Small", + "size": "0.9rem", + "slug": "small" + }, + { + "fluid": { + "max": "1.2rem", + "min": "0.9rem" + }, + "name": "Medium", + "size": "1rem", + "slug": "medium" + }, + { + "fluid": { + "max": "1.8rem", + "min": "1.2rem" + }, + "name": "Large", + "size": "1.2rem", + "slug": "large" + }, + { + "fluid": { + "max": "2.2rem", + "min": "1.8rem" + }, + "name": "Extra Large", + "size": "1.8rem", + "slug": "x-large" + }, + { + "fluid": { + "max": "2.8rem", + "min": "2rem" + }, + "name": "Extra Extra Large", + "size": "2rem", + "slug": "xx-large" + } + ] + } + }, + "styles": { + "typography": { + "fontSize": "var:preset|font-size|medium", + "fontFamily": "var:preset|font-family|fira-sans", + "letterSpacing": "-0.01em", + "lineHeight": "1.5" + }, + "blocks": { + "core/post-title": { + "typography": { + "fontWeight": "200" + } + }, + "core/pullquote": { + "typography": { + "fontFamily": "var:preset|font-family|literata", + "fontWeight": "200", + "letterSpacing": "0em" + } + }, + "core/query-pagination": { + "typography": { + "fontWeight": "300", + "letterSpacing": "0px" + } + }, + "core/quote": { + "typography": { + "fontSize": "var:preset|font-size|medium", + "letterSpacing": "-0.01em", + "lineHeight": "1.5", + "fontWeight": "300" + } + }, + "core/site-title": { + "typography": { + "fontFamily": "var:preset|font-family|literata", + "fontSize": "var:preset|font-size|x-large", + "fontWeight": "300", + "letterSpacing": "-0.56px", + "textTransform": "uppercase" + } + } + }, + "elements": { + "button": { + "typography": { + "fontFamily": "var:preset|font-family|literata", + "fontSize": "var:preset|font-size|medium", + "fontWeight": "400", + "letterSpacing": "-0.01em", + "textTransform": "uppercase" + } + }, + "heading": { + "typography": { + "fontFamily": "var:preset|font-family|literata", + "fontWeight": "200", + "letterSpacing": "-0.02em", + "lineHeight": "1.24" + } + }, + "h6": { + "typography": { + "fontWeight": "200" + } + } + } + } +} diff --git a/content/themes/twentytwentyfive/templates/404.html b/content/themes/twentytwentyfive/templates/404.html new file mode 100644 index 0000000..379f83d --- /dev/null +++ b/content/themes/twentytwentyfive/templates/404.html @@ -0,0 +1,9 @@ + + + +
    + +
    + + + diff --git a/content/themes/twentytwentyfive/templates/archive.html b/content/themes/twentytwentyfive/templates/archive.html new file mode 100644 index 0000000..3b0ddbe --- /dev/null +++ b/content/themes/twentytwentyfive/templates/archive.html @@ -0,0 +1,11 @@ + + + +
    + + + +
    + + + diff --git a/content/themes/twentytwentyfive/templates/home.html b/content/themes/twentytwentyfive/templates/home.html new file mode 100644 index 0000000..ae6870c --- /dev/null +++ b/content/themes/twentytwentyfive/templates/home.html @@ -0,0 +1,10 @@ + + + +
    + + +
    + + + diff --git a/content/themes/twentytwentyfive/templates/index.html b/content/themes/twentytwentyfive/templates/index.html new file mode 100644 index 0000000..ae6870c --- /dev/null +++ b/content/themes/twentytwentyfive/templates/index.html @@ -0,0 +1,10 @@ + + + +
    + + +
    + + + diff --git a/content/themes/twentytwentyfive/templates/page-no-title.html b/content/themes/twentytwentyfive/templates/page-no-title.html new file mode 100644 index 0000000..17e4781 --- /dev/null +++ b/content/themes/twentytwentyfive/templates/page-no-title.html @@ -0,0 +1,9 @@ + + + +
    + +
    + + + diff --git a/content/themes/twentytwentyfive/templates/page.html b/content/themes/twentytwentyfive/templates/page.html new file mode 100644 index 0000000..4331194 --- /dev/null +++ b/content/themes/twentytwentyfive/templates/page.html @@ -0,0 +1,15 @@ + + + +
    + +
    + + + +
    + +
    + + + diff --git a/content/themes/twentytwentyfive/templates/search.html b/content/themes/twentytwentyfive/templates/search.html new file mode 100644 index 0000000..3ccff6f --- /dev/null +++ b/content/themes/twentytwentyfive/templates/search.html @@ -0,0 +1,12 @@ + + + +
    + + + + +
    + + + diff --git a/content/themes/twentytwentyfive/templates/single.html b/content/themes/twentytwentyfive/templates/single.html new file mode 100644 index 0000000..90b7fb2 --- /dev/null +++ b/content/themes/twentytwentyfive/templates/single.html @@ -0,0 +1,25 @@ + + + +
    + +
    + + + + + +
    + +
    + + + + +
    + + +
    + + + diff --git a/content/themes/twentytwentyfive/theme.json b/content/themes/twentytwentyfive/theme.json new file mode 100644 index 0000000..7daeb0d --- /dev/null +++ b/content/themes/twentytwentyfive/theme.json @@ -0,0 +1,733 @@ +{ + "$schema": "https://schemas.wp.org/wp/6.7/theme.json", + "version": 3, + "settings": { + "appearanceTools": true, + "color": { + "defaultDuotone": false, + "defaultGradients": false, + "defaultPalette": false, + "palette": [ + { + "color": "#FFFFFF", + "name": "Base", + "slug": "base" + }, + { + "color": "#111111", + "name": "Contrast", + "slug": "contrast" + }, + { + "color": "#FFEE58", + "name": "Accent 1", + "slug": "accent-1" + }, + { + "color": "#F6CFF4", + "name": "Accent 2", + "slug": "accent-2" + }, + { + "color": "#503AA8", + "name": "Accent 3", + "slug": "accent-3" + }, + { + "color": "#686868", + "name": "Accent 4", + "slug": "accent-4" + }, + { + "color": "#FBFAF3", + "name": "Accent 5", + "slug": "accent-5" + }, + { + "color": "color-mix(in srgb, currentColor 20%, transparent)", + "name": "Accent 6", + "slug": "accent-6" + } + ] + }, + "layout": { + "contentSize": "645px", + "wideSize": "1340px" + }, + "spacing": { + "defaultSpacingSizes": false, + "spacingSizes": [ + { + "name": "Tiny", + "size": "10px", + "slug": "20" + }, + { + "name": "X-Small", + "size": "20px", + "slug": "30" + }, + { + "name": "Small", + "size": "30px", + "slug": "40" + }, + { + "name": "Regular", + "size": "clamp(30px, 5vw, 50px)", + "slug": "50" + }, + { + "name": "Large", + "size": "clamp(30px, 7vw, 70px)", + "slug": "60" + }, + { + "name": "X-Large", + "size": "clamp(50px, 7vw, 90px)", + "slug": "70" + }, + { + "name": "XX-Large", + "size": "clamp(70px, 10vw, 140px)", + "slug": "80" + } + ], + "units": [ + "%", + "px", + "em", + "rem", + "vh", + "vw" + ] + }, + "typography": { + "writingMode": true, + "defaultFontSizes": false, + "fluid": true, + "fontSizes": [ + { + "fluid": false, + "name": "Small", + "size": "0.875rem", + "slug": "small" + }, + { + "fluid": { + "max": "1.125rem", + "min": "1rem" + }, + "name": "Medium", + "size": "1rem", + "slug": "medium" + }, + { + "fluid": { + "max": "1.375rem", + "min": "1.125rem" + }, + "name": "Large", + "size": "1.38rem", + "slug": "large" + }, + { + "fluid": { + "max": "2rem", + "min": "1.75rem" + }, + "name": "Extra Large", + "size": "1.75rem", + "slug": "x-large" + }, + { + "fluid": { + "max": "3rem", + "min": "2.15rem" + }, + "name": "Extra Extra Large", + "size": "2.15rem", + "slug": "xx-large" + } + ], + "fontFamilies": [ + { + "name": "Manrope", + "slug": "manrope", + "fontFamily": "Manrope, sans-serif", + "fontFace": [ + { + "src": [ + "file:./assets/fonts/manrope/Manrope-VariableFont_wght.woff2" + ], + "fontWeight": "200 800", + "fontStyle": "normal", + "fontFamily": "Manrope" + } + ] + }, + { + "name": "Fira Code", + "slug": "fira-code", + "fontFamily": "\"Fira Code\", monospace", + "fontFace": [ + { + "src": [ + "file:./assets/fonts/fira-code/FiraCode-VariableFont_wght.woff2" + ], + "fontWeight": "300 700", + "fontStyle": "normal", + "fontFamily": "\"Fira Code\"" + } + ] + } + ] + }, + "useRootPaddingAwareAlignments": true + }, + "styles": { + "color": { + "background": "var:preset|color|base", + "text": "var:preset|color|contrast" + }, + "spacing": { + "blockGap": "1.2rem", + "padding": { + "left": "var:preset|spacing|50", + "right": "var:preset|spacing|50" + } + }, + "typography": { + "fontFamily": "var:preset|font-family|manrope", + "fontSize": "var:preset|font-size|large", + "fontWeight": "300", + "letterSpacing": "-0.1px", + "lineHeight": "1.4" + }, + "blocks": { + "core/avatar": { + "border": { + "radius": "100px" + } + }, + "core/button": { + "variations": { + "outline": { + "border": { + "color": "currentColor", + "width": "1px" + }, + "css": ".wp-block-button__link:not(.has-background):hover {background-color:color-mix(in srgb, var(--wp--preset--color--contrast) 5%, transparent);}", + "spacing": { + "padding": { + "bottom": "calc(1rem - 1px)", + "left": "calc(2.25rem - 1px)", + "right": "calc(2.25rem - 1px)", + "top": "calc(1rem - 1px)" + } + } + } + } + }, + "core/columns": { + "spacing": { + "blockGap": "var:preset|spacing|50" + } + }, + "core/buttons": { + "spacing": { + "blockGap": "16px" + } + }, + "core/code": { + "typography": { + "fontFamily": "var:preset|font-family|fira-code", + "fontSize": "var:preset|font-size|medium", + "fontWeight": "300" + }, + "color": { + "background": "var:preset|color|accent-5", + "text": "var:preset|color|contrast" + }, + "spacing": { + "padding": { + "right": "var:preset|spacing|40", + "bottom": "var:preset|spacing|40", + "left": "var:preset|spacing|40", + "top": "var:preset|spacing|40" + } + } + }, + "core/comment-author-name": { + "color": { + "text": "var:preset|color|accent-4" + }, + "elements": { + "link": { + "color": { + "text": "var:preset|color|accent-4" + }, + "typography": { + "textDecoration": "none" + }, + ":hover": { + "typography": { + "textDecoration": "underline" + } + } + } + }, + "typography": { + "fontSize": "var:preset|font-size|small" + }, + "spacing": { + "margin": { + "top": "5px", + "bottom": "0px" + } + } + }, + "core/comment-content": { + "typography": { + "fontSize": "var:preset|font-size|medium" + }, + "spacing": { + "margin": { + "top": "var:preset|spacing|30", + "bottom": "var:preset|spacing|30" + } + } + }, + "core/comment-date": { + "typography": { + "fontSize": "var:preset|font-size|small" + }, + "color": { + "text": "var:preset|color|contrast" + }, + "elements": { + "link": { + "color": { + "text": "var:preset|color|contrast" + } + } + } + }, + "core/comment-edit-link": { + "elements": { + "link": { + "color": { + "text": "var:preset|color|contrast" + } + } + }, + "typography": { + "fontSize": "var:preset|font-size|small" + } + }, + "core/comment-reply-link": { + "elements": { + "link": { + "color": { + "text": "var:preset|color|contrast" + } + } + }, + "typography": { + "fontSize": "var:preset|font-size|small" + } + }, + "core/post-comments-form": { + "css": "& textarea, input:not([type=submit]){border-radius:.25rem; border-color: var(--wp--preset--color--accent-6) !important;} & input[type=checkbox]{margin:0 .2rem 0 0 !important;} & label {font-size: var(--wp--preset--font-size--small); }", + "typography": { + "fontSize": "var:preset|font-size|medium" + }, + "spacing": { + "padding": { + "top": "var:preset|spacing|40", + "bottom": "var:preset|spacing|40" + } + } + }, + "core/comments-pagination": { + "typography": { + "fontSize": "var:preset|font-size|medium" + }, + "spacing": { + "margin": { + "top": "var:preset|spacing|40", + "bottom": "var:preset|spacing|40" + } + } + }, + "core/comments-pagination-next": { + "typography": { + "fontSize": "var:preset|font-size|medium" + } + }, + "core/comments-pagination-numbers": { + "typography": { + "fontSize": "var:preset|font-size|medium" + } + }, + "core/comments-pagination-previous": { + "typography": { + "fontSize": "var:preset|font-size|medium" + } + }, + "core/post-date": { + "color":{ + "text": "var:preset|color|accent-4" + }, + "elements": { + "link": { + "color" : { + "text": "var:preset|color|accent-4" + }, + ":hover": { + "typography": { + "textDecoration": "underline" + } + }, + "typography": { + "textDecoration": "none" + } + } + }, + "typography": { + "fontSize": "var:preset|font-size|small" + } + }, + "core/post-navigation-link": { + "typography": { + "fontSize": "var:preset|font-size|medium" + } + }, + "core/post-terms": { + "css": "& a { white-space: nowrap; }", + "typography": { + "fontSize": "var:preset|font-size|small", + "fontWeight": "600" + } + }, + "core/post-title": { + "elements": { + "link": { + ":hover": { + "typography": { + "textDecoration": "underline" + } + }, + "typography": { + "textDecoration": "none" + } + } + } + }, + "core/quote": { + "border": { + "style": "solid", + "width": "0 0 0 2px", + "color": "currentColor" + }, + "spacing": { + "blockGap": "var:preset|spacing|30", + "margin": { + "left": "0", + "right": "0" + }, + "padding": { + "top": "var:preset|spacing|30", + "right": "var:preset|spacing|40", + "bottom": "var:preset|spacing|30", + "left": "var:preset|spacing|40" + } + }, + "typography": { + "fontSize": "var:preset|font-size|large", + "fontWeight": "300" + }, + "elements": { + "cite": { + "typography": { + "fontSize": "var:preset|font-size|small", + "fontStyle": "normal", + "fontWeight": "300" + }, + "css": "& sub { font-size: 0.65em }" + } + }, + "css": "&.has-text-align-right { border-width: 0 2px 0 0; } &.has-text-align-center { border-width: 0;border-inline: 0; padding-inline: 0; }", + "variations": { + "plain": { + "border": { + "color": "transparent", + "style": "none", + "width": "0", + "radius": "0" + }, + "spacing": { + "padding": { + "top": "0", + "right": "0", + "bottom": "0", + "left": "0" + } + } + } + } + }, + "core/pullquote": { + "typography": { + "fontSize": "var:preset|font-size|xx-large", + "fontWeight": "300", + "lineHeight": "1.2" + }, + "elements": { + "cite": { + "typography": { + "fontSize": "var:preset|font-size|small", + "fontStyle": "normal" + } + } + }, + "spacing": { + "padding": { + "bottom": "var:preset|spacing|30", + "top": "var:preset|spacing|30" + } + }, + "css": "& p:last-of-type {margin-bottom: var(--wp--preset--spacing--30);}" + }, + "core/query-pagination": { + "typography": { + "fontSize": "var:preset|font-size|medium", + "fontWeight": "500" + } + }, + "core/search": { + "css": "& .wp-block-search__input{border-radius:3.125rem;padding-left:1.5625rem;padding-right:1.5625rem;border-color:var(--wp--preset--color--accent-6);}", + "typography": { + "fontSize": "var:preset|font-size|medium", + "lineHeight": "1.6" + }, + "elements": { + "button": { + "border": { + "radius": "3.125rem" + }, + "spacing": { + "margin": { + "left": "1.125rem" + } + }, + ":hover" : { + "border": { + "color": "transparent" + } + } + } + } + }, + "core/separator": { + "border": { + "color": "currentColor", + "style": "solid", + "width": "0 0 1px 0" + }, + "color": { + "text": "var:preset|color|accent-6" + }, + "variations": { + "wide": { + "css": " &:not(.alignfull){max-width: var(--wp--style--global--wide-size) !important;}" + } + } + }, + "core/site-tagline": { + "typography": { + "fontSize": "var:preset|font-size|medium" + } + }, + "core/site-title": { + "typography": { + "fontWeight": "700", + "letterSpacing": "-.5px" + }, + "elements": { + "link": { + "typography": { + "textDecoration": "none" + }, + ":hover": { + "typography": { + "textDecoration": "underline" + } + } + } + } + }, + "core/term-description": { + "typography": { + "fontSize": "var:preset|font-size|medium" + } + }, + "core/navigation": { + "typography": { + "fontSize": "var:preset|font-size|medium" + }, + "elements": { + "link": { + ":hover": { + "typography": { + "textDecoration": "underline" + } + }, + "typography": { + "textDecoration": "none" + } + } + } + }, + "core/list": { + "css": "& li{margin-top: 0.5rem;}" + } + }, + "elements": { + "button": { + "color": { + "background": "var:preset|color|contrast", + "text": "var:preset|color|base" + }, + ":focus": { + "outline": { + "color": "var:preset|color|accent-4", + "offset": "2px" + } + }, + ":hover": { + "color": { + "background": "color-mix(in srgb, var(--wp--preset--color--contrast) 85%, transparent)", + "text": "var:preset|color|base" + }, + "border": { + "color": "transparent" + } + }, + "spacing": { + "padding": { + "bottom": "1rem", + "left": "2.25rem", + "right": "2.25rem", + "top": "1rem" + } + }, + "typography": { + "fontSize": "var:preset|font-size|medium" + } + }, + "caption": { + "typography": { + "fontSize": "var:preset|font-size|small", + "lineHeight": "1.4" + } + }, + "h1": { + "typography": { + "fontSize": "var:preset|font-size|xx-large" + } + }, + "h2": { + "typography": { + "fontSize": "var:preset|font-size|x-large" + } + }, + "h3": { + "typography": { + "fontSize": "var:preset|font-size|large" + } + }, + "h4": { + "typography": { + "fontSize": "var:preset|font-size|medium" + } + }, + "h5": { + "typography": { + "fontSize": "var:preset|font-size|small", + "letterSpacing": "0.5px" + } + }, + "h6": { + "typography": { + "fontSize": "var:preset|font-size|small", + "fontWeight": "700", + "letterSpacing": "1.4px", + "textTransform": "uppercase" + } + }, + "heading": { + "typography": { + "fontWeight": "400", + "lineHeight": "1.125", + "letterSpacing": "-0.1px" + } + }, + "link": { + "color": { + "text": "currentColor" + }, + ":hover": { + "typography": { + "textDecoration": "none" + } + } + } + } + }, + "templateParts": [ + { + "area": "header", + "name": "header", + "title": "Header" + }, + { + "area": "header", + "name": "vertical-header", + "title": "Vertical site header" + }, + { + "area": "header", + "name": "header-large-title", + "title": "Header with large title" + + }, + { + "area": "footer", + "name": "footer", + "title": "Footer" + }, + { + "area": "footer", + "name": "footer-columns", + "title": "Footer Columns" + }, + { + "area": "footer", + "name": "footer-newsletter", + "title": "Footer Newsletter" + }, + { + "area": "uncategorized", + "name": "sidebar", + "title": "Sidebar" + } + ], + "customTemplates": [ + { + "name": "page-no-title", + "postTypes": ["page"], + "title": "Page No Title" + } + ] +} diff --git a/docs/translate.md b/docs/translate.md new file mode 100644 index 0000000..cfb15cb --- /dev/null +++ b/docs/translate.md @@ -0,0 +1,28 @@ +# Translate (GlotPress) + + +## Installing + +Create a site on the multisite with the slug `translate`. This should be a subdomain site, as some URLs are hardcoded to the root URL (/). + +Activate the GlotPress, then FAIR Translate plugins, and activate a theme. + +Run `wp --url=... fair-translate stats init` to create the stats tables. + + +## Importing data + +Build a dump of data using the https://github.com/openwebff/glotpress-dump tool. + +At a minimum, fetch the translations for the `wp/dev` project - Translate uses this as the source project for all other projects: + +```sh +bin/fetch-projects.sh +bin/fetch-translations.sh wp/dev +``` + +Then, in your development environment, import this data using the `bin/import-gp.sh` script. The `WP_ARGS` environment variable can be used to pass common arguments, such as the site URL: + +```sh +WP_ARGS="--url=translate.localserver.dev" bin/import-gp.sh wp/dev +```