typo3-typescript-sources 13.4.20 → 13.4.21

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.
@@ -178,6 +178,10 @@ jobs:
178
178
  cat > README.md << 'EOF'
179
179
  # TYPO3 TypeScript Sources
180
180
 
181
+ [![Sync and Publish](https://github.com/maikschneider/typo3-typescript-sources/actions/workflows/sync-and-publish.yml/badge.svg)](https://github.com/maikschneider/typo3-typescript-sources/actions/workflows/sync-and-publish.yml)
182
+ [![npm version](https://badge.fury.io/js/typo3-typescript-sources.svg)](https://www.npmjs.com/package/typo3-typescript-sources)
183
+ [![License: GPL v2](https://img.shields.io/badge/License-GPL%20v2-blue.svg)](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html)
184
+
181
185
  This repository contains the TypeScript sources from the TYPO3 Core, automatically extracted and published to npm.
182
186
 
183
187
  ## 📦 Installation
@@ -225,12 +229,12 @@ jobs:
225
229
  Source: https://github.com/TYPO3/typo3/tree/${TYPO3_VERSION}
226
230
  Path: Build/Sources/TypeScript/"
227
231
 
228
- # Erstelle Tag
232
+ # Erstelle Tag (entferne v-Prefix falls vorhanden)
229
233
  NPM_VERSION="${TYPO3_VERSION#v}"
230
- git tag -a "v${NPM_VERSION}" -m "Release ${NPM_VERSION} from TYPO3 ${TYPO3_VERSION}"
234
+ git tag -a "${NPM_VERSION}" -m "Release ${NPM_VERSION} from TYPO3 ${TYPO3_VERSION}"
231
235
 
232
236
  git push origin main
233
- git push origin "v${NPM_VERSION}"
237
+ git push origin "${NPM_VERSION}"
234
238
 
235
239
  - name: Setup Node.js
236
240
  uses: actions/setup-node@v4
@@ -254,7 +258,7 @@ jobs:
254
258
  env:
255
259
  GITHUB_TOKEN: ${{ secrets.PAT_TOKEN }}
256
260
  with:
257
- tag_name: v${{ needs.check-and-sync.outputs.typo3_version }}
261
+ tag_name: ${{ needs.check-and-sync.outputs.typo3_version }}
258
262
  release_name: TYPO3 ${{ needs.check-and-sync.outputs.typo3_version }}
259
263
  body: |
260
264
  Synchronized with TYPO3 Core ${{ needs.check-and-sync.outputs.typo3_version }}
package/.last-synced-tag CHANGED
@@ -1 +1 @@
1
- v13.4.20
1
+ v13.4.21
package/README.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # TYPO3 TypeScript Sources
2
2
 
3
+ [![Sync and Publish](https://github.com/maikschneider/typo3-typescript-sources/actions/workflows/sync-and-publish.yml/badge.svg)](https://github.com/maikschneider/typo3-typescript-sources/actions/workflows/sync-and-publish.yml)
4
+ [![npm version](https://badge.fury.io/js/typo3-typescript-sources.svg)](https://www.npmjs.com/package/typo3-typescript-sources)
5
+ [![License: GPL v2](https://img.shields.io/badge/License-GPL%20v2-blue.svg)](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html)
6
+
3
7
  This repository contains the TypeScript sources from the TYPO3 Core, automatically extracted and published to npm.
4
8
 
5
9
  ## 📦 Installation
@@ -12,7 +16,7 @@ npm install typo3-typescript-sources
12
16
 
13
17
  - **Original Repository:** [TYPO3/typo3](https://github.com/TYPO3/typo3)
14
18
  - **Source Path:** `Build/Sources/TypeScript/`
15
- - **Current TYPO3 Version:** `v13.4.20`
19
+ - **Current TYPO3 Version:** `v13.4.21`
16
20
 
17
21
  ## 📝 License
18
22
 
@@ -185,6 +185,8 @@ class DateTimePicker {
185
185
  // collides with using altInput – sigh.
186
186
  self.altInput.id = self.input.id;
187
187
  self.input.removeAttribute('id');
188
+ // Disable browser autofill to prevent interference with the datepicker
189
+ self.altInput.setAttribute('autocomplete', 'off');
188
190
  self.altInput.clearable();
189
191
  if (self.input.dataset.formengineInputName !== undefined) {
190
192
  self.altInput.dataset.formengineDatepickerRealInputName = self.input.dataset.formengineInputName;
@@ -196,6 +198,13 @@ class DateTimePicker {
196
198
  self.altInput.classList.toggle('has-error', !e.detail.isValid);
197
199
  }
198
200
  });
201
+
202
+ // Move the hidden input (self.input) to right after the clearable wrapper
203
+ // This prevents it from affecting :first-child CSS selectors while maintaining proper DOM order
204
+ const wrapper = self.altInput.closest('.form-control-clearable-wrapper');
205
+ if (wrapper !== null) {
206
+ wrapper.insertAdjacentElement('afterend', self.input);
207
+ }
199
208
  }
200
209
  },
201
210
  onChange: (dates: Date[], currentDateString: string, self: flatpickr.Instance): void => {
@@ -72,9 +72,13 @@ export default (function() {
72
72
  const attributeValues = LinkBrowser.getLinkAttributeValues();
73
73
  // encode link on server
74
74
  attributeValues.url = input;
75
+ const searchParams = new URLSearchParams();
76
+ for (const [key, value] of Object.entries(attributeValues)) {
77
+ searchParams.set(key, value);
78
+ }
75
79
 
76
80
  (new AjaxRequest(TYPO3.settings.ajaxUrls.link_browser_encodetypolink))
77
- .withQueryArguments(attributeValues)
81
+ .withQueryArguments(searchParams)
78
82
  .get()
79
83
  .then(async (response: AjaxResponse): Promise<void> => {
80
84
  const data: Response = await response.resolve();
@@ -1117,22 +1117,26 @@ export class Tree extends LitElement {
1117
1117
 
1118
1118
  protected createNodeContentLabel(node: TreeNodeInterface): TemplateResult
1119
1119
  {
1120
- let label = (node.prefix || '') + node.name + (node.suffix || '');
1121
- // make a text node out of it, and strip out any HTML (this is because the return value uses html()
1122
- // instead of text() which is needed to avoid XSS in a page title
1123
- const labelNode = document.createElement('div');
1124
- labelNode.textContent = label;
1125
- label = labelNode.innerHTML;
1120
+ const label = (node.prefix || '') + node.name + (node.suffix || '');
1121
+
1122
+ let nodeContent: Array<TemplateResult|string> | string = label;
1126
1123
  if (this.searchTerm) {
1127
1124
  // Escape all meta characters of regular expressions: ( ) [ ] $ * + ? . { } / | ^ -
1128
- const regexp = new RegExp(this.searchTerm.replace(/[/\-\\^$*+?.()|[\]{}]/g, '\\$&'), 'gi');
1129
- label = label.replace(regexp, '<span class="node-highlight-text">$&</span>');
1125
+ // Also wrap the search term in a capture group so the regex split retains the separator
1126
+ const regexp = new RegExp(`(${this.searchTerm.replace(/[/\-\\^$*+?.()|[\]{}]/g, '\\$&')})`, 'gi');
1127
+ const parts = label.split(regexp);
1128
+ if (parts.length > 1) {
1129
+ // grouped regex splits contain the match in every second spot, to keep things short we use a modulo-flip with the index
1130
+ nodeContent = parts.map((part, index): TemplateResult | string =>
1131
+ (index % 2 === 1) ? html`<span class="node-highlight-text">${part}</span>` : part
1132
+ );
1133
+ }
1130
1134
  }
1131
1135
 
1132
1136
  return html`
1133
1137
  <div class="node-contentlabel">
1134
- <div class="node-name" .innerHTML="${label}"></div>
1135
- ${node.note ? html`<div class="node-note">${node.note}</div>` : nothing }
1138
+ <div class="node-name">${nodeContent}</div>
1139
+ ${node.note ? html`<div class="node-note">${node.note}</div>` : nothing}
1136
1140
  </div>`;
1137
1141
  }
1138
1142
 
@@ -279,6 +279,7 @@ export class ExtensionMatrixElement extends LitElement {
279
279
  <button class="btn btn-default" title=${tooltip}
280
280
  @click=${() => this.dispatchEvent(new CustomEvent<DownloadPacksEvent>('download-packs', eventData))}>
281
281
  <typo3-backend-icon identifier="actions-download" size="small"></typo3-backend-icon>
282
+ ${language}
282
283
  </button>
283
284
  </td>
284
285
  `;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "typo3-typescript-sources",
3
- "version": "13.4.20",
3
+ "version": "13.4.21",
4
4
  "description": "TYPO3 Core TypeScript Sources - Extracted from TYPO3/typo3 repository",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -28,7 +28,7 @@
28
28
  },
29
29
  "typo3": {
30
30
  "sourceRepository": "https://github.com/TYPO3/typo3",
31
- "sourceTag": "v13.4.20",
31
+ "sourceTag": "v13.4.21",
32
32
  "sourcePath": "Build/Sources/TypeScript"
33
33
  }
34
34
  }
@@ -254,6 +254,7 @@ export class Typo3UnlinkCommand extends Core.Command {
254
254
  writer.removeAttribute('linkTarget', range);
255
255
  writer.removeAttribute('linkTitle', range);
256
256
  writer.removeAttribute('linkRel', range);
257
+ writer.removeAttribute('linkDataRteError', range);
257
258
  }
258
259
  });
259
260
  }
@@ -570,10 +571,14 @@ export class Typo3LinkUI extends Core.Plugin {
570
571
  }
571
572
 
572
573
  private showUI(): void {
573
- if (!this.getSelectedLinkElement()) {
574
+ const selectedLink = this.getSelectedLinkElement();
575
+ if (!selectedLink) {
574
576
  this.showFakeVisualSelection();
575
577
  this.openLinkBrowser(this.editor);
576
578
  } else {
579
+ // When clicking inside a link, check if we need to expand selection to full link
580
+ // This prevents link splitting when editing with partial selection
581
+ this.expandSelectionToFullLink();
577
582
  this.addToolbarView();
578
583
  this.balloon.showStack('main');
579
584
  }
@@ -735,11 +740,43 @@ export class Typo3LinkUI extends Core.Plugin {
735
740
  return position.getAncestors().find((ancestor: any) => LinkUtils.isLinkElement(ancestor));
736
741
  }
737
742
 
743
+ /**
744
+ * Expands the current selection to encompass the entire link element.
745
+ * This prevents link splitting when editing a link with partial text selection.
746
+ */
747
+ private expandSelectionToFullLink(): void {
748
+ const model = this.editor.model;
749
+ const selection = model.document.selection;
750
+
751
+ // Only expand if we have a link attribute in the selection
752
+ if (!selection.hasAttribute('linkHref')) {
753
+ return;
754
+ }
755
+
756
+ const linkHref = selection.getAttribute('linkHref') as string;
757
+ if (!linkHref) {
758
+ return;
759
+ }
760
+
761
+ model.change(writer => {
762
+ const position = selection.getFirstPosition();
763
+ // Find the full range of the link using the linkHref attribute
764
+ const linkRange = Typing.findAttributeRange(position, 'linkHref', linkHref, model);
765
+
766
+ if (linkRange) {
767
+ // Expand selection to cover the entire link
768
+ writer.setSelection(linkRange);
769
+ }
770
+ });
771
+ }
772
+
738
773
  private openLinkBrowser(editor: Core.Editor): void {
739
774
  const linkCommand = editor.commands.get('link') as unknown as Typo3LinkCommand;
740
775
  let additionalParameters = '';
741
776
 
777
+ // If editing an existing link, expand selection to full link first
742
778
  if (linkCommand.value) {
779
+ this.expandSelectionToFullLink();
743
780
  additionalParameters += '&P[curUrl][url]=' + encodeURIComponent(linkCommand.value);
744
781
  for (const [attr, value] of Object.entries(linkCommand.attrs)) {
745
782
  additionalParameters += '&P[curUrl][' + encodeURIComponent(attr) + ']=' + encodeURIComponent(value);
@@ -40,6 +40,7 @@ enum Identifiers {
40
40
  * buttons, preview mode selector, preview slider and so on.
41
41
  */
42
42
  class Preview extends Workspaces {
43
+ override ajaxRoute: string = 'workspace_preview';
43
44
  private currentSlidePosition: number = 100;
44
45
  private readonly elements: { [key: string]: HTMLElement } = {};
45
46
 
@@ -19,6 +19,8 @@ import { default as Modal, type ModalElement } from '@typo3/backend/modal';
19
19
  import { html } from 'lit';
20
20
 
21
21
  export default class Workspaces {
22
+ protected readonly ajaxRoute: string = 'workspace_dispatch';
23
+
22
24
  /**
23
25
  * Renders the send to stage window
24
26
  * @param {Object} response
@@ -70,7 +72,7 @@ export default class Workspaces {
70
72
  protected sendRemoteRequest(payload: object, progressContainer: string = '#workspace-content-wrapper'): Promise<AjaxResponse> {
71
73
  NProgress.configure({ parent: progressContainer, showSpinner: false });
72
74
  NProgress.start();
73
- return (new AjaxRequest(TYPO3.settings.ajaxUrls.workspace_dispatch)).post(
75
+ return (new AjaxRequest(TYPO3.settings.ajaxUrls[this.ajaxRoute])).post(
74
76
  payload,
75
77
  {
76
78
  headers: {