typo3-typescript-sources 13.4.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/sync-and-publish.yml +265 -0
- package/.last-synced-tag +1 -0
- package/LICENSE.txt +339 -0
- package/README-TYPO3.md +166 -0
- package/README.md +28 -0
- package/adminpanel/admin-panel.ts +375 -0
- package/adminpanel/modules/cache.ts +27 -0
- package/adminpanel/modules/preview.ts +75 -0
- package/backend/action-button/abstract-action.ts +22 -0
- package/backend/action-button/deferred-action.ts +41 -0
- package/backend/action-button/immediate-action.ts +31 -0
- package/backend/action-dispatcher.ts +104 -0
- package/backend/ajax-data-handler/message-interface.ts +18 -0
- package/backend/ajax-data-handler/response-interface.ts +20 -0
- package/backend/ajax-data-handler.ts +214 -0
- package/backend/backend-exception.ts +22 -0
- package/backend/broadcast-message.ts +50 -0
- package/backend/broadcast-service.ts +52 -0
- package/backend/browse-database.ts +38 -0
- package/backend/clear-cache.ts +88 -0
- package/backend/clipboard-panel.ts +240 -0
- package/backend/close-current-window.ts +2 -0
- package/backend/code-editor/autocomplete/completion-result.ts +105 -0
- package/backend/code-editor/autocomplete/ts-code-completion.ts +142 -0
- package/backend/code-editor/autocomplete/ts-parser.ts +485 -0
- package/backend/code-editor/autocomplete/ts-ref.ts +164 -0
- package/backend/code-editor/element/code-mirror-element.ts +282 -0
- package/backend/code-editor/language/typoscript.ts +181 -0
- package/backend/code-editor/stream-parser/typoscript.ts +1600 -0
- package/backend/color-picker.ts +158 -0
- package/backend/color-scheme-switch.ts +179 -0
- package/backend/column-selector-button.ts +302 -0
- package/backend/context-help.ts +68 -0
- package/backend/context-menu-actions.ts +322 -0
- package/backend/context-menu.ts +751 -0
- package/backend/copy-to-clipboard.ts +79 -0
- package/backend/date-time-picker.ts +270 -0
- package/backend/document-save-actions.ts +159 -0
- package/backend/drag-tooltip.ts +285 -0
- package/backend/drag-uploader.ts +914 -0
- package/backend/element/alert-element.ts +116 -0
- package/backend/element/dispatch-modal-button.ts +50 -0
- package/backend/element/draggable-resizable-element.ts +249 -0
- package/backend/element/editable-page-title.ts +306 -0
- package/backend/element/icon-element.ts +84 -0
- package/backend/element/immediate-action-element.ts +89 -0
- package/backend/element/pagination.ts +59 -0
- package/backend/element/progress-bar-element.ts +172 -0
- package/backend/element/progress-tracker-element.ts +119 -0
- package/backend/element/pseudo-button.ts +58 -0
- package/backend/element/spinner-element.ts +51 -0
- package/backend/element/thumbnail-element.ts +80 -0
- package/backend/element-browser.ts +182 -0
- package/backend/enum/data-transfer-types.ts +21 -0
- package/backend/enum/icon-types.ts +31 -0
- package/backend/enum/key-types.ts +27 -0
- package/backend/enum/severity.ts +20 -0
- package/backend/enum/viewport/scaffold-identifier.ts +24 -0
- package/backend/event/client-request.ts +25 -0
- package/backend/event/consumable.ts +18 -0
- package/backend/event/consumer-scope.ts +54 -0
- package/backend/event/event-dispatcher.ts +26 -0
- package/backend/event/interaction-request-assignment.ts +24 -0
- package/backend/event/interaction-request-map.ts +75 -0
- package/backend/event/interaction-request.ts +48 -0
- package/backend/event/trigger-request.ts +56 -0
- package/backend/form/submit-interceptor.ts +66 -0
- package/backend/form-engine/container/files-control-container.ts +716 -0
- package/backend/form-engine/container/flex-form-container-container.ts +166 -0
- package/backend/form-engine/container/flex-form-section-container.ts +210 -0
- package/backend/form-engine/container/inline-control-container.ts +1230 -0
- package/backend/form-engine/container/site-language-container.ts +616 -0
- package/backend/form-engine/element/abstract-sortable-select-items.ts +186 -0
- package/backend/form-engine/element/category-element.ts +160 -0
- package/backend/form-engine/element/color-element.ts +81 -0
- package/backend/form-engine/element/datetime-element.ts +66 -0
- package/backend/form-engine/element/extra/char-counter.ts +112 -0
- package/backend/form-engine/element/extra/select-box-filter.ts +85 -0
- package/backend/form-engine/element/folder-element.ts +66 -0
- package/backend/form-engine/element/group-element.ts +47 -0
- package/backend/form-engine/element/json-element.ts +52 -0
- package/backend/form-engine/element/link-element.ts +121 -0
- package/backend/form-engine/element/mfa-info-element.ts +169 -0
- package/backend/form-engine/element/modifier/resizable.ts +27 -0
- package/backend/form-engine/element/modifier/tabbable.ts +29 -0
- package/backend/form-engine/element/online-media-form-element.ts +65 -0
- package/backend/form-engine/element/password-element.ts +71 -0
- package/backend/form-engine/element/select-multiple-side-by-side-element.ts +83 -0
- package/backend/form-engine/element/select-single-element.ts +82 -0
- package/backend/form-engine/element/select-tree-element.ts +148 -0
- package/backend/form-engine/element/select-tree-toolbar.ts +118 -0
- package/backend/form-engine/element/select-tree.ts +210 -0
- package/backend/form-engine/element/slug-element.ts +243 -0
- package/backend/form-engine/element/suggest/result-container.ts +118 -0
- package/backend/form-engine/element/suggest/result-item.ts +90 -0
- package/backend/form-engine/element/table-permission-element.ts +101 -0
- package/backend/form-engine/element/table-wizard-element.ts +427 -0
- package/backend/form-engine/element/text-element.ts +52 -0
- package/backend/form-engine/element/text-table-element.ts +31 -0
- package/backend/form-engine/field-control/add-record.ts +40 -0
- package/backend/form-engine/field-control/edit-popup.ts +64 -0
- package/backend/form-engine/field-control/insert-clipboard.ts +50 -0
- package/backend/form-engine/field-control/link-popup.ts +53 -0
- package/backend/form-engine/field-control/list-module.ts +40 -0
- package/backend/form-engine/field-control/password-generator.ts +102 -0
- package/backend/form-engine/field-control/reset-selection.ts +48 -0
- package/backend/form-engine/field-wizard/localization-state-selector.ts +67 -0
- package/backend/form-engine/field-wizard/value-picker.ts +123 -0
- package/backend/form-engine/field-wizard/value-slider.ts +86 -0
- package/backend/form-engine/inline-relation/ajax-dispatcher.ts +124 -0
- package/backend/form-engine/inline-relation/inline-response-interface.ts +41 -0
- package/backend/form-engine-link-browser-adapter.ts +129 -0
- package/backend/form-engine-review.ts +155 -0
- package/backend/form-engine-suggest.ts +133 -0
- package/backend/form-engine-validation.ts +686 -0
- package/backend/form-engine.ts +1391 -0
- package/backend/global-event-handler.ts +252 -0
- package/backend/grid-editor.ts +1077 -0
- package/backend/hashing/md5.ts +252 -0
- package/backend/helper.ts +24 -0
- package/backend/hotkeys/hotkey-storage.ts +63 -0
- package/backend/hotkeys.ts +216 -0
- package/backend/icons.ts +236 -0
- package/backend/image-manipulation.ts +885 -0
- package/backend/info-window.ts +46 -0
- package/backend/input/clearable.ts +128 -0
- package/backend/input/index.d.ts +8 -0
- package/backend/java-script-module-import-event-handler.ts +19 -0
- package/backend/key-bindings.ts +42 -0
- package/backend/layout-module/drag-drop.ts +359 -0
- package/backend/layout-module/paste.ts +165 -0
- package/backend/link-browser.ts +89 -0
- package/backend/live-search/element/backend-search.ts +34 -0
- package/backend/live-search/element/hint.ts +33 -0
- package/backend/live-search/element/provider/default-result-item.ts +52 -0
- package/backend/live-search/element/provider/page-provider-result-item.ts +52 -0
- package/backend/live-search/element/result/item/action/action-container.ts +135 -0
- package/backend/live-search/element/result/item/action/action.ts +56 -0
- package/backend/live-search/element/result/item/item-container.ts +224 -0
- package/backend/live-search/element/result/item/item.ts +74 -0
- package/backend/live-search/element/result/result-container.ts +110 -0
- package/backend/live-search/element/result/result-detail-container.ts +50 -0
- package/backend/live-search/element/result/result-pagination.ts +122 -0
- package/backend/live-search/element/search-option-item.ts +70 -0
- package/backend/live-search/live-search-configurator.ts +54 -0
- package/backend/live-search/live-search-shortcut.ts +29 -0
- package/backend/live-search/result-types/backend-module-result-type.ts +8 -0
- package/backend/live-search/result-types/default-result-type.ts +21 -0
- package/backend/live-search/result-types/page-result-type.ts +23 -0
- package/backend/localization.ts +390 -0
- package/backend/login-refresh.ts +525 -0
- package/backend/login.ts +179 -0
- package/backend/mail-link-handler.ts +45 -0
- package/backend/modal-interface.ts +19 -0
- package/backend/modal.ts +685 -0
- package/backend/module/iframe.ts +125 -0
- package/backend/module/router.ts +275 -0
- package/backend/module-menu.ts +550 -0
- package/backend/module.ts +133 -0
- package/backend/multi-record-selection-action.ts +44 -0
- package/backend/multi-record-selection-delete-action.ts +108 -0
- package/backend/multi-record-selection-edit-action.ts +56 -0
- package/backend/multi-record-selection.ts +468 -0
- package/backend/multi-step-wizard.ts +568 -0
- package/backend/new-content-element-wizard-button.ts +51 -0
- package/backend/new-multiple-pages.ts +108 -0
- package/backend/new-record-wizard.ts +680 -0
- package/backend/notification.ts +366 -0
- package/backend/offset.ts +40 -0
- package/backend/online-media.ts +110 -0
- package/backend/page-actions.ts +91 -0
- package/backend/page-link-handler.ts +51 -0
- package/backend/pagetsconfig/pagetsconfig-includes.ts +77 -0
- package/backend/popover.ts +165 -0
- package/backend/record-download-button.ts +104 -0
- package/backend/record-link-handler.ts +31 -0
- package/backend/record-search.ts +44 -0
- package/backend/recordlist.ts +230 -0
- package/backend/resource/resource.ts +35 -0
- package/backend/security/element/csp-reports.ts +406 -0
- package/backend/security/element/sudo-mode.ts +249 -0
- package/backend/security/sudo-mode-interceptor.ts +19 -0
- package/backend/settings/editor/editable-setting.ts +231 -0
- package/backend/settings/editor.ts +451 -0
- package/backend/settings/enum/settings-mode.enum.ts +24 -0
- package/backend/settings/type/base.ts +200 -0
- package/backend/settings/type/bool.ts +56 -0
- package/backend/settings/type/color.ts +64 -0
- package/backend/settings/type/int.ts +85 -0
- package/backend/settings/type/number.ts +61 -0
- package/backend/settings/type/page.ts +100 -0
- package/backend/settings/type/string.ts +77 -0
- package/backend/settings/type/stringlist.ts +87 -0
- package/backend/severity.ts +88 -0
- package/backend/site-inline-actions.ts +32 -0
- package/backend/sortable-table.ts +208 -0
- package/backend/storage/abstract-client-storage.ts +76 -0
- package/backend/storage/browser-session.ts +28 -0
- package/backend/storage/client.ts +28 -0
- package/backend/storage/module-state-storage.ts +118 -0
- package/backend/storage/persistent.ts +204 -0
- package/backend/switch-user.ts +82 -0
- package/backend/tabs.ts +72 -0
- package/backend/telephone-link-handler.ts +40 -0
- package/backend/tests/backend/storage/browser-storage-test.ts +87 -0
- package/backend/tests/backend/storage/client-test.ts +87 -0
- package/backend/tests/backend/utility/dom-helper-test.ts +51 -0
- package/backend/tests/backend-exception-test.ts +28 -0
- package/backend/tests/element/immediate-action-element-test.ts +81 -0
- package/backend/tests/form-engine-validation-test.ts +304 -0
- package/backend/tests/grid-editor-test.ts +29 -0
- package/backend/tests/hashing/md5Test.ts +28 -0
- package/backend/tests/icons-test.ts +23 -0
- package/backend/tests/notification-test.ts +161 -0
- package/backend/tests/popover-test.ts +83 -0
- package/backend/toolbar/clear-cache-menu.ts +88 -0
- package/backend/toolbar/live-search.ts +284 -0
- package/backend/toolbar/shortcut-menu.ts +254 -0
- package/backend/toolbar/system-information-menu.ts +161 -0
- package/backend/toolbar.ts +41 -0
- package/backend/tree/file-storage-browser.ts +194 -0
- package/backend/tree/file-storage-tree-container.ts +465 -0
- package/backend/tree/file-storage-tree.ts +42 -0
- package/backend/tree/page-browser.ts +272 -0
- package/backend/tree/page-tree-element.ts +602 -0
- package/backend/tree/page-tree.ts +152 -0
- package/backend/tree/tree-module-state.ts +159 -0
- package/backend/tree/tree-node-toggle.ts +31 -0
- package/backend/tree/tree-node.ts +97 -0
- package/backend/tree/tree-toolbar.ts +117 -0
- package/backend/tree/tree.ts +1595 -0
- package/backend/url-link-handler.ts +36 -0
- package/backend/user-pass-login.ts +255 -0
- package/backend/user-settings-manager.ts +189 -0
- package/backend/utility/collapse-state-persister.ts +205 -0
- package/backend/utility/collapse-state-search.ts +183 -0
- package/backend/utility/dom-helper.ts +91 -0
- package/backend/utility/drag-drop-utility.ts +47 -0
- package/backend/utility/message-utility.ts +45 -0
- package/backend/utility/top-level-module-import.ts +32 -0
- package/backend/utility.ts +194 -0
- package/backend/viewport/abstract-container.ts +22 -0
- package/backend/viewport/content-container.ts +98 -0
- package/backend/viewport/loader.ts +28 -0
- package/backend/viewport/navigation-container.ts +119 -0
- package/backend/viewport/resizable-navigation.ts +176 -0
- package/backend/viewport/toolbar.ts +27 -0
- package/backend/viewport/topbar.ts +39 -0
- package/backend/viewport.ts +46 -0
- package/backend/window-manager.ts +84 -0
- package/backend/wizard/move-content-element.ts +107 -0
- package/backend/wizard/move-page.ts +74 -0
- package/backend/wizard.ts +331 -0
- package/belog/backend-log.ts +88 -0
- package/beuser/backend-user-listing.ts +40 -0
- package/beuser/permissions.ts +291 -0
- package/core/ajax/ajax-request-types.ts +15 -0
- package/core/ajax/ajax-request.ts +202 -0
- package/core/ajax/ajax-response.ts +57 -0
- package/core/ajax/input-transformer.ts +92 -0
- package/core/ajax/simple-response-interface.ts +5 -0
- package/core/authentication/mfa-provider/totp.ts +54 -0
- package/core/cache/dedupe-async-task.ts +95 -0
- package/core/directive/markdown.ts +82 -0
- package/core/directive/nl2br.ts +16 -0
- package/core/document-service.ts +35 -0
- package/core/event/debounce-event.ts +40 -0
- package/core/event/event-interface.ts +24 -0
- package/core/event/regular-event.ts +58 -0
- package/core/event/request-animation-frame-event.ts +42 -0
- package/core/event/throttle-event.ts +54 -0
- package/core/java-script-item-handler.ts +29 -0
- package/core/java-script-item-processor.ts +171 -0
- package/core/lit-helper.ts +126 -0
- package/core/literals.ts +17 -0
- package/core/referrer-refresh.ts +2 -0
- package/core/security-utility.ts +89 -0
- package/core/tests/ajax/ajax-request-test.ts +290 -0
- package/core/tests/ajax/input-transformer-test.ts +64 -0
- package/core/tests/cache/dedupe-async-task-test.ts +152 -0
- package/core/tests/event/throttle-event-test.ts +47 -0
- package/core/tests/literals-test.ts +24 -0
- package/core/tests/security-utility-test.ts +50 -0
- package/core/utility/types.ts +9 -0
- package/dashboard/chart-initializer.ts +136 -0
- package/dashboard/dashboard.ts +1487 -0
- package/extensionmanager/distribution-image.ts +55 -0
- package/extensionmanager/main.ts +291 -0
- package/extensionmanager/repository.ts +195 -0
- package/extensionmanager/update.ts +118 -0
- package/extensionmanager/upload-form.ts +42 -0
- package/filelist/browse-files.ts +148 -0
- package/filelist/browse-folders.ts +94 -0
- package/filelist/context-menu-actions.ts +335 -0
- package/filelist/create-folder.ts +69 -0
- package/filelist/file-delete.ts +69 -0
- package/filelist/file-list-actions.ts +132 -0
- package/filelist/file-list-dragdrop.ts +139 -0
- package/filelist/file-list-rename-handler.ts +128 -0
- package/filelist/file-list-transfer-handler.ts +138 -0
- package/filelist/file-list.ts +396 -0
- package/filelist/file-replace.ts +37 -0
- package/filelist/linkbrowser-file-handler.ts +94 -0
- package/filelist/linkbrowser-folder-handler.ts +74 -0
- package/filelist/rename-file.ts +109 -0
- package/form/backend/form-editor/component/property-grid-editor.ts +340 -0
- package/form/backend/form-editor/core.ts +2104 -0
- package/form/backend/form-editor/helper.ts +226 -0
- package/form/backend/form-editor/inspector-component.ts +2323 -0
- package/form/backend/form-editor/mediator.ts +941 -0
- package/form/backend/form-editor/modals-component.ts +433 -0
- package/form/backend/form-editor/stage-component.ts +908 -0
- package/form/backend/form-editor/tree-component.ts +548 -0
- package/form/backend/form-editor/view-model.ts +1343 -0
- package/form/backend/form-editor.ts +846 -0
- package/form/backend/form-manager/main.ts +39 -0
- package/form/backend/form-manager/view-model.ts +789 -0
- package/form/backend/form-manager.ts +180 -0
- package/form/backend/helper.ts +60 -0
- package/form/frontend/date-picker.ts +38 -0
- package/frontend/default_frontend.ts +82 -0
- package/impexp/context-menu-actions.ts +50 -0
- package/impexp/import-export.ts +62 -0
- package/indexed-search/pagination.ts +26 -0
- package/indexed-search/statistics.ts +50 -0
- package/info/translation-status.ts +48 -0
- package/install/ajax/ajax-queue.ts +83 -0
- package/install/init-install.ts +2 -0
- package/install/init-installer.ts +2 -0
- package/install/install.ts +25 -0
- package/install/installer.ts +458 -0
- package/install/message-interface.ts +18 -0
- package/install/module/abstract-inline-module.ts +27 -0
- package/install/module/abstract-interactable-module.ts +107 -0
- package/install/module/environment/environment-check.ts +92 -0
- package/install/module/environment/folder-structure.ts +145 -0
- package/install/module/environment/image-processing.ts +141 -0
- package/install/module/environment/mail-test.ts +127 -0
- package/install/module/environment/php-info.ts +50 -0
- package/install/module/environment/system-information.ts +50 -0
- package/install/module/maintenance/cache.ts +59 -0
- package/install/module/maintenance/clear-tables.ts +134 -0
- package/install/module/maintenance/clear-typo3temp-files.ts +137 -0
- package/install/module/maintenance/create-admin.ts +126 -0
- package/install/module/maintenance/database-analyzer.ts +266 -0
- package/install/module/maintenance/dump-autoload.ts +58 -0
- package/install/module/maintenance/language-packs.ts +338 -0
- package/install/module/maintenance/reset-backend-user-uc.ts +58 -0
- package/install/module/password-strength.ts +56 -0
- package/install/module/settings/change-install-tool-password.ts +101 -0
- package/install/module/settings/extension-configuration.ts +224 -0
- package/install/module/settings/features.ts +102 -0
- package/install/module/settings/local-configuration.ts +316 -0
- package/install/module/settings/presets.ts +147 -0
- package/install/module/settings/system-maintainer.ts +111 -0
- package/install/module/upgrade/core-update.ts +255 -0
- package/install/module/upgrade/extension-compat-tester.ts +195 -0
- package/install/module/upgrade/extension-scanner.ts +381 -0
- package/install/module/upgrade/tca-ext-tables-check.ts +93 -0
- package/install/module/upgrade/tca-migrations-check.ts +101 -0
- package/install/module/upgrade/upgrade-docs.ts +310 -0
- package/install/module/upgrade/upgrade-wizards.ts +612 -0
- package/install/renderable/clearable.ts +113 -0
- package/install/renderable/flash-message.ts +64 -0
- package/install/renderable/info-box.ts +66 -0
- package/install/renderable/language-packs.ts +304 -0
- package/install/renderable/offset-group.ts +38 -0
- package/install/renderable/severity.ts +49 -0
- package/install/renderable/wrap-group.ts +36 -0
- package/install/router.ts +468 -0
- package/linkvalidator/linkvalidator-modal.ts +45 -0
- package/linkvalidator/linkvalidator.ts +101 -0
- package/lowlevel/query-generator.ts +132 -0
- package/lowlevel/reference-index.ts +44 -0
- package/opendocs/toolbar/opendocs-menu.ts +117 -0
- package/package.json +34 -0
- package/recycler/recycler.ts +539 -0
- package/redirects/event-handler.ts +108 -0
- package/redirects/form-engine-evaluation.ts +34 -0
- package/redirects/redirects-module.ts +58 -0
- package/rte-ckeditor/ckeditor5.ts +402 -0
- package/rte-ckeditor/css-prefixer.ts +94 -0
- package/rte-ckeditor/legacy/ckeditor5-bundle.ts +17 -0
- package/rte-ckeditor/legacy/ckeditor5-inspector.ts +2 -0
- package/rte-ckeditor/plugin/typo3-link.ts +810 -0
- package/rte-ckeditor/plugin/whitespace.ts +114 -0
- package/rte-ckeditor/rte-link-browser.ts +112 -0
- package/rte-ckeditor/tests/css-prefixer-test.ts +314 -0
- package/scheduler/scheduler-add-group.ts +119 -0
- package/scheduler/scheduler-editable-group-name.ts +307 -0
- package/scheduler/scheduler-sortable-groups.ts +59 -0
- package/scheduler/scheduler.ts +466 -0
- package/setup/setup-module.ts +122 -0
- package/styleguide/checkbox-demo.ts +5 -0
- package/styleguide/element/theme-switcher-element.ts +101 -0
- package/styleguide/filter.ts +22 -0
- package/styleguide/find-icons.ts +78 -0
- package/styleguide/processing-indicator.ts +78 -0
- package/styleguide/render-notifications.ts +64 -0
- package/sys-note/element/delete-button.ts +78 -0
- package/tstemplate/constant-editor.ts +64 -0
- package/tstemplate/information-module.ts +31 -0
- package/tstemplate/template-analyzer.ts +77 -0
- package/viewpage/main.ts +253 -0
- package/workspaces/backend.ts +979 -0
- package/workspaces/preview.ts +232 -0
- package/workspaces/renderable/comment-view.ts +79 -0
- package/workspaces/renderable/diff-view.ts +58 -0
- package/workspaces/renderable/history-view.ts +97 -0
- package/workspaces/renderable/record-information.ts +118 -0
- package/workspaces/renderable/record-table.ts +355 -0
- package/workspaces/renderable/send-to-stage-form.ts +108 -0
- package/workspaces/toolbar/workspaces-menu.ts +190 -0
- package/workspaces/utility/icon-helper.ts +57 -0
- package/workspaces/workspaces.ts +136 -0
|
@@ -0,0 +1,485 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This file is part of the TYPO3 CMS project.
|
|
3
|
+
*
|
|
4
|
+
* It is free software; you can redistribute it and/or modify it under
|
|
5
|
+
* the terms of the GNU General Public License, either version 2
|
|
6
|
+
* of the License, or any later version.
|
|
7
|
+
*
|
|
8
|
+
* For the full copyright and license information, please read the
|
|
9
|
+
* LICENSE.txt file that was distributed with this source code.
|
|
10
|
+
*
|
|
11
|
+
* The TYPO3 project - inspiring people to share!
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import type { TsRef } from './ts-ref';
|
|
15
|
+
import type { TsObjTree } from './ts-code-completion';
|
|
16
|
+
import type { CodeMirror5CompatibleCompletionState } from '../language/typoscript';
|
|
17
|
+
|
|
18
|
+
export class TreeNode {
|
|
19
|
+
public value: string;
|
|
20
|
+
public childNodes: Record<string, TreeNode> = {};
|
|
21
|
+
public extPath = '';
|
|
22
|
+
public name: string;
|
|
23
|
+
public isExternal: boolean;
|
|
24
|
+
|
|
25
|
+
public global: boolean;
|
|
26
|
+
public parent: TreeNode = null;
|
|
27
|
+
|
|
28
|
+
private readonly tsParser: TsParser;
|
|
29
|
+
|
|
30
|
+
constructor(nodeName: string, tsParser: TsParser) {
|
|
31
|
+
this.name = nodeName;
|
|
32
|
+
this.childNodes = {};
|
|
33
|
+
this.extPath = '';
|
|
34
|
+
this.value = '';
|
|
35
|
+
this.isExternal = false;
|
|
36
|
+
|
|
37
|
+
this.tsParser = tsParser;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Returns local properties and the properties of the external templates
|
|
42
|
+
*/
|
|
43
|
+
public getChildNodes(): Record<string, TreeNode> {
|
|
44
|
+
const node = this.getExtNode();
|
|
45
|
+
if (node !== null && typeof node.c === 'object') {
|
|
46
|
+
for (const key of Object.keys(node.c)) {
|
|
47
|
+
const tn = new TreeNode(key, this.tsParser);
|
|
48
|
+
tn.global = true;
|
|
49
|
+
tn.value = (node.c[key].v) ? node.c[key].v : '';
|
|
50
|
+
tn.isExternal = true;
|
|
51
|
+
this.childNodes[key] = tn;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return this.childNodes;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Returns the value of a node
|
|
59
|
+
*/
|
|
60
|
+
public getValue(): string {
|
|
61
|
+
if (this.value) {
|
|
62
|
+
return this.value;
|
|
63
|
+
}
|
|
64
|
+
const node = this.getExtNode();
|
|
65
|
+
if (node && node.v) {
|
|
66
|
+
return node.v;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const type = this.getNodeTypeFromTsref();
|
|
70
|
+
if (type) {
|
|
71
|
+
return type;
|
|
72
|
+
}
|
|
73
|
+
return '';
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* This method will try to resolve the properties recursively from right
|
|
78
|
+
* to left. If the node's value property is not set, it will look for the
|
|
79
|
+
* value of its parent node, and if there is a matching childProperty
|
|
80
|
+
* (according to the TSREF) it will return the childProperties value.
|
|
81
|
+
* If there is no value in the parent node it will go one step further
|
|
82
|
+
* and look into the parent node of the parent node,...
|
|
83
|
+
*/
|
|
84
|
+
private getNodeTypeFromTsref(): string {
|
|
85
|
+
const path = this.extPath.split('.'),
|
|
86
|
+
lastSeg = path.pop();
|
|
87
|
+
|
|
88
|
+
// attention: there will be recursive calls if necessary
|
|
89
|
+
const parentValue = this.parent.getValue();
|
|
90
|
+
if (parentValue) {
|
|
91
|
+
if (this.tsParser.tsRef.typeHasProperty(parentValue, lastSeg)) {
|
|
92
|
+
const type = this.tsParser.tsRef.getType(parentValue);
|
|
93
|
+
return type.properties[lastSeg].value;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return '';
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Will look in the external ts-tree (static templates, templates on other pages)
|
|
101
|
+
* if there is a value or childproperties assigned to the current node.
|
|
102
|
+
* The method uses the extPath of the current node to navigate to the corresponding
|
|
103
|
+
* node in the external tree
|
|
104
|
+
*/
|
|
105
|
+
private getExtNode(): TsObjTree {
|
|
106
|
+
let extTree = this.tsParser.extTsObjTree;
|
|
107
|
+
|
|
108
|
+
if (this.extPath === '') {
|
|
109
|
+
return extTree;
|
|
110
|
+
}
|
|
111
|
+
const path = this.extPath.split('.');
|
|
112
|
+
|
|
113
|
+
for (let i = 0; i < path.length; i++) {
|
|
114
|
+
const pathSeg = path[i];
|
|
115
|
+
if (typeof extTree.c === 'undefined' || typeof extTree.c[pathSeg] === 'undefined') {
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
extTree = extTree.c[pathSeg];
|
|
119
|
+
}
|
|
120
|
+
return extTree;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
class Stack<T> extends Array<T> {
|
|
125
|
+
public lastElementEquals(el: T): boolean {
|
|
126
|
+
return this.length > 0 && this[this.length - 1] === el;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
public popIfLastElementEquals(el: T): boolean {
|
|
130
|
+
if (this.lastElementEquals(el)) {
|
|
131
|
+
this.pop();
|
|
132
|
+
return true;
|
|
133
|
+
}
|
|
134
|
+
return false;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export class TsParser {
|
|
139
|
+
public readonly tsRef: TsRef;
|
|
140
|
+
public readonly extTsObjTree: TsObjTree;
|
|
141
|
+
private tsTree: TreeNode;
|
|
142
|
+
|
|
143
|
+
private clone: <T extends object | unknown>(myObj: T) => T;
|
|
144
|
+
|
|
145
|
+
constructor(tsRef: TsRef, extTsObjTree: TsObjTree) {
|
|
146
|
+
this.tsRef = tsRef;
|
|
147
|
+
this.extTsObjTree = extTsObjTree;
|
|
148
|
+
this.tsTree = new TreeNode('_L_', this);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Check if there is an operator in the line and return it
|
|
153
|
+
* if there is none, return -1
|
|
154
|
+
*/
|
|
155
|
+
public getOperator(line: string): string | -1 {
|
|
156
|
+
const operators = [':=', '=<', '<', '>', '='];
|
|
157
|
+
for (let i = 0; i < operators.length; i++) {
|
|
158
|
+
const op = operators[i];
|
|
159
|
+
if (line.indexOf(op) !== -1) {
|
|
160
|
+
// check if there is some HTML in this line (simple check, however it's the only difference between a reference operator and HTML)
|
|
161
|
+
// we do this check only in case of the two operators "=<" and "<" since the delete operator would trigger our "HTML-finder"
|
|
162
|
+
if ((op === '=<' || op === '<') && line.indexOf('>') > -1) {
|
|
163
|
+
// if there is a ">" in the line suppose there's some HTML
|
|
164
|
+
return '=';
|
|
165
|
+
}
|
|
166
|
+
return op;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return -1;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Build the TypoScript object tree
|
|
174
|
+
*/
|
|
175
|
+
public buildTsObjTree(completionState: CodeMirror5CompatibleCompletionState): TreeNode {
|
|
176
|
+
this.tsTree = new TreeNode('', this);
|
|
177
|
+
this.tsTree.value = 'TLO';
|
|
178
|
+
|
|
179
|
+
let currentLine = 1,
|
|
180
|
+
line = '',
|
|
181
|
+
ignoreLine = false,
|
|
182
|
+
insideCondition = false;
|
|
183
|
+
const stack = new Stack<string>();
|
|
184
|
+
const prefixes = [];
|
|
185
|
+
let path;
|
|
186
|
+
|
|
187
|
+
while (currentLine <= completionState.currentLineNumber) {
|
|
188
|
+
line = '';
|
|
189
|
+
const tokens = completionState.lineTokens[currentLine - 1];
|
|
190
|
+
for (let i = 0; i <= tokens.length; ++i) {
|
|
191
|
+
if (i < tokens.length && tokens[i].string.length > 0) {
|
|
192
|
+
const tokenValue = tokens[i].string;
|
|
193
|
+
|
|
194
|
+
if (tokenValue.startsWith('#')) {
|
|
195
|
+
stack.push('#');
|
|
196
|
+
} else if (tokenValue === '(') {
|
|
197
|
+
stack.push('(');
|
|
198
|
+
} else if (tokenValue.startsWith('/*')) {
|
|
199
|
+
stack.push('/*');
|
|
200
|
+
} else if (tokenValue === '{') {
|
|
201
|
+
// TODO: ignore whole block if wrong whitespaces in this line
|
|
202
|
+
if (this.getOperator(line) === -1) {
|
|
203
|
+
stack.push('{');
|
|
204
|
+
prefixes.push(line.trim());
|
|
205
|
+
ignoreLine = true;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
// TODO: conditions
|
|
209
|
+
// if condition starts -> ignore everything until end of condition
|
|
210
|
+
if (tokenValue.search(/^\s*\[.*\]/) !== -1
|
|
211
|
+
&& line.search(/\S/) === -1
|
|
212
|
+
&& tokenValue.search(/^\s*\[(global|end|GLOBAL|END)\]/) === -1
|
|
213
|
+
&& !stack.lastElementEquals('#')
|
|
214
|
+
&& !stack.lastElementEquals('/*')
|
|
215
|
+
&& !stack.lastElementEquals('{')
|
|
216
|
+
&& !stack.lastElementEquals('(')
|
|
217
|
+
) {
|
|
218
|
+
insideCondition = true;
|
|
219
|
+
ignoreLine = true;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// if end of condition reached
|
|
223
|
+
if (line.search(/\S/) === -1
|
|
224
|
+
&& !stack.lastElementEquals('#')
|
|
225
|
+
&& !stack.lastElementEquals('/*')
|
|
226
|
+
&& !stack.lastElementEquals('(')
|
|
227
|
+
&& (
|
|
228
|
+
(tokenValue.search(/^\s*\[(global|end|GLOBAL|END)\]/) !== -1
|
|
229
|
+
&& !stack.lastElementEquals('{'))
|
|
230
|
+
|| (tokenValue.search(/^\s*\[(global|GLOBAL)\]/) !== -1)
|
|
231
|
+
)
|
|
232
|
+
) {
|
|
233
|
+
insideCondition = false;
|
|
234
|
+
ignoreLine = true;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
if (tokenValue === ')') {
|
|
238
|
+
stack.popIfLastElementEquals('(');
|
|
239
|
+
}
|
|
240
|
+
if (tokenValue.startsWith('*/')) {
|
|
241
|
+
stack.popIfLastElementEquals('/*');
|
|
242
|
+
ignoreLine = true;
|
|
243
|
+
}
|
|
244
|
+
if (tokenValue === '}') {
|
|
245
|
+
//no characters except whitespace allowed before closing bracket
|
|
246
|
+
const trimmedLine = line.replace(/\s/g, '');
|
|
247
|
+
if (trimmedLine === '') {
|
|
248
|
+
stack.popIfLastElementEquals('{');
|
|
249
|
+
if (prefixes.length > 0) {
|
|
250
|
+
prefixes.pop();
|
|
251
|
+
}
|
|
252
|
+
ignoreLine = true;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
if (!stack.lastElementEquals('#')) {
|
|
256
|
+
line += tokenValue;
|
|
257
|
+
}
|
|
258
|
+
} else {
|
|
259
|
+
// ignore comments, ...
|
|
260
|
+
if (!stack.lastElementEquals('/*') && !stack.lastElementEquals('(') && !ignoreLine && !insideCondition) {
|
|
261
|
+
line = line.trim();
|
|
262
|
+
// check if there is any operator in this line
|
|
263
|
+
const op = this.getOperator(line);
|
|
264
|
+
if (op !== -1) {
|
|
265
|
+
// figure out the position of the operator
|
|
266
|
+
const pos = line.indexOf(op);
|
|
267
|
+
// the target objectpath should be left to the operator
|
|
268
|
+
path = line.substring(0, pos);
|
|
269
|
+
// if we are in between curly brackets: add prefixes to object path
|
|
270
|
+
if (prefixes.length > 0) {
|
|
271
|
+
path = prefixes.join('.') + '.' + path;
|
|
272
|
+
}
|
|
273
|
+
// the type or value should be right to the operator
|
|
274
|
+
let str = line.substring(pos + op.length, line.length).trim();
|
|
275
|
+
path = path.trim();
|
|
276
|
+
switch (op) { // set a value or create a new object
|
|
277
|
+
case '=':
|
|
278
|
+
//ignore if path is empty or contains whitespace
|
|
279
|
+
if (path.search(/\s/g) === -1 && path.length > 0) {
|
|
280
|
+
this.setTreeNodeValue(path, str);
|
|
281
|
+
}
|
|
282
|
+
break;
|
|
283
|
+
case '=<': // reference to another object in the tree
|
|
284
|
+
// resolve relative path
|
|
285
|
+
if (prefixes.length > 0 && str.substr(0, 1) === '.') {
|
|
286
|
+
str = prefixes.join('.') + str;
|
|
287
|
+
}
|
|
288
|
+
//ignore if either path or str is empty or contains whitespace
|
|
289
|
+
if (path.search(/\s/g) === -1
|
|
290
|
+
&& path.length > 0
|
|
291
|
+
&& str.search(/\s/g) === -1
|
|
292
|
+
&& str.length > 0
|
|
293
|
+
) {
|
|
294
|
+
this.setReference(path, str);
|
|
295
|
+
}
|
|
296
|
+
break;
|
|
297
|
+
case '<': // copy from another object in the tree
|
|
298
|
+
// resolve relative path
|
|
299
|
+
if (prefixes.length > 0 && str.substr(0, 1) === '.') {
|
|
300
|
+
str = prefixes.join('.') + str;
|
|
301
|
+
}
|
|
302
|
+
//ignore if either path or str is empty or contains whitespace
|
|
303
|
+
if (path.search(/\s/g) === -1
|
|
304
|
+
&& path.length > 0
|
|
305
|
+
&& str.search(/\s/g) === -1
|
|
306
|
+
&& str.length > 0
|
|
307
|
+
) {
|
|
308
|
+
this.setCopy(path, str);
|
|
309
|
+
}
|
|
310
|
+
break;
|
|
311
|
+
case '>': // delete object value and properties
|
|
312
|
+
this.deleteTreeNodeValue(path);
|
|
313
|
+
break;
|
|
314
|
+
case ':=': // function operator
|
|
315
|
+
// TODO: function-operator
|
|
316
|
+
break;
|
|
317
|
+
default:
|
|
318
|
+
break;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
stack.popIfLastElementEquals('#');
|
|
323
|
+
ignoreLine = false;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
currentLine++;
|
|
327
|
+
}
|
|
328
|
+
// when node at cursorPos is reached:
|
|
329
|
+
// save currentLine, currentTsTreeNode and filter if necessary
|
|
330
|
+
// if there is a reference or copy operator ('<' or '=<')
|
|
331
|
+
// return the treeNode of the path right to the operator,
|
|
332
|
+
// else try to build a path from the whole line
|
|
333
|
+
if (!stack.lastElementEquals('/*') && !stack.lastElementEquals('(') && !ignoreLine) {
|
|
334
|
+
const i = line.indexOf('<');
|
|
335
|
+
if (i !== -1) {
|
|
336
|
+
path = line.substring(i + 1, line.length).trim();
|
|
337
|
+
if (prefixes.length > 0 && path.substr(0, 1) === '.') {
|
|
338
|
+
path = prefixes.join('.') + path;
|
|
339
|
+
}
|
|
340
|
+
} else {
|
|
341
|
+
path = line;
|
|
342
|
+
if (prefixes.length > 0) {
|
|
343
|
+
path = prefixes.join('.') + '.' + path;
|
|
344
|
+
path = path.replace(/\s/g, '');
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
const lastDot = path.lastIndexOf('.');
|
|
348
|
+
path = path.substring(0, lastDot);
|
|
349
|
+
}
|
|
350
|
+
return this.getTreeNode(path);
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
/**
|
|
354
|
+
* Iterates through the object tree, and creates treenodes
|
|
355
|
+
* along the path, if necessary
|
|
356
|
+
*/
|
|
357
|
+
public getTreeNode(path: string): TreeNode | undefined {
|
|
358
|
+
path = path.trim();
|
|
359
|
+
if (path.length === 0) {
|
|
360
|
+
return this.tsTree;
|
|
361
|
+
}
|
|
362
|
+
const aPath = path.split('.');
|
|
363
|
+
|
|
364
|
+
let subTree = this.tsTree.childNodes,
|
|
365
|
+
pathSeg,
|
|
366
|
+
parent = this.tsTree;
|
|
367
|
+
|
|
368
|
+
// step through the path from left to right
|
|
369
|
+
for (let i = 0; i < aPath.length; i++) {
|
|
370
|
+
pathSeg = aPath[i];
|
|
371
|
+
|
|
372
|
+
// if there isn't already a treenode
|
|
373
|
+
if (typeof subTree[pathSeg] === 'undefined' || typeof subTree[pathSeg].childNodes === 'undefined') { // if this subpath is not defined in the code
|
|
374
|
+
// create a new treenode
|
|
375
|
+
subTree[pathSeg] = new TreeNode(pathSeg, this);
|
|
376
|
+
subTree[pathSeg].parent = parent;
|
|
377
|
+
// the extPath has to be set, so the TreeNode can retrieve the respecting node in the external templates
|
|
378
|
+
let extPath = parent.extPath;
|
|
379
|
+
if (extPath) {
|
|
380
|
+
extPath += '.';
|
|
381
|
+
}
|
|
382
|
+
extPath += pathSeg;
|
|
383
|
+
subTree[pathSeg].extPath = extPath;
|
|
384
|
+
}
|
|
385
|
+
if (i === aPath.length - 1) {
|
|
386
|
+
return subTree[pathSeg];
|
|
387
|
+
}
|
|
388
|
+
parent = subTree[pathSeg];
|
|
389
|
+
subTree = subTree[pathSeg].childNodes;
|
|
390
|
+
}
|
|
391
|
+
return undefined;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
/**
|
|
395
|
+
* Navigates to the respecting treenode,
|
|
396
|
+
* create nodes in the path, if necessary, and sets the value
|
|
397
|
+
*/
|
|
398
|
+
public setTreeNodeValue(path: string, value: string): void {
|
|
399
|
+
const treeNode = this.getTreeNode(path);
|
|
400
|
+
// if we are inside a GIFBUILDER Object
|
|
401
|
+
if (treeNode.parent !== null && treeNode.parent.value === 'GIFBUILDER' && value === 'TEXT') {
|
|
402
|
+
value = 'GB_TEXT';
|
|
403
|
+
}
|
|
404
|
+
if (treeNode.parent !== null && treeNode.parent.value === 'GIFBUILDER' && value === 'IMAGE') {
|
|
405
|
+
value = 'GB_IMAGE';
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
// just override if it is a real objecttype
|
|
409
|
+
if (this.tsRef.isType(value)) {
|
|
410
|
+
treeNode.value = value;
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
/**
|
|
415
|
+
* Navigates to the respecting treenode,
|
|
416
|
+
* creates nodes if necessary, empties the value and childNodes-Array
|
|
417
|
+
*/
|
|
418
|
+
public deleteTreeNodeValue(path: string) {
|
|
419
|
+
const treeNode = this.getTreeNode(path);
|
|
420
|
+
// currently the node is not deleted really, it's just not displayed cause value == null
|
|
421
|
+
// deleting it would be a cleaner solution
|
|
422
|
+
treeNode.value = null;
|
|
423
|
+
treeNode.childNodes = {};
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
/**
|
|
427
|
+
* Copies a reference of the treeNode specified by path2
|
|
428
|
+
* to the location specified by path1
|
|
429
|
+
*/
|
|
430
|
+
public setReference(path1: string, path2: string): void {
|
|
431
|
+
const path1arr = path1.split('.'),
|
|
432
|
+
lastNodeName = path1arr[path1arr.length - 1],
|
|
433
|
+
treeNode1 = this.getTreeNode(path1),
|
|
434
|
+
treeNode2 = this.getTreeNode(path2);
|
|
435
|
+
|
|
436
|
+
if (treeNode1.parent !== null) {
|
|
437
|
+
treeNode1.parent.childNodes[lastNodeName] = treeNode2;
|
|
438
|
+
} else {
|
|
439
|
+
this.tsTree.childNodes[lastNodeName] = treeNode2;
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
/**
|
|
444
|
+
* copies a treeNode specified by path2
|
|
445
|
+
* to the location specified by path1
|
|
446
|
+
*/
|
|
447
|
+
public setCopy(path1: string, path2: string): void {
|
|
448
|
+
this.clone = <T extends object | unknown>(myObj: T): T => {
|
|
449
|
+
if (typeof myObj !== 'object') {
|
|
450
|
+
return myObj;
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
const myNewObj: Record<string, unknown> = {};
|
|
454
|
+
for (const i in myObj) {
|
|
455
|
+
if (i === 'tsParser') {
|
|
456
|
+
continue;
|
|
457
|
+
}
|
|
458
|
+
// disable recursive cloning for parent object -> copy by reference
|
|
459
|
+
if (i !== 'parent') {
|
|
460
|
+
if (typeof myObj[i] === 'object') {
|
|
461
|
+
myNewObj[i] = this.clone(myObj[i]);
|
|
462
|
+
} else {
|
|
463
|
+
myNewObj[i] = myObj[i];
|
|
464
|
+
}
|
|
465
|
+
} else {
|
|
466
|
+
if ('parent' in myObj) {
|
|
467
|
+
myNewObj.parent = myObj.parent;
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
return myNewObj as T;
|
|
472
|
+
};
|
|
473
|
+
|
|
474
|
+
const path1arr = path1.split('.'),
|
|
475
|
+
lastNodeName = path1arr[path1arr.length - 1],
|
|
476
|
+
treeNode1 = this.getTreeNode(path1),
|
|
477
|
+
treeNode2 = this.getTreeNode(path2);
|
|
478
|
+
|
|
479
|
+
if (treeNode1.parent !== null) {
|
|
480
|
+
treeNode1.parent.childNodes[lastNodeName] = this.clone(treeNode2);
|
|
481
|
+
} else {
|
|
482
|
+
this.tsTree.childNodes[lastNodeName] = this.clone(treeNode2);
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This file is part of the TYPO3 CMS project.
|
|
3
|
+
*
|
|
4
|
+
* It is free software; you can redistribute it and/or modify it under
|
|
5
|
+
* the terms of the GNU General Public License, either version 2
|
|
6
|
+
* of the License, or any later version.
|
|
7
|
+
*
|
|
8
|
+
* For the full copyright and license information, please read the
|
|
9
|
+
* LICENSE.txt file that was distributed with this source code.
|
|
10
|
+
*
|
|
11
|
+
* The TYPO3 project - inspiring people to share!
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import AjaxRequest from '@typo3/core/ajax/ajax-request';
|
|
15
|
+
|
|
16
|
+
type TypeId = string;
|
|
17
|
+
|
|
18
|
+
type PropertyName = string;
|
|
19
|
+
|
|
20
|
+
type PlainDocData = Record<TypeId, {
|
|
21
|
+
extends: TypeId,
|
|
22
|
+
name: TypeId,
|
|
23
|
+
properties: Record<PropertyName, {
|
|
24
|
+
name: PropertyName,
|
|
25
|
+
type: string
|
|
26
|
+
}>,
|
|
27
|
+
}>;
|
|
28
|
+
|
|
29
|
+
export class TsRefType {
|
|
30
|
+
public readonly typeId: TypeId;
|
|
31
|
+
public extends: TypeId;
|
|
32
|
+
public properties: Record<PropertyName, TsRefProperty> & { clone?: () => void } = {};
|
|
33
|
+
|
|
34
|
+
constructor(
|
|
35
|
+
typeId: string,
|
|
36
|
+
extendsTypeId: string | null,
|
|
37
|
+
properties: Record<PropertyName, TsRefProperty>
|
|
38
|
+
) {
|
|
39
|
+
this.typeId = typeId;
|
|
40
|
+
this.extends = extendsTypeId;
|
|
41
|
+
this.properties = properties;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export class TsRefProperty {
|
|
46
|
+
public readonly parentType: string;
|
|
47
|
+
public readonly name: PropertyName;
|
|
48
|
+
public readonly value: string;
|
|
49
|
+
|
|
50
|
+
constructor(parentType: string, name: string, value: string) {
|
|
51
|
+
this.parentType = parentType;
|
|
52
|
+
this.name = name;
|
|
53
|
+
this.value = value;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export class TsRef {
|
|
58
|
+
public typeTree: Record<TypeId, TsRefType> = {};
|
|
59
|
+
public doc: PlainDocData = null;
|
|
60
|
+
public cssClass: string;
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Load available TypoScript reference
|
|
64
|
+
*/
|
|
65
|
+
public async loadTsrefAsync(): Promise<void> {
|
|
66
|
+
const response = await new AjaxRequest(TYPO3.settings.ajaxUrls.codeeditor_tsref).get();
|
|
67
|
+
this.doc = await response.resolve();
|
|
68
|
+
this.buildTree();
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Build the TypoScript reference tree
|
|
73
|
+
*/
|
|
74
|
+
public buildTree(): void {
|
|
75
|
+
for (const typeId of Object.keys(this.doc)) {
|
|
76
|
+
const arr = this.doc[typeId];
|
|
77
|
+
this.typeTree[typeId] = new TsRefType(
|
|
78
|
+
typeId,
|
|
79
|
+
arr.extends || undefined,
|
|
80
|
+
Object.fromEntries(
|
|
81
|
+
Object.entries(arr.properties).map(
|
|
82
|
+
([propName, property]) => [propName, new TsRefProperty(typeId, propName, property.type)]
|
|
83
|
+
)
|
|
84
|
+
)
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
for (const typeId of Object.keys(this.typeTree)) {
|
|
88
|
+
if (typeof this.typeTree[typeId].extends !== 'undefined') {
|
|
89
|
+
this.addPropertiesToType(this.typeTree[typeId], this.typeTree[typeId].extends, 100);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Adds properties to TypoScript types
|
|
96
|
+
*/
|
|
97
|
+
public addPropertiesToType(
|
|
98
|
+
addToType: TsRefType,
|
|
99
|
+
addFromTypeNames: string,
|
|
100
|
+
maxRecDepth: number
|
|
101
|
+
): void {
|
|
102
|
+
if (maxRecDepth < 0) {
|
|
103
|
+
throw 'Maximum recursion depth exceeded while trying to resolve the extends in the TSREF!';
|
|
104
|
+
}
|
|
105
|
+
const exts = addFromTypeNames.split(',');
|
|
106
|
+
for (let i = 0; i < exts.length; i++) {
|
|
107
|
+
// "Type 'array' which is used to extend 'undefined', was not found in the TSREF!"
|
|
108
|
+
if (typeof this.typeTree[exts[i]] !== 'undefined') {
|
|
109
|
+
if (typeof this.typeTree[exts[i]].extends !== 'undefined') {
|
|
110
|
+
this.addPropertiesToType(this.typeTree[exts[i]], this.typeTree[exts[i]].extends, maxRecDepth - 1);
|
|
111
|
+
}
|
|
112
|
+
const properties = this.typeTree[exts[i]].properties;
|
|
113
|
+
for (const propName in properties) {
|
|
114
|
+
// only add this property if it was not already added by a supertype (subtypes override supertypes)
|
|
115
|
+
if (typeof addToType.properties[propName] === 'undefined') {
|
|
116
|
+
addToType.properties[propName] = properties[propName];
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Get properties from given TypoScript type id
|
|
125
|
+
*/
|
|
126
|
+
public getPropertiesFromTypeId(tId: TypeId): Record<PropertyName, TsRefProperty> {
|
|
127
|
+
if (typeof this.typeTree[tId] !== 'undefined') {
|
|
128
|
+
// clone is needed to assure that nothing of the tsref is overwritten by user setup
|
|
129
|
+
this.typeTree[tId].properties.clone = function() {
|
|
130
|
+
const result = {} as Record<PropertyName, TsRefProperty>;
|
|
131
|
+
for (const key of Object.keys(this)) {
|
|
132
|
+
result[key] = new TsRefProperty(this[key].parentType, this[key].name, this[key].value);
|
|
133
|
+
}
|
|
134
|
+
return result;
|
|
135
|
+
};
|
|
136
|
+
return this.typeTree[tId].properties;
|
|
137
|
+
}
|
|
138
|
+
return {};
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Check if a property of a type exists
|
|
143
|
+
*/
|
|
144
|
+
public typeHasProperty(typeId: TypeId, propertyName: PropertyName): boolean {
|
|
145
|
+
return (
|
|
146
|
+
typeof this.typeTree[typeId] !== 'undefined' &&
|
|
147
|
+
typeof this.typeTree[typeId].properties[propertyName] !== 'undefined'
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Get the type
|
|
153
|
+
*/
|
|
154
|
+
public getType(typeId: TypeId): TsRefType {
|
|
155
|
+
return this.typeTree[typeId];
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Check if type exists in the type tree
|
|
160
|
+
*/
|
|
161
|
+
public isType(typeId: TypeId): boolean {
|
|
162
|
+
return typeof this.typeTree[typeId] !== 'undefined';
|
|
163
|
+
}
|
|
164
|
+
}
|