From ac202c8d253c44c548be6285dfbb2484b0502373 Mon Sep 17 00:00:00 2001 From: Andreas Kienast <a.fernandez@scripting-base.de> Date: Mon, 20 Nov 2023 15:42:25 +0100 Subject: [PATCH] [!!!][TASK] Merge EXT:t3editor into backend MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch merges the "t3editor" extension into EXT:backend. The overall benefit is a globally available syntax highlighting at various places, without the need to have an extra extension installed. Another benefit it the removal of installation checks of EXT:t3editor and fallbacks if the "soft requirement" is not fulfilled, reducing soft-cross-dependencies. Resolves: #102440 Releases: main Change-Id: I76301c9cff08f61a5721fa34f4e3e950687b67b0 Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/81799 Reviewed-by: Stefan Bürk <stefan@buerk.tech> Tested-by: Christian Kuhn <lolli@schwarzbu.ch> Tested-by: core-ci <typo3@b13.com> Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch> Tested-by: Stefan Bürk <stefan@buerk.tech> --- .gitattributes | 3 - Build/Gruntfile.js | 62 ++-- .../autocomplete/completion-result.ts | 4 +- .../autocomplete/ts-code-completion.ts | 12 +- .../code-editor}/autocomplete/ts-parser.ts | 6 +- .../code-editor}/autocomplete/ts-ref.ts | 2 +- .../element/code-mirror-element.ts | 24 +- .../code-editor}/language/typoscript.ts | 6 +- .../code-editor}/stream-parser/typoscript.ts | 0 .../Sources/TypeScript/backend/grid-editor.ts | 2 +- .../pagetsconfig/pagetsconfig-includes.ts | 4 +- .../tstemplate/template-analyzer.ts | 4 +- Build/tsconfig.json | 3 - Build/web-test-runner.config.mjs | 80 ++--- composer.json | 3 - composer.lock | 2 +- .../adminpanel/Documentation/Settings.cfg | 1 - .../Classes/CodeEditor}/Addon.php | 2 +- .../Classes/CodeEditor/CodeEditor.php} | 23 +- .../Exception/InvalidModeException.php | 2 +- .../Classes/CodeEditor}/Mode.php | 2 +- .../CodeEditor}/Registry/AddonRegistry.php | 8 +- .../CodeEditor}/Registry/ModeRegistry.php | 19 +- .../CodeEditor}/CodeCompletionController.php | 15 +- .../TypoScriptReferenceController.php | 4 +- .../InitializeCodeEditorInEditFileForm.php} | 20 +- .../Element/BackendLayoutWizardElement.php | 23 +- .../Form/Element/CodeEditorElement.php} | 41 +-- .../Classes/Form/Element/JsonElement.php | 16 +- .../backend/Classes/Form/NodeFactory.php | 3 +- .../Configuration/Backend/AjaxRoutes.php | 12 + .../Configuration/Backend/T3editor/Addons.php | 2 +- .../Configuration/Backend/T3editor/Modes.php | 4 +- .../Configuration/JavaScriptModules.php | 43 +++ .../Configuration/TCA/Overrides/be_groups.php | 4 +- .../Configuration/TCA/Overrides/be_users.php | 4 +- .../Configuration/TCA/Overrides/pages.php | 4 +- .../TCA/Overrides/sys_template.php | 8 +- .../TCA/Overrides/tt_content.php | 19 + .../Private/Language/locallang_codeeditor.xlf | 14 + .../Resources/Private/tsref.xml | 0 .../Contrib/@codemirror/autocomplete.js | 0 .../Contrib/@codemirror/commands.js | 0 .../Contrib/@codemirror/lang-css.js | 0 .../Contrib/@codemirror/lang-html.js | 0 .../Contrib/@codemirror/lang-javascript.js | 0 .../Contrib/@codemirror/lang-json.js | 0 .../Contrib/@codemirror/lang-php.js | 0 .../Contrib/@codemirror/lang-sql.js | 0 .../Contrib/@codemirror/lang-xml.js | 0 .../Contrib/@codemirror/language.js | 0 .../JavaScript/Contrib/@codemirror/lint.js | 0 .../JavaScript/Contrib/@codemirror/search.js | 0 .../JavaScript/Contrib/@codemirror/state.js | 0 .../Contrib/@codemirror/theme-one-dark.js | 0 .../JavaScript/Contrib/@codemirror/view.js | 0 .../JavaScript/Contrib/@lezer/common.js | 0 .../Public/JavaScript/Contrib/@lezer/css.js | 0 .../JavaScript/Contrib/@lezer/highlight.js | 0 .../Public/JavaScript/Contrib/@lezer/html.js | 0 .../JavaScript/Contrib/@lezer/javascript.js | 0 .../Public/JavaScript/Contrib/@lezer/json.js | 0 .../Public/JavaScript/Contrib/@lezer/lr.js | 0 .../Public/JavaScript/Contrib/@lezer/php.js | 0 .../Public/JavaScript/Contrib/@lezer/xml.js | 0 .../Public/JavaScript/Contrib/crelt.js | 0 .../Public/JavaScript/Contrib/style-mod.js | 0 .../Public/JavaScript/Contrib/w3c-keyname.js | 0 .../autocomplete/completion-result.js | 0 .../autocomplete/ts-code-completion.js | 13 + .../code-editor}/autocomplete/ts-parser.js | 0 .../code-editor/autocomplete/ts-ref.js | 13 + .../element/code-mirror-element.js | 2 +- .../code-editor/language/typoscript.js | 13 + .../code-editor}/stream-parser/typoscript.js | 0 .../pagetsconfig/pagetsconfig-includes.js | 4 +- .../Registry/AddonRegistryTest.php | 6 +- .../CodeEditor}/Registry/ModeRegistryTest.php | 6 +- .../Unit/Form/Element/JsonElementTest.php | 6 +- typo3/sysext/backend/composer.json | 2 + .../Configuration/Tca/TcaMigration.php | 30 ++ ...102440-EXTt3editorMergedIntoEXTbackend.rst | 59 +++ ...102440-EXTt3editorMergedIntoEXTBackend.rst | 45 +++ typo3/sysext/core/Documentation/Settings.cfg | 1 - .../FileList/FileOperationsCest.php | 9 +- .../Application/Impexp/UsersCest.php | 13 +- .../Application/Template/TemplateCest.php | 8 +- .../Functional/Package/PackageStatesTest.php | 2 - .../Configuration/Tca/TcaMigrationTest.php | 64 ++++ .../dashboard/Documentation/Settings.cfg | 1 - .../ExtensionComposerStatusController.php | 38 +- .../sysext/felogin/Documentation/Settings.cfg | 1 - .../Documentation/Settings.cfg | 1 - typo3/sysext/form/Documentation/Settings.cfg | 1 - .../sysext/impexp/Documentation/Settings.cfg | 1 - .../indexed_search/Documentation/Settings.cfg | 1 - .../linkvalidator/Documentation/Settings.cfg | 1 - .../lowlevel/Documentation/Settings.cfg | 1 - .../reactions/Documentation/Settings.cfg | 1 - .../recycler/Documentation/Settings.cfg | 1 - .../redirects/Documentation/Settings.cfg | 1 - .../sysext/reports/Documentation/Settings.cfg | 1 - .../rte_ckeditor/Documentation/Settings.cfg | 1 - .../scheduler/Documentation/Settings.cfg | 1 - typo3/sysext/seo/Documentation/Settings.cfg | 1 - ...ditor.php => TypeTextFormatCodeEditor.php} | 4 +- .../FieldGeneratorResolver.php | 2 +- .../TCA/tx_styleguide_elements_t3editor.php | 8 +- ...lements_t3editor_flex_1_inline_1_child.php | 2 +- ...guide_elements_t3editor_inline_1_child.php | 2 +- ...tx_styleguide_inline_1n_inline_2_child.php | 2 +- ...tyleguide_inline_expand_inline_1_child.php | 2 +- .../TCA/tx_styleguide_l10nreadonly.php | 2 +- .../Configuration/TCA/tx_styleguide_type.php | 2 +- .../TCA/tx_styleguide_typeforeign.php | 2 +- typo3/sysext/t3editor/.gitattributes | 2 - .../Configuration/Backend/AjaxRoutes.php | 18 - .../Configuration/JavaScriptModules.php | 57 --- .../t3editor/Configuration/Services.yaml | 8 - .../TCA/Overrides/tt_content.php | 19 - .../CodeSnippets/Automatic/T3editor1.rst.txt | 23 -- .../Documentation/Developer/Extend.rst | 137 ------- .../Documentation/Developer/Index.rst | 14 - .../t3editor/Documentation/Developer/TCA.rst | 37 -- .../Images/AutomaticScreenshots/T3editor1.png | Bin 44707 -> 0 bytes .../AutomaticScreenshots/T3editor1.rst.txt | 9 - .../t3editor/Documentation/Includes.rst.txt | 34 -- typo3/sysext/t3editor/Documentation/Index.rst | 54 --- .../Documentation/Installation/Index.rst | 59 --- .../Documentation/Introduction/Index.rst | 27 -- .../t3editor/Documentation/Settings.cfg | 66 ---- .../sysext/t3editor/Documentation/Sitemap.rst | 9 - .../t3editor/Documentation/genindex.rst | 7 - .../t3editor/Documentation/screenshots.json | 49 --- typo3/sysext/t3editor/LICENSE.txt | 339 ------------------ typo3/sysext/t3editor/README.rst | 13 - .../Resources/Private/Language/locallang.xlf | 47 --- .../Resources/Public/Icons/Extension.png | Bin 2275 -> 0 bytes .../autocomplete/ts-code-completion.js | 13 - .../Public/JavaScript/autocomplete/ts-ref.js | 13 - .../Public/JavaScript/language/typoscript.js | 13 - typo3/sysext/t3editor/composer.json | 44 --- typo3/sysext/t3editor/ext_emconf.php | 19 - typo3/sysext/t3editor/ext_localconf.php | 14 - .../Configuration/JavaScriptModules.php | 1 - .../Public/JavaScript/template-analyzer.js | 4 +- .../workspaces/Documentation/Settings.cfg | 1 - 147 files changed, 600 insertions(+), 1437 deletions(-) rename Build/Sources/TypeScript/{t3editor => backend/code-editor}/autocomplete/completion-result.ts (95%) rename Build/Sources/TypeScript/{t3editor => backend/code-editor}/autocomplete/ts-code-completion.ts (90%) rename Build/Sources/TypeScript/{t3editor => backend/code-editor}/autocomplete/ts-parser.ts (98%) rename Build/Sources/TypeScript/{t3editor => backend/code-editor}/autocomplete/ts-ref.ts (99%) rename Build/Sources/TypeScript/{t3editor => backend/code-editor}/element/code-mirror-element.ts (94%) rename Build/Sources/TypeScript/{t3editor => backend/code-editor}/language/typoscript.ts (96%) rename Build/Sources/TypeScript/{t3editor => backend/code-editor}/stream-parser/typoscript.ts (100%) rename typo3/sysext/{t3editor/Classes => backend/Classes/CodeEditor}/Addon.php (97%) rename typo3/sysext/{t3editor/Classes/T3editor.php => backend/Classes/CodeEditor/CodeEditor.php} (88%) rename typo3/sysext/{t3editor/Classes => backend/Classes/CodeEditor}/Exception/InvalidModeException.php (92%) rename typo3/sysext/{t3editor/Classes => backend/Classes/CodeEditor}/Mode.php (97%) rename typo3/sysext/{t3editor/Classes => backend/Classes/CodeEditor}/Registry/AddonRegistry.php (86%) rename typo3/sysext/{t3editor/Classes => backend/Classes/CodeEditor}/Registry/ModeRegistry.php (85%) rename typo3/sysext/{t3editor/Classes/Controller => backend/Classes/Controller/CodeEditor}/CodeCompletionController.php (90%) rename typo3/sysext/{t3editor/Classes/Controller => backend/Classes/Controller/CodeEditor}/TypoScriptReferenceController.php (96%) rename typo3/sysext/{t3editor/Classes/EventListener/InitializeT3editorInEditFileForm.php => backend/Classes/EventListener/InitializeCodeEditorInEditFileForm.php} (69%) rename typo3/sysext/{t3editor/Classes/Form/Element/T3editorElement.php => backend/Classes/Form/Element/CodeEditorElement.php} (90%) rename typo3/sysext/{t3editor => backend}/Configuration/Backend/T3editor/Addons.php (99%) rename typo3/sysext/{t3editor => backend}/Configuration/Backend/T3editor/Modes.php (92%) rename typo3/sysext/{t3editor => backend}/Configuration/TCA/Overrides/be_groups.php (77%) rename typo3/sysext/{t3editor => backend}/Configuration/TCA/Overrides/be_users.php (77%) rename typo3/sysext/{t3editor => backend}/Configuration/TCA/Overrides/pages.php (78%) rename typo3/sysext/{t3editor => backend}/Configuration/TCA/Overrides/sys_template.php (75%) create mode 100644 typo3/sysext/backend/Configuration/TCA/Overrides/tt_content.php create mode 100644 typo3/sysext/backend/Resources/Private/Language/locallang_codeeditor.xlf rename typo3/sysext/{t3editor => backend}/Resources/Private/tsref.xml (100%) rename typo3/sysext/{t3editor => backend}/Resources/Public/JavaScript/Contrib/@codemirror/autocomplete.js (100%) rename typo3/sysext/{t3editor => backend}/Resources/Public/JavaScript/Contrib/@codemirror/commands.js (100%) rename typo3/sysext/{t3editor => backend}/Resources/Public/JavaScript/Contrib/@codemirror/lang-css.js (100%) rename typo3/sysext/{t3editor => backend}/Resources/Public/JavaScript/Contrib/@codemirror/lang-html.js (100%) rename typo3/sysext/{t3editor => backend}/Resources/Public/JavaScript/Contrib/@codemirror/lang-javascript.js (100%) rename typo3/sysext/{t3editor => backend}/Resources/Public/JavaScript/Contrib/@codemirror/lang-json.js (100%) rename typo3/sysext/{t3editor => backend}/Resources/Public/JavaScript/Contrib/@codemirror/lang-php.js (100%) rename typo3/sysext/{t3editor => backend}/Resources/Public/JavaScript/Contrib/@codemirror/lang-sql.js (100%) rename typo3/sysext/{t3editor => backend}/Resources/Public/JavaScript/Contrib/@codemirror/lang-xml.js (100%) rename typo3/sysext/{t3editor => backend}/Resources/Public/JavaScript/Contrib/@codemirror/language.js (100%) rename typo3/sysext/{t3editor => backend}/Resources/Public/JavaScript/Contrib/@codemirror/lint.js (100%) rename typo3/sysext/{t3editor => backend}/Resources/Public/JavaScript/Contrib/@codemirror/search.js (100%) rename typo3/sysext/{t3editor => backend}/Resources/Public/JavaScript/Contrib/@codemirror/state.js (100%) rename typo3/sysext/{t3editor => backend}/Resources/Public/JavaScript/Contrib/@codemirror/theme-one-dark.js (100%) rename typo3/sysext/{t3editor => backend}/Resources/Public/JavaScript/Contrib/@codemirror/view.js (100%) rename typo3/sysext/{t3editor => backend}/Resources/Public/JavaScript/Contrib/@lezer/common.js (100%) rename typo3/sysext/{t3editor => backend}/Resources/Public/JavaScript/Contrib/@lezer/css.js (100%) rename typo3/sysext/{t3editor => backend}/Resources/Public/JavaScript/Contrib/@lezer/highlight.js (100%) rename typo3/sysext/{t3editor => backend}/Resources/Public/JavaScript/Contrib/@lezer/html.js (100%) rename typo3/sysext/{t3editor => backend}/Resources/Public/JavaScript/Contrib/@lezer/javascript.js (100%) rename typo3/sysext/{t3editor => backend}/Resources/Public/JavaScript/Contrib/@lezer/json.js (100%) rename typo3/sysext/{t3editor => backend}/Resources/Public/JavaScript/Contrib/@lezer/lr.js (100%) rename typo3/sysext/{t3editor => backend}/Resources/Public/JavaScript/Contrib/@lezer/php.js (100%) rename typo3/sysext/{t3editor => backend}/Resources/Public/JavaScript/Contrib/@lezer/xml.js (100%) rename typo3/sysext/{t3editor => backend}/Resources/Public/JavaScript/Contrib/crelt.js (100%) rename typo3/sysext/{t3editor => backend}/Resources/Public/JavaScript/Contrib/style-mod.js (100%) rename typo3/sysext/{t3editor => backend}/Resources/Public/JavaScript/Contrib/w3c-keyname.js (100%) rename typo3/sysext/{t3editor/Resources/Public/JavaScript => backend/Resources/Public/JavaScript/code-editor}/autocomplete/completion-result.js (100%) create mode 100644 typo3/sysext/backend/Resources/Public/JavaScript/code-editor/autocomplete/ts-code-completion.js rename typo3/sysext/{t3editor/Resources/Public/JavaScript => backend/Resources/Public/JavaScript/code-editor}/autocomplete/ts-parser.js (100%) create mode 100644 typo3/sysext/backend/Resources/Public/JavaScript/code-editor/autocomplete/ts-ref.js rename typo3/sysext/{t3editor/Resources/Public/JavaScript => backend/Resources/Public/JavaScript/code-editor}/element/code-mirror-element.js (73%) create mode 100644 typo3/sysext/backend/Resources/Public/JavaScript/code-editor/language/typoscript.js rename typo3/sysext/{t3editor/Resources/Public/JavaScript => backend/Resources/Public/JavaScript/code-editor}/stream-parser/typoscript.js (100%) rename typo3/sysext/{t3editor/Tests/Unit => backend/Tests/Unit/CodeEditor}/Registry/AddonRegistryTest.php (94%) rename typo3/sysext/{t3editor/Tests/Unit => backend/Tests/Unit/CodeEditor}/Registry/ModeRegistryTest.php (93%) create mode 100644 typo3/sysext/core/Documentation/Changelog/13.0/Breaking-102440-EXTt3editorMergedIntoEXTbackend.rst create mode 100644 typo3/sysext/core/Documentation/Changelog/13.0/Deprecation-102440-EXTt3editorMergedIntoEXTBackend.rst rename typo3/sysext/styleguide/Classes/TcaDataGenerator/FieldGenerator/{TypeTextFormatT3editor.php => TypeTextFormatCodeEditor.php} (88%) delete mode 100644 typo3/sysext/t3editor/.gitattributes delete mode 100644 typo3/sysext/t3editor/Configuration/Backend/AjaxRoutes.php delete mode 100644 typo3/sysext/t3editor/Configuration/JavaScriptModules.php delete mode 100644 typo3/sysext/t3editor/Configuration/Services.yaml delete mode 100644 typo3/sysext/t3editor/Configuration/TCA/Overrides/tt_content.php delete mode 100644 typo3/sysext/t3editor/Documentation/CodeSnippets/Automatic/T3editor1.rst.txt delete mode 100644 typo3/sysext/t3editor/Documentation/Developer/Extend.rst delete mode 100644 typo3/sysext/t3editor/Documentation/Developer/Index.rst delete mode 100644 typo3/sysext/t3editor/Documentation/Developer/TCA.rst delete mode 100644 typo3/sysext/t3editor/Documentation/Images/AutomaticScreenshots/T3editor1.png delete mode 100644 typo3/sysext/t3editor/Documentation/Images/AutomaticScreenshots/T3editor1.rst.txt delete mode 100644 typo3/sysext/t3editor/Documentation/Includes.rst.txt delete mode 100644 typo3/sysext/t3editor/Documentation/Index.rst delete mode 100644 typo3/sysext/t3editor/Documentation/Installation/Index.rst delete mode 100644 typo3/sysext/t3editor/Documentation/Introduction/Index.rst delete mode 100644 typo3/sysext/t3editor/Documentation/Settings.cfg delete mode 100644 typo3/sysext/t3editor/Documentation/Sitemap.rst delete mode 100644 typo3/sysext/t3editor/Documentation/genindex.rst delete mode 100644 typo3/sysext/t3editor/Documentation/screenshots.json delete mode 100644 typo3/sysext/t3editor/LICENSE.txt delete mode 100644 typo3/sysext/t3editor/README.rst delete mode 100644 typo3/sysext/t3editor/Resources/Private/Language/locallang.xlf delete mode 100644 typo3/sysext/t3editor/Resources/Public/Icons/Extension.png delete mode 100644 typo3/sysext/t3editor/Resources/Public/JavaScript/autocomplete/ts-code-completion.js delete mode 100644 typo3/sysext/t3editor/Resources/Public/JavaScript/autocomplete/ts-ref.js delete mode 100644 typo3/sysext/t3editor/Resources/Public/JavaScript/language/typoscript.js delete mode 100644 typo3/sysext/t3editor/composer.json delete mode 100644 typo3/sysext/t3editor/ext_emconf.php delete mode 100644 typo3/sysext/t3editor/ext_localconf.php diff --git a/.gitattributes b/.gitattributes index 31a0c994dec2..0654e70912b5 100644 --- a/.gitattributes +++ b/.gitattributes @@ -33,6 +33,3 @@ *.t3s text eol=lf *.txt text eol=lf /typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Contrib/plugins/codesnippet/lib/highlight/LICENSE text eol=lf -/typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/cm/AUTHORS text eol=lf -/typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/cm/LICENSE text eol=lf -/typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/cm/bin/source-highlight text eol=lf diff --git a/Build/Gruntfile.js b/Build/Gruntfile.js index 13876b08e577..a20d305e6122 100644 --- a/Build/Gruntfile.js +++ b/Build/Gruntfile.js @@ -118,7 +118,6 @@ module.exports = function (grunt) { linkvalidator: '<%= paths.sysext %>linkvalidator/Resources/', backend: '<%= paths.sysext %>backend/Resources/', styleguide: '<%= paths.sysext %>styleguide/Resources/', - t3editor: '<%= paths.sysext %>t3editor/Resources/', workspaces: '<%= paths.sysext %>workspaces/Resources/', ckeditor: '<%= paths.sysext %>rte_ckeditor/Resources/', core: '<%= paths.sysext %>core/Resources/', @@ -268,9 +267,6 @@ module.exports = function (grunt) { styleguide: { src: '<%= paths.styleguide %>Public/Css/*.css' }, - t3editor: { - src: '<%= paths.t3editor %>Public/Css/**/*.css' - }, workspaces: { src: '<%= paths.workspaces %>Public/Css/*.css' } @@ -443,36 +439,36 @@ module.exports = function (grunt) { { expand: true, cwd: '<%= paths.node_modules %>@codemirror', - dest: '<%= paths.t3editor %>Public/JavaScript/Contrib/@codemirror/', + dest: '<%= paths.backend %>Public/JavaScript/Contrib/@codemirror/', rename: (dest, src) => dest + src.replace('/dist/index', ''), src: ['*/dist/index.js'] }, { expand: true, cwd: '<%= paths.node_modules %>@lezer', - dest: '<%= paths.t3editor %>Public/JavaScript/Contrib/@lezer/', + dest: '<%= paths.backend %>Public/JavaScript/Contrib/@lezer/', rename: (dest, src) => dest + src.replace('/dist/index.es', ''), src: ['*/dist/index.es.js'] }, { src: '<%= paths.node_modules %>@lezer/lr/dist/index.js', - dest: '<%= paths.t3editor %>Public/JavaScript/Contrib/@lezer/lr.js' + dest: '<%= paths.backend %>Public/JavaScript/Contrib/@lezer/lr.js' }, { src: '<%= paths.node_modules %>@lezer/common/dist/index.js', - dest: '<%= paths.t3editor %>Public/JavaScript/Contrib/@lezer/common.js' + dest: '<%= paths.backend %>Public/JavaScript/Contrib/@lezer/common.js' }, { src: '<%= paths.node_modules %>crelt/index.es.js', - dest: '<%= paths.t3editor %>Public/JavaScript/Contrib/crelt.js' + dest: '<%= paths.backend %>Public/JavaScript/Contrib/crelt.js' }, { src: '<%= paths.node_modules %>style-mod/src/style-mod.js', - dest: '<%= paths.t3editor %>Public/JavaScript/Contrib/style-mod.js' + dest: '<%= paths.backend %>Public/JavaScript/Contrib/style-mod.js' }, { src: '<%= paths.node_modules %>w3c-keyname/index.es.js', - dest: '<%= paths.t3editor %>Public/JavaScript/Contrib/w3c-keyname.js' + dest: '<%= paths.backend %>Public/JavaScript/Contrib/w3c-keyname.js' }, ] } @@ -769,6 +765,33 @@ module.exports = function (grunt) { }, thirdparty: { files: { + '<%= paths.backend %>Public/JavaScript/Contrib/@codemirror/autocomplete.js': ['<%= paths.backend %>Public/JavaScript/Contrib/@codemirror/autocomplete.js'], + '<%= paths.backend %>Public/JavaScript/Contrib/@codemirror/commands.js': ['<%= paths.backend %>Public/JavaScript/Contrib/@codemirror/commands.js'], + '<%= paths.backend %>Public/JavaScript/Contrib/@codemirror/lang-css.js': ['<%= paths.backend %>Public/JavaScript/Contrib/@codemirror/lang-css.js'], + '<%= paths.backend %>Public/JavaScript/Contrib/@codemirror/lang-html.js': ['<%= paths.backend %>Public/JavaScript/Contrib/@codemirror/lang-html.js'], + '<%= paths.backend %>Public/JavaScript/Contrib/@codemirror/lang-javascript.js': ['<%= paths.backend %>Public/JavaScript/Contrib/@codemirror/lang-javascript.js'], + '<%= paths.backend %>Public/JavaScript/Contrib/@codemirror/lang-json.js': ['<%= paths.backend %>Public/JavaScript/Contrib/@codemirror/lang-json.js'], + '<%= paths.backend %>Public/JavaScript/Contrib/@codemirror/lang-php.js': ['<%= paths.backend %>Public/JavaScript/Contrib/@codemirror/lang-php.js'], + '<%= paths.backend %>Public/JavaScript/Contrib/@codemirror/lang-sql.js': ['<%= paths.backend %>Public/JavaScript/Contrib/@codemirror/lang-sql.js'], + '<%= paths.backend %>Public/JavaScript/Contrib/@codemirror/language.js': ['<%= paths.backend %>Public/JavaScript/Contrib/@codemirror/language.js'], + '<%= paths.backend %>Public/JavaScript/Contrib/@codemirror/lang-xml.js': ['<%= paths.backend %>Public/JavaScript/Contrib/@codemirror/lang-xml.js'], + '<%= paths.backend %>Public/JavaScript/Contrib/@codemirror/lint.js': ['<%= paths.backend %>Public/JavaScript/Contrib/@codemirror/lint.js'], + '<%= paths.backend %>Public/JavaScript/Contrib/@codemirror/search.js': ['<%= paths.backend %>Public/JavaScript/Contrib/@codemirror/search.js'], + '<%= paths.backend %>Public/JavaScript/Contrib/@codemirror/state.js': ['<%= paths.backend %>Public/JavaScript/Contrib/@codemirror/state.js'], + '<%= paths.backend %>Public/JavaScript/Contrib/@codemirror/theme-one-dark.js': ['<%= paths.backend %>Public/JavaScript/Contrib/@codemirror/theme-one-dark.js'], + '<%= paths.backend %>Public/JavaScript/Contrib/@codemirror/view.js': ['<%= paths.backend %>Public/JavaScript/Contrib/@codemirror/view.js'], + '<%= paths.backend %>Public/JavaScript/Contrib/@lezer/common.js': ['<%= paths.backend %>Public/JavaScript/Contrib/@lezer/common.js'], + '<%= paths.backend %>Public/JavaScript/Contrib/@lezer/css.js': ['<%= paths.backend %>Public/JavaScript/Contrib/@lezer/css.js'], + '<%= paths.backend %>Public/JavaScript/Contrib/@lezer/highlight.js': ['<%= paths.backend %>Public/JavaScript/Contrib/@lezer/highlight.js'], + '<%= paths.backend %>Public/JavaScript/Contrib/@lezer/html.js': ['<%= paths.backend %>Public/JavaScript/Contrib/@lezer/html.js'], + '<%= paths.backend %>Public/JavaScript/Contrib/@lezer/javascript.js': ['<%= paths.backend %>Public/JavaScript/Contrib/@lezer/javascript.js'], + '<%= paths.backend %>Public/JavaScript/Contrib/@lezer/json.js': ['<%= paths.backend %>Public/JavaScript/Contrib/@lezer/json.js'], + '<%= paths.backend %>Public/JavaScript/Contrib/@lezer/lr.js': ['<%= paths.backend %>Public/JavaScript/Contrib/@lezer/lr.js'], + '<%= paths.backend %>Public/JavaScript/Contrib/@lezer/php.js': ['<%= paths.backend %>Public/JavaScript/Contrib/@lezer/php.js'], + '<%= paths.backend %>Public/JavaScript/Contrib/@lezer/xml.js': ['<%= paths.backend %>Public/JavaScript/Contrib/@lezer/xml.js'], + '<%= paths.backend %>Public/JavaScript/Contrib/crelt.js': ['<%= paths.backend %>Public/JavaScript/Contrib/crelt.js'], + '<%= paths.backend %>Public/JavaScript/Contrib/style-mod.js': ['<%= paths.backend %>Public/JavaScript/Contrib/style-mod.js'], + '<%= paths.backend %>Public/JavaScript/Contrib/w3c-keyname.js': ['<%= paths.backend %>Public/JavaScript/Contrib/w3c-keyname.js'], '<%= paths.core %>Public/JavaScript/Contrib/cropperjs.js': ['<%= paths.core %>Public/JavaScript/Contrib/cropperjs.js'], '<%= paths.core %>Public/JavaScript/Contrib/flatpickr/flatpickr.min.js': ['<%= paths.core %>Public/JavaScript/Contrib/flatpickr/flatpickr.min.js'], '<%= paths.core %>Public/JavaScript/Contrib/flatpickr/locales.js': ['<%= paths.core %>Public/JavaScript/Contrib/flatpickr/locales.js'], @@ -778,21 +801,6 @@ module.exports = function (grunt) { '<%= paths.core %>Public/JavaScript/Contrib/taboverride.js': ['<%= paths.core %>Public/JavaScript/Contrib/taboverride.js'] } }, - t3editor: { - files: [ - { - expand: true, - src: [ - '<%= paths.t3editor %>Public/JavaScript/Contrib/**/*.js' - ], - dest: '<%= paths.t3editor %>Public/JavaScript/Contrib', - cwd: '.', - rename: function (dest, src) { - return src; - } - } - ] - }, typescript: { options: { output: { @@ -830,7 +838,7 @@ module.exports = function (grunt) { lint: ['eslint', 'stylelint', 'exec:lintspaces'], compile_assets: ['scripts', 'css'], compile_flags: ['flags-build'], - minify_assets: ['terser:thirdparty', 'terser:t3editor'], + minify_assets: ['terser:thirdparty'], copy_static: ['copy:core_icons', 'copy:install_icons', 'copy:module_icons', 'copy:extension_icons', 'copy:fonts', 'copy-lit', 'copy:t3editor'], build: ['copy:core_icons', 'copy:install_icons', 'copy:module_icons', 'copy:extension_icons', 'copy:fonts', 'copy:t3editor'], }, diff --git a/Build/Sources/TypeScript/t3editor/autocomplete/completion-result.ts b/Build/Sources/TypeScript/backend/code-editor/autocomplete/completion-result.ts similarity index 95% rename from Build/Sources/TypeScript/t3editor/autocomplete/completion-result.ts rename to Build/Sources/TypeScript/backend/code-editor/autocomplete/completion-result.ts index 2eb7118076ad..c64c8ea25ac8 100644 --- a/Build/Sources/TypeScript/t3editor/autocomplete/completion-result.ts +++ b/Build/Sources/TypeScript/backend/code-editor/autocomplete/completion-result.ts @@ -11,8 +11,8 @@ * The TYPO3 project - inspiring people to share! */ -import type { TsRef, TsRefType } from '@typo3/t3editor/autocomplete/ts-ref'; -import type { TreeNode } from '@typo3/t3editor/autocomplete/ts-parser'; +import type { TsRef, TsRefType } from './ts-ref'; +import type { TreeNode } from './ts-parser'; export type Proposal = { type: string, diff --git a/Build/Sources/TypeScript/t3editor/autocomplete/ts-code-completion.ts b/Build/Sources/TypeScript/backend/code-editor/autocomplete/ts-code-completion.ts similarity index 90% rename from Build/Sources/TypeScript/t3editor/autocomplete/ts-code-completion.ts rename to Build/Sources/TypeScript/backend/code-editor/autocomplete/ts-code-completion.ts index 346731bfdb68..b438e57e37e0 100644 --- a/Build/Sources/TypeScript/t3editor/autocomplete/ts-code-completion.ts +++ b/Build/Sources/TypeScript/backend/code-editor/autocomplete/ts-code-completion.ts @@ -12,15 +12,15 @@ */ /** - * Module: @typo3/t3editor/autocomplete/ts-code-completion + * Module: ./ts-code-completion * Contains the TsCodeCompletion class */ import AjaxRequest from '@typo3/core/ajax/ajax-request'; -import { TsRef } from '@typo3/t3editor/autocomplete/ts-ref'; -import { TsParser } from '@typo3/t3editor/autocomplete/ts-parser'; -import { CompletionResult, Proposal } from '@typo3/t3editor/autocomplete/completion-result'; +import { TsRef } from './ts-ref'; +import { TsParser } from './ts-parser'; +import { CompletionResult, Proposal } from './completion-result'; -import type { CodeMirror5CompatibleCompletionState } from '@typo3/t3editor/language/typoscript'; +import type { CodeMirror5CompatibleCompletionState } from '../language/typoscript'; export type ContentObjectIdentifier = string; @@ -77,7 +77,7 @@ export class TsCodeCompletion { if (Number.isNaN(id) || id === 0) { return null; } - new AjaxRequest(TYPO3.settings.ajaxUrls.t3editor_codecompletion_loadtemplates) + new AjaxRequest(TYPO3.settings.ajaxUrls.codeeditor_codecompletion_loadtemplates) .withQueryArguments({ pageId: id }) .get() .then(async (response) => { diff --git a/Build/Sources/TypeScript/t3editor/autocomplete/ts-parser.ts b/Build/Sources/TypeScript/backend/code-editor/autocomplete/ts-parser.ts similarity index 98% rename from Build/Sources/TypeScript/t3editor/autocomplete/ts-parser.ts rename to Build/Sources/TypeScript/backend/code-editor/autocomplete/ts-parser.ts index c893bad5db99..9b48fd22c0db 100644 --- a/Build/Sources/TypeScript/t3editor/autocomplete/ts-parser.ts +++ b/Build/Sources/TypeScript/backend/code-editor/autocomplete/ts-parser.ts @@ -11,9 +11,9 @@ * The TYPO3 project - inspiring people to share! */ -import type { TsRef } from '@typo3/t3editor/autocomplete/ts-ref'; -import type { TsObjTree } from '@typo3/t3editor/autocomplete/ts-code-completion'; -import type { CodeMirror5CompatibleCompletionState } from '@typo3/t3editor/language/typoscript'; +import type { TsRef } from './ts-ref'; +import type { TsObjTree } from './ts-code-completion'; +import type { CodeMirror5CompatibleCompletionState } from '../language/typoscript'; export class TreeNode { public value: string; diff --git a/Build/Sources/TypeScript/t3editor/autocomplete/ts-ref.ts b/Build/Sources/TypeScript/backend/code-editor/autocomplete/ts-ref.ts similarity index 99% rename from Build/Sources/TypeScript/t3editor/autocomplete/ts-ref.ts rename to Build/Sources/TypeScript/backend/code-editor/autocomplete/ts-ref.ts index f9a47cb9ac0c..e51a09addfb2 100644 --- a/Build/Sources/TypeScript/t3editor/autocomplete/ts-ref.ts +++ b/Build/Sources/TypeScript/backend/code-editor/autocomplete/ts-ref.ts @@ -63,7 +63,7 @@ export class TsRef { * Load available TypoScript reference */ public async loadTsrefAsync(): Promise<void> { - const response = await new AjaxRequest(TYPO3.settings.ajaxUrls.t3editor_tsref).get(); + const response = await new AjaxRequest(TYPO3.settings.ajaxUrls.codeeditor_tsref).get(); this.doc = await response.resolve(); this.buildTree(); } diff --git a/Build/Sources/TypeScript/t3editor/element/code-mirror-element.ts b/Build/Sources/TypeScript/backend/code-editor/element/code-mirror-element.ts similarity index 94% rename from Build/Sources/TypeScript/t3editor/element/code-mirror-element.ts rename to Build/Sources/TypeScript/backend/code-editor/element/code-mirror-element.ts index fae36389b743..d2b12c319e8e 100644 --- a/Build/Sources/TypeScript/t3editor/element/code-mirror-element.ts +++ b/Build/Sources/TypeScript/backend/code-editor/element/code-mirror-element.ts @@ -31,7 +31,7 @@ import { executeJavaScriptModuleInstruction, loadModule, resolveSubjectRef, Java import '@typo3/backend/element/spinner-element'; /** - * Module: @typo3/t3editor/element/code-mirror-element + * Module: @typo3/backend/code-editor/element/code-mirror-element * Renders CodeMirror into FormEngine */ @customElement('typo3-t3editor-codemirror') @@ -161,6 +161,28 @@ export class CodeMirrorElement extends LitElement { observer.observe(this); } + /** + * @internal + */ + public setContent(newContent: string): void { + if (this.editorView !== null) { + this.editorView.dispatch({ + changes: { + from: 0, + to: this.editorView.state.doc.length, + insert: newContent + } + }); + } + } + + /** + * @internal + */ + public getContent(): string { + return this.editorView.state.doc.toString(); + } + private onKeydown(event: KeyboardEvent): void { if (event.ctrlKey && event.altKey && event.key === 'f') { event.preventDefault(); diff --git a/Build/Sources/TypeScript/t3editor/language/typoscript.ts b/Build/Sources/TypeScript/backend/code-editor/language/typoscript.ts similarity index 96% rename from Build/Sources/TypeScript/t3editor/language/typoscript.ts rename to Build/Sources/TypeScript/backend/code-editor/language/typoscript.ts index d14857f36f6a..b675f2e38cdc 100644 --- a/Build/Sources/TypeScript/t3editor/language/typoscript.ts +++ b/Build/Sources/TypeScript/backend/code-editor/language/typoscript.ts @@ -1,8 +1,8 @@ import DocumentService from '@typo3/core/document-service'; import { StreamLanguage, LanguageSupport } from '@codemirror/language'; import { CompletionContext, CompletionResult } from '@codemirror/autocomplete'; -import { TypoScriptStreamParserFactory } from '@typo3/t3editor/stream-parser/typoscript'; -import { TsCodeCompletion } from '@typo3/t3editor/autocomplete/ts-code-completion'; +import { TypoScriptStreamParserFactory } from '../stream-parser/typoscript'; +import { TsCodeCompletion } from '../autocomplete/ts-code-completion'; import { syntaxTree } from '@codemirror/language'; import type { SyntaxNodeRef } from '@lezer/common'; @@ -23,7 +23,7 @@ export interface CodeMirror5CompatibleCompletionState { } /** - * Module: @typo3/t3editor/language/typoscript + * Module: @typo3/backend/code-editor/language/typoscript * * Entry Point module for CodeMirror v6 language highlighting and code completion for TypoScript. * This module combines our CodeMirror v5 style typoscript parser (via the StreamLanguage shim) and diff --git a/Build/Sources/TypeScript/t3editor/stream-parser/typoscript.ts b/Build/Sources/TypeScript/backend/code-editor/stream-parser/typoscript.ts similarity index 100% rename from Build/Sources/TypeScript/t3editor/stream-parser/typoscript.ts rename to Build/Sources/TypeScript/backend/code-editor/stream-parser/typoscript.ts diff --git a/Build/Sources/TypeScript/backend/grid-editor.ts b/Build/Sources/TypeScript/backend/grid-editor.ts index c1fe1b5fd346..dfae9dd4955f 100644 --- a/Build/Sources/TypeScript/backend/grid-editor.ts +++ b/Build/Sources/TypeScript/backend/grid-editor.ts @@ -20,7 +20,7 @@ import { html, LitElement, nothing, TemplateResult } from 'lit'; import { classMap } from 'lit/directives/class-map'; import { StyleInfo, styleMap } from 'lit/directives/style-map'; import { ref, Ref, createRef } from 'lit/directives/ref'; -import { CodeMirrorElement } from '@typo3/t3editor/element/code-mirror-element'; +import { CodeMirrorElement } from '@typo3/backend/code-editor/element/code-mirror-element'; type Cell = { spanned: number, rowspan: number, colspan: number, name: string, colpos: string, column: number } diff --git a/Build/Sources/TypeScript/backend/pagetsconfig/pagetsconfig-includes.ts b/Build/Sources/TypeScript/backend/pagetsconfig/pagetsconfig-includes.ts index 63d54180e595..399289ce1089 100644 --- a/Build/Sources/TypeScript/backend/pagetsconfig/pagetsconfig-includes.ts +++ b/Build/Sources/TypeScript/backend/pagetsconfig/pagetsconfig-includes.ts @@ -52,13 +52,13 @@ class PageTsConfigIncludes { private async fetchModalContent(url: string): Promise<TemplateResult> { // no `await` purpose (webcomponents initialize lazily) - topLevelModuleImport('@typo3/t3editor/element/code-mirror-element.js'); + topLevelModuleImport('@typo3/backend/code-editor/element/code-mirror-element.js'); const response: AjaxResponse = await (new AjaxRequest(url)).get(); const source: string = await response.resolve(); const mode: JavaScriptItemPayload = { - name: '@typo3/t3editor/language/typoscript.js', + name: '@typo3/backend/code-editor/language/typoscript.js', flags: 2 /* FLAG_USE_IMPORTMAP */, exportName: 'typoscript', items: [ diff --git a/Build/Sources/TypeScript/tstemplate/template-analyzer.ts b/Build/Sources/TypeScript/tstemplate/template-analyzer.ts index 7a97ec41c71a..9ca647265811 100644 --- a/Build/Sources/TypeScript/tstemplate/template-analyzer.ts +++ b/Build/Sources/TypeScript/tstemplate/template-analyzer.ts @@ -52,13 +52,13 @@ class TemplateAnalyzer { private async fetchModalContent(url: string): Promise<TemplateResult> { // no `await` purpose (webcomponents initialize lazily) - topLevelModuleImport('@typo3/t3editor/element/code-mirror-element.js'); + topLevelModuleImport('@typo3/backend/code-editor/element/code-mirror-element.js'); const response: AjaxResponse = await (new AjaxRequest(url)).get(); const source: string = await response.resolve(); const mode: JavaScriptItemPayload = { - name: '@typo3/t3editor/language/typoscript.js', + name: '@typo3/backend/code-editor/language/typoscript.js', flags: 2 /* FLAG_USE_IMPORTMAP */, exportName: 'typoscript', items: [ diff --git a/Build/tsconfig.json b/Build/tsconfig.json index ec982534e9c2..e61ea0d675fb 100644 --- a/Build/tsconfig.json +++ b/Build/tsconfig.json @@ -84,9 +84,6 @@ "@typo3/styleguide/*": [ "styleguide/*" ], - "@typo3/t3editor/*": [ - "t3editor/*" - ], "@typo3/tstemplate/*": [ "tstemplate/*" ], diff --git a/Build/web-test-runner.config.mjs b/Build/web-test-runner.config.mjs index 20ff56bbf559..9aa7d819e127 100644 --- a/Build/web-test-runner.config.mjs +++ b/Build/web-test-runner.config.mjs @@ -198,46 +198,46 @@ export default { '@typo3/lowlevel/': './typo3/sysext/lowlevel/Resources/Public/JavaScript/', '@typo3/opendocs/': './typo3/sysext/opendocs/Resources/Public/JavaScript/', - '@typo3/t3editor/': './typo3/sysext/t3editor/Resources/Public/JavaScript/', - 'crelt': './typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/crelt.js', - 'style-mod': './typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/style-mod.js', - 'w3c-keyname': './typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/w3c-keyname.js', - '@lezer/common': './typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@lezer/common.js', - '@lezer/css': './typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@lezer/css.js', - '@lezer/html': './typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@lezer/html.js', - '@lezer/javascript': './typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@lezer/javascript.js', - '@lezer/json': './typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@lezer/json.js', - '@lezer/php': './typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@lezer/php.js', - '@lezer/xml': './typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@lezer/xml.js', - '@lezer/lr': './typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@lezer/lr.js', - '@lezer/highlight': './typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@lezer/highlight.js', - '@codemirror/autocomplete': './typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@codemirror/autocomplete.js', - '@codemirror/closebrackets': './typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@codemirror/closebrackets.js', - '@codemirror/commands': './typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@codemirror/commands.js', - '@codemirror/comment': './typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@codemirror/comment.js', - '@codemirror/fold': './typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@codemirror/fold.js', - '@codemirror/gutter': './typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@codemirror/gutter.js', - '@codemirror/highlight': './typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@codemirror/highlight.js', - '@codemirror/history': './typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@codemirror/history.js', - '@codemirror/language': './typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@codemirror/language.js', - '@codemirror/lang-css': './typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@codemirror/lang-css.js', - '@codemirror/lang-html': './typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@codemirror/lang-html.js', - '@codemirror/lang-javascript': './typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@codemirror/lang-javascript.js', - '@codemirror/lang-json': './typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@codemirror/lang-json.js', - '@codemirror/lang-php': './typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@codemirror/lang-php.js', - '@codemirror/lang-sql': './typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@codemirror/lang-sql.js', - '@codemirror/lang-xml': './typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@codemirror/lang-xml.js', - '@codemirror/lint': './typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@codemirror/lint.js', - '@codemirror/matchbrackets': './typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@codemirror/matchbrackets.js', - '@codemirror/panel': './typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@codemirror/panel.js', - '@codemirror/rangeset': './typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@codemirror/rangeset.js', - '@codemirror/rectangular-selection': './typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@codemirror/rectangular-selection.js', - '@codemirror/search': './typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@codemirror/search.js', - '@codemirror/state': './typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@codemirror/state.js', - '@codemirror/text': './typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@codemirror/text.js', - '@codemirror/tooltip': './typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@codemirror/tooltip.js', - '@codemirror/theme-one-dark': './typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@codemirror/theme-one-dark.js', - '@codemirror/view': './typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@codemirror/view.js', + '@typo3/t3editor/': './typo3/sysext/backend/code-editor/Resources/Public/JavaScript/', + 'crelt': './typo3/sysext/backend/code-editor/Resources/Public/JavaScript/Contrib/crelt.js', + 'style-mod': './typo3/sysext/backend/code-editor/Resources/Public/JavaScript/Contrib/style-mod.js', + 'w3c-keyname': './typo3/sysext/backend/code-editor/Resources/Public/JavaScript/Contrib/w3c-keyname.js', + '@lezer/common': './typo3/sysext/backend/code-editor/Resources/Public/JavaScript/Contrib/@lezer/common.js', + '@lezer/css': './typo3/sysext/backend/code-editor/Resources/Public/JavaScript/Contrib/@lezer/css.js', + '@lezer/html': './typo3/sysext/backend/code-editor/Resources/Public/JavaScript/Contrib/@lezer/html.js', + '@lezer/javascript': './typo3/sysext/backend/code-editor/Resources/Public/JavaScript/Contrib/@lezer/javascript.js', + '@lezer/json': './typo3/sysext/backend/code-editor/Resources/Public/JavaScript/Contrib/@lezer/json.js', + '@lezer/php': './typo3/sysext/backend/code-editor/Resources/Public/JavaScript/Contrib/@lezer/php.js', + '@lezer/xml': './typo3/sysext/backend/code-editor/Resources/Public/JavaScript/Contrib/@lezer/xml.js', + '@lezer/lr': './typo3/sysext/backend/code-editor/Resources/Public/JavaScript/Contrib/@lezer/lr.js', + '@lezer/highlight': './typo3/sysext/backend/code-editor/Resources/Public/JavaScript/Contrib/@lezer/highlight.js', + '@codemirror/autocomplete': './typo3/sysext/backend/code-editor/Resources/Public/JavaScript/Contrib/@codemirror/autocomplete.js', + '@codemirror/closebrackets': './typo3/sysext/backend/code-editor/Resources/Public/JavaScript/Contrib/@codemirror/closebrackets.js', + '@codemirror/commands': './typo3/sysext/backend/code-editor/Resources/Public/JavaScript/Contrib/@codemirror/commands.js', + '@codemirror/comment': './typo3/sysext/backend/code-editor/Resources/Public/JavaScript/Contrib/@codemirror/comment.js', + '@codemirror/fold': './typo3/sysext/backend/code-editor/Resources/Public/JavaScript/Contrib/@codemirror/fold.js', + '@codemirror/gutter': './typo3/sysext/backend/code-editor/Resources/Public/JavaScript/Contrib/@codemirror/gutter.js', + '@codemirror/highlight': './typo3/sysext/backend/code-editor/Resources/Public/JavaScript/Contrib/@codemirror/highlight.js', + '@codemirror/history': './typo3/sysext/backend/code-editor/Resources/Public/JavaScript/Contrib/@codemirror/history.js', + '@codemirror/language': './typo3/sysext/backend/code-editor/Resources/Public/JavaScript/Contrib/@codemirror/language.js', + '@codemirror/lang-css': './typo3/sysext/backend/code-editor/Resources/Public/JavaScript/Contrib/@codemirror/lang-css.js', + '@codemirror/lang-html': './typo3/sysext/backend/code-editor/Resources/Public/JavaScript/Contrib/@codemirror/lang-html.js', + '@codemirror/lang-javascript': './typo3/sysext/backend/code-editor/Resources/Public/JavaScript/Contrib/@codemirror/lang-javascript.js', + '@codemirror/lang-json': './typo3/sysext/backend/code-editor/Resources/Public/JavaScript/Contrib/@codemirror/lang-json.js', + '@codemirror/lang-php': './typo3/sysext/backend/code-editor/Resources/Public/JavaScript/Contrib/@codemirror/lang-php.js', + '@codemirror/lang-sql': './typo3/sysext/backend/code-editor/Resources/Public/JavaScript/Contrib/@codemirror/lang-sql.js', + '@codemirror/lang-xml': './typo3/sysext/backend/code-editor/Resources/Public/JavaScript/Contrib/@codemirror/lang-xml.js', + '@codemirror/lint': './typo3/sysext/backend/code-editor/Resources/Public/JavaScript/Contrib/@codemirror/lint.js', + '@codemirror/matchbrackets': './typo3/sysext/backend/code-editor/Resources/Public/JavaScript/Contrib/@codemirror/matchbrackets.js', + '@codemirror/panel': './typo3/sysext/backend/code-editor/Resources/Public/JavaScript/Contrib/@codemirror/panel.js', + '@codemirror/rangeset': './typo3/sysext/backend/code-editor/Resources/Public/JavaScript/Contrib/@codemirror/rangeset.js', + '@codemirror/rectangular-selection': './typo3/sysext/backend/code-editor/Resources/Public/JavaScript/Contrib/@codemirror/rectangular-selection.js', + '@codemirror/search': './typo3/sysext/backend/code-editor/Resources/Public/JavaScript/Contrib/@codemirror/search.js', + '@codemirror/state': './typo3/sysext/backend/code-editor/Resources/Public/JavaScript/Contrib/@codemirror/state.js', + '@codemirror/text': './typo3/sysext/backend/code-editor/Resources/Public/JavaScript/Contrib/@codemirror/text.js', + '@codemirror/tooltip': './typo3/sysext/backend/code-editor/Resources/Public/JavaScript/Contrib/@codemirror/tooltip.js', + '@codemirror/theme-one-dark': './typo3/sysext/backend/code-editor/Resources/Public/JavaScript/Contrib/@codemirror/theme-one-dark.js', + '@codemirror/view': './typo3/sysext/backend/code-editor/Resources/Public/JavaScript/Contrib/@codemirror/view.js', '@typo3/tstemplate/': './typo3/sysext/tstemplate/Resources/Public/JavaScript/', '@typo3/viewpage/': './typo3/sysext/viewpage/Resources/Public/JavaScript/', diff --git a/composer.json b/composer.json index 6ccc1266025b..3ed530c79e8f 100644 --- a/composer.json +++ b/composer.json @@ -210,7 +210,6 @@ "typo3/cms-setup": "self.version", "typo3/cms-styleguide": "self.version", "typo3/cms-sys-note": "self.version", - "typo3/cms-t3editor": "self.version", "typo3/cms-tstemplate": "self.version", "typo3/cms-viewpage": "self.version", "typo3/cms-webhooks": "self.version", @@ -249,7 +248,6 @@ "TYPO3\\CMS\\Setup\\": "typo3/sysext/setup/Classes/", "TYPO3\\CMS\\Styleguide\\": "typo3/sysext/styleguide/Classes/", "TYPO3\\CMS\\SysNote\\": "typo3/sysext/sys_note/Classes/", - "TYPO3\\CMS\\T3editor\\": "typo3/sysext/t3editor/Classes/", "TYPO3\\CMS\\Tstemplate\\": "typo3/sysext/tstemplate/Classes/", "TYPO3\\CMS\\Viewpage\\": "typo3/sysext/viewpage/Classes/", "TYPO3\\CMS\\Webhooks\\": "typo3/sysext/webhooks/Classes/", @@ -297,7 +295,6 @@ "TYPO3\\CMS\\Webhooks\\Tests\\": "typo3/sysext/webhooks/Tests/", "TYPO3\\CMS\\Workspaces\\Tests\\": "typo3/sysext/workspaces/Tests/", "TYPO3\\CMS\\Recycler\\Tests\\": "typo3/sysext/recycler/Tests/", - "TYPO3\\CMS\\T3editor\\Tests\\": "typo3/sysext/t3editor/Tests/", "TYPO3Tests\\ActionControllerArgumentTest\\": "typo3/sysext/extbase/Tests/Functional/Mvc/Controller/Fixture/Extension/action_controller_argument_test/Classes/", "TYPO3Tests\\ActionControllerTest\\": "typo3/sysext/extbase/Tests/Functional/Mvc/Controller/Fixture/Extension/action_controller_test/Classes/", "TYPO3Tests\\BlogExample\\": "typo3/sysext/extbase/Tests/Functional/Fixtures/Extensions/blog_example/Classes/", diff --git a/composer.lock b/composer.lock index a7656243d2cd..18395b81046d 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "2220edce56b7861d31cf5b5c4b223a7f", + "content-hash": "f2d56574283e2c7cac53e10db857e541", "packages": [ { "name": "bacon/bacon-qr-code", diff --git a/typo3/sysext/adminpanel/Documentation/Settings.cfg b/typo3/sysext/adminpanel/Documentation/Settings.cfg index 876bf2008789..3d784f056f8c 100644 --- a/typo3/sysext/adminpanel/Documentation/Settings.cfg +++ b/typo3/sysext/adminpanel/Documentation/Settings.cfg @@ -68,5 +68,4 @@ t3tsref = https://docs.typo3.org/m/typo3/reference-typoscript/main/en-us/ # ext_rte_ckeditor = https://docs.typo3.org/c/typo3/cms-rte-ckeditor/main/en-us/ # ext_scheduler = https://docs.typo3.org/c/typo3/cms-scheduler/main/en-us/ # ext_seo = https://docs.typo3.org/c/typo3/cms-seo/main/en-us/ -# ext_t3editor = https://docs.typo3.org/c/typo3/cms-t3editor/main/en-us/ # ext_workspaces = https://docs.typo3.org/c/typo3/cms-workspaces/main/en-us/ diff --git a/typo3/sysext/t3editor/Classes/Addon.php b/typo3/sysext/backend/Classes/CodeEditor/Addon.php similarity index 97% rename from typo3/sysext/t3editor/Classes/Addon.php rename to typo3/sysext/backend/Classes/CodeEditor/Addon.php index ad13538124da..87b3a073ae04 100644 --- a/typo3/sysext/t3editor/Classes/Addon.php +++ b/typo3/sysext/backend/Classes/CodeEditor/Addon.php @@ -15,7 +15,7 @@ declare(strict_types=1); * The TYPO3 project - inspiring people to share! */ -namespace TYPO3\CMS\T3editor; +namespace TYPO3\CMS\Backend\CodeEditor; use TYPO3\CMS\Core\Page\JavaScriptModuleInstruction; diff --git a/typo3/sysext/t3editor/Classes/T3editor.php b/typo3/sysext/backend/Classes/CodeEditor/CodeEditor.php similarity index 88% rename from typo3/sysext/t3editor/Classes/T3editor.php rename to typo3/sysext/backend/Classes/CodeEditor/CodeEditor.php index 49544c00d049..aa2486de6e80 100644 --- a/typo3/sysext/t3editor/Classes/T3editor.php +++ b/typo3/sysext/backend/Classes/CodeEditor/CodeEditor.php @@ -15,35 +15,32 @@ declare(strict_types=1); * The TYPO3 project - inspiring people to share! */ -namespace TYPO3\CMS\T3editor; +namespace TYPO3\CMS\Backend\CodeEditor; +use TYPO3\CMS\Backend\CodeEditor\Registry\AddonRegistry; +use TYPO3\CMS\Backend\CodeEditor\Registry\ModeRegistry; use TYPO3\CMS\Core\Cache\CacheManager; use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface; use TYPO3\CMS\Core\Package\Cache\PackageDependentCacheIdentifier; use TYPO3\CMS\Core\Package\PackageManager; use TYPO3\CMS\Core\SingletonInterface; use TYPO3\CMS\Core\Utility\GeneralUtility; -use TYPO3\CMS\T3editor\Registry\AddonRegistry; -use TYPO3\CMS\T3editor\Registry\ModeRegistry; /** - * Provides necessary code to setup a t3editor instance in FormEngine + * Provides necessary code to set up a code editor instance in FormEngine * @internal * @todo: refactor to use DI */ -class T3editor implements SingletonInterface +class CodeEditor implements SingletonInterface { - /** - * @var array - */ - protected $configuration; + protected ?array $configuration = null; /** * Registers the configuration and bootstraps the modes / addons. * * @throws \InvalidArgumentException */ - public function registerConfiguration() + public function registerConfiguration(): void { $configuration = $this->buildConfiguration(); @@ -83,7 +80,7 @@ class T3editor implements SingletonInterface } /** - * Compiles the configuration for t3editor. Configuration is stored in caching framework. + * Compiles the configuration for code editor. Configuration is stored in caching framework. * * @throws \TYPO3\CMS\Core\Cache\Exception\NoSuchCacheException * @throws \TYPO3\CMS\Core\Cache\Exception\InvalidDataException @@ -113,7 +110,7 @@ class T3editor implements SingletonInterface $configurationPath = $package->getPackagePath() . 'Configuration/Backend/T3editor'; $modesFileNameForPackage = $configurationPath . '/Modes.php'; if (is_file($modesFileNameForPackage)) { - $definedModes = require_once $modesFileNameForPackage; + $definedModes = require $modesFileNameForPackage; if (is_array($definedModes)) { $this->configuration['modes'] = array_merge($this->configuration['modes'], $definedModes); } @@ -121,7 +118,7 @@ class T3editor implements SingletonInterface $addonsFileNameForPackage = $configurationPath . '/Addons.php'; if (is_file($addonsFileNameForPackage)) { - $definedAddons = require_once $addonsFileNameForPackage; + $definedAddons = require $addonsFileNameForPackage; if (is_array($definedAddons)) { $this->configuration['addons'] = array_merge($this->configuration['addons'], $definedAddons); } diff --git a/typo3/sysext/t3editor/Classes/Exception/InvalidModeException.php b/typo3/sysext/backend/Classes/CodeEditor/Exception/InvalidModeException.php similarity index 92% rename from typo3/sysext/t3editor/Classes/Exception/InvalidModeException.php rename to typo3/sysext/backend/Classes/CodeEditor/Exception/InvalidModeException.php index 3a8167472504..9435a78ef01b 100644 --- a/typo3/sysext/t3editor/Classes/Exception/InvalidModeException.php +++ b/typo3/sysext/backend/Classes/CodeEditor/Exception/InvalidModeException.php @@ -15,7 +15,7 @@ declare(strict_types=1); * The TYPO3 project - inspiring people to share! */ -namespace TYPO3\CMS\T3editor\Exception; +namespace TYPO3\CMS\Backend\CodeEditor\Exception; use TYPO3\CMS\Core\Exception; diff --git a/typo3/sysext/t3editor/Classes/Mode.php b/typo3/sysext/backend/Classes/CodeEditor/Mode.php similarity index 97% rename from typo3/sysext/t3editor/Classes/Mode.php rename to typo3/sysext/backend/Classes/CodeEditor/Mode.php index 52e32cfc9966..a0ba4cc45064 100644 --- a/typo3/sysext/t3editor/Classes/Mode.php +++ b/typo3/sysext/backend/Classes/CodeEditor/Mode.php @@ -15,7 +15,7 @@ declare(strict_types=1); * The TYPO3 project - inspiring people to share! */ -namespace TYPO3\CMS\T3editor; +namespace TYPO3\CMS\Backend\CodeEditor; use TYPO3\CMS\Core\Page\JavaScriptModuleInstruction; diff --git a/typo3/sysext/t3editor/Classes/Registry/AddonRegistry.php b/typo3/sysext/backend/Classes/CodeEditor/Registry/AddonRegistry.php similarity index 86% rename from typo3/sysext/t3editor/Classes/Registry/AddonRegistry.php rename to typo3/sysext/backend/Classes/CodeEditor/Registry/AddonRegistry.php index f2d5eff2f3a2..f4f897268410 100644 --- a/typo3/sysext/t3editor/Classes/Registry/AddonRegistry.php +++ b/typo3/sysext/backend/Classes/CodeEditor/Registry/AddonRegistry.php @@ -15,13 +15,13 @@ declare(strict_types=1); * The TYPO3 project - inspiring people to share! */ -namespace TYPO3\CMS\T3editor\Registry; +namespace TYPO3\CMS\Backend\CodeEditor\Registry; +use TYPO3\CMS\Backend\CodeEditor\Addon; use TYPO3\CMS\Core\SingletonInterface; -use TYPO3\CMS\T3editor\Addon; /** - * Registers and holds t3editor modes + * Registers and holds code editor modes * @internal */ class AddonRegistry implements SingletonInterface @@ -32,7 +32,7 @@ class AddonRegistry implements SingletonInterface protected $registeredAddons = []; /** - * Registers addons for global use in t3editor + * Registers addons for global use in code editor */ public function register(Addon $addon): AddonRegistry { diff --git a/typo3/sysext/t3editor/Classes/Registry/ModeRegistry.php b/typo3/sysext/backend/Classes/CodeEditor/Registry/ModeRegistry.php similarity index 85% rename from typo3/sysext/t3editor/Classes/Registry/ModeRegistry.php rename to typo3/sysext/backend/Classes/CodeEditor/Registry/ModeRegistry.php index e42cd0d7d4e3..0366fea7ee1f 100644 --- a/typo3/sysext/t3editor/Classes/Registry/ModeRegistry.php +++ b/typo3/sysext/backend/Classes/CodeEditor/Registry/ModeRegistry.php @@ -15,14 +15,14 @@ declare(strict_types=1); * The TYPO3 project - inspiring people to share! */ -namespace TYPO3\CMS\T3editor\Registry; +namespace TYPO3\CMS\Backend\CodeEditor\Registry; +use TYPO3\CMS\Backend\CodeEditor\Exception\InvalidModeException; +use TYPO3\CMS\Backend\CodeEditor\Mode; use TYPO3\CMS\Core\SingletonInterface; -use TYPO3\CMS\T3editor\Exception\InvalidModeException; -use TYPO3\CMS\T3editor\Mode; /** - * Registers and holds t3editor modes + * Registers and holds code editor modes * @internal */ class ModeRegistry implements SingletonInterface @@ -30,15 +30,12 @@ class ModeRegistry implements SingletonInterface /** * @var Mode[] */ - protected $registeredModes = []; + protected array $registeredModes = []; - /** - * @var Mode - */ - protected $defaultMode; + protected Mode $defaultMode; /** - * Registers modes for t3editor + * Registers modes for code editor */ public function register(Mode $mode): ModeRegistry { @@ -78,7 +75,7 @@ class ModeRegistry implements SingletonInterface } } - throw new InvalidModeException('Tried to get unregistered t3editor mode by format code "' . $formatCode . '"', 1499710203); + throw new InvalidModeException('Tried to get unregistered code editor mode by format code "' . $formatCode . '"', 1499710203); } /** diff --git a/typo3/sysext/t3editor/Classes/Controller/CodeCompletionController.php b/typo3/sysext/backend/Classes/Controller/CodeEditor/CodeCompletionController.php similarity index 90% rename from typo3/sysext/t3editor/Classes/Controller/CodeCompletionController.php rename to typo3/sysext/backend/Classes/Controller/CodeEditor/CodeCompletionController.php index 17ef7b66e467..17fd106245c4 100644 --- a/typo3/sysext/t3editor/Classes/Controller/CodeCompletionController.php +++ b/typo3/sysext/backend/Classes/Controller/CodeEditor/CodeCompletionController.php @@ -15,7 +15,7 @@ declare(strict_types=1); * The TYPO3 project - inspiring people to share! */ -namespace TYPO3\CMS\T3editor\Controller; +namespace TYPO3\CMS\Backend\Controller\CodeEditor; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; @@ -33,7 +33,7 @@ use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Core\Utility\RootlineUtility; /** - * Code completion for t3editor + * Code completion for code editor * * @internal This is a specific Backend Controller implementation and is not considered part of the Public TYPO3 API. */ @@ -49,18 +49,18 @@ class CodeCompletionController /** * Loads all templates up to a given page id (walking the rootline) and - * cleans parts that are not required for the t3editor code-completion. + * cleans parts that are not required for the code editor code-completion. */ public function loadCompletions(ServerRequestInterface $request): ResponseInterface { // Check whether access is granted (only admin have access to sys_template records): if (!$GLOBALS['BE_USER']->isAdmin()) { - return new HtmlResponse($this->getLanguageService()->sL('LLL:EXT:t3editor/Resources/Private/Language/locallang.xlf:noPermission'), 500); + return new HtmlResponse($this->getLanguageService()->sL('LLL:EXT:backend/Resources/Private/Language/locallang_codeeditor.xlf:noPermission'), 500); } $pageId = (int)($request->getParsedBody()['pageId'] ?? $request->getQueryParams()['pageId']); // Check whether there is a pageId given: if (!$pageId) { - return new HtmlResponse($this->getLanguageService()->sL('LLL:EXT:t3editor/Resources/Private/Language/locallang.xlf:pageIDInteger'), 500); + return new HtmlResponse($this->getLanguageService()->sL('LLL:EXT:backend/Resources/Private/Language/locallang_codeeditor.xlf:pageIDInteger'), 500); } // Fetch the templates return new JsonResponse($this->getMergedTemplates($pageId, $request)); @@ -68,7 +68,7 @@ class CodeCompletionController /** * Gets merged templates by walking the rootline to a given page id. - * This is loaded once via ajax when a t3editor in typoscript mode is fired. + * This is loaded once via ajax when a code editor in typoscript mode is fired. * JS then knows the object types and can auto-complete on CTRL+space. * * @return array Setup part of merged template records @@ -83,8 +83,7 @@ class CodeCompletionController $setupAstBuilderVisitor = GeneralUtility::makeInstance(IncludeTreeAstBuilderVisitor::class); $this->treeTraverser->traverse($setupIncludeTree, [$setupAstBuilderVisitor]); $setupAst = $setupAstBuilderVisitor->getAst(); - $result = $this->treeWalkCleanup($setupAst->toArray()); - return $result; + return $this->treeWalkCleanup($setupAst->toArray()); } /** diff --git a/typo3/sysext/t3editor/Classes/Controller/TypoScriptReferenceController.php b/typo3/sysext/backend/Classes/Controller/CodeEditor/TypoScriptReferenceController.php similarity index 96% rename from typo3/sysext/t3editor/Classes/Controller/TypoScriptReferenceController.php rename to typo3/sysext/backend/Classes/Controller/CodeEditor/TypoScriptReferenceController.php index 343fa0709fb3..bbf5899e8f97 100644 --- a/typo3/sysext/t3editor/Classes/Controller/TypoScriptReferenceController.php +++ b/typo3/sysext/backend/Classes/Controller/CodeEditor/TypoScriptReferenceController.php @@ -15,7 +15,7 @@ declare(strict_types=1); * The TYPO3 project - inspiring people to share! */ -namespace TYPO3\CMS\T3editor\Controller; +namespace TYPO3\CMS\Backend\Controller\CodeEditor; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; @@ -39,7 +39,7 @@ class TypoScriptReferenceController public function loadReference(ServerRequestInterface $request): ResponseInterface { // Load the TSref XML information: - $this->loadFile(GeneralUtility::getFileAbsFileName('EXT:t3editor/Resources/Private/tsref.xml')); + $this->loadFile(GeneralUtility::getFileAbsFileName('EXT:backend/Resources/Private/tsref.xml')); return new JsonResponse($this->getTypes()); } diff --git a/typo3/sysext/t3editor/Classes/EventListener/InitializeT3editorInEditFileForm.php b/typo3/sysext/backend/Classes/EventListener/InitializeCodeEditorInEditFileForm.php similarity index 69% rename from typo3/sysext/t3editor/Classes/EventListener/InitializeT3editorInEditFileForm.php rename to typo3/sysext/backend/Classes/EventListener/InitializeCodeEditorInEditFileForm.php index 0c8c1210e540..3e289c7d0d9e 100644 --- a/typo3/sysext/t3editor/Classes/EventListener/InitializeT3editorInEditFileForm.php +++ b/typo3/sysext/backend/Classes/EventListener/InitializeCodeEditorInEditFileForm.php @@ -15,28 +15,28 @@ declare(strict_types=1); * The TYPO3 project - inspiring people to share! */ -namespace TYPO3\CMS\T3editor\EventListener; +namespace TYPO3\CMS\Backend\EventListener; +use TYPO3\CMS\Backend\CodeEditor\CodeEditor; +use TYPO3\CMS\Backend\CodeEditor\Exception\InvalidModeException; +use TYPO3\CMS\Backend\CodeEditor\Registry\ModeRegistry; use TYPO3\CMS\Core\Attribute\AsEventListener; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Filelist\Event\ModifyEditFileFormDataEvent; -use TYPO3\CMS\T3editor\Exception\InvalidModeException; -use TYPO3\CMS\T3editor\Registry\ModeRegistry; -use TYPO3\CMS\T3editor\T3editor; /** - * Listener which modifies the form data to initialize t3editor with + * Listener which modifies the form data to initialize code editor with * the resolved format option (based on the file extension). */ -final class InitializeT3editorInEditFileForm +final class InitializeCodeEditorInEditFileForm { public function __construct(private readonly ModeRegistry $modeRegistry) {} - #[AsEventListener('typo3-t3editor/initialize-t3editor-in-edit-file-form')] + #[AsEventListener('typo3-code editor/initialize-code-editor-in-edit-file-form')] public function __invoke(ModifyEditFileFormDataEvent $event): void { - // Compile and register t3editor configuration - GeneralUtility::makeInstance(T3editor::class)->registerConfiguration(); + // Compile and register code editor configuration + GeneralUtility::makeInstance(CodeEditor::class)->registerConfiguration(); $fileExtension = $event->getFile()->getExtension(); @@ -47,7 +47,7 @@ final class InitializeT3editorInEditFileForm } $formData = $event->getFormData(); - $formData['processedTca']['columns']['data']['config']['renderType'] = 't3editor'; + $formData['processedTca']['columns']['data']['config']['renderType'] = 'codeEditor'; $formData['processedTca']['columns']['data']['config']['format'] = $mode->getFormatCode(); $event->setFormData($formData); } diff --git a/typo3/sysext/backend/Classes/Form/Element/BackendLayoutWizardElement.php b/typo3/sysext/backend/Classes/Form/Element/BackendLayoutWizardElement.php index 3d607c940d4a..2099e73a981b 100644 --- a/typo3/sysext/backend/Classes/Form/Element/BackendLayoutWizardElement.php +++ b/typo3/sysext/backend/Classes/Form/Element/BackendLayoutWizardElement.php @@ -21,7 +21,6 @@ use TYPO3\CMS\Core\EventDispatcher\NoopEventDispatcher; use TYPO3\CMS\Core\Page\JavaScriptModuleInstruction; use TYPO3\CMS\Core\TypoScript\AST\AstBuilder; use TYPO3\CMS\Core\TypoScript\TypoScriptStringFactory; -use TYPO3\CMS\Core\Utility\ExtensionManagementUtility; use TYPO3\CMS\Core\Utility\GeneralUtility; /** @@ -83,20 +82,16 @@ class BackendLayoutWizardElement extends AbstractFormElement $fieldWizardHtml = $fieldWizardResult['html']; $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldWizardResult, false); - $codeMirrorConfig = []; - // Use CodeMirror if available - if (ExtensionManagementUtility::isLoaded('t3editor')) { - $codeMirrorConfig = [ - 'label' => $lang->sL('LLL:EXT:backend/Resources/Private/Language/locallang_alt_doc.xlf:buttons.pageTsConfig'), - 'panel' => 'top', - 'mode' => GeneralUtility::jsonEncodeForHtmlAttribute(JavaScriptModuleInstruction::create('@typo3/t3editor/language/typoscript.js', 'typoscript')->invoke(), false), - 'nolazyload' => 'true', - 'readonly' => 'true', - ]; - - $resultArray['javaScriptModules'][] = JavaScriptModuleInstruction::create('@typo3/t3editor/element/code-mirror-element.js'); - } + $codeMirrorConfig = [ + 'label' => $lang->sL('LLL:EXT:backend/Resources/Private/Language/locallang_alt_doc.xlf:buttons.pageTsConfig'), + 'panel' => 'top', + 'mode' => GeneralUtility::jsonEncodeForHtmlAttribute(JavaScriptModuleInstruction::create('@typo3/backend/code-editor/language/typoscript.js', 'typoscript')->invoke(), false), + 'nolazyload' => 'true', + 'readonly' => 'true', + ]; + + $resultArray['javaScriptModules'][] = JavaScriptModuleInstruction::create('@typo3/backend/code-editor/element/code-mirror-element.js'); $json = (string)json_encode($this->rows, JSON_HEX_QUOT | JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS); $codeMirrorConfig = (string)json_encode($codeMirrorConfig, JSON_HEX_QUOT | JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS); diff --git a/typo3/sysext/t3editor/Classes/Form/Element/T3editorElement.php b/typo3/sysext/backend/Classes/Form/Element/CodeEditorElement.php similarity index 90% rename from typo3/sysext/t3editor/Classes/Form/Element/T3editorElement.php rename to typo3/sysext/backend/Classes/Form/Element/CodeEditorElement.php index d8ebcd4033d9..9cec1d81d317 100644 --- a/typo3/sysext/t3editor/Classes/Form/Element/T3editorElement.php +++ b/typo3/sysext/backend/Classes/Form/Element/CodeEditorElement.php @@ -15,33 +15,25 @@ declare(strict_types=1); * The TYPO3 project - inspiring people to share! */ -namespace TYPO3\CMS\T3editor\Form\Element; +namespace TYPO3\CMS\Backend\Form\Element; -use TYPO3\CMS\Backend\Form\Element\AbstractFormElement; +use TYPO3\CMS\Backend\CodeEditor\CodeEditor; +use TYPO3\CMS\Backend\CodeEditor\Exception\InvalidModeException; +use TYPO3\CMS\Backend\CodeEditor\Mode; +use TYPO3\CMS\Backend\CodeEditor\Registry\AddonRegistry; +use TYPO3\CMS\Backend\CodeEditor\Registry\ModeRegistry; use TYPO3\CMS\Core\Page\JavaScriptModuleInstruction; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Core\Utility\MathUtility; -use TYPO3\CMS\T3editor\Exception\InvalidModeException; -use TYPO3\CMS\T3editor\Mode; -use TYPO3\CMS\T3editor\Registry\AddonRegistry; -use TYPO3\CMS\T3editor\Registry\ModeRegistry; -use TYPO3\CMS\T3editor\T3editor; /** - * t3editor FormEngine widget + * CodeEditor FormEngine widget * @internal */ -class T3editorElement extends AbstractFormElement +class CodeEditorElement extends AbstractFormElement { - /** - * @var array - */ - protected $resultArray; - - /** - * @var string - */ - protected $mode = ''; + protected array $resultArray = []; + protected string $mode = ''; /** * Default field information enabled for this element. @@ -78,20 +70,20 @@ class T3editorElement extends AbstractFormElement ]; /** - * Render t3editor element + * Render code editor element * * @return array As defined in initializeResultArray() of AbstractNode - * @throws \TYPO3\CMS\T3editor\Exception\InvalidModeException + * @throws InvalidModeException * @throws \InvalidArgumentException * @throws \BadFunctionCallException */ public function render(): array { $this->resultArray = $this->initializeResultArray(); - $this->resultArray['javaScriptModules'][] = JavaScriptModuleInstruction::create('@typo3/t3editor/element/code-mirror-element.js'); + $this->resultArray['javaScriptModules'][] = JavaScriptModuleInstruction::create('@typo3/backend/code-editor/element/code-mirror-element.js'); - // Compile and register t3editor configuration - GeneralUtility::makeInstance(T3editor::class)->registerConfiguration(); + // Compile and register code editor configuration + GeneralUtility::makeInstance(CodeEditor::class)->registerConfiguration(); $addonRegistry = GeneralUtility::makeInstance(AddonRegistry::class); $registeredAddons = $addonRegistry->getAddons(); @@ -178,7 +170,7 @@ class T3editorElement extends AbstractFormElement * @param array $attributes Any additional editor parameters * * @return string Generated HTML code for editor - * @throws \TYPO3\CMS\T3editor\Exception\InvalidModeException + * @throws \TYPO3\CMS\Backend\CodeEditor\Exception\InvalidModeException */ protected function getHTMLCodeForEditor( string $name, @@ -212,6 +204,7 @@ class T3editorElement extends AbstractFormElement } } $codeMirrorConfig = [ + 'name' => $name, 'mode' => GeneralUtility::jsonEncodeForHtmlAttribute($mode->getModule(), false), 'addons' => GeneralUtility::jsonEncodeForHtmlAttribute($addons, false), 'keymaps' => GeneralUtility::jsonEncodeForHtmlAttribute($keymaps, false), diff --git a/typo3/sysext/backend/Classes/Form/Element/JsonElement.php b/typo3/sysext/backend/Classes/Form/Element/JsonElement.php index b04fd2a65639..2e8768835790 100644 --- a/typo3/sysext/backend/Classes/Form/Element/JsonElement.php +++ b/typo3/sysext/backend/Classes/Form/Element/JsonElement.php @@ -17,14 +17,13 @@ declare(strict_types=1); namespace TYPO3\CMS\Backend\Form\Element; +use TYPO3\CMS\Backend\CodeEditor\CodeEditor; +use TYPO3\CMS\Backend\CodeEditor\Registry\AddonRegistry; +use TYPO3\CMS\Backend\CodeEditor\Registry\ModeRegistry; use TYPO3\CMS\Core\Page\JavaScriptModuleInstruction; -use TYPO3\CMS\Core\Utility\ExtensionManagementUtility; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Core\Utility\MathUtility; use TYPO3\CMS\Core\Utility\StringUtility; -use TYPO3\CMS\T3editor\Registry\AddonRegistry; -use TYPO3\CMS\T3editor\Registry\ModeRegistry; -use TYPO3\CMS\T3editor\T3editor; /** * Handles type=json elements. @@ -75,7 +74,7 @@ class JsonElement extends AbstractFormElement $config = $parameterArray['fieldConf']['config']; $readOnly = (bool)($config['readOnly'] ?? false); $placeholder = trim((string)($config['placeholder'] ?? '')); - $enableCodeEditor = ($config['enableCodeEditor'] ?? true) && ExtensionManagementUtility::isLoaded('t3editor'); + $enableCodeEditor = $config['enableCodeEditor'] ?? true; $itemValue = ''; if (!empty($parameterArray['itemFormElValue'])) { @@ -108,7 +107,6 @@ class JsonElement extends AbstractFormElement $fieldInformationHtml = $fieldInformationResult['html']; $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldInformationResult, false); - // Early return readonly display in case t3editor is not available if ($readOnly && !$enableCodeEditor) { $html = []; $html[] = $this->renderLabel($fieldId); @@ -148,8 +146,8 @@ class JsonElement extends AbstractFormElement // Use CodeMirror if available if ($enableCodeEditor) { - // Compile and register t3editor configuration - GeneralUtility::makeInstance(T3editor::class)->registerConfiguration(); + // Compile and register code editor configuration + GeneralUtility::makeInstance(CodeEditor::class)->registerConfiguration(); $modeRegistry = GeneralUtility::makeInstance(ModeRegistry::class); $mode = $modeRegistry->isRegistered('json') @@ -186,7 +184,7 @@ class JsonElement extends AbstractFormElement $codeMirrorConfig['keymaps'] = GeneralUtility::jsonEncodeForHtmlAttribute($keymaps, false); } - $resultArray['javaScriptModules'][] = JavaScriptModuleInstruction::create('@typo3/t3editor/element/code-mirror-element.js'); + $resultArray['javaScriptModules'][] = JavaScriptModuleInstruction::create('@typo3/backend/code-editor/element/code-mirror-element.js'); $editorHtml = ' <typo3-t3editor-codemirror ' . GeneralUtility::implodeAttributes($codeMirrorConfig, true, true) . '> <textarea ' . GeneralUtility::implodeAttributes($attributes, true, true) . '>' . htmlspecialchars($itemValue) . '</textarea> diff --git a/typo3/sysext/backend/Classes/Form/NodeFactory.php b/typo3/sysext/backend/Classes/Form/NodeFactory.php index d47427ac6b83..62af8046aca0 100644 --- a/typo3/sysext/backend/Classes/Form/NodeFactory.php +++ b/typo3/sysext/backend/Classes/Form/NodeFactory.php @@ -90,8 +90,7 @@ class NodeFactory 'selectSingle' => Element\SelectSingleElement::class, 'selectSingleBox' => Element\SelectSingleBoxElement::class, 'color' => Element\ColorElement::class, - // t3editor is defined with a fallback so extensions can use it even if ext:t3editor is not loaded - 't3editor' => Element\TextElement::class, + 'codeEditor' => Element\CodeEditorElement::class, 'text' => Element\TextElement::class, 'textTable' => Element\TextTableElement::class, 'unknown' => Element\UnknownElement::class, diff --git a/typo3/sysext/backend/Configuration/Backend/AjaxRoutes.php b/typo3/sysext/backend/Configuration/Backend/AjaxRoutes.php index c0f6cfa9ad36..9f48f395ced4 100644 --- a/typo3/sysext/backend/Configuration/Backend/AjaxRoutes.php +++ b/typo3/sysext/backend/Configuration/Backend/AjaxRoutes.php @@ -401,4 +401,16 @@ return [ 'path' => '/sudo-mode/verify', 'target' => Controller\Security\SudoModeController::class . '::verifyAction', ], + + // Get TSRef + 'codeeditor_tsref' => [ + 'path' => '/code-editor/tsref', + 'target' => \TYPO3\CMS\Backend\Controller\CodeEditor\TypoScriptReferenceController::class . '::loadReference', + ], + + // Load code completion templates + 'codeeditor_codecompletion_loadtemplates' => [ + 'path' => '/code-editor/codecompletion/load-templates', + 'target' => \TYPO3\CMS\Backend\Controller\CodeEditor\CodeCompletionController::class . '::loadCompletions', + ], ]; diff --git a/typo3/sysext/t3editor/Configuration/Backend/T3editor/Addons.php b/typo3/sysext/backend/Configuration/Backend/T3editor/Addons.php similarity index 99% rename from typo3/sysext/t3editor/Configuration/Backend/T3editor/Addons.php rename to typo3/sysext/backend/Configuration/Backend/T3editor/Addons.php index 4022859d9ed4..4dca915722eb 100644 --- a/typo3/sysext/t3editor/Configuration/Backend/T3editor/Addons.php +++ b/typo3/sysext/backend/Configuration/Backend/T3editor/Addons.php @@ -3,7 +3,7 @@ use TYPO3\CMS\Core\Page\JavaScriptModuleInstruction; /** - * Addons for t3editor + * Addons for code editor */ return [ 'highlightActiveLineGutter' => [ diff --git a/typo3/sysext/t3editor/Configuration/Backend/T3editor/Modes.php b/typo3/sysext/backend/Configuration/Backend/T3editor/Modes.php similarity index 92% rename from typo3/sysext/t3editor/Configuration/Backend/T3editor/Modes.php rename to typo3/sysext/backend/Configuration/Backend/T3editor/Modes.php index 8db36582ffc6..07b893f66921 100644 --- a/typo3/sysext/t3editor/Configuration/Backend/T3editor/Modes.php +++ b/typo3/sysext/backend/Configuration/Backend/T3editor/Modes.php @@ -3,7 +3,7 @@ use TYPO3\CMS\Core\Page\JavaScriptModuleInstruction; /** - * Mode definitions for t3editor + * Mode definitions for code editor */ return [ 'css' => [ @@ -32,7 +32,7 @@ return [ 'extensions' => ['sql'], ], 'typoscript' => [ - 'module' => JavaScriptModuleInstruction::create('@typo3/t3editor/language/typoscript.js', 'typoscript')->invoke(), + 'module' => JavaScriptModuleInstruction::create('@typo3/backend/code-editor/language/typoscript.js', 'typoscript')->invoke(), 'extensions' => ['ts', 'typoscript', 'tsconfig'], ], 'xml' => [ diff --git a/typo3/sysext/backend/Configuration/JavaScriptModules.php b/typo3/sysext/backend/Configuration/JavaScriptModules.php index 06d31e79604c..725020f631f4 100644 --- a/typo3/sysext/backend/Configuration/JavaScriptModules.php +++ b/typo3/sysext/backend/Configuration/JavaScriptModules.php @@ -16,6 +16,49 @@ return [ 'EXT:backend/Resources/Public/JavaScript/Contrib/', ], ], + '@typo3/t3editor/' => [ + // @deprecated since TYPO3 v13, will be removed in TYPO3 v14 + 'path' => 'EXT:backend/Resources/Public/JavaScript/code-editor', + ], + 'crelt' => 'EXT:backend/Resources/Public/JavaScript/Contrib/crelt.js', + 'style-mod' => 'EXT:backend/Resources/Public/JavaScript/Contrib/style-mod.js', + 'w3c-keyname' => 'EXT:backend/Resources/Public/JavaScript/Contrib/w3c-keyname.js', + '@lezer/common' => 'EXT:backend/Resources/Public/JavaScript/Contrib/@lezer/common.js', + '@lezer/css' => 'EXT:backend/Resources/Public/JavaScript/Contrib/@lezer/css.js', + '@lezer/html' => 'EXT:backend/Resources/Public/JavaScript/Contrib/@lezer/html.js', + '@lezer/javascript' => 'EXT:backend/Resources/Public/JavaScript/Contrib/@lezer/javascript.js', + '@lezer/json' => 'EXT:backend/Resources/Public/JavaScript/Contrib/@lezer/json.js', + '@lezer/php' => 'EXT:backend/Resources/Public/JavaScript/Contrib/@lezer/php.js', + '@lezer/xml' => 'EXT:backend/Resources/Public/JavaScript/Contrib/@lezer/xml.js', + '@lezer/lr' => 'EXT:backend/Resources/Public/JavaScript/Contrib/@lezer/lr.js', + '@lezer/highlight' => 'EXT:backend/Resources/Public/JavaScript/Contrib/@lezer/highlight.js', + '@codemirror/autocomplete' => 'EXT:backend/Resources/Public/JavaScript/Contrib/@codemirror/autocomplete.js', + '@codemirror/closebrackets' => 'EXT:backend/Resources/Public/JavaScript/Contrib/@codemirror/closebrackets.js', + '@codemirror/commands' => 'EXT:backend/Resources/Public/JavaScript/Contrib/@codemirror/commands.js', + '@codemirror/comment' => 'EXT:backend/Resources/Public/JavaScript/Contrib/@codemirror/comment.js', + '@codemirror/fold' => 'EXT:backend/Resources/Public/JavaScript/Contrib/@codemirror/fold.js', + '@codemirror/gutter' => 'EXT:backend/Resources/Public/JavaScript/Contrib/@codemirror/gutter.js', + '@codemirror/highlight' => 'EXT:backend/Resources/Public/JavaScript/Contrib/@codemirror/highlight.js', + '@codemirror/history' => 'EXT:backend/Resources/Public/JavaScript/Contrib/@codemirror/history.js', + '@codemirror/language' => 'EXT:backend/Resources/Public/JavaScript/Contrib/@codemirror/language.js', + '@codemirror/lang-css' => 'EXT:backend/Resources/Public/JavaScript/Contrib/@codemirror/lang-css.js', + '@codemirror/lang-html' => 'EXT:backend/Resources/Public/JavaScript/Contrib/@codemirror/lang-html.js', + '@codemirror/lang-javascript' => 'EXT:backend/Resources/Public/JavaScript/Contrib/@codemirror/lang-javascript.js', + '@codemirror/lang-json' => 'EXT:backend/Resources/Public/JavaScript/Contrib/@codemirror/lang-json.js', + '@codemirror/lang-php' => 'EXT:backend/Resources/Public/JavaScript/Contrib/@codemirror/lang-php.js', + '@codemirror/lang-sql' => 'EXT:backend/Resources/Public/JavaScript/Contrib/@codemirror/lang-sql.js', + '@codemirror/lang-xml' => 'EXT:backend/Resources/Public/JavaScript/Contrib/@codemirror/lang-xml.js', + '@codemirror/lint' => 'EXT:backend/Resources/Public/JavaScript/Contrib/@codemirror/lint.js', + '@codemirror/matchbrackets' => 'EXT:backend/Resources/Public/JavaScript/Contrib/@codemirror/matchbrackets.js', + '@codemirror/panel' => 'EXT:backend/Resources/Public/JavaScript/Contrib/@codemirror/panel.js', + '@codemirror/rangeset' => 'EXT:backend/Resources/Public/JavaScript/Contrib/@codemirror/rangeset.js', + '@codemirror/rectangular-selection' => 'EXT:backend/Resources/Public/JavaScript/Contrib/@codemirror/rectangular-selection.js', + '@codemirror/search' => 'EXT:backend/Resources/Public/JavaScript/Contrib/@codemirror/search.js', + '@codemirror/state' => 'EXT:backend/Resources/Public/JavaScript/Contrib/@codemirror/state.js', + '@codemirror/text' => 'EXT:backend/Resources/Public/JavaScript/Contrib/@codemirror/text.js', + '@codemirror/tooltip' => 'EXT:backend/Resources/Public/JavaScript/Contrib/@codemirror/tooltip.js', + '@codemirror/theme-one-dark' => 'EXT:backend/Resources/Public/JavaScript/Contrib/@codemirror/theme-one-dark.js', + '@codemirror/view' => 'EXT:backend/Resources/Public/JavaScript/Contrib/@codemirror/view.js', '@typo3/backend/contrib/mark.js' => 'EXT:backend/Resources/Public/JavaScript/Contrib/mark.js', 'alwan' => 'EXT:backend/Resources/Public/JavaScript/Contrib/alwan.js', 'lodash-es' => 'EXT:backend/Resources/Public/JavaScript/Contrib/lodash-es.js', diff --git a/typo3/sysext/t3editor/Configuration/TCA/Overrides/be_groups.php b/typo3/sysext/backend/Configuration/TCA/Overrides/be_groups.php similarity index 77% rename from typo3/sysext/t3editor/Configuration/TCA/Overrides/be_groups.php rename to typo3/sysext/backend/Configuration/TCA/Overrides/be_groups.php index 022ce270cb3a..972c1cf317e3 100644 --- a/typo3/sysext/t3editor/Configuration/TCA/Overrides/be_groups.php +++ b/typo3/sysext/backend/Configuration/TCA/Overrides/be_groups.php @@ -2,8 +2,8 @@ defined('TYPO3') or die(); -// Activate t3editor for be_groups TSconfig +// Activate code editor for be_groups TSconfig if (is_array($GLOBALS['TCA']['be_groups']['columns']['TSconfig']['config'])) { - $GLOBALS['TCA']['be_groups']['columns']['TSconfig']['config']['renderType'] = 't3editor'; + $GLOBALS['TCA']['be_groups']['columns']['TSconfig']['config']['renderType'] = 'codeEditor'; $GLOBALS['TCA']['be_groups']['columns']['TSconfig']['config']['format'] = 'typoscript'; } diff --git a/typo3/sysext/t3editor/Configuration/TCA/Overrides/be_users.php b/typo3/sysext/backend/Configuration/TCA/Overrides/be_users.php similarity index 77% rename from typo3/sysext/t3editor/Configuration/TCA/Overrides/be_users.php rename to typo3/sysext/backend/Configuration/TCA/Overrides/be_users.php index 615c48ce2dcd..ad252ddd99f7 100644 --- a/typo3/sysext/t3editor/Configuration/TCA/Overrides/be_users.php +++ b/typo3/sysext/backend/Configuration/TCA/Overrides/be_users.php @@ -2,8 +2,8 @@ defined('TYPO3') or die(); -// Activate t3editor for be_users TSconfig +// Activate code editor for be_users TSconfig if (is_array($GLOBALS['TCA']['be_users']['columns']['TSconfig']['config'])) { - $GLOBALS['TCA']['be_users']['columns']['TSconfig']['config']['renderType'] = 't3editor'; + $GLOBALS['TCA']['be_users']['columns']['TSconfig']['config']['renderType'] = 'codeEditor'; $GLOBALS['TCA']['be_users']['columns']['TSconfig']['config']['format'] = 'typoscript'; } diff --git a/typo3/sysext/t3editor/Configuration/TCA/Overrides/pages.php b/typo3/sysext/backend/Configuration/TCA/Overrides/pages.php similarity index 78% rename from typo3/sysext/t3editor/Configuration/TCA/Overrides/pages.php rename to typo3/sysext/backend/Configuration/TCA/Overrides/pages.php index c548fbeaac54..386852803ca1 100644 --- a/typo3/sysext/t3editor/Configuration/TCA/Overrides/pages.php +++ b/typo3/sysext/backend/Configuration/TCA/Overrides/pages.php @@ -2,8 +2,8 @@ defined('TYPO3') or die(); -// Activate t3editor for pages TSconfig +// Activate code editor for pages TSconfig if (is_array($GLOBALS['TCA']['pages']['columns']['TSconfig']['config'])) { - $GLOBALS['TCA']['pages']['columns']['TSconfig']['config']['renderType'] = 't3editor'; + $GLOBALS['TCA']['pages']['columns']['TSconfig']['config']['renderType'] = 'codeEditor'; $GLOBALS['TCA']['pages']['columns']['TSconfig']['config']['format'] = 'typoscript'; } diff --git a/typo3/sysext/t3editor/Configuration/TCA/Overrides/sys_template.php b/typo3/sysext/backend/Configuration/TCA/Overrides/sys_template.php similarity index 75% rename from typo3/sysext/t3editor/Configuration/TCA/Overrides/sys_template.php rename to typo3/sysext/backend/Configuration/TCA/Overrides/sys_template.php index 2a6e3054af82..5eb79624664e 100644 --- a/typo3/sysext/t3editor/Configuration/TCA/Overrides/sys_template.php +++ b/typo3/sysext/backend/Configuration/TCA/Overrides/sys_template.php @@ -2,14 +2,14 @@ defined('TYPO3') or die(); -// Activate t3editor for sys_template constants +// Activate code editor for sys_template constants if (is_array($GLOBALS['TCA']['sys_template']['columns']['constants']['config'])) { - $GLOBALS['TCA']['sys_template']['columns']['constants']['config']['renderType'] = 't3editor'; + $GLOBALS['TCA']['sys_template']['columns']['constants']['config']['renderType'] = 'codeEditor'; $GLOBALS['TCA']['sys_template']['columns']['constants']['config']['format'] = 'typoscript'; } -// Activate t3editor for sys_template config +// Activate code editor for sys_template config if (is_array($GLOBALS['TCA']['sys_template']['columns']['config']['config'])) { - $GLOBALS['TCA']['sys_template']['columns']['config']['config']['renderType'] = 't3editor'; + $GLOBALS['TCA']['sys_template']['columns']['config']['config']['renderType'] = 'codeEditor'; $GLOBALS['TCA']['sys_template']['columns']['config']['config']['format'] = 'typoscript'; } diff --git a/typo3/sysext/backend/Configuration/TCA/Overrides/tt_content.php b/typo3/sysext/backend/Configuration/TCA/Overrides/tt_content.php new file mode 100644 index 000000000000..9d77cef3909f --- /dev/null +++ b/typo3/sysext/backend/Configuration/TCA/Overrides/tt_content.php @@ -0,0 +1,19 @@ +<?php + +defined('TYPO3') or die(); + +// Activate codeEditor for tt_content type HTML if this type exists +if (is_array($GLOBALS['TCA']['tt_content']['types']['html'] ?? null)) { + $GLOBALS['TCA']['tt_content']['types']['html']['columnsOverrides'] = array_replace_recursive( + $GLOBALS['TCA']['tt_content']['types']['html']['columnsOverrides'] ?? [], + [ + 'bodytext' => [ + 'config' => [ + 'renderType' => 'codeEditor', + 'wrap' => 'off', + 'format' => 'html', + ], + ], + ] + ); +} diff --git a/typo3/sysext/backend/Resources/Private/Language/locallang_codeeditor.xlf b/typo3/sysext/backend/Resources/Private/Language/locallang_codeeditor.xlf new file mode 100644 index 000000000000..b739f22aa0e5 --- /dev/null +++ b/typo3/sysext/backend/Resources/Private/Language/locallang_codeeditor.xlf @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> + <file source-language="en" datatype="plaintext" original="EXT:backend/Resources/Private/Language/locallang_codeeditor.xlf" date="2023-11-20T10:56:42Z" product-name="backend"> + <header/> + <body> + <trans-unit id="pageIDInteger" resname="pageIDInteger"> + <source>Syntax error: Parameter pageID must be a valid integer.</source> + </trans-unit> + <trans-unit id="noPermission" resname="noPermission"> + <source>Access denied: No permission to template records.</source> + </trans-unit> + </body> + </file> +</xliff> diff --git a/typo3/sysext/t3editor/Resources/Private/tsref.xml b/typo3/sysext/backend/Resources/Private/tsref.xml similarity index 100% rename from typo3/sysext/t3editor/Resources/Private/tsref.xml rename to typo3/sysext/backend/Resources/Private/tsref.xml diff --git a/typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@codemirror/autocomplete.js b/typo3/sysext/backend/Resources/Public/JavaScript/Contrib/@codemirror/autocomplete.js similarity index 100% rename from typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@codemirror/autocomplete.js rename to typo3/sysext/backend/Resources/Public/JavaScript/Contrib/@codemirror/autocomplete.js diff --git a/typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@codemirror/commands.js b/typo3/sysext/backend/Resources/Public/JavaScript/Contrib/@codemirror/commands.js similarity index 100% rename from typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@codemirror/commands.js rename to typo3/sysext/backend/Resources/Public/JavaScript/Contrib/@codemirror/commands.js diff --git a/typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@codemirror/lang-css.js b/typo3/sysext/backend/Resources/Public/JavaScript/Contrib/@codemirror/lang-css.js similarity index 100% rename from typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@codemirror/lang-css.js rename to typo3/sysext/backend/Resources/Public/JavaScript/Contrib/@codemirror/lang-css.js diff --git a/typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@codemirror/lang-html.js b/typo3/sysext/backend/Resources/Public/JavaScript/Contrib/@codemirror/lang-html.js similarity index 100% rename from typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@codemirror/lang-html.js rename to typo3/sysext/backend/Resources/Public/JavaScript/Contrib/@codemirror/lang-html.js diff --git a/typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@codemirror/lang-javascript.js b/typo3/sysext/backend/Resources/Public/JavaScript/Contrib/@codemirror/lang-javascript.js similarity index 100% rename from typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@codemirror/lang-javascript.js rename to typo3/sysext/backend/Resources/Public/JavaScript/Contrib/@codemirror/lang-javascript.js diff --git a/typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@codemirror/lang-json.js b/typo3/sysext/backend/Resources/Public/JavaScript/Contrib/@codemirror/lang-json.js similarity index 100% rename from typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@codemirror/lang-json.js rename to typo3/sysext/backend/Resources/Public/JavaScript/Contrib/@codemirror/lang-json.js diff --git a/typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@codemirror/lang-php.js b/typo3/sysext/backend/Resources/Public/JavaScript/Contrib/@codemirror/lang-php.js similarity index 100% rename from typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@codemirror/lang-php.js rename to typo3/sysext/backend/Resources/Public/JavaScript/Contrib/@codemirror/lang-php.js diff --git a/typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@codemirror/lang-sql.js b/typo3/sysext/backend/Resources/Public/JavaScript/Contrib/@codemirror/lang-sql.js similarity index 100% rename from typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@codemirror/lang-sql.js rename to typo3/sysext/backend/Resources/Public/JavaScript/Contrib/@codemirror/lang-sql.js diff --git a/typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@codemirror/lang-xml.js b/typo3/sysext/backend/Resources/Public/JavaScript/Contrib/@codemirror/lang-xml.js similarity index 100% rename from typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@codemirror/lang-xml.js rename to typo3/sysext/backend/Resources/Public/JavaScript/Contrib/@codemirror/lang-xml.js diff --git a/typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@codemirror/language.js b/typo3/sysext/backend/Resources/Public/JavaScript/Contrib/@codemirror/language.js similarity index 100% rename from typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@codemirror/language.js rename to typo3/sysext/backend/Resources/Public/JavaScript/Contrib/@codemirror/language.js diff --git a/typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@codemirror/lint.js b/typo3/sysext/backend/Resources/Public/JavaScript/Contrib/@codemirror/lint.js similarity index 100% rename from typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@codemirror/lint.js rename to typo3/sysext/backend/Resources/Public/JavaScript/Contrib/@codemirror/lint.js diff --git a/typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@codemirror/search.js b/typo3/sysext/backend/Resources/Public/JavaScript/Contrib/@codemirror/search.js similarity index 100% rename from typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@codemirror/search.js rename to typo3/sysext/backend/Resources/Public/JavaScript/Contrib/@codemirror/search.js diff --git a/typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@codemirror/state.js b/typo3/sysext/backend/Resources/Public/JavaScript/Contrib/@codemirror/state.js similarity index 100% rename from typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@codemirror/state.js rename to typo3/sysext/backend/Resources/Public/JavaScript/Contrib/@codemirror/state.js diff --git a/typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@codemirror/theme-one-dark.js b/typo3/sysext/backend/Resources/Public/JavaScript/Contrib/@codemirror/theme-one-dark.js similarity index 100% rename from typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@codemirror/theme-one-dark.js rename to typo3/sysext/backend/Resources/Public/JavaScript/Contrib/@codemirror/theme-one-dark.js diff --git a/typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@codemirror/view.js b/typo3/sysext/backend/Resources/Public/JavaScript/Contrib/@codemirror/view.js similarity index 100% rename from typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@codemirror/view.js rename to typo3/sysext/backend/Resources/Public/JavaScript/Contrib/@codemirror/view.js diff --git a/typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@lezer/common.js b/typo3/sysext/backend/Resources/Public/JavaScript/Contrib/@lezer/common.js similarity index 100% rename from typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@lezer/common.js rename to typo3/sysext/backend/Resources/Public/JavaScript/Contrib/@lezer/common.js diff --git a/typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@lezer/css.js b/typo3/sysext/backend/Resources/Public/JavaScript/Contrib/@lezer/css.js similarity index 100% rename from typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@lezer/css.js rename to typo3/sysext/backend/Resources/Public/JavaScript/Contrib/@lezer/css.js diff --git a/typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@lezer/highlight.js b/typo3/sysext/backend/Resources/Public/JavaScript/Contrib/@lezer/highlight.js similarity index 100% rename from typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@lezer/highlight.js rename to typo3/sysext/backend/Resources/Public/JavaScript/Contrib/@lezer/highlight.js diff --git a/typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@lezer/html.js b/typo3/sysext/backend/Resources/Public/JavaScript/Contrib/@lezer/html.js similarity index 100% rename from typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@lezer/html.js rename to typo3/sysext/backend/Resources/Public/JavaScript/Contrib/@lezer/html.js diff --git a/typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@lezer/javascript.js b/typo3/sysext/backend/Resources/Public/JavaScript/Contrib/@lezer/javascript.js similarity index 100% rename from typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@lezer/javascript.js rename to typo3/sysext/backend/Resources/Public/JavaScript/Contrib/@lezer/javascript.js diff --git a/typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@lezer/json.js b/typo3/sysext/backend/Resources/Public/JavaScript/Contrib/@lezer/json.js similarity index 100% rename from typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@lezer/json.js rename to typo3/sysext/backend/Resources/Public/JavaScript/Contrib/@lezer/json.js diff --git a/typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@lezer/lr.js b/typo3/sysext/backend/Resources/Public/JavaScript/Contrib/@lezer/lr.js similarity index 100% rename from typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@lezer/lr.js rename to typo3/sysext/backend/Resources/Public/JavaScript/Contrib/@lezer/lr.js diff --git a/typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@lezer/php.js b/typo3/sysext/backend/Resources/Public/JavaScript/Contrib/@lezer/php.js similarity index 100% rename from typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@lezer/php.js rename to typo3/sysext/backend/Resources/Public/JavaScript/Contrib/@lezer/php.js diff --git a/typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@lezer/xml.js b/typo3/sysext/backend/Resources/Public/JavaScript/Contrib/@lezer/xml.js similarity index 100% rename from typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/@lezer/xml.js rename to typo3/sysext/backend/Resources/Public/JavaScript/Contrib/@lezer/xml.js diff --git a/typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/crelt.js b/typo3/sysext/backend/Resources/Public/JavaScript/Contrib/crelt.js similarity index 100% rename from typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/crelt.js rename to typo3/sysext/backend/Resources/Public/JavaScript/Contrib/crelt.js diff --git a/typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/style-mod.js b/typo3/sysext/backend/Resources/Public/JavaScript/Contrib/style-mod.js similarity index 100% rename from typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/style-mod.js rename to typo3/sysext/backend/Resources/Public/JavaScript/Contrib/style-mod.js diff --git a/typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/w3c-keyname.js b/typo3/sysext/backend/Resources/Public/JavaScript/Contrib/w3c-keyname.js similarity index 100% rename from typo3/sysext/t3editor/Resources/Public/JavaScript/Contrib/w3c-keyname.js rename to typo3/sysext/backend/Resources/Public/JavaScript/Contrib/w3c-keyname.js diff --git a/typo3/sysext/t3editor/Resources/Public/JavaScript/autocomplete/completion-result.js b/typo3/sysext/backend/Resources/Public/JavaScript/code-editor/autocomplete/completion-result.js similarity index 100% rename from typo3/sysext/t3editor/Resources/Public/JavaScript/autocomplete/completion-result.js rename to typo3/sysext/backend/Resources/Public/JavaScript/code-editor/autocomplete/completion-result.js diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/code-editor/autocomplete/ts-code-completion.js b/typo3/sysext/backend/Resources/Public/JavaScript/code-editor/autocomplete/ts-code-completion.js new file mode 100644 index 000000000000..f52aef629947 --- /dev/null +++ b/typo3/sysext/backend/Resources/Public/JavaScript/code-editor/autocomplete/ts-code-completion.js @@ -0,0 +1,13 @@ +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ +import AjaxRequest from"@typo3/core/ajax/ajax-request.js";import{TsRef}from"@typo3/backend/code-editor/autocomplete/ts-ref.js";import{TsParser}from"@typo3/backend/code-editor/autocomplete/ts-parser.js";import{CompletionResult}from"@typo3/backend/code-editor/autocomplete/completion-result.js";export class TsCodeCompletion{constructor(e){this.extTsObjTree={},this.parser=null,this.proposals=null,this.compResult=null,this.tsRef=new TsRef,this.parser=new TsParser(this.tsRef,this.extTsObjTree),this.tsRef.loadTsrefAsync(),this.loadExtTemplatesAsync(e)}refreshCodeCompletion(e){const t=this.getFilter(e),s=this.parser.buildTsObjTree(e);this.compResult=new CompletionResult(this.tsRef,s),this.proposals=this.compResult.getFilteredProposals(t);const r=[];for(let e=0;e<this.proposals.length;e++)r[e]=this.proposals[e].word;return r}loadExtTemplatesAsync(e){if(Number.isNaN(e)||0===e)return null;new AjaxRequest(TYPO3.settings.ajaxUrls.codeeditor_codecompletion_loadtemplates).withQueryArguments({pageId:e}).get().then((async e=>{this.extTsObjTree.c=await e.resolve(),this.resolveExtReferencesRec(this.extTsObjTree.c)}))}resolveExtReferencesRec(e){for(const t of Object.keys(e)){let s;if(e[t].v&&"<"===e[t].v[0]&&-1===e[t].v.indexOf(">")){const r=e[t].v.replace(/</,"").trim();-1===r.indexOf(" ")&&(s=this.getExtChildNode(r),null!==s&&(e[t]=s))}!s&&e[t].c&&this.resolveExtReferencesRec(e[t].c)}}getExtChildNode(e){let t=this.extTsObjTree;const s=e.split(".");for(let e=0;e<s.length;e++){const r=s[e];if(void 0===t.c||void 0===t.c[r])return null;t=t.c[r]}return t}getFilter(e){return e.completingAfterDot?"":e.token.string.replace(".","").replace(/\s/g,"")}} \ No newline at end of file diff --git a/typo3/sysext/t3editor/Resources/Public/JavaScript/autocomplete/ts-parser.js b/typo3/sysext/backend/Resources/Public/JavaScript/code-editor/autocomplete/ts-parser.js similarity index 100% rename from typo3/sysext/t3editor/Resources/Public/JavaScript/autocomplete/ts-parser.js rename to typo3/sysext/backend/Resources/Public/JavaScript/code-editor/autocomplete/ts-parser.js diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/code-editor/autocomplete/ts-ref.js b/typo3/sysext/backend/Resources/Public/JavaScript/code-editor/autocomplete/ts-ref.js new file mode 100644 index 000000000000..77d2adca30fe --- /dev/null +++ b/typo3/sysext/backend/Resources/Public/JavaScript/code-editor/autocomplete/ts-ref.js @@ -0,0 +1,13 @@ +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ +import AjaxRequest from"@typo3/core/ajax/ajax-request.js";export class TsRefType{constructor(e,t,s){this.properties={},this.typeId=e,this.extends=t,this.properties=s}}export class TsRefProperty{constructor(e,t,s){this.parentType=e,this.name=t,this.value=s}}export class TsRef{constructor(){this.typeTree={},this.doc=null}async loadTsrefAsync(){const e=await new AjaxRequest(TYPO3.settings.ajaxUrls.codeeditor_tsref).get();this.doc=await e.resolve(),this.buildTree()}buildTree(){for(const e of Object.keys(this.doc)){const t=this.doc[e];this.typeTree[e]=new TsRefType(e,t.extends||void 0,Object.fromEntries(Object.entries(t.properties).map((([t,s])=>[t,new TsRefProperty(e,t,s.type)]))))}for(const e of Object.keys(this.typeTree))void 0!==this.typeTree[e].extends&&this.addPropertiesToType(this.typeTree[e],this.typeTree[e].extends,100)}addPropertiesToType(e,t,s){if(s<0)throw"Maximum recursion depth exceeded while trying to resolve the extends in the TSREF!";const r=t.split(",");for(let t=0;t<r.length;t++)if(void 0!==this.typeTree[r[t]]){void 0!==this.typeTree[r[t]].extends&&this.addPropertiesToType(this.typeTree[r[t]],this.typeTree[r[t]].extends,s-1);const i=this.typeTree[r[t]].properties;for(const t in i)void 0===e.properties[t]&&(e.properties[t]=i[t])}}getPropertiesFromTypeId(e){return void 0!==this.typeTree[e]?(this.typeTree[e].properties.clone=function(){const e={};for(const t of Object.keys(this))e[t]=new TsRefProperty(this[t].parentType,this[t].name,this[t].value);return e},this.typeTree[e].properties):{}}typeHasProperty(e,t){return void 0!==this.typeTree[e]&&void 0!==this.typeTree[e].properties[t]}getType(e){return this.typeTree[e]}isType(e){return void 0!==this.typeTree[e]}} \ No newline at end of file diff --git a/typo3/sysext/t3editor/Resources/Public/JavaScript/element/code-mirror-element.js b/typo3/sysext/backend/Resources/Public/JavaScript/code-editor/element/code-mirror-element.js similarity index 73% rename from typo3/sysext/t3editor/Resources/Public/JavaScript/element/code-mirror-element.js rename to typo3/sysext/backend/Resources/Public/JavaScript/code-editor/element/code-mirror-element.js index 3e85a8648451..c15b16b82d81 100644 --- a/typo3/sysext/t3editor/Resources/Public/JavaScript/element/code-mirror-element.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/code-editor/element/code-mirror-element.js @@ -15,7 +15,7 @@ var __decorate=function(e,t,o,r){var i,a=arguments.length,l=a<3?t:null===r?r=Obj <div id="codemirror-parent" @keydown=${e=>this.onKeydown(e)}></div> ${this.label&&"bottom"===this.panel?html`<div class="codemirror-label codemirror-label-bottom">${this.label}</div>`:""} ${null===this.editorView?html`<typo3-backend-spinner size="large"></typo3-backend-spinner>`:""} - `}firstUpdated(){if(this.nolazyload)return void this.initializeEditor(this.firstElementChild);const e={root:document.body},t=new IntersectionObserver((e=>{e.forEach((e=>{e.intersectionRatio>0&&(t.unobserve(e.target),this.firstElementChild&&"textarea"===this.firstElementChild.nodeName.toLowerCase()&&this.initializeEditor(this.firstElementChild))}))}),e);t.observe(this)}onKeydown(e){e.ctrlKey&&e.altKey&&"f"===e.key&&(e.preventDefault(),this.fullscreen=!0),"Escape"===e.key&&this.fullscreen&&(e.preventDefault(),this.fullscreen=!1)}async initializeEditor(e){const t=EditorView.updateListener.of((t=>{t.docChanged&&(e.value=t.state.doc.toString(),e.dispatchEvent(new CustomEvent("change",{bubbles:!0})))}));this.lineDigits>0?this.style.setProperty("--rows",this.lineDigits.toString()):e.getAttribute("rows")&&this.style.setProperty("--rows",e.getAttribute("rows")),this.editorTheme=new Compartment;const o=[this.editorTheme.of([]),t,lineNumbers(),highlightSpecialChars(),drawSelection(),EditorState.allowMultipleSelections.of(!0),syntaxHighlighting(defaultHighlightStyle,{fallback:!0})];if(this.readonly&&o.push(EditorState.readOnly.of(!0)),this.placeholder&&o.push(placeholder(this.placeholder)),this.mode){const e=await executeJavaScriptModuleInstruction(this.mode);o.push(...e)}this.addons.length>0&&o.push(...await Promise.all(this.addons.map((e=>executeJavaScriptModuleInstruction(e)))));const r=[...defaultKeymap,indentWithTab];if(this.keymaps.length>0){const e=await Promise.all(this.keymaps.map((e=>loadModule(e).then((t=>resolveSubjectRef(t,e))))));e.forEach((e=>r.push(...e)))}o.push(keymap.of(r)),this.editorView=new EditorView({state:EditorState.create({doc:e.value,extensions:o}),parent:this.renderRoot.querySelector("#codemirror-parent"),root:this.renderRoot});const i=window.matchMedia("(prefers-color-scheme: dark)");this.toggleDarkMode(i.matches),i.addEventListener("change",(e=>{this.toggleDarkMode(e.matches)}))}toggleDarkMode(e){this.editorView.dispatch({effects:this.editorTheme.reconfigure(e?oneDark:[])})}};CodeMirrorElement.styles=css` + `}firstUpdated(){if(this.nolazyload)return void this.initializeEditor(this.firstElementChild);const e={root:document.body},t=new IntersectionObserver((e=>{e.forEach((e=>{e.intersectionRatio>0&&(t.unobserve(e.target),this.firstElementChild&&"textarea"===this.firstElementChild.nodeName.toLowerCase()&&this.initializeEditor(this.firstElementChild))}))}),e);t.observe(this)}setContent(e){null!==this.editorView&&this.editorView.dispatch({changes:{from:0,to:this.editorView.state.doc.length,insert:e}})}getContent(){return this.editorView.state.doc.toString()}onKeydown(e){e.ctrlKey&&e.altKey&&"f"===e.key&&(e.preventDefault(),this.fullscreen=!0),"Escape"===e.key&&this.fullscreen&&(e.preventDefault(),this.fullscreen=!1)}async initializeEditor(e){const t=EditorView.updateListener.of((t=>{t.docChanged&&(e.value=t.state.doc.toString(),e.dispatchEvent(new CustomEvent("change",{bubbles:!0})))}));this.lineDigits>0?this.style.setProperty("--rows",this.lineDigits.toString()):e.getAttribute("rows")&&this.style.setProperty("--rows",e.getAttribute("rows")),this.editorTheme=new Compartment;const o=[this.editorTheme.of([]),t,lineNumbers(),highlightSpecialChars(),drawSelection(),EditorState.allowMultipleSelections.of(!0),syntaxHighlighting(defaultHighlightStyle,{fallback:!0})];if(this.readonly&&o.push(EditorState.readOnly.of(!0)),this.placeholder&&o.push(placeholder(this.placeholder)),this.mode){const e=await executeJavaScriptModuleInstruction(this.mode);o.push(...e)}this.addons.length>0&&o.push(...await Promise.all(this.addons.map((e=>executeJavaScriptModuleInstruction(e)))));const r=[...defaultKeymap,indentWithTab];if(this.keymaps.length>0){const e=await Promise.all(this.keymaps.map((e=>loadModule(e).then((t=>resolveSubjectRef(t,e))))));e.forEach((e=>r.push(...e)))}o.push(keymap.of(r)),this.editorView=new EditorView({state:EditorState.create({doc:e.value,extensions:o}),parent:this.renderRoot.querySelector("#codemirror-parent"),root:this.renderRoot});const i=window.matchMedia("(prefers-color-scheme: dark)");this.toggleDarkMode(i.matches),i.addEventListener("change",(e=>{this.toggleDarkMode(e.matches)}))}toggleDarkMode(e){this.editorView.dispatch({effects:this.editorTheme.reconfigure(e?oneDark:[])})}};CodeMirrorElement.styles=css` @media (prefers-color-scheme: dark) { :host { color-scheme: dark; diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/code-editor/language/typoscript.js b/typo3/sysext/backend/Resources/Public/JavaScript/code-editor/language/typoscript.js new file mode 100644 index 000000000000..4297206199fa --- /dev/null +++ b/typo3/sysext/backend/Resources/Public/JavaScript/code-editor/language/typoscript.js @@ -0,0 +1,13 @@ +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ +import DocumentService from"@typo3/core/document-service.js";import{StreamLanguage,LanguageSupport}from"@codemirror/language";import{TypoScriptStreamParserFactory}from"@typo3/backend/code-editor/stream-parser/typoscript.js";import{TsCodeCompletion}from"@typo3/backend/code-editor/autocomplete/ts-code-completion.js";import{syntaxTree}from"@codemirror/language";export function typoscript(){const e=StreamLanguage.define((new TypoScriptStreamParserFactory).create()),t=e.data.of({autocomplete:complete});return new LanguageSupport(e,[t])}const tsCodeCompletionInitializer=(async()=>{await DocumentService.ready();const e=parseInt(document.querySelector('input[name="effectivePid"]')?.value,10);return new TsCodeCompletion(e)})();export async function complete(e){if(!e.explicit)return null;const t=parseCodeMirror5CompatibleCompletionState(e),o=e.pos-(t.completingAfterDot?1:0),r=syntaxTree(e.state).resolveInner(o,-1),n="Document"===r.name||t.completingAfterDot?"":e.state.sliceDoc(r.from,o),s="Document"===r.name||t.completingAfterDot?e.pos:r.from;let a={start:r.from,end:o,string:n,type:r.name};/^[\w$_]*$/.test(n)||(a={start:e.pos,end:e.pos,string:"",type:"."===n?"property":null}),t.token=a;const i=(await tsCodeCompletionInitializer).refreshCodeCompletion(t);if(("string"===r.name||"comment"===r.name)&&tokenIsSubStringOfKeywords(n,i))return null;return{from:s,options:getCompletions(n,i).map((e=>({label:e,type:"keyword"})))}}function parseCodeMirror5CompatibleCompletionState(e){const t=e.state.sliceDoc().split(e.state.lineBreak).length,o=e.state.sliceDoc(0,e.pos).split(e.state.lineBreak).length,r=e.state.sliceDoc().split(e.state.lineBreak)[o-1],n="."===e.state.sliceDoc(e.pos-1,e.pos);return{lineTokens:extractCodemirror5StyleLineTokens(t,e),currentLineNumber:o,currentLine:r,lineCount:t,completingAfterDot:n}}function extractCodemirror5StyleLineTokens(e,t){const o=Array(e).fill("").map((()=>[]));let r=0,n=1;return syntaxTree(t.state).cursor().iterate((s=>{const a=s.type.name||s.name;if("Document"===a)return;const i=s.from,c=s.to;r<i&&t.state.sliceDoc(r,i).split(t.state.lineBreak).forEach((t=>{t&&(o[Math.min(n-1,e-1)].push({type:null,string:t,start:r,end:r+t.length}),n++,r+=t.length)}));const l=t.state.sliceDoc(s.from,s.to);n=t.state.sliceDoc(0,s.from).split(t.state.lineBreak).length,o[n-1].push({type:a,string:l,start:i,end:c}),r=c})),r<t.state.doc.length&&o[n-1].push({type:null,string:t.state.sliceDoc(r),start:r,end:t.state.doc.length}),o}function tokenIsSubStringOfKeywords(e,t){const o=e.length;for(let r=0;r<t.length;++r)if(e===t[r].substr(o))return!0;return!1}function getCompletions(e,t){const o=new Set;for(let n=0,s=t.length;n<s;++n)0!==(r=t[n]).lastIndexOf(e,0)||o.has(r)||o.add(r);var r;const n=Array.from(o);return n.sort(),n} \ No newline at end of file diff --git a/typo3/sysext/t3editor/Resources/Public/JavaScript/stream-parser/typoscript.js b/typo3/sysext/backend/Resources/Public/JavaScript/code-editor/stream-parser/typoscript.js similarity index 100% rename from typo3/sysext/t3editor/Resources/Public/JavaScript/stream-parser/typoscript.js rename to typo3/sysext/backend/Resources/Public/JavaScript/code-editor/stream-parser/typoscript.js diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/pagetsconfig/pagetsconfig-includes.js b/typo3/sysext/backend/Resources/Public/JavaScript/pagetsconfig/pagetsconfig-includes.js index 47e8262775a3..9cf60d62e199 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/pagetsconfig/pagetsconfig-includes.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/pagetsconfig/pagetsconfig-includes.js @@ -10,8 +10,8 @@ * * The TYPO3 project - inspiring people to share! */ -import DocumentService from"@typo3/core/document-service.js";import{default as Modal}from"@typo3/backend/modal.js";import{topLevelModuleImport}from"@typo3/backend/utility/top-level-module-import.js";import{html}from"lit";import{until}from"lit/directives/until.js";import AjaxRequest from"@typo3/core/ajax/ajax-request.js";class PageTsConfigIncludes{constructor(){this.registerEventListeners()}async registerEventListeners(){await DocumentService.ready(),document.querySelectorAll(".t3js-pagetsconfig-includes-modal").forEach((e=>{e.addEventListener("click",(t=>{t.preventDefault();const o=Modal.types.default,r=e.dataset.modalTitle||e.textContent.trim(),a=e.getAttribute("href"),l=Modal.sizes.large,i=html`${until(this.fetchModalContent(a),html`<div class="modal-loading"><typo3-backend-spinner size="default"></typo3-backend-spinner></div>`)}`;Modal.advanced({type:o,title:r,size:l,content:i})}))}))}async fetchModalContent(e){topLevelModuleImport("@typo3/t3editor/element/code-mirror-element.js");const t=await new AjaxRequest(e).get(),o=await t.resolve();return html` - <typo3-t3editor-codemirror .mode="${{name:"@typo3/t3editor/language/typoscript.js",flags:2,exportName:"typoscript",items:[{type:"invoke",args:[]}]}}" nolazyload readonly class="flex-grow-1 mh-100"> +import DocumentService from"@typo3/core/document-service.js";import{default as Modal}from"@typo3/backend/modal.js";import{topLevelModuleImport}from"@typo3/backend/utility/top-level-module-import.js";import{html}from"lit";import{until}from"lit/directives/until.js";import AjaxRequest from"@typo3/core/ajax/ajax-request.js";class PageTsConfigIncludes{constructor(){this.registerEventListeners()}async registerEventListeners(){await DocumentService.ready(),document.querySelectorAll(".t3js-pagetsconfig-includes-modal").forEach((e=>{e.addEventListener("click",(t=>{t.preventDefault();const o=Modal.types.default,r=e.dataset.modalTitle||e.textContent.trim(),a=e.getAttribute("href"),l=Modal.sizes.large,i=html`${until(this.fetchModalContent(a),html`<div class="modal-loading"><typo3-backend-spinner size="default"></typo3-backend-spinner></div>`)}`;Modal.advanced({type:o,title:r,size:l,content:i})}))}))}async fetchModalContent(e){topLevelModuleImport("@typo3/backend/code-editor/element/code-mirror-element.js");const t=await new AjaxRequest(e).get(),o=await t.resolve();return html` + <typo3-t3editor-codemirror .mode="${{name:"@typo3/backend/code-editor/language/typoscript.js",flags:2,exportName:"typoscript",items:[{type:"invoke",args:[]}]}}" nolazyload readonly class="flex-grow-1 mh-100"> <textarea readonly disabled class="form-control">${o}</textarea> </typo3-t3editor-codemirror> `}}export default new PageTsConfigIncludes; \ No newline at end of file diff --git a/typo3/sysext/t3editor/Tests/Unit/Registry/AddonRegistryTest.php b/typo3/sysext/backend/Tests/Unit/CodeEditor/Registry/AddonRegistryTest.php similarity index 94% rename from typo3/sysext/t3editor/Tests/Unit/Registry/AddonRegistryTest.php rename to typo3/sysext/backend/Tests/Unit/CodeEditor/Registry/AddonRegistryTest.php index 6a7417324a0d..fe3cd3b3bc23 100644 --- a/typo3/sysext/t3editor/Tests/Unit/Registry/AddonRegistryTest.php +++ b/typo3/sysext/backend/Tests/Unit/CodeEditor/Registry/AddonRegistryTest.php @@ -15,11 +15,11 @@ declare(strict_types=1); * The TYPO3 project - inspiring people to share! */ -namespace TYPO3\CMS\T3editor\Tests\Unit\Registry; +namespace TYPO3\CMS\Backend\Tests\Unit\CodeEditor\Registry; +use TYPO3\CMS\Backend\CodeEditor\Addon; +use TYPO3\CMS\Backend\CodeEditor\Registry\AddonRegistry; use TYPO3\CMS\Core\Utility\GeneralUtility; -use TYPO3\CMS\T3editor\Addon; -use TYPO3\CMS\T3editor\Registry\AddonRegistry; use TYPO3\TestingFramework\Core\Unit\UnitTestCase; /** diff --git a/typo3/sysext/t3editor/Tests/Unit/Registry/ModeRegistryTest.php b/typo3/sysext/backend/Tests/Unit/CodeEditor/Registry/ModeRegistryTest.php similarity index 93% rename from typo3/sysext/t3editor/Tests/Unit/Registry/ModeRegistryTest.php rename to typo3/sysext/backend/Tests/Unit/CodeEditor/Registry/ModeRegistryTest.php index 930b1f5df323..33f329cd13b8 100644 --- a/typo3/sysext/t3editor/Tests/Unit/Registry/ModeRegistryTest.php +++ b/typo3/sysext/backend/Tests/Unit/CodeEditor/Registry/ModeRegistryTest.php @@ -15,12 +15,12 @@ declare(strict_types=1); * The TYPO3 project - inspiring people to share! */ -namespace TYPO3\CMS\T3editor\Tests\Unit\Registry; +namespace TYPO3\CMS\Backend\Tests\Unit\CodeEditor\Registry; +use TYPO3\CMS\Backend\CodeEditor\Mode; +use TYPO3\CMS\Backend\CodeEditor\Registry\ModeRegistry; use TYPO3\CMS\Core\Page\JavaScriptModuleInstruction; use TYPO3\CMS\Core\Utility\GeneralUtility; -use TYPO3\CMS\T3editor\Mode; -use TYPO3\CMS\T3editor\Registry\ModeRegistry; use TYPO3\TestingFramework\Core\Unit\UnitTestCase; /** diff --git a/typo3/sysext/backend/Tests/Unit/Form/Element/JsonElementTest.php b/typo3/sysext/backend/Tests/Unit/Form/Element/JsonElementTest.php index 30c522dfd0f2..3124606db1d7 100644 --- a/typo3/sysext/backend/Tests/Unit/Form/Element/JsonElementTest.php +++ b/typo3/sysext/backend/Tests/Unit/Form/Element/JsonElementTest.php @@ -17,6 +17,8 @@ declare(strict_types=1); namespace TYPO3\CMS\Backend\Tests\Unit\Form\Element; +use TYPO3\CMS\Backend\CodeEditor\Mode; +use TYPO3\CMS\Backend\CodeEditor\Registry\ModeRegistry; use TYPO3\CMS\Backend\Form\Element\JsonElement; use TYPO3\CMS\Backend\Form\NodeExpansion\FieldInformation; use TYPO3\CMS\Backend\Form\NodeFactory; @@ -26,8 +28,6 @@ use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface; use TYPO3\CMS\Core\Package\PackageManager; use TYPO3\CMS\Core\Page\JavaScriptModuleInstruction; use TYPO3\CMS\Core\Utility\GeneralUtility; -use TYPO3\CMS\T3editor\Mode; -use TYPO3\CMS\T3editor\Registry\ModeRegistry; use TYPO3\TestingFramework\Core\Unit\UnitTestCase; final class JsonElementTest extends UnitTestCase @@ -119,7 +119,7 @@ final class JsonElementTest extends UnitTestCase $subject->setData($data); $result = $subject->render(); - self::assertEquals('@typo3/t3editor/element/code-mirror-element.js', $result['javaScriptModules'][0]->getName()); + self::assertEquals('@typo3/backend/code-editor/element/code-mirror-element.js', $result['javaScriptModules'][0]->getName()); self::assertStringContainsString('<typo3-t3editor-codemirror', $result['html']); self::assertStringContainsString('placeholder="placeholder"', $result['html']); self::assertStringContainsString('"foo": "bar"', $result['html']); diff --git a/typo3/sysext/backend/composer.json b/typo3/sysext/backend/composer.json index 5f827e229a9b..930c3a2400d3 100644 --- a/typo3/sysext/backend/composer.json +++ b/typo3/sysext/backend/composer.json @@ -19,6 +19,7 @@ "sort-packages": true }, "require": { + "ext-libxml": "*", "psr/event-dispatcher": "^1.0", "typo3/cms-core": "13.0.*@dev" }, @@ -34,6 +35,7 @@ "typo3/cms-cshmanual": "*", "typo3/cms-func-wizards": "*", "typo3/cms-recordlist": "*", + "typo3/cms-t3editor": "*", "typo3/cms-wizard-crpages": "*", "typo3/cms-wizard-sortpages": "*" }, diff --git a/typo3/sysext/core/Classes/Configuration/Tca/TcaMigration.php b/typo3/sysext/core/Classes/Configuration/Tca/TcaMigration.php index 0d1f0cfd081a..ac6c864b2919 100644 --- a/typo3/sysext/core/Classes/Configuration/Tca/TcaMigration.php +++ b/typo3/sysext/core/Classes/Configuration/Tca/TcaMigration.php @@ -83,6 +83,7 @@ class TcaMigration $tca = $this->migrateItemsToAssociativeArray($tca); $tca = $this->removeMmInsertFields($tca); $tca = $this->removeMmHasUidField($tca); + $tca = $this->migrateT3EditorToCodeEditor($tca); return $tca; } @@ -1479,4 +1480,33 @@ class TcaMigration } return $tca; } + + protected function migrateT3EditorToCodeEditor(array $tca): array + { + foreach ($tca as $table => $tableDefinition) { + if (!is_array($tableDefinition['columns'] ?? false)) { + continue; + } + foreach ($tableDefinition['columns'] as $fieldName => $fieldConfig) { + if (($fieldConfig['config']['renderType'] ?? '') === 't3editor') { + $tca[$table]['columns'][$fieldName]['config']['renderType'] = 'codeEditor'; + $this->messages[] = 'The TCA field \'' . $fieldName . '\' of table \'' . $table . '\' uses ' + . '\'renderType\' with the value \'t3editor\', which has been migrated to \'codeEditor\'. ' + . 'Please adjust your TCA accordingly.'; + } + } + + foreach ($tableDefinition['types'] ?? [] as $typeName => $typeConfig) { + foreach ($typeConfig['columnsOverrides'] ?? [] as $columnOverride => $columnOverrideConfig) { + if (($columnOverrideConfig['config']['renderType'] ?? '') === 't3editor') { + $tca[$table]['types'][$typeName]['columnsOverrides'][$columnOverride]['config']['renderType'] = 'codeEditor'; + $this->messages[] = 'The TCA column override \'' . $columnOverride . '\' of table \'' . $table . '\' uses ' + . '\'renderType\' with the value \'t3editor\', which has been migrated to \'codeEditor\'. ' + . 'Please adjust your TCA accordingly.'; + } + } + } + } + return $tca; + } } diff --git a/typo3/sysext/core/Documentation/Changelog/13.0/Breaking-102440-EXTt3editorMergedIntoEXTbackend.rst b/typo3/sysext/core/Documentation/Changelog/13.0/Breaking-102440-EXTt3editorMergedIntoEXTbackend.rst new file mode 100644 index 000000000000..5c2324b2e4d0 --- /dev/null +++ b/typo3/sysext/core/Documentation/Changelog/13.0/Breaking-102440-EXTt3editorMergedIntoEXTbackend.rst @@ -0,0 +1,59 @@ +.. include:: /Includes.rst.txt + +.. _breaking-102440-1700638677: + +======================================================== +Breaking: #102440 - EXT:t3editor merged into EXT:backend +======================================================== + +See :issue:`102440` + +Description +=========== + +TYPO3 comes with a code editor extension called "t3editor" for a long time. +Since then, the extension was always optional. When the extension is installed, +selected text areas are converted to code editors based on CodeMirror. + +The optional extension has been merged into `EXT:backend`, making the code +editor always available. + + +Impact +====== + +An integrator cannot optionally install the code editor anymore as it's part of +the mandatory "backend" extension now. + +By default, this affects the following occurrences: + +* TCA: `be_groups.TSconfig` +* TCA: `be_users.TSconfig` +* TCA: `pages.TSconfig` +* TCA: `sys_template.constants` +* TCA: `sys_template.config` +* TCA: `tt_content.bodytext`, if the content element is of type "HTML" +* EXT:filelist: edit file content +* Composer status view in Extension Manager + +Also, checks whether the extension is installed via +:php:`TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded('t3editor')` +are now obsolete. + + +Affected installations +====================== + +All installations are affected. + + +Migration +========= + +Extension checks using :php:`TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded('t3editor')` +don't have an effect anymore and must get removed. + +In addition, please see <Deprecation-102440-EXTt3editorMergedIntoEXTBackend>. + + +.. index:: Backend, JavaScript, PHP-API, NotScanned, ext:t3editor diff --git a/typo3/sysext/core/Documentation/Changelog/13.0/Deprecation-102440-EXTt3editorMergedIntoEXTBackend.rst b/typo3/sysext/core/Documentation/Changelog/13.0/Deprecation-102440-EXTt3editorMergedIntoEXTBackend.rst new file mode 100644 index 000000000000..a75c51b8fdcc --- /dev/null +++ b/typo3/sysext/core/Documentation/Changelog/13.0/Deprecation-102440-EXTt3editorMergedIntoEXTBackend.rst @@ -0,0 +1,45 @@ +.. include:: /Includes.rst.txt + +.. _deprecation-102440-1700638677: + +=========================================================== +Deprecation: #102440 - EXT:t3editor merged into EXT:backend +=========================================================== + +See :issue:`102440` + +Description +=========== + +The JavaScript module specifier for modules shipped with the previous "t3editor" +extension has changed from :js:`@typo3/t3editor/` to +:js:`@typo3/backend/code-editor/`. The old specifier :js:`@typo3/t3editor/` is +still available, but deprecated. + +The value of the existing TCA option `renderType` switched from `t3editor` to +`codeEditor`. + + +Impact +====== + +The module specifier :js:`@typo3/t3editor/` automatically maps to +:js:`@typo3/backend/code-editor/`. The TCA render type `t3editor` is +automatically migrated to `codeEditor`, triggering a deprecation log entry. + + +Affected installations +====================== + +All extensions using t3editor are affected. + + +Migration +========= + +The JavaScript module namespace :js:`@typo3/t3editor/` maps to +:js:`@typo3/backend/code-editor/`. + +Rewrite all TCA render types usages of `t3editor` to `codeEditor`. + +.. index:: Backend, JavaScript, TCA, NotScanned, ext:t3editor diff --git a/typo3/sysext/core/Documentation/Settings.cfg b/typo3/sysext/core/Documentation/Settings.cfg index eeed4b941b7c..a45e7df05221 100644 --- a/typo3/sysext/core/Documentation/Settings.cfg +++ b/typo3/sysext/core/Documentation/Settings.cfg @@ -62,5 +62,4 @@ ext_reactions = https://docs.typo3.org/c/typo3/cms-reactions/main/en-us/ # ext_rte_ckeditor = https://docs.typo3.org/c/typo3/cms-rte-ckeditor/main/en-us/ # ext_scheduler = https://docs.typo3.org/c/typo3/cms-scheduler/main/en-us/ # ext_seo = https://docs.typo3.org/c/typo3/cms-seo/main/en-us/ -# ext_t3editor = https://docs.typo3.org/c/typo3/cms-t3editor/main/en-us/ # ext_workspaces = https://docs.typo3.org/c/typo3/cms-workspaces/main/en-us/ diff --git a/typo3/sysext/core/Tests/Acceptance/Application/FileList/FileOperationsCest.php b/typo3/sysext/core/Tests/Acceptance/Application/FileList/FileOperationsCest.php index ebf4bf0b7bc7..5450c8119b8e 100644 --- a/typo3/sysext/core/Tests/Acceptance/Application/FileList/FileOperationsCest.php +++ b/typo3/sysext/core/Tests/Acceptance/Application/FileList/FileOperationsCest.php @@ -35,7 +35,7 @@ final class FileOperationsCest public function fileCrud(ApplicationTester $I, ModalDialog $modalDialog): void { - $fileTextareaSelector = 'textarea[name="data[editfile][0][data]"]'; + $codeMirrorSelector = 'typo3-t3editor-codemirror[name="data[editfile][0][data]"]'; $fileName = 'typo3-test.txt'; $flashMessageSelector = '.typo3-messages'; @@ -48,13 +48,14 @@ final class FileOperationsCest $I->wait(0.2); $I->click('Create file'); $I->see('File created:', $flashMessageSelector); - $I->fillField($fileTextareaSelector, 'Some Text'); + $I->waitForElementVisible($codeMirrorSelector); + $I->executeJS("document.querySelector('" . $codeMirrorSelector . "').setContent('Some Text')"); // Save file $I->amGoingTo('save the file'); $I->click('.module-docheader button[name="_save"]'); - $textareaValue = $I->grabValueFrom($fileTextareaSelector); - $I->assertEquals('Some Text', $textareaValue); + $I->waitForElementVisible($codeMirrorSelector); + $I->executeJS("console.assert(document.querySelector('" . $codeMirrorSelector . "').getContent() === 'Some Text')"); $I->see('File saved to', $flashMessageSelector); // Save file diff --git a/typo3/sysext/core/Tests/Acceptance/Application/Impexp/UsersCest.php b/typo3/sysext/core/Tests/Acceptance/Application/Impexp/UsersCest.php index 85d72131b8f6..5ff4f7140faf 100644 --- a/typo3/sysext/core/Tests/Acceptance/Application/Impexp/UsersCest.php +++ b/typo3/sysext/core/Tests/Acceptance/Application/Impexp/UsersCest.php @@ -67,7 +67,7 @@ final class UsersCest extends AbstractCest $selectedPageTitle = 'Root'; $selectedPageIcon = '//*[text()=\'' . $selectedPageTitle . '\']/../*[contains(@class, \'node-icon-container\')]'; - $this->setUserTsConfig($I, 2, "options.impexp.enableImportForNonAdminUser = 1\noptions.impexp.enableExportForNonAdminUser = 1"); + $this->setUserTsConfig($I, 2, 'options.impexp.enableImportForNonAdminUser = 1\noptions.impexp.enableExportForNonAdminUser = 1'); $I->useExistingSession('editor'); $I->click($selectedPageIcon); @@ -79,6 +79,9 @@ final class UsersCest extends AbstractCest $I->useExistingSession('admin'); } + /** + * @depends showImportExportInContextMenuForNonAdminUserIfFlagSet + */ public function hideImportCheckboxForceAllUidsForNonAdmin(ApplicationTester $I): void { $selectedPageTitle = 'Root'; @@ -101,6 +104,9 @@ final class UsersCest extends AbstractCest $I->useExistingSession('admin'); } + /** + * @depends showImportExportInContextMenuForNonAdminUserIfFlagSet + */ public function hideUploadTabAndImportPathIfNoImportFolderAvailable(ApplicationTester $I, PageTree $pageTree): void { $selectedPageTitle = 'Root'; @@ -221,13 +227,16 @@ final class UsersCest extends AbstractCest $I->switchToContentFrame(); } + $codeMirrorSelector = 'typo3-t3editor-codemirror[name="data[be_users][' . $userId . '][TSconfig]"]'; + $I->waitForElementVisible($this->inModuleHeader . ' [name=BackendUserModuleMenu]'); $I->selectOption($this->inModuleHeader . ' [name=BackendUserModuleMenu]', ['text' => 'Backend users']); $I->waitForElement('#typo3-backend-user-list'); $I->click('//table[@id="typo3-backend-user-list"]/tbody/tr[descendant::a[@data-contextmenu-uid="' . $userId . '"]]//a[@title="Edit"]'); $I->waitForElement('#EditDocumentController'); $I->click('//form[@id="EditDocumentController"]//ul/li[5]/a'); - $I->fillField('//div[@class="tab-content"]/div[5]/fieldset[1]//textarea', $userTsConfig); + $I->waitForElementVisible($codeMirrorSelector); + $I->executeJS("document.querySelector('" . $codeMirrorSelector . "').setContent('" . $userTsConfig . "')"); $I->click($this->inModuleHeader . ' .btn[title="Save"]'); $I->wait(0.5); $I->click($this->inModuleHeader . ' .btn[title="Close"]'); diff --git a/typo3/sysext/core/Tests/Acceptance/Application/Template/TemplateCest.php b/typo3/sysext/core/Tests/Acceptance/Application/Template/TemplateCest.php index f728aa904311..cbb5c23cecad 100644 --- a/typo3/sysext/core/Tests/Acceptance/Application/Template/TemplateCest.php +++ b/typo3/sysext/core/Tests/Acceptance/Application/Template/TemplateCest.php @@ -93,11 +93,11 @@ final class TemplateCest $I->waitForElement('#EditDocumentController'); $I->waitForElementNotVisible('#t3js-ui-block'); + $codeMirrorSelector = 'typo3-t3editor-codemirror[name$="[config]"]'; + $I->wantTo('change the setup, save the TypoScript record and close the form'); - // grab and fill setup textarea - $config = $I->grabTextFrom('//textarea[contains(@data-formengine-input-name, "data[sys_template]") and contains(@data-formengine-input-name, "[config]")]'); - $config = str_replace('HELLO WORLD!', 'Hello Acceptance Test!', $config); - $I->fillField('//textarea[contains(@data-formengine-input-name, "data[sys_template]") and contains(@data-formengine-input-name, "[config]")]', $config); + $I->waitForElementVisible($codeMirrorSelector); + $I->executeJS("const codeMirror = document.querySelector('" . $codeMirrorSelector . "'); const config = codeMirror.getContent().replace('HELLO WORLD!', 'Hello Acceptance Test!'); codeMirror.setContent(config)"); $I->switchToMainFrame(); $I->waitForElementNotVisible('typo3-notification-message', 20); $I->switchToContentFrame(); diff --git a/typo3/sysext/core/Tests/Functional/Package/PackageStatesTest.php b/typo3/sysext/core/Tests/Functional/Package/PackageStatesTest.php index 69c30120f1df..4af328ae5fa6 100644 --- a/typo3/sysext/core/Tests/Functional/Package/PackageStatesTest.php +++ b/typo3/sysext/core/Tests/Functional/Package/PackageStatesTest.php @@ -59,7 +59,6 @@ final class PackageStatesTest extends FunctionalTestCase 'seo', 'setup', 'sys_note', - 't3editor', 'tstemplate', 'viewpage', 'webhooks', @@ -133,7 +132,6 @@ final class PackageStatesTest extends FunctionalTestCase 'reactions', 'seo', 'sys_note', - 't3editor', 'tstemplate', 'viewpage', 'webhooks', diff --git a/typo3/sysext/core/Tests/Unit/Configuration/Tca/TcaMigrationTest.php b/typo3/sysext/core/Tests/Unit/Configuration/Tca/TcaMigrationTest.php index 2cf72279037f..56c0137fa0bf 100644 --- a/typo3/sysext/core/Tests/Unit/Configuration/Tca/TcaMigrationTest.php +++ b/typo3/sysext/core/Tests/Unit/Configuration/Tca/TcaMigrationTest.php @@ -3733,4 +3733,68 @@ final class TcaMigrationTest extends UnitTestCase ]; self::assertSame($expected, (new TcaMigration())->migrate($input)); } + + /** + * @test + */ + public function migrationChangesRenderTypeFromT3Editor(): void + { + $input = [ + 'aTable' => [ + 'columns' => [ + 'aColumn' => [ + 'config' => [ + 'type' => 'text', + 'renderType' => 't3editor', + ], + ], + 'bColumn' => [ + 'config' => [ + 'type' => 'text', + ], + ], + ], + 'types' => [ + 'aType' => [ + 'columnsOverrides' => [ + 'bColumn' => [ + 'config' => [ + 'renderType' => 't3editor', + ], + ], + ], + ], + ], + ], + ]; + $expected = [ + 'aTable' => [ + 'columns' => [ + 'aColumn' => [ + 'config' => [ + 'type' => 'text', + 'renderType' => 'codeEditor', + ], + ], + 'bColumn' => [ + 'config' => [ + 'type' => 'text', + ], + ], + ], + 'types' => [ + 'aType' => [ + 'columnsOverrides' => [ + 'bColumn' => [ + 'config' => [ + 'renderType' => 'codeEditor', + ], + ], + ], + ], + ], + ], + ]; + self::assertSame($expected, (new TcaMigration())->migrate($input)); + } } diff --git a/typo3/sysext/dashboard/Documentation/Settings.cfg b/typo3/sysext/dashboard/Documentation/Settings.cfg index 3b4a80744c17..28a3b28ba8c6 100644 --- a/typo3/sysext/dashboard/Documentation/Settings.cfg +++ b/typo3/sysext/dashboard/Documentation/Settings.cfg @@ -62,5 +62,4 @@ ext_core = https://docs.typo3.org/c/typo3/cms-core/main/en-us/ # ext_rte_ckeditor = https://docs.typo3.org/c/typo3/cms-rte-ckeditor/main/en-us/ # ext_scheduler = https://docs.typo3.org/c/typo3/cms-scheduler/main/en-us/ # ext_seo = https://docs.typo3.org/c/typo3/cms-seo/main/en-us/ -# ext_t3editor = https://docs.typo3.org/c/typo3/cms-t3editor/main/en-us/ # ext_workspaces = https://docs.typo3.org/c/typo3/cms-workspaces/main/en-us/ diff --git a/typo3/sysext/extensionmanager/Classes/Controller/ExtensionComposerStatusController.php b/typo3/sysext/extensionmanager/Classes/Controller/ExtensionComposerStatusController.php index d5570d9b7a35..30e15115c390 100644 --- a/typo3/sysext/extensionmanager/Classes/Controller/ExtensionComposerStatusController.php +++ b/typo3/sysext/extensionmanager/Classes/Controller/ExtensionComposerStatusController.php @@ -23,9 +23,7 @@ use TYPO3\CMS\Core\Imaging\IconFactory; use TYPO3\CMS\Core\Imaging\IconSize; use TYPO3\CMS\Core\Page\JavaScriptModuleInstruction; use TYPO3\CMS\Core\Page\PageRenderer; -use TYPO3\CMS\Core\Utility\ExtensionManagementUtility; use TYPO3\CMS\Core\Utility\GeneralUtility; -use TYPO3\CMS\Core\Utility\MathUtility; use TYPO3\CMS\Extensionmanager\Package\ComposerDeficitDetector; use TYPO3\CMS\Extensionmanager\Service\ComposerManifestProposalGenerator; @@ -100,27 +98,21 @@ class ExtensionComposerStatusController extends AbstractController if ($composerManifest === '') { return ''; } - $rows = MathUtility::forceIntegerInRange(count(explode(LF, $composerManifest)), 1, PHP_INT_MAX); - if (ExtensionManagementUtility::isLoaded('t3editor')) { - $this->pageRenderer->loadJavaScriptModule('@typo3/t3editor/element/code-mirror-element.js'); - $codeMirrorConfig = [ - 'label' => $extensionKey . ' > composer.json', - 'panel' => 'bottom', - 'mode' => GeneralUtility::jsonEncodeForHtmlAttribute(JavaScriptModuleInstruction::create('@codemirror/lang-json', 'json')->invoke(), false), - 'nolazyload' => 'true', - 'autoheight' => 'true', - ]; - $textareaAttributes = [ - 'rows' => (string)count(explode(LF, $composerManifest)), - 'class' => 'form-control', - ]; - return '<typo3-t3editor-codemirror ' . GeneralUtility::implodeAttributes($codeMirrorConfig, true) . '>' - . '<textarea ' . GeneralUtility::implodeAttributes($textareaAttributes, true) . '>' . htmlspecialchars($composerManifest) . '</textarea>' - . '</typo3-t3editor-codemirror>'; - } - return '<textarea ' . GeneralUtility::implodeAttributes(['class' => 'form-control', 'rows' => (string)++$rows], true) . '>' - . htmlspecialchars($composerManifest) - . '</textarea>'; + $this->pageRenderer->loadJavaScriptModule('@typo3/backend/code-editor/element/code-mirror-element.js'); + $codeMirrorConfig = [ + 'label' => $extensionKey . ' > composer.json', + 'panel' => 'bottom', + 'mode' => GeneralUtility::jsonEncodeForHtmlAttribute(JavaScriptModuleInstruction::create('@codemirror/lang-json', 'json')->invoke(), false), + 'nolazyload' => 'true', + 'autoheight' => 'true', + ]; + $textareaAttributes = [ + 'rows' => (string)count(explode(LF, $composerManifest)), + 'class' => 'form-control', + ]; + return '<typo3-t3editor-codemirror ' . GeneralUtility::implodeAttributes($codeMirrorConfig, true) . '>' + . '<textarea ' . GeneralUtility::implodeAttributes($textareaAttributes, true) . '>' . htmlspecialchars($composerManifest) . '</textarea>' + . '</typo3-t3editor-codemirror>'; } protected function registerDocHeaderButtons(ModuleTemplate $view): void diff --git a/typo3/sysext/felogin/Documentation/Settings.cfg b/typo3/sysext/felogin/Documentation/Settings.cfg index 71498ef20009..1c1bb4006855 100644 --- a/typo3/sysext/felogin/Documentation/Settings.cfg +++ b/typo3/sysext/felogin/Documentation/Settings.cfg @@ -62,5 +62,4 @@ t3coreapi = https://docs.typo3.org/m/typo3/reference-coreapi/main/en-us/ # ext_rte_ckeditor = https://docs.typo3.org/c/typo3/cms-rte-ckeditor/main/en-us/ # ext_scheduler = https://docs.typo3.org/c/typo3/cms-scheduler/main/en-us/ # ext_seo = https://docs.typo3.org/c/typo3/cms-seo/main/en-us/ -# ext_t3editor = https://docs.typo3.org/c/typo3/cms-t3editor/main/en-us/ # ext_workspaces = https://docs.typo3.org/c/typo3/cms-workspaces/main/en-us/ diff --git a/typo3/sysext/fluid_styled_content/Documentation/Settings.cfg b/typo3/sysext/fluid_styled_content/Documentation/Settings.cfg index 4d7c2c832caf..23a0b124eeba 100644 --- a/typo3/sysext/fluid_styled_content/Documentation/Settings.cfg +++ b/typo3/sysext/fluid_styled_content/Documentation/Settings.cfg @@ -62,5 +62,4 @@ t3upgrade = https://docs.typo3.org/m/typo3/guide-installation/main/en-us/ # ext_rte_ckeditor = https://docs.typo3.org/c/typo3/cms-rte-ckeditor/main/en-us/ # ext_scheduler = https://docs.typo3.org/c/typo3/cms-scheduler/main/en-us/ # ext_seo = https://docs.typo3.org/c/typo3/cms-seo/main/en-us/ -# ext_t3editor = https://docs.typo3.org/c/typo3/cms-t3editor/main/en-us/ # ext_workspaces = https://docs.typo3.org/c/typo3/cms-workspaces/main/en-us/ diff --git a/typo3/sysext/form/Documentation/Settings.cfg b/typo3/sysext/form/Documentation/Settings.cfg index a4e2e6d0430e..bbfe8b2b43b4 100644 --- a/typo3/sysext/form/Documentation/Settings.cfg +++ b/typo3/sysext/form/Documentation/Settings.cfg @@ -62,7 +62,6 @@ t3coreapi = https://docs.typo3.org/m/typo3/reference-coreapi/main/en-us/ # ext_rte_ckeditor = https://docs.typo3.org/c/typo3/cms-rte-ckeditor/main/en-us/ # ext_scheduler = https://docs.typo3.org/c/typo3/cms-scheduler/main/en-us/ # ext_seo = https://docs.typo3.org/c/typo3/cms-seo/main/en-us/ -# ext_t3editor = https://docs.typo3.org/c/typo3/cms-t3editor/main/en-us/ # ext_workspaces = https://docs.typo3.org/c/typo3/cms-workspaces/main/en-us/ [extlinks] diff --git a/typo3/sysext/impexp/Documentation/Settings.cfg b/typo3/sysext/impexp/Documentation/Settings.cfg index e2b855bb910a..91502ac1dbbe 100644 --- a/typo3/sysext/impexp/Documentation/Settings.cfg +++ b/typo3/sysext/impexp/Documentation/Settings.cfg @@ -62,5 +62,4 @@ t3tsconfig = https://docs.typo3.org/m/typo3/reference-tsconfig/main/en-us/ # ext_rte_ckeditor = https://docs.typo3.org/c/typo3/cms-rte-ckeditor/main/en-us/ # ext_scheduler = https://docs.typo3.org/c/typo3/cms-scheduler/main/en-us/ # ext_seo = https://docs.typo3.org/c/typo3/cms-seo/main/en-us/ -# ext_t3editor = https://docs.typo3.org/c/typo3/cms-t3editor/main/en-us/ # ext_workspaces = https://docs.typo3.org/c/typo3/cms-workspaces/main/en-us/ diff --git a/typo3/sysext/indexed_search/Documentation/Settings.cfg b/typo3/sysext/indexed_search/Documentation/Settings.cfg index 09c30b3cccab..1cf37f9f282a 100644 --- a/typo3/sysext/indexed_search/Documentation/Settings.cfg +++ b/typo3/sysext/indexed_search/Documentation/Settings.cfg @@ -62,5 +62,4 @@ t3tsref = https://docs.typo3.org/m/typo3/reference-typoscript/main/en-us/ # ext_rte_ckeditor = https://docs.typo3.org/c/typo3/cms-rte-ckeditor/main/en-us/ # ext_scheduler = https://docs.typo3.org/c/typo3/cms-scheduler/main/en-us/ # ext_seo = https://docs.typo3.org/c/typo3/cms-seo/main/en-us/ -# ext_t3editor = https://docs.typo3.org/c/typo3/cms-t3editor/main/en-us/ # ext_workspaces = https://docs.typo3.org/c/typo3/cms-workspaces/main/en-us/ diff --git a/typo3/sysext/linkvalidator/Documentation/Settings.cfg b/typo3/sysext/linkvalidator/Documentation/Settings.cfg index f65e2b9f7174..fb137e2a4011 100644 --- a/typo3/sysext/linkvalidator/Documentation/Settings.cfg +++ b/typo3/sysext/linkvalidator/Documentation/Settings.cfg @@ -62,5 +62,4 @@ t3tca = https://docs.typo3.org/m/typo3/reference-tca/main/en-us/ # ext_rte_ckeditor = https://docs.typo3.org/c/typo3/cms-rte-ckeditor/main/en-us/ # ext_scheduler = https://docs.typo3.org/c/typo3/cms-scheduler/main/en-us/ # ext_seo = https://docs.typo3.org/c/typo3/cms-seo/main/en-us/ -# ext_t3editor = https://docs.typo3.org/c/typo3/cms-t3editor/main/en-us/ # ext_workspaces = https://docs.typo3.org/c/typo3/cms-workspaces/main/en-us/ diff --git a/typo3/sysext/lowlevel/Documentation/Settings.cfg b/typo3/sysext/lowlevel/Documentation/Settings.cfg index c54790ed56e8..3b5ad2d69215 100644 --- a/typo3/sysext/lowlevel/Documentation/Settings.cfg +++ b/typo3/sysext/lowlevel/Documentation/Settings.cfg @@ -62,5 +62,4 @@ ext_reactions = https://docs.typo3.org/c/typo3/cms-reactions/main/en-us/ # ext_rte_ckeditor = https://docs.typo3.org/c/typo3/cms-rte-ckeditor/main/en-us/ # ext_scheduler = https://docs.typo3.org/c/typo3/cms-scheduler/main/en-us/ # ext_seo = https://docs.typo3.org/c/typo3/cms-seo/main/en-us/ -# ext_t3editor = https://docs.typo3.org/c/typo3/cms-t3editor/main/en-us/ # ext_workspaces = https://docs.typo3.org/c/typo3/cms-workspaces/main/en-us/ diff --git a/typo3/sysext/reactions/Documentation/Settings.cfg b/typo3/sysext/reactions/Documentation/Settings.cfg index 043f36b3f652..3e10d3e4b385 100644 --- a/typo3/sysext/reactions/Documentation/Settings.cfg +++ b/typo3/sysext/reactions/Documentation/Settings.cfg @@ -62,7 +62,6 @@ t3tca = https://docs.typo3.org/m/typo3/reference-tca/main/en-us/ # ext_rte_ckeditor = https://docs.typo3.org/c/typo3/cms-rte-ckeditor/main/en-us/ # ext_scheduler = https://docs.typo3.org/c/typo3/cms-scheduler/main/en-us/ # ext_seo = https://docs.typo3.org/c/typo3/cms-seo/main/en-us/ -# ext_t3editor = https://docs.typo3.org/c/typo3/cms-t3editor/main/en-us/ # ext_workspaces = https://docs.typo3.org/c/typo3/cms-workspaces/main/en-us/ [extlinks] diff --git a/typo3/sysext/recycler/Documentation/Settings.cfg b/typo3/sysext/recycler/Documentation/Settings.cfg index b269d124d4dc..f1b80247eafa 100644 --- a/typo3/sysext/recycler/Documentation/Settings.cfg +++ b/typo3/sysext/recycler/Documentation/Settings.cfg @@ -62,5 +62,4 @@ ext_lowlevel = https://docs.typo3.org/c/typo3/cms-lowlevel/main/en-us/ # ext_rte_ckeditor = https://docs.typo3.org/c/typo3/cms-rte-ckeditor/main/en-us/ ext_scheduler = https://docs.typo3.org/c/typo3/cms-scheduler/main/en-us/ # ext_seo = https://docs.typo3.org/c/typo3/cms-seo/main/en-us/ -# ext_t3editor = https://docs.typo3.org/c/typo3/cms-t3editor/main/en-us/ # ext_workspaces = https://docs.typo3.org/c/typo3/cms-workspaces/main/en-us/ diff --git a/typo3/sysext/redirects/Documentation/Settings.cfg b/typo3/sysext/redirects/Documentation/Settings.cfg index ff19acfe5e78..ebf2902dcea1 100644 --- a/typo3/sysext/redirects/Documentation/Settings.cfg +++ b/typo3/sysext/redirects/Documentation/Settings.cfg @@ -62,5 +62,4 @@ t3coreapi = https://docs.typo3.org/m/typo3/reference-coreapi/main/en-us/ # ext_rte_ckeditor = https://docs.typo3.org/c/typo3/cms-rte-ckeditor/main/en-us/ # ext_scheduler = https://docs.typo3.org/c/typo3/cms-scheduler/main/en-us/ # ext_seo = https://docs.typo3.org/c/typo3/cms-seo/main/en-us/ -# ext_t3editor = https://docs.typo3.org/c/typo3/cms-t3editor/main/en-us/ ext_workspaces = https://docs.typo3.org/c/typo3/cms-workspaces/main/en-us/ diff --git a/typo3/sysext/reports/Documentation/Settings.cfg b/typo3/sysext/reports/Documentation/Settings.cfg index e7707936069d..253dbcc7c648 100644 --- a/typo3/sysext/reports/Documentation/Settings.cfg +++ b/typo3/sysext/reports/Documentation/Settings.cfg @@ -62,5 +62,4 @@ t3start = https://docs.typo3.org/m/typo3/tutorial-getting-started/main/en # ext_rte_ckeditor = https://docs.typo3.org/c/typo3/cms-rte-ckeditor/main/en-us/ ext_scheduler = https://docs.typo3.org/c/typo3/cms-scheduler/main/en-us/ # ext_seo = https://docs.typo3.org/c/typo3/cms-seo/main/en-us/ -# ext_t3editor = https://docs.typo3.org/c/typo3/cms-t3editor/main/en-us/ # ext_workspaces = https://docs.typo3.org/c/typo3/cms-workspaces/main/en-us/ diff --git a/typo3/sysext/rte_ckeditor/Documentation/Settings.cfg b/typo3/sysext/rte_ckeditor/Documentation/Settings.cfg index f1ed4b50f187..165b16f84d77 100644 --- a/typo3/sysext/rte_ckeditor/Documentation/Settings.cfg +++ b/typo3/sysext/rte_ckeditor/Documentation/Settings.cfg @@ -62,5 +62,4 @@ t3tsref = https://docs.typo3.org/m/typo3/reference-typoscript/main/en-us/ # ext_rte_ckeditor = https://docs.typo3.org/c/typo3/cms-rte-ckeditor/main/en-us/ # ext_scheduler = https://docs.typo3.org/c/typo3/cms-scheduler/main/en-us/ # ext_seo = https://docs.typo3.org/c/typo3/cms-seo/main/en-us/ -# ext_t3editor = https://docs.typo3.org/c/typo3/cms-t3editor/main/en-us/ # ext_workspaces = https://docs.typo3.org/c/typo3/cms-workspaces/main/en-us/ diff --git a/typo3/sysext/scheduler/Documentation/Settings.cfg b/typo3/sysext/scheduler/Documentation/Settings.cfg index af38559d2c23..d669c74cc577 100644 --- a/typo3/sysext/scheduler/Documentation/Settings.cfg +++ b/typo3/sysext/scheduler/Documentation/Settings.cfg @@ -62,5 +62,4 @@ t3coreapi = https://docs.typo3.org/m/typo3/reference-coreapi/main/en-us/ # ext_rte_ckeditor = https://docs.typo3.org/c/typo3/cms-rte-ckeditor/main/en-us/ # ext_scheduler = https://docs.typo3.org/c/typo3/cms-scheduler/main/en-us/ # ext_seo = https://docs.typo3.org/c/typo3/cms-seo/main/en-us/ -# ext_t3editor = https://docs.typo3.org/c/typo3/cms-t3editor/main/en-us/ # ext_workspaces = https://docs.typo3.org/c/typo3/cms-workspaces/main/en-us/ diff --git a/typo3/sysext/seo/Documentation/Settings.cfg b/typo3/sysext/seo/Documentation/Settings.cfg index 725b0ed50e87..9d174f99c66b 100644 --- a/typo3/sysext/seo/Documentation/Settings.cfg +++ b/typo3/sysext/seo/Documentation/Settings.cfg @@ -62,5 +62,4 @@ ext_redirects = https://docs.typo3.org/c/typo3/cms-redirects/main/en-us/ # ext_rte_ckeditor = https://docs.typo3.org/c/typo3/cms-rte-ckeditor/main/en-us/ # ext_scheduler = https://docs.typo3.org/c/typo3/cms-scheduler/main/en-us/ # ext_seo = https://docs.typo3.org/c/typo3/cms-seo/main/en-us/ -# ext_t3editor = https://docs.typo3.org/c/typo3/cms-t3editor/main/en-us/ # ext_workspaces = https://docs.typo3.org/c/typo3/cms-workspaces/main/en-us/ diff --git a/typo3/sysext/styleguide/Classes/TcaDataGenerator/FieldGenerator/TypeTextFormatT3editor.php b/typo3/sysext/styleguide/Classes/TcaDataGenerator/FieldGenerator/TypeTextFormatCodeEditor.php similarity index 88% rename from typo3/sysext/styleguide/Classes/TcaDataGenerator/FieldGenerator/TypeTextFormatT3editor.php rename to typo3/sysext/styleguide/Classes/TcaDataGenerator/FieldGenerator/TypeTextFormatCodeEditor.php index a52d7b0bba2c..5c11ece8c5e6 100644 --- a/typo3/sysext/styleguide/Classes/TcaDataGenerator/FieldGenerator/TypeTextFormatT3editor.php +++ b/typo3/sysext/styleguide/Classes/TcaDataGenerator/FieldGenerator/TypeTextFormatCodeEditor.php @@ -24,7 +24,7 @@ use TYPO3\CMS\Styleguide\TcaDataGenerator\FieldGeneratorInterface; * * @internal */ -final class TypeTextFormatT3editor extends AbstractFieldGenerator implements FieldGeneratorInterface +final class TypeTextFormatCodeEditor extends AbstractFieldGenerator implements FieldGeneratorInterface { /** * @var array General match if type=text @@ -33,7 +33,7 @@ final class TypeTextFormatT3editor extends AbstractFieldGenerator implements Fie 'fieldConfig' => [ 'config' => [ 'type' => 'text', - 'renderType' => 't3editor', + 'renderType' => 'codeEditor', 'format' => 'html', ], ], diff --git a/typo3/sysext/styleguide/Classes/TcaDataGenerator/FieldGeneratorResolver.php b/typo3/sysext/styleguide/Classes/TcaDataGenerator/FieldGeneratorResolver.php index 975a2093cf7b..5ddaed69ecf0 100644 --- a/typo3/sysext/styleguide/Classes/TcaDataGenerator/FieldGeneratorResolver.php +++ b/typo3/sysext/styleguide/Classes/TcaDataGenerator/FieldGeneratorResolver.php @@ -82,7 +82,7 @@ final class FieldGeneratorResolver FieldGenerator\TypeTextDefaultExtrasRichtext::class, FieldGenerator\TypeTextFormatDatetime::class, - FieldGenerator\TypeTextFormatT3editor::class, + FieldGenerator\TypeTextFormatCodeEditor::class, FieldGenerator\TypeTextMax30::class, FieldGenerator\TypeTextWizardSelect::class, FieldGenerator\TypeTextWizardTable::class, diff --git a/typo3/sysext/styleguide/Configuration/TCA/tx_styleguide_elements_t3editor.php b/typo3/sysext/styleguide/Configuration/TCA/tx_styleguide_elements_t3editor.php index 9b55dc406b77..17755a80a573 100644 --- a/typo3/sysext/styleguide/Configuration/TCA/tx_styleguide_elements_t3editor.php +++ b/typo3/sysext/styleguide/Configuration/TCA/tx_styleguide_elements_t3editor.php @@ -79,7 +79,7 @@ return [ 'description' => 'field description', 'config' => [ 'type' => 'text', - 'renderType' => 't3editor', + 'renderType' => 'codeEditor', 'format' => 'html', 'rows' => 7, ], @@ -107,7 +107,7 @@ return [ 'description' => 'readOnly=true', 'config' => [ 'type' => 'text', - 'renderType' => 't3editor', + 'renderType' => 'codeEditor', 'format' => 'html', 'readOnly' => true, ], @@ -139,7 +139,7 @@ return [ <description>field description</description> <config> <type>text</type> - <renderType>t3editor</renderType> + <renderType>codeEditor</renderType> <format>html</format> </config> </t3editor_1> @@ -165,7 +165,7 @@ return [ <description>field description</description> <config> <type>text</type> - <renderType>t3editor</renderType> + <renderType>codeEditor</renderType> <format>html</format> </config> </t3editor_1> diff --git a/typo3/sysext/styleguide/Configuration/TCA/tx_styleguide_elements_t3editor_flex_1_inline_1_child.php b/typo3/sysext/styleguide/Configuration/TCA/tx_styleguide_elements_t3editor_flex_1_inline_1_child.php index 14e10cdb7245..fa8a2360c48f 100644 --- a/typo3/sysext/styleguide/Configuration/TCA/tx_styleguide_elements_t3editor_flex_1_inline_1_child.php +++ b/typo3/sysext/styleguide/Configuration/TCA/tx_styleguide_elements_t3editor_flex_1_inline_1_child.php @@ -84,7 +84,7 @@ return [ 'description' => 'field description', 'config' => [ 'type' => 'text', - 'renderType' => 't3editor', + 'renderType' => 'codeEditor', 'format' => 'html', ], ], diff --git a/typo3/sysext/styleguide/Configuration/TCA/tx_styleguide_elements_t3editor_inline_1_child.php b/typo3/sysext/styleguide/Configuration/TCA/tx_styleguide_elements_t3editor_inline_1_child.php index bdaa98440269..d89bbb7b4553 100644 --- a/typo3/sysext/styleguide/Configuration/TCA/tx_styleguide_elements_t3editor_inline_1_child.php +++ b/typo3/sysext/styleguide/Configuration/TCA/tx_styleguide_elements_t3editor_inline_1_child.php @@ -84,7 +84,7 @@ return [ 'description' => 'field description', 'config' => [ 'type' => 'text', - 'renderType' => 't3editor', + 'renderType' => 'codeEditor', 'format' => 'html', ], ], diff --git a/typo3/sysext/styleguide/Configuration/TCA/tx_styleguide_inline_1n_inline_2_child.php b/typo3/sysext/styleguide/Configuration/TCA/tx_styleguide_inline_1n_inline_2_child.php index 02cbce357261..c54c94d2b529 100644 --- a/typo3/sysext/styleguide/Configuration/TCA/tx_styleguide_inline_1n_inline_2_child.php +++ b/typo3/sysext/styleguide/Configuration/TCA/tx_styleguide_inline_1n_inline_2_child.php @@ -153,7 +153,7 @@ return [ 'label' => 't3editor_1', 'config' => [ 'type' => 'text', - 'renderType' => 't3editor', + 'renderType' => 'codeEditor', ], ], diff --git a/typo3/sysext/styleguide/Configuration/TCA/tx_styleguide_inline_expand_inline_1_child.php b/typo3/sysext/styleguide/Configuration/TCA/tx_styleguide_inline_expand_inline_1_child.php index 95a91111d177..6aedec33146f 100644 --- a/typo3/sysext/styleguide/Configuration/TCA/tx_styleguide_inline_expand_inline_1_child.php +++ b/typo3/sysext/styleguide/Configuration/TCA/tx_styleguide_inline_expand_inline_1_child.php @@ -153,7 +153,7 @@ return [ 'label' => 't3editor_1', 'config' => [ 'type' => 'text', - 'renderType' => 't3editor', + 'renderType' => 'codeEditor', ], ], diff --git a/typo3/sysext/styleguide/Configuration/TCA/tx_styleguide_l10nreadonly.php b/typo3/sysext/styleguide/Configuration/TCA/tx_styleguide_l10nreadonly.php index 4ab2c727cfc7..daad98edbbfa 100644 --- a/typo3/sysext/styleguide/Configuration/TCA/tx_styleguide_l10nreadonly.php +++ b/typo3/sysext/styleguide/Configuration/TCA/tx_styleguide_l10nreadonly.php @@ -347,7 +347,7 @@ return [ 'l10n_display' => 'defaultAsReadonly', 'config' => [ 'type' => 'text', - 'renderType' => 't3editor', + 'renderType' => 'codeEditor', 'format' => 'html', 'rows' => 5, ], diff --git a/typo3/sysext/styleguide/Configuration/TCA/tx_styleguide_type.php b/typo3/sysext/styleguide/Configuration/TCA/tx_styleguide_type.php index bd5d49c38236..30884be410ec 100644 --- a/typo3/sysext/styleguide/Configuration/TCA/tx_styleguide_type.php +++ b/typo3/sysext/styleguide/Configuration/TCA/tx_styleguide_type.php @@ -127,7 +127,7 @@ return [ ], 'text_1' => [ 'config' => [ - 'renderType' => 't3editor', + 'renderType' => 'codeEditor', 'format' => 'html', ], ], diff --git a/typo3/sysext/styleguide/Configuration/TCA/tx_styleguide_typeforeign.php b/typo3/sysext/styleguide/Configuration/TCA/tx_styleguide_typeforeign.php index a293cd7025a1..e1491d5030db 100644 --- a/typo3/sysext/styleguide/Configuration/TCA/tx_styleguide_typeforeign.php +++ b/typo3/sysext/styleguide/Configuration/TCA/tx_styleguide_typeforeign.php @@ -127,7 +127,7 @@ return [ ], 'text_1' => [ 'config' => [ - 'renderType' => 't3editor', + 'renderType' => 'codeEditor', 'format' => 'html', ], ], diff --git a/typo3/sysext/t3editor/.gitattributes b/typo3/sysext/t3editor/.gitattributes deleted file mode 100644 index 79ede152a838..000000000000 --- a/typo3/sysext/t3editor/.gitattributes +++ /dev/null @@ -1,2 +0,0 @@ -/.gitattributes export-ignore -/Tests/ export-ignore diff --git a/typo3/sysext/t3editor/Configuration/Backend/AjaxRoutes.php b/typo3/sysext/t3editor/Configuration/Backend/AjaxRoutes.php deleted file mode 100644 index b5315e7786ca..000000000000 --- a/typo3/sysext/t3editor/Configuration/Backend/AjaxRoutes.php +++ /dev/null @@ -1,18 +0,0 @@ -<?php - -/** - * Definitions for routes provided by EXT:t3editor - */ -return [ - // Get TSRef - 't3editor_tsref' => [ - 'path' => '/t3editor/tsref', - 'target' => \TYPO3\CMS\T3editor\Controller\TypoScriptReferenceController::class . '::loadReference', - ], - - // Load code completion templates - 't3editor_codecompletion_loadtemplates' => [ - 'path' => '/t3editor/codecompletion/load-templates', - 'target' => \TYPO3\CMS\T3editor\Controller\CodeCompletionController::class . '::loadCompletions', - ], -]; diff --git a/typo3/sysext/t3editor/Configuration/JavaScriptModules.php b/typo3/sysext/t3editor/Configuration/JavaScriptModules.php deleted file mode 100644 index 2ea4afd6712b..000000000000 --- a/typo3/sysext/t3editor/Configuration/JavaScriptModules.php +++ /dev/null @@ -1,57 +0,0 @@ -<?php - -return [ - 'dependencies' => [ - 'backend', - ], - 'tags' => [ - 'backend.form', - ], - 'imports' => [ - '@typo3/t3editor/' => [ - 'path' => 'EXT:t3editor/Resources/Public/JavaScript/', - 'exclude' => [ - 'EXT:core/Resources/Public/JavaScript/Contrib/', - ], - ], - 'crelt' => 'EXT:t3editor/Resources/Public/JavaScript/Contrib/crelt.js', - 'style-mod' => 'EXT:t3editor/Resources/Public/JavaScript/Contrib/style-mod.js', - 'w3c-keyname' => 'EXT:t3editor/Resources/Public/JavaScript/Contrib/w3c-keyname.js', - '@lezer/common' => 'EXT:t3editor/Resources/Public/JavaScript/Contrib/@lezer/common.js', - '@lezer/css' => 'EXT:t3editor/Resources/Public/JavaScript/Contrib/@lezer/css.js', - '@lezer/html' => 'EXT:t3editor/Resources/Public/JavaScript/Contrib/@lezer/html.js', - '@lezer/javascript' => 'EXT:t3editor/Resources/Public/JavaScript/Contrib/@lezer/javascript.js', - '@lezer/json' => 'EXT:t3editor/Resources/Public/JavaScript/Contrib/@lezer/json.js', - '@lezer/php' => 'EXT:t3editor/Resources/Public/JavaScript/Contrib/@lezer/php.js', - '@lezer/xml' => 'EXT:t3editor/Resources/Public/JavaScript/Contrib/@lezer/xml.js', - '@lezer/lr' => 'EXT:t3editor/Resources/Public/JavaScript/Contrib/@lezer/lr.js', - '@lezer/highlight' => 'EXT:t3editor/Resources/Public/JavaScript/Contrib/@lezer/highlight.js', - '@codemirror/autocomplete' => 'EXT:t3editor/Resources/Public/JavaScript/Contrib/@codemirror/autocomplete.js', - '@codemirror/closebrackets' => 'EXT:t3editor/Resources/Public/JavaScript/Contrib/@codemirror/closebrackets.js', - '@codemirror/commands' => 'EXT:t3editor/Resources/Public/JavaScript/Contrib/@codemirror/commands.js', - '@codemirror/comment' => 'EXT:t3editor/Resources/Public/JavaScript/Contrib/@codemirror/comment.js', - '@codemirror/fold' => 'EXT:t3editor/Resources/Public/JavaScript/Contrib/@codemirror/fold.js', - '@codemirror/gutter' => 'EXT:t3editor/Resources/Public/JavaScript/Contrib/@codemirror/gutter.js', - '@codemirror/highlight' => 'EXT:t3editor/Resources/Public/JavaScript/Contrib/@codemirror/highlight.js', - '@codemirror/history' => 'EXT:t3editor/Resources/Public/JavaScript/Contrib/@codemirror/history.js', - '@codemirror/language' => 'EXT:t3editor/Resources/Public/JavaScript/Contrib/@codemirror/language.js', - '@codemirror/lang-css' => 'EXT:t3editor/Resources/Public/JavaScript/Contrib/@codemirror/lang-css.js', - '@codemirror/lang-html' => 'EXT:t3editor/Resources/Public/JavaScript/Contrib/@codemirror/lang-html.js', - '@codemirror/lang-javascript' => 'EXT:t3editor/Resources/Public/JavaScript/Contrib/@codemirror/lang-javascript.js', - '@codemirror/lang-json' => 'EXT:t3editor/Resources/Public/JavaScript/Contrib/@codemirror/lang-json.js', - '@codemirror/lang-php' => 'EXT:t3editor/Resources/Public/JavaScript/Contrib/@codemirror/lang-php.js', - '@codemirror/lang-sql' => 'EXT:t3editor/Resources/Public/JavaScript/Contrib/@codemirror/lang-sql.js', - '@codemirror/lang-xml' => 'EXT:t3editor/Resources/Public/JavaScript/Contrib/@codemirror/lang-xml.js', - '@codemirror/lint' => 'EXT:t3editor/Resources/Public/JavaScript/Contrib/@codemirror/lint.js', - '@codemirror/matchbrackets' => 'EXT:t3editor/Resources/Public/JavaScript/Contrib/@codemirror/matchbrackets.js', - '@codemirror/panel' => 'EXT:t3editor/Resources/Public/JavaScript/Contrib/@codemirror/panel.js', - '@codemirror/rangeset' => 'EXT:t3editor/Resources/Public/JavaScript/Contrib/@codemirror/rangeset.js', - '@codemirror/rectangular-selection' => 'EXT:t3editor/Resources/Public/JavaScript/Contrib/@codemirror/rectangular-selection.js', - '@codemirror/search' => 'EXT:t3editor/Resources/Public/JavaScript/Contrib/@codemirror/search.js', - '@codemirror/state' => 'EXT:t3editor/Resources/Public/JavaScript/Contrib/@codemirror/state.js', - '@codemirror/text' => 'EXT:t3editor/Resources/Public/JavaScript/Contrib/@codemirror/text.js', - '@codemirror/tooltip' => 'EXT:t3editor/Resources/Public/JavaScript/Contrib/@codemirror/tooltip.js', - '@codemirror/theme-one-dark' => 'EXT:t3editor/Resources/Public/JavaScript/Contrib/@codemirror/theme-one-dark.js', - '@codemirror/view' => 'EXT:t3editor/Resources/Public/JavaScript/Contrib/@codemirror/view.js', - ], -]; diff --git a/typo3/sysext/t3editor/Configuration/Services.yaml b/typo3/sysext/t3editor/Configuration/Services.yaml deleted file mode 100644 index f9134d1f5234..000000000000 --- a/typo3/sysext/t3editor/Configuration/Services.yaml +++ /dev/null @@ -1,8 +0,0 @@ -services: - _defaults: - autowire: true - autoconfigure: true - public: false - - TYPO3\CMS\T3editor\: - resource: '../Classes/*' diff --git a/typo3/sysext/t3editor/Configuration/TCA/Overrides/tt_content.php b/typo3/sysext/t3editor/Configuration/TCA/Overrides/tt_content.php deleted file mode 100644 index b3faba5ae8fd..000000000000 --- a/typo3/sysext/t3editor/Configuration/TCA/Overrides/tt_content.php +++ /dev/null @@ -1,19 +0,0 @@ -<?php - -defined('TYPO3') or die(); - -// Activate t3editor for tt_content type HTML if this type exists -if (is_array($GLOBALS['TCA']['tt_content']['types']['html'])) { - if (!isset($GLOBALS['TCA']['tt_content']['types']['html']['columnsOverrides'])) { - $GLOBALS['TCA']['tt_content']['types']['html']['columnsOverrides'] = []; - } - if (!isset($GLOBALS['TCA']['tt_content']['types']['html']['columnsOverrides']['bodytext'])) { - $GLOBALS['TCA']['tt_content']['types']['html']['columnsOverrides']['bodytext'] = []; - } - if (!isset($GLOBALS['TCA']['tt_content']['types']['html']['columnsOverrides']['bodytext']['config'])) { - $GLOBALS['TCA']['tt_content']['types']['html']['columnsOverrides']['bodytext']['config'] = []; - } - $GLOBALS['TCA']['tt_content']['types']['html']['columnsOverrides']['bodytext']['config']['renderType'] = 't3editor'; - $GLOBALS['TCA']['tt_content']['types']['html']['columnsOverrides']['bodytext']['config']['wrap'] = 'off'; - $GLOBALS['TCA']['tt_content']['types']['html']['columnsOverrides']['bodytext']['config']['format'] = 'html'; -} diff --git a/typo3/sysext/t3editor/Documentation/CodeSnippets/Automatic/T3editor1.rst.txt b/typo3/sysext/t3editor/Documentation/CodeSnippets/Automatic/T3editor1.rst.txt deleted file mode 100644 index a0c871ee47ef..000000000000 --- a/typo3/sysext/t3editor/Documentation/CodeSnippets/Automatic/T3editor1.rst.txt +++ /dev/null @@ -1,23 +0,0 @@ -.. ==================================== -.. Automatically generated code snippet -.. ==================================== -.. -.. Extracted from typo3/sysext/styleguide/Configuration/TCA/tx_styleguide_elements_t3editor.php - - -.. code-block:: php - :caption: :file:`Configuration/TCA/tx_styleguide_elements_t3editor.php` - - 'columns' => [ - 't3editor_1' => [ - 'exclude' => true, - 'label' => 't3editor_1 format=html, rows=7', - 'description' => 'field description', - 'config' => [ - 'type' => 'text', - 'renderType' => 't3editor', - 'format' => 'html', - 'rows' => 7, - ], - ], - ] diff --git a/typo3/sysext/t3editor/Documentation/Developer/Extend.rst b/typo3/sysext/t3editor/Documentation/Developer/Extend.rst deleted file mode 100644 index 7947c12089bc..000000000000 --- a/typo3/sysext/t3editor/Documentation/Developer/Extend.rst +++ /dev/null @@ -1,137 +0,0 @@ -.. include:: /Includes.rst.txt - -=============== -Extend T3editor -=============== - -Custom modes (used for syntax highlighting) and addons can be registered. - -CodeMirror delivers a lot more modes and addons than registered in T3editor -by default. - -More supported addons and modes are available at: - -* https://github.com/codemirror/CodeMirror/tree/5.27.4/addon -* https://github.com/codemirror/CodeMirror/tree/5.27.4/mode - -Prerequisites -============= - -To do this, extensions may have these two files to feed T3editor: - -* :file:`Configuration/Backend/T3editor/Addons.php` -* :file:`Configuration/Backend/T3editor/Modes.php` - -Both files return an array, as known as in TCA and Backend Routes, for example. - -.. _register_addon: - -Register an addon -================= - -To register an addon, the following code may be used: - -.. code-block:: php - :caption: :file:`EXT:myext/Configuration/Backend/T3editor/Addons.php` - - <?php - - return [ - 'my/addon' => [ - 'module' => JavaScriptModuleInstruction::create('@codemirror/addon', 'addon')->invoke() - 'cssFiles' => [ - 'EXT:my_extension/Resources/Public/Css/MyAddon.css', - ], - 'options' [ - 'foobar' => 'baz', - ], - 'modes' => ['htmlmixed', 'xml'], - ], - ]; - -.. confval:: <identifier> - - :type: string - :Required: true - - Represents the unique identifier of the module (`my/addon` in this example). - -.. confval:: module - - :type: string - :Required: true - - Holds the JavaScriptModuleInstruction of the CodeMirror module. - -.. confval:: cssFiles - - :type: array - - Holds all CSS files that must be loaded for the module. - -.. confval:: options - - :type: array - - Options that are used by the addon. - -.. confval:: modes - - :type: array - - If set the addon is only loaded if any of the modes supplied here is used. - - -.. _register_mode: - -Register a mode -=============== - -To register a mode, the following code may be used: - -.. code-block:: php - :caption: :file:`EXT:myext/Configuration/Backend/T3editor/Modes.php` - - <?php - - return [ - 'css' => [ - 'module' => 'cm/mode/css/css', - 'extensions' => ['css'], - ], - ]; - - -.. confval:: <identifier> - - :type: string - :Required: true - - Represents the unique identifier and format code of the mode - (`css` in this example). The format code is used in TCA to - define the CodeMirror mode to be used. - - Example:: - - $GLOBALS['TCA']['tt_content']['types']['css']['columnsOverrides']['bodytext']['config']['format'] = 'css'; - -.. confval:: module - - :type: string - :Required: true - - Holds the JavaScriptModuleInstruction of the CodeMirror module. - -.. confval:: extensions - - :type: array - - Binds the mode to specific file extensions. This is important for using - T3editor in the module :guilabel:`Filelist`. - -.. confval:: default - - :type: bool - - If set, the mode is used as fallback if no sufficient mode is available. - By factory default, the default mode is `html`. diff --git a/typo3/sysext/t3editor/Documentation/Developer/Index.rst b/typo3/sysext/t3editor/Documentation/Developer/Index.rst deleted file mode 100644 index cef64cdc332b..000000000000 --- a/typo3/sysext/t3editor/Documentation/Developer/Index.rst +++ /dev/null @@ -1,14 +0,0 @@ -.. include:: /Includes.rst.txt -.. highlight:: php - -.. _developer: - -================ -Developer corner -================ - -.. toctree:: - :titlesonly: - - TCA - Extend diff --git a/typo3/sysext/t3editor/Documentation/Developer/TCA.rst b/typo3/sysext/t3editor/Documentation/Developer/TCA.rst deleted file mode 100644 index 4ea8948feeef..000000000000 --- a/typo3/sysext/t3editor/Documentation/Developer/TCA.rst +++ /dev/null @@ -1,37 +0,0 @@ -.. include:: /Includes.rst.txt - -.. _tca: -.. _renderType: - -=================== -Use t3editor in TCA -=================== - -Extensions may configure backend fields to use the t3editor by TCA. The editor -is only available for fields of type `text`. By setting the -:ref:`renderType to t3editor <t3tca:columns-text-renderType-t3editor>` the -syntax highlighting can be activated. - -By setting the property :ref:`format <t3tca:columns-text-properties-format>` -the mode for syntax highlighting can be chosen. Allowed values: -`css`, `html`, `javascript`, `php`, `typoscript`, `xml` and any -:ref:`custom mode <register_mode>` registered by an extension. - -.. versionadded:: 11.3 - TCA fields of renderType :php:`t3editor` support the - :php:`'readOnly' => true` option. If set, syntax highlighting - is applied as usual, but the corresponding text can not be edited. - - -.. _tca_examples: - -Examples -======== - -.. include:: /CodeSnippets/Automatic/T3editor1.rst.txt - -Displays an edior like the following: - -.. include:: /Images/AutomaticScreenshots/T3editor1.rst.txt - - diff --git a/typo3/sysext/t3editor/Documentation/Images/AutomaticScreenshots/T3editor1.png b/typo3/sysext/t3editor/Documentation/Images/AutomaticScreenshots/T3editor1.png deleted file mode 100644 index 72a317d07e7cf5a0cb7fcca42eb831cb987fac5e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 44707 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%0ATg;0wrQ#q$RQfCquR&oTmdd)WM7BAi`5-ifiCS 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 diff --git a/typo3/sysext/t3editor/Documentation/Images/AutomaticScreenshots/T3editor1.rst.txt b/typo3/sysext/t3editor/Documentation/Images/AutomaticScreenshots/T3editor1.rst.txt deleted file mode 100644 index ec43cb55f45c..000000000000 --- a/typo3/sysext/t3editor/Documentation/Images/AutomaticScreenshots/T3editor1.rst.txt +++ /dev/null @@ -1,9 +0,0 @@ -.. ========================================== -.. Automatically generated screenshot include -.. ========================================== -.. - -.. figure:: /Images/AutomaticScreenshots/T3editor1.png - :class: with-shadow - - A t3editor with syntax highlighting for HTML and 7 rows. \ No newline at end of file diff --git a/typo3/sysext/t3editor/Documentation/Includes.rst.txt b/typo3/sysext/t3editor/Documentation/Includes.rst.txt deleted file mode 100644 index 469841d32a76..000000000000 --- a/typo3/sysext/t3editor/Documentation/Includes.rst.txt +++ /dev/null @@ -1,34 +0,0 @@ -.. More information about this file: - https://docs.typo3.org/m/typo3/docs-how-to-document/main/en-us/GeneralConventions/FileStructure.html#includes-rst-txt - -.. ---------- -.. text roles -.. ---------- - -.. role:: aspect(emphasis) -.. role:: bash(code) -.. role:: html(code) -.. role:: js(code) -.. role:: php(code) -.. role:: rst(code) -.. role:: sep(strong) -.. role:: sql(code) - -.. role:: tsconfig(code) - :class: typoscript - -.. role:: typoscript(code) -.. role:: xml(code) - :class: html - -.. role:: yaml(code) - -.. default-role:: code - -.. --------- -.. highlight -.. --------- - -.. By default, code blocks use PHP syntax highlighting - -.. highlight:: php diff --git a/typo3/sysext/t3editor/Documentation/Index.rst b/typo3/sysext/t3editor/Documentation/Index.rst deleted file mode 100644 index 00931e5f3ee3..000000000000 --- a/typo3/sysext/t3editor/Documentation/Index.rst +++ /dev/null @@ -1,54 +0,0 @@ -.. include:: /Includes.rst.txt - -============== -TYPO3 T3Editor -============== - -:Extension key: - t3editor - -:Package name: - typo3/cms-t3editor - -:Version: - |release| - -:Language: - en - -:Author: - TYPO3 contributors - -:License: - This document is published under the - `Open Content License <https://www.openhub.net/licenses/opl>`__. - -:Rendered: - |today| - ----- - -This extension provides a JavaScript-driven editor with syntax highlighting and -code completion, based on the `CodeMirror`_ editor. - -.. _CodeMirror: https://codemirror.net/ - ----- - -**Table of Contents:** - -.. toctree:: - :maxdepth: 2 - :titlesonly: - - Introduction/Index - Installation/Index - Developer/Index - -.. Meta Menu - -.. toctree:: - :hidden: - - Sitemap - genindex diff --git a/typo3/sysext/t3editor/Documentation/Installation/Index.rst b/typo3/sysext/t3editor/Documentation/Installation/Index.rst deleted file mode 100644 index c23924909742..000000000000 --- a/typo3/sysext/t3editor/Documentation/Installation/Index.rst +++ /dev/null @@ -1,59 +0,0 @@ -.. include:: /Includes.rst.txt - -.. _installation: - -============ -Installation -============ - -.. _installation_composer: - -With Composer -============= - -If your TYPO3 installation is using Composer, install the t3editor -extension by: - -.. code-block:: bash - - composer require typo3/cms-t3editor - -If you are using Composer and not working with the latest version of TYPO3 -you will need to add a version constraint: - -.. code-block:: bash - - composer require typo3/cms-t3editor:"^10.4" - -Installing the extension prior to version 11.4 ----------------------------------------------- - -Before TYPO3 11.4 it was still necessary to manually activate extensions -installed via Composer using the Extension Manager. - -If you are using TYPO3 with Composer and are using a version of TYPO3 that is -lower than 11.4, you will need to activate the extension: - -- Access :guilabel:`Admin Tools > Extension Manager > Installed Extensions` -- Search for `t3editor` -- Activate the extension by selecting the :guilabel:`Activate` button in the - column labeled :guilabel:`A/D` - -.. _installation_legacy: - -Without Composer -================ - -If you are working with an installation of TYPO3 that doesn't use Composer, this -extension will already be part of the installation due to the fact that -legacy `.tar` & `.zip` packages come bundled with all system extensions. - -However, whilst the extension is already downloaded, it is likely that the -extension is not activated. - -To activate the t3editor, navigate to -:guilabel:`Admin Tools > Extension Manager > Installed Extensions` and -search for "t3editor". If the extension is not active, activate it by selecting -the :guilabel:`Activate` button in the column labeled :guilabel:`A/D`. - -System Maintainer rights are required to activate the extension. diff --git a/typo3/sysext/t3editor/Documentation/Introduction/Index.rst b/typo3/sysext/t3editor/Documentation/Introduction/Index.rst deleted file mode 100644 index bff8e543dc14..000000000000 --- a/typo3/sysext/t3editor/Documentation/Introduction/Index.rst +++ /dev/null @@ -1,27 +0,0 @@ -.. include:: /Includes.rst.txt - -.. _introduction: - -============ -Introduction -============ - -.. _what-it-does: - -What does it do? -================ - -This system extension provides a backend editor with syntax highlighting. -The editor is used for TCA fields with type `text` and renderType `t3editor` -and in the module :guilabel:`Filelist`. - -.. _screenshots: - -Screenshots -=========== - -.. include:: /Images/AutomaticScreenshots/T3editor1.rst.txt - -Configured by the following TCA: - -.. include:: /CodeSnippets/Automatic/T3editor1.rst.txt diff --git a/typo3/sysext/t3editor/Documentation/Settings.cfg b/typo3/sysext/t3editor/Documentation/Settings.cfg deleted file mode 100644 index e5f17c6adb60..000000000000 --- a/typo3/sysext/t3editor/Documentation/Settings.cfg +++ /dev/null @@ -1,66 +0,0 @@ -# More information about this file: -# https://docs.typo3.org/m/typo3/docs-how-to-document/main/en-us/GeneralConventions/FileStructure.html#settings-cfg - -[general] - -project = T3Editor -version = main (development) -release = main (development) -copyright = since 2007 by the TYPO3 contributors - -[html_theme_options] - -# "Edit on GitHub" button -github_repository = typo3/typo3 -github_branch = main -path_to_documentation_dir = typo3/sysext/t3editor/Documentation/ - -# Footer links -project_home = https://extensions.typo3.org/extension/t3editor/ -project_contact = https://typo3.slack.com/archives/C025BQLFA -project_repository = https://github.com/typo3/typo3 -project_issues = https://forge.typo3.org/projects/typo3cms-core/issues -project_discussions = - -use_opensearch = - -[intersphinx_mapping] - -# Official TYPO3 manuals -# h2document = https://docs.typo3.org/m/typo3/docs-how-to-document/main/en-us/ -# t3content = https://docs.typo3.org/m/typo3/guide-contentandmarketing/main/en-us/ -# t3contribute = https://docs.typo3.org/m/typo3/guide-contributionworkflow/main/en-us/ -# t3coreapi = https://docs.typo3.org/m/typo3/reference-coreapi/main/en-us/ -# t3editors = https://docs.typo3.org/m/typo3/tutorial-editors/main/en-us/ -# t3extexample = https://docs.typo3.org/m/typo3/guide-example-extension-manual/main/en-us/ -# t3home = https://docs.typo3.org/ -# t3sitepackage = https://docs.typo3.org/m/typo3/tutorial-sitepackage/main/en-us/ -# t3start = https://docs.typo3.org/m/typo3/tutorial-getting-started/main/en-us/ -t3tca = https://docs.typo3.org/m/typo3/reference-tca/main/en-us/ -# t3translate = https://docs.typo3.org/m/typo3/guide-frontendlocalization/main/en-us/ -# t3tsconfig = https://docs.typo3.org/m/typo3/reference-tsconfig/main/en-us/ -# t3tsref = https://docs.typo3.org/m/typo3/reference-typoscript/main/en-us/ -# t3ts45 = https://docs.typo3.org/m/typo3/tutorial-typoscript-in-45-minutes/main/en-us/ -# t3viewhelper = https://docs.typo3.org/other/typo3/view-helper-reference/main/en-us/ -# t3upgrade = https://docs.typo3.org/m/typo3/guide-installation/main/en-us/ - -# TYPO3 system extensions -# ext_adminpanel = https://docs.typo3.org/c/typo3/cms-adminpanel/main/en-us/ -# ext_core = https://docs.typo3.org/c/typo3/cms-core/main/en-us/ -# ext_dashboard = https://docs.typo3.org/c/typo3/cms-dashboard/main/en-us/ -# ext_felogin = https://docs.typo3.org/c/typo3/cms-felogin/main/en-us/ -# ext_form = https://docs.typo3.org/c/typo3/cms-form/main/en-us/ -# ext_fsc = https://docs.typo3.org/c/typo3/cms-fluid-styled-content/main/en-us/ -# ext_impexp = https://docs.typo3.org/c/typo3/cms-impexp/main/en-us/ -# ext_indexed_search = https://docs.typo3.org/c/typo3/cms-indexed-search/main/en-us/ -# ext_linkvalidator = https://docs.typo3.org/c/typo3/cms-linkvalidator/main/en-us/ -# ext_lowlevel = https://docs.typo3.org/c/typo3/cms-lowlevel/main/en-us/ -# ext_reactions = https://docs.typo3.org/c/typo3/cms-reactions/main/en-us/ -# ext_recycler = https://docs.typo3.org/c/typo3/cms-recycler/main/en-us/ -# ext_redirects = https://docs.typo3.org/c/typo3/cms-redirects/main/en-us/ -# ext_reports = https://docs.typo3.org/c/typo3/cms-reports/main/en-us/ -# ext_rte_ckeditor = https://docs.typo3.org/c/typo3/cms-rte-ckeditor/main/en-us/ -# ext_scheduler = https://docs.typo3.org/c/typo3/cms-scheduler/main/en-us/ -# ext_seo = https://docs.typo3.org/c/typo3/cms-seo/main/en-us/ -# ext_t3editor = https://docs.typo3.org/c/typo3/cms-t3editor/main/en-us/ -# ext_workspaces = https://docs.typo3.org/c/typo3/cms-workspaces/main/en-us/ diff --git a/typo3/sysext/t3editor/Documentation/Sitemap.rst b/typo3/sysext/t3editor/Documentation/Sitemap.rst deleted file mode 100644 index 09d3c6f56e97..000000000000 --- a/typo3/sysext/t3editor/Documentation/Sitemap.rst +++ /dev/null @@ -1,9 +0,0 @@ -:template: sitemap.html - -.. include:: /Includes.rst.txt - -======= -Sitemap -======= - -.. The sitemap.html template will insert here the page tree automatically. diff --git a/typo3/sysext/t3editor/Documentation/genindex.rst b/typo3/sysext/t3editor/Documentation/genindex.rst deleted file mode 100644 index 806ec56a77c4..000000000000 --- a/typo3/sysext/t3editor/Documentation/genindex.rst +++ /dev/null @@ -1,7 +0,0 @@ -.. include:: /Includes.rst.txt - -===== -Index -===== - -.. Sphinx will insert here the general index automatically. diff --git a/typo3/sysext/t3editor/Documentation/screenshots.json b/typo3/sysext/t3editor/Documentation/screenshots.json deleted file mode 100644 index 6c2b51260324..000000000000 --- a/typo3/sysext/t3editor/Documentation/screenshots.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "suites": { - "Styleguide": { - "screenshots": { - "options": [ - { - "action": "setCodeSnippetsTargetPath", - "path": "CodeSnippets/Automatic" - }, - {"action": "setScreenshotsImagePath","path": "Images/AutomaticScreenshots"}, - {"action": "setScreenshotsRstPath","path": "Images/AutomaticScreenshots"} - ], - "t3editor": [ - { - "action": "resizeWindow", - "width": 640, - "height": 640 - }, - { - "action": "setCodeSnippetsSourcePath", - "path": "typo3/sysext/styleguide" - }, - { - "action": "makeScreenshotOfField", - "fields": "t3editor_1", - "fileName": "T3editor1", - "table": "tx_styleguide_elements_t3editor", - "captionText": "A t3editor with syntax highlighting for HTML and 7 rows.", - "uid": { - "action": "getUidByField", - "table": "tx_styleguide_elements_t3editor", - "field": "sys_language_uid", - "value": 0 - } - }, - { - "action": "createPhpArrayCodeSnippet", - "sourceFile": "Configuration/TCA/tx_styleguide_elements_t3editor.php", - "caption": ":file:`Configuration/TCA/tx_styleguide_elements_t3editor.php`", - "fields": [ - "columns/t3editor_1" - ], - "targetFileName": "T3editor1" - } - ] - } - } - } -} diff --git a/typo3/sysext/t3editor/LICENSE.txt b/typo3/sysext/t3editor/LICENSE.txt deleted file mode 100644 index d159169d1050..000000000000 --- a/typo3/sysext/t3editor/LICENSE.txt +++ /dev/null @@ -1,339 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Lesser General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - <one line to give the program's name and a brief idea of what it does.> - Copyright (C) <year> <name of author> - - 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. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - <signature of Ty Coon>, 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. diff --git a/typo3/sysext/t3editor/README.rst b/typo3/sysext/t3editor/README.rst deleted file mode 100644 index be9910d45ca3..000000000000 --- a/typo3/sysext/t3editor/README.rst +++ /dev/null @@ -1,13 +0,0 @@ -============================ -TYPO3 extension ``t3editor`` -============================ - -This extension provides a JavaScript-driven editor with syntax highlighting and -code completion, based on the `CodeMirror`_ editor. - -.. _CodeMirror: https://codemirror.net/ - -:Repository: https://github.com/typo3/typo3 -:Issues: https://forge.typo3.org/ -:Read online: https://docs.typo3.org/c/typo3/cms-t3editor/main/en-us/ -:TER: https://extensions.typo3.org/extension/t3editor/ diff --git a/typo3/sysext/t3editor/Resources/Private/Language/locallang.xlf b/typo3/sysext/t3editor/Resources/Private/Language/locallang.xlf deleted file mode 100644 index 56b1ae23a46e..000000000000 --- a/typo3/sysext/t3editor/Resources/Private/Language/locallang.xlf +++ /dev/null @@ -1,47 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> - <file source-language="en" datatype="plaintext" original="EXT:t3editor/Resources/Private/Language/locallang.xlf" date="2011-10-17T20:22:37Z" product-name="t3editor"> - <header/> - <body> - <trans-unit id="deactivate" resname="deactivate"> - <source>Deactivate t3editor</source> - </trans-unit> - <trans-unit id="template" resname="template"> - <source>Template</source> - </trans-unit> - <trans-unit id="file" resname="file"> - <source>File</source> - </trans-unit> - <trans-unit id="delimiter" resname="delimiter"> - <source></source> - </trans-unit> - <trans-unit id="constants" resname="constants"> - <source>Constants</source> - </trans-unit> - <trans-unit id="setup" resname="setup"> - <source>Setup</source> - </trans-unit> - <trans-unit id="unknownContentType" resname="unknownContentType"> - <source>Unknown content type</source> - </trans-unit> - <trans-unit id="pageIDInteger" resname="pageIDInteger"> - <source>Syntax error: Parameter pageID must be a valid integer.</source> - </trans-unit> - <trans-unit id="noPermission" resname="noPermission"> - <source>Access denied: No permission to template records.</source> - </trans-unit> - <trans-unit id="typeIDMissing" resname="typeIDMissing"> - <source>Syntax error: At least parameter typeID has to be supplied.</source> - </trans-unit> - <trans-unit id="js.label_lines" resname="js.label_lines"> - <source>lines</source> - </trans-unit> - <trans-unit id="js.label_documentModified" resname="js.label_documentModified"> - <source>document has been modified</source> - </trans-unit> - <trans-unit id="js.label_errorWhileSaving" resname="js.label_errorWhileSaving"> - <source>An error occurred while saving the data.</source> - </trans-unit> - </body> - </file> -</xliff> diff --git a/typo3/sysext/t3editor/Resources/Public/Icons/Extension.png b/typo3/sysext/t3editor/Resources/Public/Icons/Extension.png deleted file mode 100644 index 6d9d2eba87289ac9a13834a5ea2a46bcae30d995..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2275 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 diff --git a/typo3/sysext/t3editor/Resources/Public/JavaScript/autocomplete/ts-code-completion.js b/typo3/sysext/t3editor/Resources/Public/JavaScript/autocomplete/ts-code-completion.js deleted file mode 100644 index d32b4018abaa..000000000000 --- a/typo3/sysext/t3editor/Resources/Public/JavaScript/autocomplete/ts-code-completion.js +++ /dev/null @@ -1,13 +0,0 @@ -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ -import AjaxRequest from"@typo3/core/ajax/ajax-request.js";import{TsRef}from"@typo3/t3editor/autocomplete/ts-ref.js";import{TsParser}from"@typo3/t3editor/autocomplete/ts-parser.js";import{CompletionResult}from"@typo3/t3editor/autocomplete/completion-result.js";export class TsCodeCompletion{constructor(e){this.extTsObjTree={},this.parser=null,this.proposals=null,this.compResult=null,this.tsRef=new TsRef,this.parser=new TsParser(this.tsRef,this.extTsObjTree),this.tsRef.loadTsrefAsync(),this.loadExtTemplatesAsync(e)}refreshCodeCompletion(e){const t=this.getFilter(e),s=this.parser.buildTsObjTree(e);this.compResult=new CompletionResult(this.tsRef,s),this.proposals=this.compResult.getFilteredProposals(t);const o=[];for(let e=0;e<this.proposals.length;e++)o[e]=this.proposals[e].word;return o}loadExtTemplatesAsync(e){if(Number.isNaN(e)||0===e)return null;new AjaxRequest(TYPO3.settings.ajaxUrls.t3editor_codecompletion_loadtemplates).withQueryArguments({pageId:e}).get().then((async e=>{this.extTsObjTree.c=await e.resolve(),this.resolveExtReferencesRec(this.extTsObjTree.c)}))}resolveExtReferencesRec(e){for(const t of Object.keys(e)){let s;if(e[t].v&&"<"===e[t].v[0]&&-1===e[t].v.indexOf(">")){const o=e[t].v.replace(/</,"").trim();-1===o.indexOf(" ")&&(s=this.getExtChildNode(o),null!==s&&(e[t]=s))}!s&&e[t].c&&this.resolveExtReferencesRec(e[t].c)}}getExtChildNode(e){let t=this.extTsObjTree;const s=e.split(".");for(let e=0;e<s.length;e++){const o=s[e];if(void 0===t.c||void 0===t.c[o])return null;t=t.c[o]}return t}getFilter(e){return e.completingAfterDot?"":e.token.string.replace(".","").replace(/\s/g,"")}} \ No newline at end of file diff --git a/typo3/sysext/t3editor/Resources/Public/JavaScript/autocomplete/ts-ref.js b/typo3/sysext/t3editor/Resources/Public/JavaScript/autocomplete/ts-ref.js deleted file mode 100644 index ed706c121ea6..000000000000 --- a/typo3/sysext/t3editor/Resources/Public/JavaScript/autocomplete/ts-ref.js +++ /dev/null @@ -1,13 +0,0 @@ -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ -import AjaxRequest from"@typo3/core/ajax/ajax-request.js";export class TsRefType{constructor(e,t,s){this.properties={},this.typeId=e,this.extends=t,this.properties=s}}export class TsRefProperty{constructor(e,t,s){this.parentType=e,this.name=t,this.value=s}}export class TsRef{constructor(){this.typeTree={},this.doc=null}async loadTsrefAsync(){const e=await new AjaxRequest(TYPO3.settings.ajaxUrls.t3editor_tsref).get();this.doc=await e.resolve(),this.buildTree()}buildTree(){for(const e of Object.keys(this.doc)){const t=this.doc[e];this.typeTree[e]=new TsRefType(e,t.extends||void 0,Object.fromEntries(Object.entries(t.properties).map((([t,s])=>[t,new TsRefProperty(e,t,s.type)]))))}for(const e of Object.keys(this.typeTree))void 0!==this.typeTree[e].extends&&this.addPropertiesToType(this.typeTree[e],this.typeTree[e].extends,100)}addPropertiesToType(e,t,s){if(s<0)throw"Maximum recursion depth exceeded while trying to resolve the extends in the TSREF!";const r=t.split(",");for(let t=0;t<r.length;t++)if(void 0!==this.typeTree[r[t]]){void 0!==this.typeTree[r[t]].extends&&this.addPropertiesToType(this.typeTree[r[t]],this.typeTree[r[t]].extends,s-1);const i=this.typeTree[r[t]].properties;for(const t in i)void 0===e.properties[t]&&(e.properties[t]=i[t])}}getPropertiesFromTypeId(e){return void 0!==this.typeTree[e]?(this.typeTree[e].properties.clone=function(){const e={};for(const t of Object.keys(this))e[t]=new TsRefProperty(this[t].parentType,this[t].name,this[t].value);return e},this.typeTree[e].properties):{}}typeHasProperty(e,t){return void 0!==this.typeTree[e]&&void 0!==this.typeTree[e].properties[t]}getType(e){return this.typeTree[e]}isType(e){return void 0!==this.typeTree[e]}} \ No newline at end of file diff --git a/typo3/sysext/t3editor/Resources/Public/JavaScript/language/typoscript.js b/typo3/sysext/t3editor/Resources/Public/JavaScript/language/typoscript.js deleted file mode 100644 index 46c8356ce913..000000000000 --- a/typo3/sysext/t3editor/Resources/Public/JavaScript/language/typoscript.js +++ /dev/null @@ -1,13 +0,0 @@ -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ -import DocumentService from"@typo3/core/document-service.js";import{StreamLanguage,LanguageSupport}from"@codemirror/language";import{TypoScriptStreamParserFactory}from"@typo3/t3editor/stream-parser/typoscript.js";import{TsCodeCompletion}from"@typo3/t3editor/autocomplete/ts-code-completion.js";import{syntaxTree}from"@codemirror/language";export function typoscript(){const t=StreamLanguage.define((new TypoScriptStreamParserFactory).create()),e=t.data.of({autocomplete:complete});return new LanguageSupport(t,[e])}const tsCodeCompletionInitializer=(async()=>{await DocumentService.ready();const t=parseInt(document.querySelector('input[name="effectivePid"]')?.value,10);return new TsCodeCompletion(t)})();export async function complete(t){if(!t.explicit)return null;const e=parseCodeMirror5CompatibleCompletionState(t),o=t.pos-(e.completingAfterDot?1:0),r=syntaxTree(t.state).resolveInner(o,-1),n="Document"===r.name||e.completingAfterDot?"":t.state.sliceDoc(r.from,o),s="Document"===r.name||e.completingAfterDot?t.pos:r.from;let a={start:r.from,end:o,string:n,type:r.name};/^[\w$_]*$/.test(n)||(a={start:t.pos,end:t.pos,string:"",type:"."===n?"property":null}),e.token=a;const i=(await tsCodeCompletionInitializer).refreshCodeCompletion(e);if(("string"===r.name||"comment"===r.name)&&tokenIsSubStringOfKeywords(n,i))return null;return{from:s,options:getCompletions(n,i).map((t=>({label:t,type:"keyword"})))}}function parseCodeMirror5CompatibleCompletionState(t){const e=t.state.sliceDoc().split(t.state.lineBreak).length,o=t.state.sliceDoc(0,t.pos).split(t.state.lineBreak).length,r=t.state.sliceDoc().split(t.state.lineBreak)[o-1],n="."===t.state.sliceDoc(t.pos-1,t.pos);return{lineTokens:extractCodemirror5StyleLineTokens(e,t),currentLineNumber:o,currentLine:r,lineCount:e,completingAfterDot:n}}function extractCodemirror5StyleLineTokens(t,e){const o=Array(t).fill("").map((()=>[]));let r=0,n=1;return syntaxTree(e.state).cursor().iterate((s=>{const a=s.type.name||s.name;if("Document"===a)return;const i=s.from,c=s.to;r<i&&e.state.sliceDoc(r,i).split(e.state.lineBreak).forEach((e=>{e&&(o[Math.min(n-1,t-1)].push({type:null,string:e,start:r,end:r+e.length}),n++,r+=e.length)}));const l=e.state.sliceDoc(s.from,s.to);n=e.state.sliceDoc(0,s.from).split(e.state.lineBreak).length,o[n-1].push({type:a,string:l,start:i,end:c}),r=c})),r<e.state.doc.length&&o[n-1].push({type:null,string:e.state.sliceDoc(r),start:r,end:e.state.doc.length}),o}function tokenIsSubStringOfKeywords(t,e){const o=t.length;for(let r=0;r<e.length;++r)if(t===e[r].substr(o))return!0;return!1}function getCompletions(t,e){const o=new Set;for(let n=0,s=e.length;n<s;++n)0!==(r=e[n]).lastIndexOf(t,0)||o.has(r)||o.add(r);var r;const n=Array.from(o);return n.sort(),n} \ No newline at end of file diff --git a/typo3/sysext/t3editor/composer.json b/typo3/sysext/t3editor/composer.json deleted file mode 100644 index a47050324d8d..000000000000 --- a/typo3/sysext/t3editor/composer.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "name": "typo3/cms-t3editor", - "type": "typo3-cms-framework", - "description": "TYPO3 CMS T3Editor - JavaScript-driven editor with syntax highlighting and code completion. Based on CodeMirror.", - "homepage": "https://typo3.org", - "license": ["GPL-2.0-or-later"], - "authors": [{ - "name": "TYPO3 Core Team", - "email": "typo3cms@typo3.org", - "role": "Developer" - }], - "support": { - "chat": "https://typo3.org/help", - "docs": "https://docs.typo3.org/c/typo3/cms-t3editor/main/en-us", - "issues": "https://forge.typo3.org", - "source": "https://github.com/typo3/typo3" - }, - "config": { - "sort-packages": true - }, - "require": { - "ext-libxml": "*", - "typo3/cms-core": "13.0.*@dev" - }, - "conflict": { - "typo3/cms": "*" - }, - "extra": { - "branch-alias": { - "dev-main": "13.0.x-dev" - }, - "typo3/cms": { - "Package": { - "partOfFactoryDefault": true - }, - "extension-key": "t3editor" - } - }, - "autoload": { - "psr-4": { - "TYPO3\\CMS\\T3editor\\": "Classes/" - } - } -} diff --git a/typo3/sysext/t3editor/ext_emconf.php b/typo3/sysext/t3editor/ext_emconf.php deleted file mode 100644 index 0d6c7ec0134f..000000000000 --- a/typo3/sysext/t3editor/ext_emconf.php +++ /dev/null @@ -1,19 +0,0 @@ -<?php - -$EM_CONF[$_EXTKEY] = [ - 'title' => 'TYPO3 CMS T3Editor', - 'description' => 'JavaScript-driven editor with syntax highlighting and code completion. Based on CodeMirror.', - 'category' => 'be', - 'state' => 'stable', - 'author' => 'TYPO3 Core Team', - 'author_email' => 'typo3cms@typo3.org', - 'author_company' => '', - 'version' => '13.0.0', - 'constraints' => [ - 'depends' => [ - 'typo3' => '13.0.0', - ], - 'conflicts' => [], - 'suggests' => [], - ], -]; diff --git a/typo3/sysext/t3editor/ext_localconf.php b/typo3/sysext/t3editor/ext_localconf.php deleted file mode 100644 index 6fa08b2f897d..000000000000 --- a/typo3/sysext/t3editor/ext_localconf.php +++ /dev/null @@ -1,14 +0,0 @@ -<?php - -declare(strict_types=1); - -use TYPO3\CMS\T3editor\Form\Element\T3editorElement; - -defined('TYPO3') or die(); - -// Register backend FormEngine node -$GLOBALS['TYPO3_CONF_VARS']['SYS']['formEngine']['nodeRegistry'][1433089350] = [ - 'nodeName' => 't3editor', - 'priority' => 40, - 'class' => T3editorElement::class, -]; diff --git a/typo3/sysext/tstemplate/Configuration/JavaScriptModules.php b/typo3/sysext/tstemplate/Configuration/JavaScriptModules.php index ef530bda2a53..d823cd436766 100644 --- a/typo3/sysext/tstemplate/Configuration/JavaScriptModules.php +++ b/typo3/sysext/tstemplate/Configuration/JavaScriptModules.php @@ -4,7 +4,6 @@ return [ 'dependencies' => [ 'backend', 'core', - 't3editor', ], 'tags' => [ 'backend.module', diff --git a/typo3/sysext/tstemplate/Resources/Public/JavaScript/template-analyzer.js b/typo3/sysext/tstemplate/Resources/Public/JavaScript/template-analyzer.js index 2befe3ae7e0d..f411a0ef9f25 100644 --- a/typo3/sysext/tstemplate/Resources/Public/JavaScript/template-analyzer.js +++ b/typo3/sysext/tstemplate/Resources/Public/JavaScript/template-analyzer.js @@ -10,8 +10,8 @@ * * The TYPO3 project - inspiring people to share! */ -import DocumentService from"@typo3/core/document-service.js";import{default as Modal}from"@typo3/backend/modal.js";import{topLevelModuleImport}from"@typo3/backend/utility/top-level-module-import.js";import{html}from"lit";import{until}from"lit/directives/until.js";import AjaxRequest from"@typo3/core/ajax/ajax-request.js";class TemplateAnalyzer{constructor(){this.registerEventListeners()}async registerEventListeners(){await DocumentService.ready(),document.querySelectorAll(".t3js-typoscript-analyzer-modal").forEach((e=>{e.addEventListener("click",(t=>{t.preventDefault();const o=Modal.types.default,r=e.dataset.modalTitle||e.textContent.trim(),a=e.getAttribute("href"),l=Modal.sizes.large,i=html`${until(this.fetchModalContent(a),html`<div class="modal-loading"><typo3-backend-spinner size="default"></typo3-backend-spinner></div>`)}`;Modal.advanced({type:o,title:r,size:l,content:i})}))}))}async fetchModalContent(e){topLevelModuleImport("@typo3/t3editor/element/code-mirror-element.js");const t=await new AjaxRequest(e).get(),o=await t.resolve();return html` - <typo3-t3editor-codemirror .mode="${{name:"@typo3/t3editor/language/typoscript.js",flags:2,exportName:"typoscript",items:[{type:"invoke",args:[]}]}}" nolazyload readonly class="flex-grow-1 mh-100"> +import DocumentService from"@typo3/core/document-service.js";import{default as Modal}from"@typo3/backend/modal.js";import{topLevelModuleImport}from"@typo3/backend/utility/top-level-module-import.js";import{html}from"lit";import{until}from"lit/directives/until.js";import AjaxRequest from"@typo3/core/ajax/ajax-request.js";class TemplateAnalyzer{constructor(){this.registerEventListeners()}async registerEventListeners(){await DocumentService.ready(),document.querySelectorAll(".t3js-typoscript-analyzer-modal").forEach((e=>{e.addEventListener("click",(t=>{t.preventDefault();const o=Modal.types.default,r=e.dataset.modalTitle||e.textContent.trim(),a=e.getAttribute("href"),l=Modal.sizes.large,i=html`${until(this.fetchModalContent(a),html`<div class="modal-loading"><typo3-backend-spinner size="default"></typo3-backend-spinner></div>`)}`;Modal.advanced({type:o,title:r,size:l,content:i})}))}))}async fetchModalContent(e){topLevelModuleImport("@typo3/backend/code-editor/element/code-mirror-element.js");const t=await new AjaxRequest(e).get(),o=await t.resolve();return html` + <typo3-t3editor-codemirror .mode="${{name:"@typo3/backend/code-editor/language/typoscript.js",flags:2,exportName:"typoscript",items:[{type:"invoke",args:[]}]}}" nolazyload readonly class="flex-grow-1 mh-100"> <textarea readonly disabled class="form-control">${o}</textarea> </typo3-t3editor-codemirror> `}}export default new TemplateAnalyzer; \ No newline at end of file diff --git a/typo3/sysext/workspaces/Documentation/Settings.cfg b/typo3/sysext/workspaces/Documentation/Settings.cfg index 443f6cd0ae32..1765aa3c636a 100644 --- a/typo3/sysext/workspaces/Documentation/Settings.cfg +++ b/typo3/sysext/workspaces/Documentation/Settings.cfg @@ -62,5 +62,4 @@ t3tsconfig = https://docs.typo3.org/m/typo3/reference-tsconfig/main/en-us/ # ext_rte_ckeditor = https://docs.typo3.org/c/typo3/cms-rte-ckeditor/main/en-us/ # ext_scheduler = https://docs.typo3.org/c/typo3/cms-scheduler/main/en-us/ # ext_seo = https://docs.typo3.org/c/typo3/cms-seo/main/en-us/ -# ext_t3editor = https://docs.typo3.org/c/typo3/cms-t3editor/main/en-us/ # ext_workspaces = https://docs.typo3.org/c/typo3/cms-workspaces/main/en-us/ -- GitLab