From 8c0449801c2f99f699efa76bb1853020fee3bbf7 Mon Sep 17 00:00:00 2001 From: Rami Yushuvaev Date: Thu, 13 Nov 2025 13:33:37 +0000 Subject: [PATCH] Migrate to native CSS direction management --- config/RtlCssPlugin.ts | 50 ----------------------- config/webpack-css.ts | 4 -- package-lock.json | 27 ------------ package.json | 2 - src/css/common/_direction.scss | 8 ++++ src/css/common/_switch.scss | 4 +- src/css/common/_tooltips.scss | 4 +- src/css/edit.scss | 1 + src/css/manage/_cloud.scss | 12 +++--- src/css/welcome.scss | 2 +- src/php/admin-menus/class-edit-menu.php | 3 +- src/php/admin-menus/class-manage-menu.php | 3 +- 12 files changed, 23 insertions(+), 97 deletions(-) delete mode 100644 config/RtlCssPlugin.ts create mode 100644 src/css/common/_direction.scss diff --git a/config/RtlCssPlugin.ts b/config/RtlCssPlugin.ts deleted file mode 100644 index b6fbd940..00000000 --- a/config/RtlCssPlugin.ts +++ /dev/null @@ -1,50 +0,0 @@ -import path from 'path' -import rtlcss from 'rtlcss' -import type { Compiler } from 'webpack' -import type { ConfigureOptions } from 'rtlcss' - -export interface WebpackRTLPluginOptions { - entries: Set - rtlcssConfig: ConfigureOptions - transformFilename: (sourceFilename: string) => string -} - -export class RtlCssPlugin { - private readonly options: WebpackRTLPluginOptions - - private static readonly defaultOptions: WebpackRTLPluginOptions = { - entries: new Set(), - rtlcssConfig: {}, - transformFilename: sourceFilename => - `${path.parse(sourceFilename).name}-rtl.css` - } - - constructor(options: Partial) { - this.options = { ...RtlCssPlugin.defaultOptions, ...options } - } - - apply(compiler: Compiler) { - const { Compilation, sources: { ConcatSource } } = compiler.webpack - const rtlcssProcessor = rtlcss.configure(this.options.rtlcssConfig) - - compiler.hooks.compilation.tap(RtlCssPlugin.name, compilation => { - compilation.hooks.processAssets.tap({ - name: RtlCssPlugin.name, - stage: Compilation.PROCESS_ASSETS_STAGE_ADDITIONAL - }, assets => { - for (const chunk of compilation.chunks) { - if (chunk.name && this.options.entries.has(chunk.name)) { - for (const sourceFilename of chunk.files) { - if ('.css' === path.extname(sourceFilename)) { - const rtlFilename = this.options.transformFilename(sourceFilename) - const ltrCss = assets[sourceFilename].source() - const rtlCss = rtlcssProcessor.process(ltrCss).css - compilation.emitAsset(rtlFilename, new ConcatSource(rtlCss), { sourceFilename }) - } - } - } - } - }) - }) - } -} diff --git a/config/webpack-css.ts b/config/webpack-css.ts index d1710e99..828d7a02 100644 --- a/config/webpack-css.ts +++ b/config/webpack-css.ts @@ -7,7 +7,6 @@ import hslCompat from 'postcss-color-hsl' import MiniCssExtractPlugin from 'mini-css-extract-plugin' import RemoveEmptyScriptsPlugin from 'webpack-remove-empty-scripts' import { glob } from 'glob' -import { RtlCssPlugin } from './RtlCssPlugin' import type { Configuration, EntryObject } from 'webpack' import type { Config as PostCssConfig } from 'postcss-load-config' @@ -103,9 +102,6 @@ export const cssWebpackConfig: Configuration = { .replace(/^codemirror-theme-/, 'editor-themes/') .replace(/-css\.css$/, '.css') : '[name].css' - }), - new RtlCssPlugin({ - entries: new Set(['manage-css', 'edit-css']) }) ] } diff --git a/package-lock.json b/package-lock.json index 99945c97..094c0311 100644 --- a/package-lock.json +++ b/package-lock.json @@ -38,7 +38,6 @@ "@types/prismjs": "^1.26.5", "@types/react": "^18.3.1", "@types/react-dom": "^18.3.1", - "@types/rtlcss": "^3.5.4", "@types/tinymce": "^4.6.9", "@types/web": "^0.0.202", "@typescript-eslint/eslint-plugin": "^8.24.0", @@ -66,7 +65,6 @@ "postcss-load-config": "^6.0.1", "postcss-loader": "^8.1.1", "react-is": "^19.0.0", - "rtlcss": "^4.3.0", "sass": "^1.84.0", "sass-loader": "^16.0.4", "style-loader": "^4.0.0", @@ -2969,14 +2967,6 @@ "@types/node": "*" } }, - "node_modules/@types/rtlcss": { - "version": "3.5.4", - "dev": true, - "license": "MIT", - "dependencies": { - "postcss": "^8.2.x" - } - }, "node_modules/@types/sizzle": { "version": "2.3.6", "dev": true, @@ -10565,23 +10555,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/rtlcss": { - "version": "4.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0", - "postcss": "^8.4.21", - "strip-json-comments": "^3.1.1" - }, - "bin": { - "rtlcss": "bin/rtlcss.js" - }, - "engines": { - "node": ">=12.0.0" - } - }, "node_modules/run-async": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", diff --git a/package.json b/package.json index f7807da7..2dc30a96 100644 --- a/package.json +++ b/package.json @@ -73,7 +73,6 @@ "@types/prismjs": "^1.26.5", "@types/react": "^18.3.1", "@types/react-dom": "^18.3.1", - "@types/rtlcss": "^3.5.4", "@types/tinymce": "^4.6.9", "@types/web": "^0.0.202", "@typescript-eslint/eslint-plugin": "^8.24.0", @@ -100,7 +99,6 @@ "postcss-load-config": "^6.0.1", "postcss-loader": "^8.1.1", "react-is": "^19.0.0", - "rtlcss": "^4.3.0", "sass": "^1.84.0", "sass-loader": "^16.0.4", "style-loader": "^4.0.0", diff --git a/src/css/common/_direction.scss b/src/css/common/_direction.scss new file mode 100644 index 00000000..45b6db3b --- /dev/null +++ b/src/css/common/_direction.scss @@ -0,0 +1,8 @@ +:root { + --cs-direction-multiplier: 1; // LTR = 1, RTL = -1 +} + +html[dir="rtl"], +body.rtl { + --cs-direction-multiplier: -1; +} diff --git a/src/css/common/_switch.scss b/src/css/common/_switch.scss index 0123a950..3704c81f 100644 --- a/src/css/common/_switch.scss +++ b/src/css/common/_switch.scss @@ -40,13 +40,13 @@ input[type='checkbox'].switch:checked { &::before { background-color: white; - transform: translateX(100%); + transform: translateX(calc(100% * var(--cs-direction-multiplier))); } } .erroneous-snippet .snippet-activation-switch::before { content: '!'; - transform: translateX(50%); + transform: translateX(calc(50% * var(--cs-direction-multiplier))); text-align: center; font-weight: bold; line-height: 1; diff --git a/src/css/common/_tooltips.scss b/src/css/common/_tooltips.scss index b76547c3..3feec529 100644 --- a/src/css/common/_tooltips.scss +++ b/src/css/common/_tooltips.scss @@ -172,13 +172,13 @@ $bg-color: hsl(0deg 0% 20% / 90%); .tooltip-inline.tooltip-end:hover, .tooltip-inline.tooltip-end:focus { &::before, .tooltip-content { - transform: translateX(10px); + transform: translateX(calc(10px * var(--cs-direction-multiplier))); } } .tooltip-inline.tooltip-start:hover, .tooltip-inline.tooltip-start:focus { &::before, .tooltip-content { - transform: translateX(-10px); + transform: translateX(calc(-10px * var(--cs-direction-multiplier))); } } diff --git a/src/css/edit.scss b/src/css/edit.scss index 37a77f6f..862af07f 100644 --- a/src/css/edit.scss +++ b/src/css/edit.scss @@ -2,6 +2,7 @@ * Styles for the edit snippet admin page. */ +@use 'common/direction'; @use 'common/codemirror'; @use 'common/badges'; @use 'common/switch'; diff --git a/src/css/manage/_cloud.scss b/src/css/manage/_cloud.scss index 572f42a9..14e01376 100644 --- a/src/css/manage/_cloud.scss +++ b/src/css/manage/_cloud.scss @@ -237,7 +237,6 @@ td.column-download { gap: 5px; } - .cloud-table > tbody > tr { block-size: 80px; box-shadow: inset 0 -1px 0 rgb(0 0 0 / 10%); @@ -265,7 +264,6 @@ td.column-download { background-color: #ce0000; border-radius: 50%; - .cloud-connect-active & { background-color: #25a349; } @@ -284,6 +282,10 @@ td.column-download { block-size: 1.25rem; /* 20px */ transform-origin: bottom left; + [dir="rtl"] & { + transform-origin: bottom right; + } + &:hover { stroke: #059669; fill: #6ee7b7; @@ -325,15 +327,15 @@ td.column-download { } 33% { - transform: rotate(7deg) + transform: rotate(calc(7deg * var(--cs-direction-multiplier))); } 66% { - transform: rotate(-15deg) + transform: rotate(calc(-15deg * var(--cs-direction-multiplier))); } 90% { - transform: rotate(5deg) + transform: rotate(calc(5deg * var(--cs-direction-multiplier))); } 100% { diff --git a/src/css/welcome.scss b/src/css/welcome.scss index 81c9872a..5ebfe850 100644 --- a/src/css/welcome.scss +++ b/src/css/welcome.scss @@ -378,6 +378,6 @@ a.csp-card { @keyframes loading-rotate { 100% { - transform: rotate(360deg); + transform: rotate(calc(360deg * var(--cs-direction-multiplier))); } } diff --git a/src/php/admin-menus/class-edit-menu.php b/src/php/admin-menus/class-edit-menu.php index 9fc8f3da..e6f99c73 100644 --- a/src/php/admin-menus/class-edit-menu.php +++ b/src/php/admin-menus/class-edit-menu.php @@ -150,7 +150,6 @@ public function load_snippet_data() { */ public function enqueue_assets() { $plugin = code_snippets(); - $rtl = is_rtl() ? '-rtl' : ''; $settings = Settings\get_settings_values(); $tags_enabled = $settings['general']['enable_tags']; @@ -160,7 +159,7 @@ public function enqueue_assets() { wp_enqueue_style( self::CSS_HANDLE, - plugins_url( "dist/edit$rtl.css", $plugin->file ), + plugins_url( 'dist/edit.css', $plugin->file ), [ 'code-editor', 'wp-components', diff --git a/src/php/admin-menus/class-manage-menu.php b/src/php/admin-menus/class-manage-menu.php index ba53ea90..d342dde9 100644 --- a/src/php/admin-menus/class-manage-menu.php +++ b/src/php/admin-menus/class-manage-menu.php @@ -182,11 +182,10 @@ public function load() { */ public function enqueue_assets() { $plugin = code_snippets(); - $rtl = is_rtl() ? '-rtl' : ''; wp_enqueue_style( 'code-snippets-manage', - plugins_url( "dist/manage$rtl.css", $plugin->file ), + plugins_url( 'dist/manage.css', $plugin->file ), [], $plugin->version );