typo3-typescript-sources 13.4.36 → 13.4.39

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.
@@ -2,212 +2,222 @@ name: Sync TYPO3 TypeScript Sources and Publish
2
2
 
3
3
  on:
4
4
  schedule:
5
- # Check daily at 2 AM for new tags
5
+ # Check daily at 2 AM for new tags and new commits on TYPO3 main
6
6
  - cron: '0 2 * * *'
7
7
  workflow_dispatch:
8
8
  inputs:
9
+ target:
10
+ description: 'Branch to sync'
11
+ type: choice
12
+ options:
13
+ - all
14
+ - main
15
+ - v14.x
16
+ - v13.x
17
+ default: all
9
18
  tag:
10
- description: 'Specific TYPO3 tag (e.g. v14.0.0 or v13.4.0)'
19
+ description: 'Specific TYPO3 tag for a tagged branch (e.g. v14.3.8); ignored for main'
11
20
  required: false
12
21
  type: string
13
22
 
14
23
  permissions:
15
24
  contents: read
16
25
 
26
+ env:
27
+ PACKAGE_NAME: typo3-typescript-sources
28
+ UPSTREAM_REPO: https://github.com/TYPO3/typo3.git
29
+
17
30
  jobs:
18
31
  setup:
19
32
  runs-on: ubuntu-latest
20
33
  outputs:
21
34
  matrix: ${{ steps.set-matrix.outputs.matrix }}
22
35
  steps:
23
- - name: Build version matrix
36
+ - name: Build branch matrix
24
37
  id: set-matrix
38
+ env:
39
+ TARGET: ${{ inputs.target || 'all' }}
25
40
  run: |
26
- if [[ "${{ github.event_name }}" == "schedule" ]]; then
27
- # Schedule runs daily for both major versions
28
- echo 'matrix={"include":[{"major_version":"14","target_branch":"main"},{"major_version":"13","target_branch":"v13.x"}]}' >> $GITHUB_OUTPUT
29
- elif [[ "${{ github.ref_name }}" == "v13.x" ]]; then
30
- echo 'matrix={"include":[{"major_version":"13","target_branch":"v13.x"}]}' >> $GITHUB_OUTPUT
31
- else
32
- echo 'matrix={"include":[{"major_version":"14","target_branch":"main"}]}' >> $GITHUB_OUTPUT
33
- fi
34
-
35
- check-and-sync:
41
+ # mode "head": follow an upstream branch, no git tag, no npm release
42
+ # mode "tag": follow the newest upstream vMAJOR.x.y tag, tag + publish
43
+ BRANCHES='[
44
+ {"target_branch":"main","mode":"head","source_ref":"main","major":"","npm_tag":""},
45
+ {"target_branch":"v14.x","mode":"tag","source_ref":"","major":"14","npm_tag":"latest"},
46
+ {"target_branch":"v13.x","mode":"tag","source_ref":"","major":"13","npm_tag":"v13-latest"}
47
+ ]'
48
+ MATRIX=$(jq -c --arg t "$TARGET" '{include: [.[] | select($t == "all" or .target_branch == $t)]}' <<< "$BRANCHES")
49
+ echo "matrix=$MATRIX" >> "$GITHUB_OUTPUT"
50
+
51
+ sync:
36
52
  needs: setup
37
53
  runs-on: ubuntu-latest
54
+ permissions:
55
+ contents: read
56
+ id-token: write
57
+ concurrency:
58
+ group: sync-${{ matrix.target_branch }}
59
+ cancel-in-progress: false
38
60
  strategy:
39
61
  fail-fast: false
40
62
  matrix: ${{ fromJson(needs.setup.outputs.matrix) }}
63
+ env:
64
+ TARGET_BRANCH: ${{ matrix.target_branch }}
65
+ MODE: ${{ matrix.mode }}
66
+ MAJOR: ${{ matrix.major }}
67
+ NPM_TAG: ${{ matrix.npm_tag }}
41
68
  steps:
42
69
  - name: Checkout split repository
43
- uses: actions/checkout@v4
70
+ uses: actions/checkout@v6
44
71
  with:
45
72
  ref: ${{ matrix.target_branch }}
73
+ token: ${{ secrets.PAT_TOKEN }}
46
74
  fetch-depth: 0
47
75
 
48
- - name: Check for new TYPO3 tags
76
+ - name: Setup Git
77
+ run: |
78
+ git config --global user.name "TYPO3 TypeScript Sync Bot"
79
+ git config --global user.email "bot@maikschneider.de"
80
+
81
+ - name: Check upstream for changes
49
82
  id: check
83
+ env:
84
+ SOURCE_BRANCH: ${{ matrix.source_ref }}
85
+ MANUAL_TAG: ${{ inputs.tag }}
50
86
  run: |
51
- MAJOR="${{ matrix.major_version }}"
52
-
53
- # Fetch all tags from TYPO3 repository for the target major version
54
- git ls-remote --tags https://github.com/TYPO3/typo3.git | \
55
- grep -E "refs/tags/v${MAJOR}\.[0-9]+\.[0-9]+$" | \
56
- sed 's/.*refs\/tags\///' | \
57
- sort -V > /tmp/typo3_tags.txt
58
-
59
- # Get last synced tag
60
- LAST_SYNCED=""
61
- if [ -f .last-synced-tag ]; then
62
- LAST_SYNCED=$(cat .last-synced-tag)
87
+ if [ "$MODE" = "head" ]; then
88
+ UPSTREAM_SHA=$(git ls-remote "$UPSTREAM_REPO" "refs/heads/${SOURCE_BRANCH}" | cut -f1)
89
+ if [ -z "$UPSTREAM_SHA" ]; then
90
+ echo "Error: upstream branch ${SOURCE_BRANCH} not found"
91
+ exit 1
92
+ fi
93
+
94
+ LAST_SYNCED=$(cat .last-synced-commit 2>/dev/null || true)
95
+ if [ "$UPSTREAM_SHA" = "$LAST_SYNCED" ]; then
96
+ echo "No new commits on ${SOURCE_BRANCH} (current: $LAST_SYNCED)"
97
+ echo "has_changes=false" >> "$GITHUB_OUTPUT"
98
+ else
99
+ echo "New commit on ${SOURCE_BRANCH}: $UPSTREAM_SHA (previous: ${LAST_SYNCED:-none})"
100
+ echo "has_changes=true" >> "$GITHUB_OUTPUT"
101
+ echo "source_ref=${SOURCE_BRANCH}" >> "$GITHUB_OUTPUT"
102
+ fi
103
+ exit 0
63
104
  fi
64
105
 
65
- # Manual tag input takes priority
66
- if [ -n "${{ github.event.inputs.tag }}" ]; then
67
- NEW_TAG="${{ github.event.inputs.tag }}"
68
- # Validate that the manual tag matches the expected major version
69
- if ! echo "$NEW_TAG" | grep -qE "^v${MAJOR}\."; then
70
- echo "Error: Tag $NEW_TAG does not match expected major version v${MAJOR}.x for this branch"
71
- echo "has_new_version=false" >> $GITHUB_OUTPUT
106
+ if [ -n "$MANUAL_TAG" ]; then
107
+ if ! echo "$MANUAL_TAG" | grep -qE "^v${MAJOR}\.[0-9]+\.[0-9]+$"; then
108
+ echo "Tag $MANUAL_TAG does not belong to ${TARGET_BRANCH} (v${MAJOR}.x), skipping sync"
109
+ echo "has_changes=false" >> "$GITHUB_OUTPUT"
72
110
  exit 0
73
111
  fi
112
+ NEW_TAG="$MANUAL_TAG"
74
113
  echo "Manually specified tag: $NEW_TAG"
75
114
  else
76
- # Find newest tag that has not been synced yet
77
- NEW_TAG=$(tail -n1 /tmp/typo3_tags.txt)
115
+ NEW_TAG=$(git ls-remote --tags "$UPSTREAM_REPO" | \
116
+ grep -E "refs/tags/v${MAJOR}\.[0-9]+\.[0-9]+$" | \
117
+ sed 's/.*refs\/tags\///' | \
118
+ sort -V | tail -n1)
78
119
  fi
79
120
 
80
121
  if [ -z "$NEW_TAG" ]; then
81
122
  echo "No TYPO3 v${MAJOR}.x tag found"
82
- echo "has_new_version=false" >> $GITHUB_OUTPUT
123
+ echo "has_changes=false" >> "$GITHUB_OUTPUT"
83
124
  exit 0
84
125
  fi
85
126
 
127
+ LAST_SYNCED=$(cat .last-synced-tag 2>/dev/null || true)
86
128
  if [ "$NEW_TAG" = "$LAST_SYNCED" ]; then
87
129
  echo "No new version available (current: $LAST_SYNCED)"
88
- echo "has_new_version=false" >> $GITHUB_OUTPUT
130
+ echo "has_changes=false" >> "$GITHUB_OUTPUT"
89
131
  else
90
- echo "New version found: $NEW_TAG (previous: $LAST_SYNCED)"
91
- echo "has_new_version=true" >> $GITHUB_OUTPUT
92
- echo "typo3_version=$NEW_TAG" >> $GITHUB_OUTPUT
132
+ echo "New version found: $NEW_TAG (previous: ${LAST_SYNCED:-none})"
133
+ echo "has_changes=true" >> "$GITHUB_OUTPUT"
134
+ echo "source_ref=${NEW_TAG}" >> "$GITHUB_OUTPUT"
93
135
  fi
94
136
 
95
- - name: Setup Git
96
- if: steps.check.outputs.has_new_version == 'true'
137
+ - name: Clone TYPO3 repository
138
+ if: steps.check.outputs.has_changes == 'true'
139
+ env:
140
+ SOURCE_REF: ${{ steps.check.outputs.source_ref }}
97
141
  run: |
98
- git config --global user.name "TYPO3 TypeScript Sync Bot"
99
- git config --global user.email "bot@maikschneider.de"
142
+ git clone --depth 1 --branch "$SOURCE_REF" "$UPSTREAM_REPO" "$RUNNER_TEMP/typo3-source"
143
+ if [ ! -d "$RUNNER_TEMP/typo3-source/Build/Sources/TypeScript" ]; then
144
+ echo "✗ Error: Build/Sources/TypeScript not found"
145
+ exit 1
146
+ fi
100
147
 
101
- - name: Clone TYPO3 repository at specific tag
102
- if: steps.check.outputs.has_new_version == 'true'
148
+ - name: Sync content to split repository
149
+ if: steps.check.outputs.has_changes == 'true'
150
+ id: sync
151
+ env:
152
+ SOURCE_REF: ${{ steps.check.outputs.source_ref }}
103
153
  run: |
104
- TYPO3_TAG="${{ steps.check.outputs.typo3_version }}"
105
- echo "Cloning TYPO3 repository at tag: $TYPO3_TAG"
154
+ SRC="$RUNNER_TEMP/typo3-source"
106
155
 
107
- git clone --depth 1 --branch "$TYPO3_TAG" \
108
- https://github.com/TYPO3/typo3.git typo3-source
156
+ find . -mindepth 1 -maxdepth 1 ! -name '.git' ! -name '.github' -exec rm -rf {} +
109
157
 
110
- - name: Extract TypeScript sources
111
- if: steps.check.outputs.has_new_version == 'true'
112
- run: |
113
- mkdir -p typescript-split
158
+ cp -r "$SRC/Build/Sources/TypeScript/." .
159
+ [ -f "$SRC/LICENSE.txt" ] && cp "$SRC/LICENSE.txt" .
160
+ [ -f "$SRC/README.md" ] && cp "$SRC/README.md" README-TYPO3.md
114
161
 
115
- # Copy TypeScript sources
116
- if [ -d "typo3-source/Build/Sources/TypeScript" ]; then
117
- cp -r typo3-source/Build/Sources/TypeScript/* typescript-split/
118
- echo "✓ TypeScript sources extracted"
162
+ if [ "$MODE" = "head" ]; then
163
+ SOURCE_SHA=$(git -C "$SRC" rev-parse HEAD)
164
+ VERSION=$(sed -n "s/.*const VERSION = '\(.*\)';/\1/p" "$SRC/typo3/sysext/core/Classes/Information/Typo3Version.php")
165
+ if [ -z "$VERSION" ]; then
166
+ echo "Error: could not read version from Typo3Version.php"
167
+ exit 1
168
+ fi
169
+ echo "$SOURCE_SHA" > .last-synced-commit
170
+ echo "version_label=${SOURCE_REF}@${SOURCE_SHA:0:12} (${VERSION})" >> "$GITHUB_OUTPUT"
171
+ echo "source_tree=${SOURCE_SHA}" >> "$GITHUB_OUTPUT"
119
172
  else
120
- echo "✗ Error: Build/Sources/TypeScript not found"
121
- exit 1
173
+ VERSION="${SOURCE_REF#v}"
174
+ echo "$SOURCE_REF" > .last-synced-tag
175
+ echo "version_label=${SOURCE_REF}" >> "$GITHUB_OUTPUT"
176
+ echo "source_tree=${SOURCE_REF}" >> "$GITHUB_OUTPUT"
122
177
  fi
123
178
 
124
- # Copy relevant root files
125
- [ -f "typo3-source/LICENSE.txt" ] && cp typo3-source/LICENSE.txt typescript-split/
126
- [ -f "typo3-source/README.md" ] && cp typo3-source/README.md typescript-split/README-TYPO3.md
127
-
128
- - name: Checkout split repository for sync
129
- if: steps.check.outputs.has_new_version == 'true'
130
- uses: actions/checkout@v4
131
- with:
132
- path: split-repo
133
- ref: ${{ matrix.target_branch }}
134
- token: ${{ secrets.PAT_TOKEN }}
135
- fetch-depth: 0
179
+ echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
136
180
 
137
- - name: Sync content to split repository
138
- if: steps.check.outputs.has_new_version == 'true'
139
- run: |
140
- # Delete old contents (except .git, .github, package.json)
141
- cd split-repo
142
- find . -mindepth 1 -maxdepth 1 \
143
- ! -name '.git' \
144
- ! -name '.github' \
145
- ! -name 'package.json' \
146
- ! -name 'package-lock.json' \
147
- ! -name '.last-synced-tag' \
148
- ! -name 'README.md' \
149
- ! -name 'node_modules' \
150
- -exec rm -rf {} +
151
-
152
- # Copy new contents
153
- cp -r ../typescript-split/* .
154
-
155
- # Save synced tag
156
- echo "${{ steps.check.outputs.typo3_version }}" > .last-synced-tag
157
-
158
- - name: Create/Update package.json
159
- if: steps.check.outputs.has_new_version == 'true'
160
- working-directory: split-repo
181
+ - name: Create package.json
182
+ if: steps.check.outputs.has_changes == 'true'
183
+ env:
184
+ VERSION: ${{ steps.sync.outputs.version }}
185
+ SOURCE_TREE: ${{ steps.sync.outputs.source_tree }}
161
186
  run: |
162
- TYPO3_VERSION="${{ steps.check.outputs.typo3_version }}"
163
- # Remove 'v' prefix for npm version
164
- NPM_VERSION="${TYPO3_VERSION#v}"
165
-
166
- cat > package.json << EOF
167
- {
168
- "name": "typo3-typescript-sources",
169
- "version": "${NPM_VERSION}",
170
- "description": "TYPO3 Core TypeScript Sources - Extracted from TYPO3/typo3 repository",
171
- "main": "index.js",
172
- "types": "index.d.ts",
173
- "scripts": {
174
- "test": "echo \"No tests specified\""
175
- },
176
- "repository": {
177
- "type": "git",
178
- "url": "git+https://github.com/maikschneider/typo3-typescript-sources.git"
179
- },
180
- "keywords": [
181
- "typo3",
182
- "typescript",
183
- "sources",
184
- "cms"
185
- ],
186
- "author": "TYPO3 Core Team",
187
- "license": "GPL-2.0-or-later",
188
- "bugs": {
189
- "url": "https://github.com/maikschneider/typo3-typescript-sources/issues"
190
- },
191
- "homepage": "https://github.com/maikschneider/typo3-typescript-sources#readme",
192
- "publishConfig": {
193
- "access": "public"
194
- },
195
- "typo3": {
196
- "sourceRepository": "https://github.com/TYPO3/typo3",
197
- "sourceTag": "${TYPO3_VERSION}",
198
- "sourcePath": "Build/Sources/TypeScript"
199
- }
200
- }
201
- EOF
202
-
203
- echo "✓ package.json created with version $NPM_VERSION"
187
+ # main is installed from git only; "private" guards against an accidental npm publish
188
+ jq -n \
189
+ --arg name "$PACKAGE_NAME" \
190
+ --arg version "$VERSION" \
191
+ --arg source "$SOURCE_TREE" \
192
+ --argjson private "$([ "$MODE" = "head" ] && echo true || echo false)" \
193
+ '{
194
+ name: $name,
195
+ version: $version,
196
+ description: "TYPO3 Core TypeScript Sources - Extracted from TYPO3/typo3 repository",
197
+ main: "index.js",
198
+ types: "index.d.ts",
199
+ scripts: { test: "echo \"No tests specified\"" },
200
+ repository: { type: "git", url: "git+https://github.com/maikschneider/typo3-typescript-sources.git" },
201
+ keywords: ["typo3", "typescript", "sources", "cms"],
202
+ author: "TYPO3 Core Team",
203
+ license: "GPL-2.0-or-later",
204
+ bugs: { url: "https://github.com/maikschneider/typo3-typescript-sources/issues" },
205
+ homepage: "https://github.com/maikschneider/typo3-typescript-sources#readme",
206
+ publishConfig: { access: "public" },
207
+ typo3: {
208
+ sourceRepository: "https://github.com/TYPO3/typo3",
209
+ sourceTag: $source,
210
+ sourcePath: "Build/Sources/TypeScript"
211
+ }
212
+ } + (if $private then { private: true } else {} end)' > package.json
213
+
214
+ echo "✓ package.json created with version $VERSION"
204
215
 
205
216
  - name: Create README
206
- if: steps.check.outputs.has_new_version == 'true'
207
- working-directory: split-repo
217
+ if: steps.check.outputs.has_changes == 'true'
218
+ env:
219
+ VERSION_LABEL: ${{ steps.sync.outputs.version_label }}
208
220
  run: |
209
- TYPO3_VERSION="${{ steps.check.outputs.typo3_version }}"
210
-
211
221
  cat > README.md << 'EOF'
212
222
  # TYPO3 TypeScript Sources
213
223
 
@@ -220,7 +230,14 @@ jobs:
220
230
  ## 📦 Installation
221
231
 
222
232
  ```bash
233
+ # Current LTS (v14)
223
234
  npm install typo3-typescript-sources
235
+
236
+ # v13
237
+ npm install typo3-typescript-sources@v13-latest
238
+
239
+ # TYPO3 main (development, not published to npm)
240
+ npm install github:maikschneider/typo3-typescript-sources#main
224
241
  ```
225
242
 
226
243
  ## 🔍 Source
@@ -231,10 +248,11 @@ jobs:
231
248
 
232
249
  ## 🌿 Branches
233
250
 
234
- | Branch | TYPO3 Version | npm tag |
235
- |----------|---------------|-----------|
236
- | `main` | v14.x | `latest` |
237
- | `v13.x` | v13.x | `v13-latest` |
251
+ | Branch | TYPO3 Source | npm tag |
252
+ |----------|----------------------|--------------|
253
+ | `main` | `main` (every commit) | – |
254
+ | `v14.x` | v14.x releases | `latest` |
255
+ | `v13.x` | v13.x releases | `v13-latest` |
238
256
 
239
257
  ## 📝 License
240
258
 
@@ -250,68 +268,99 @@ jobs:
250
268
  For official TYPO3 packages, please refer to the [TYPO3 Core repository](https://github.com/TYPO3/typo3).
251
269
  EOF
252
270
 
253
- # Replace placeholder
254
- sed -i "s/TYPO3_VERSION_PLACEHOLDER/${TYPO3_VERSION}/" README.md
271
+ sed -i "s|TYPO3_VERSION_PLACEHOLDER|${VERSION_LABEL}|" README.md
255
272
 
256
273
  - name: Commit changes
257
- if: steps.check.outputs.has_new_version == 'true'
258
- working-directory: split-repo
274
+ if: steps.check.outputs.has_changes == 'true'
275
+ id: commit
276
+ env:
277
+ VERSION: ${{ steps.sync.outputs.version }}
278
+ VERSION_LABEL: ${{ steps.sync.outputs.version_label }}
279
+ SOURCE_TREE: ${{ steps.sync.outputs.source_tree }}
259
280
  run: |
260
- TARGET_BRANCH="${{ matrix.target_branch }}"
261
- git add .
281
+ git add -A
262
282
 
263
283
  if git diff --staged --quiet; then
264
284
  echo "No changes to commit"
285
+ echo "committed=false" >> "$GITHUB_OUTPUT"
265
286
  exit 0
266
287
  fi
267
288
 
268
- TYPO3_VERSION="${{ steps.check.outputs.typo3_version }}"
269
- git commit -m "Sync with TYPO3 ${TYPO3_VERSION}
270
-
271
- Source: https://github.com/TYPO3/typo3/tree/${TYPO3_VERSION}
289
+ git commit -m "Sync with TYPO3 ${VERSION_LABEL}" \
290
+ -m "Source: https://github.com/TYPO3/typo3/tree/${SOURCE_TREE}
272
291
  Path: Build/Sources/TypeScript/"
273
292
 
274
- # Create tag (remove v-prefix)
275
- NPM_VERSION="${TYPO3_VERSION#v}"
276
- git tag -a "${NPM_VERSION}" -m "Release ${NPM_VERSION} from TYPO3 ${TYPO3_VERSION}"
293
+ if [ "$MODE" = "tag" ]; then
294
+ git tag -a "${VERSION}" -m "Release ${VERSION} from TYPO3 ${VERSION_LABEL}"
295
+ fi
277
296
 
278
- git push origin "${TARGET_BRANCH}"
279
- git push origin "${NPM_VERSION}"
297
+ echo "committed=true" >> "$GITHUB_OUTPUT"
280
298
 
281
299
  - name: Setup Node.js
282
- if: steps.check.outputs.has_new_version == 'true'
283
- uses: actions/setup-node@v4
300
+ if: matrix.mode == 'tag'
301
+ uses: actions/setup-node@v6
284
302
  with:
285
- node-version: '20'
286
- registry-url: 'https://registry.npmjs.org'
303
+ node-version: '24'
287
304
 
288
- - name: Publish to npm
289
- if: steps.check.outputs.has_new_version == 'true'
290
- working-directory: split-repo
305
+ - name: Publish unpublished versions to npm
306
+ if: matrix.mode == 'tag'
307
+ id: publish
291
308
  run: |
292
- echo "//registry.npmjs.org/:_authToken=${NODE_AUTH_TOKEN}" > ~/.npmrc
309
+ # Trusted publishing (OIDC) needs npm >= 11.5.1
310
+ npm install -g npm@^11.5.1
293
311
 
294
- MAJOR="${{ matrix.major_version }}"
295
- if [ "$MAJOR" = "13" ]; then
296
- npm publish --access public --tag v13-latest
297
- else
298
- npm publish --access public
299
- fi
312
+ PUBLISHED=$(npm view "$PACKAGE_NAME" versions --json 2>/dev/null || echo '[]')
313
+
314
+ # Ascending order, so the dist-tag ends on the newest version
315
+ PUBLISHED_NOW=""
316
+ for VERSION in $(git tag -l | grep -E "^${MAJOR}\.[0-9]+\.[0-9]+$" | sort -V); do
317
+ if jq -e --arg v "$VERSION" '[.] | flatten | index($v) != null' <<< "$PUBLISHED" > /dev/null; then
318
+ continue
319
+ fi
320
+
321
+ echo "Publishing ${VERSION} with dist-tag ${NPM_TAG}"
322
+ DIR="$RUNNER_TEMP/publish-${VERSION}"
323
+ git worktree add --detach "$DIR" "$VERSION"
324
+ (cd "$DIR" && npm publish --access public --tag "$NPM_TAG")
325
+ git worktree remove --force "$DIR"
326
+ PUBLISHED_NOW="${PUBLISHED_NOW} ${VERSION}"
327
+ done
328
+
329
+ echo "versions=${PUBLISHED_NOW# }" >> "$GITHUB_OUTPUT"
330
+
331
+ - name: Push changes
332
+ if: steps.commit.outputs.committed == 'true'
300
333
  env:
301
- NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
334
+ VERSION: ${{ steps.sync.outputs.version }}
335
+ run: |
336
+ git push origin "HEAD:${TARGET_BRANCH}"
337
+ if [ "$MODE" = "tag" ]; then
338
+ git push origin "refs/tags/${VERSION}"
339
+ fi
302
340
 
303
- - name: Create GitHub Release
304
- if: steps.check.outputs.has_new_version == 'true'
305
- uses: actions/create-release@v1
341
+ - name: Create GitHub releases
342
+ if: matrix.mode == 'tag' && steps.publish.outputs.versions != ''
306
343
  env:
307
- GITHUB_TOKEN: ${{ secrets.PAT_TOKEN }}
308
- with:
309
- tag_name: ${{ steps.check.outputs.typo3_version }}
310
- release_name: TYPO3 ${{ steps.check.outputs.typo3_version }}
311
- body: |
312
- Synchronized with TYPO3 Core ${{ steps.check.outputs.typo3_version }}
313
-
314
- **Source:** https://github.com/TYPO3/typo3/tree/${{ steps.check.outputs.typo3_version }}
315
- **Path:** `Build/Sources/TypeScript/`
316
- draft: false
317
- prerelease: false
344
+ GH_TOKEN: ${{ secrets.PAT_TOKEN }}
345
+ VERSIONS: ${{ steps.publish.outputs.versions }}
346
+ run: |
347
+ NEWEST=$(tr ' ' '\n' <<< "$VERSIONS" | sort -V | tail -n1)
348
+ for VERSION in $VERSIONS; do
349
+ if gh release view "$VERSION" > /dev/null 2>&1; then
350
+ continue
351
+ fi
352
+
353
+ LATEST=false
354
+ if [ "$NPM_TAG" = "latest" ] && [ "$VERSION" = "$NEWEST" ]; then
355
+ LATEST=true
356
+ fi
357
+
358
+ gh release create "$VERSION" \
359
+ --verify-tag \
360
+ --title "TYPO3 ${VERSION}" \
361
+ --latest="$LATEST" \
362
+ --notes "Synchronized with TYPO3 Core v${VERSION}
363
+
364
+ **Source:** https://github.com/TYPO3/typo3/tree/v${VERSION}
365
+ **Path:** \`Build/Sources/TypeScript/\`"
366
+ done
package/.last-synced-tag CHANGED
@@ -1 +1 @@
1
- v13.4.36
1
+ v13.4.39
package/README.md CHANGED
@@ -9,21 +9,29 @@ This repository contains the TypeScript sources from the TYPO3 Core, automatical
9
9
  ## 📦 Installation
10
10
 
11
11
  ```bash
12
+ # Current LTS (v14)
12
13
  npm install typo3-typescript-sources
14
+
15
+ # v13
16
+ npm install typo3-typescript-sources@v13-latest
17
+
18
+ # TYPO3 main (development, not published to npm)
19
+ npm install github:maikschneider/typo3-typescript-sources#main
13
20
  ```
14
21
 
15
22
  ## 🔍 Source
16
23
 
17
24
  - **Original Repository:** [TYPO3/typo3](https://github.com/TYPO3/typo3)
18
25
  - **Source Path:** `Build/Sources/TypeScript/`
19
- - **Current TYPO3 Version:** `v13.4.36`
26
+ - **Current TYPO3 Version:** `v13.4.39`
20
27
 
21
28
  ## 🌿 Branches
22
29
 
23
- | Branch | TYPO3 Version | npm tag |
24
- |----------|---------------|-----------|
25
- | `main` | v14.x | `latest` |
26
- | `v13.x` | v13.x | `v13-latest` |
30
+ | Branch | TYPO3 Source | npm tag |
31
+ |----------|----------------------|--------------|
32
+ | `main` | `main` (every commit) | – |
33
+ | `v14.x` | v14.x releases | `latest` |
34
+ | `v13.x` | v13.x releases | `v13-latest` |
27
35
 
28
36
  ## 📝 License
29
37
 
@@ -0,0 +1,82 @@
1
+ import DragDropUtility from '@typo3/backend/utility/drag-drop-utility.js';
2
+ import { expect } from '@open-wc/testing';
3
+ import { stub, type SinonStub } from 'sinon';
4
+ import type { } from 'mocha';
5
+
6
+ type DragEventState = {
7
+ dropEffect: DataTransfer['dropEffect'],
8
+ effectAllowed?: DataTransfer['effectAllowed'],
9
+ ctrlKey?: boolean,
10
+ altKey?: boolean,
11
+ };
12
+
13
+ function createDragEvent(state: DragEventState): DragEvent {
14
+ return {
15
+ ctrlKey: state.ctrlKey ?? false,
16
+ altKey: state.altKey ?? false,
17
+ dataTransfer: {
18
+ dropEffect: state.dropEffect,
19
+ effectAllowed: state.effectAllowed ?? 'copyMove',
20
+ },
21
+ } as unknown as DragEvent;
22
+ }
23
+
24
+ describe('@typo3/backend/utility/drag-drop-utility', () => {
25
+ let userAgentStub: SinonStub;
26
+
27
+ afterEach(() => {
28
+ userAgentStub?.restore();
29
+ });
30
+
31
+ function emulatePlatform(userAgent: string): void {
32
+ userAgentStub = stub(navigator, 'userAgent').get(() => userAgent);
33
+ }
34
+
35
+ describe('on Windows', () => {
36
+ beforeEach(() => {
37
+ emulatePlatform('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/156.0.0.0 Safari/537.36');
38
+ });
39
+
40
+ it('detects a copy intention when Ctrl is held although the browser preset dropEffect to "move"', () => {
41
+ const event = createDragEvent({ dropEffect: 'move', ctrlKey: true });
42
+ expect(DragDropUtility.isCopyModifierFromEvent(event)).to.equal(true);
43
+ });
44
+
45
+ it('detects a move intention without modifier', () => {
46
+ const event = createDragEvent({ dropEffect: 'move' });
47
+ expect(DragDropUtility.isCopyModifierFromEvent(event)).to.equal(false);
48
+ });
49
+
50
+ it('keeps the copy intention propagated by dropEffect', () => {
51
+ const event = createDragEvent({ dropEffect: 'copy' });
52
+ expect(DragDropUtility.isCopyModifierFromEvent(event)).to.equal(true);
53
+ });
54
+
55
+ it('reflects the copy intention in dropEffect', () => {
56
+ const event = createDragEvent({ dropEffect: 'move', ctrlKey: true });
57
+ DragDropUtility.updateEventAndTooltipToReflectCopyMoveIntention(event);
58
+ expect(event.dataTransfer.dropEffect).to.equal('copy');
59
+ });
60
+ });
61
+
62
+ describe('on macOS', () => {
63
+ beforeEach(() => {
64
+ emulatePlatform('Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/156.0.0.0 Safari/537.36');
65
+ });
66
+
67
+ it('detects a copy intention when Option is held although the browser preset dropEffect to "move"', () => {
68
+ const event = createDragEvent({ dropEffect: 'move', altKey: true });
69
+ expect(DragDropUtility.isCopyModifierFromEvent(event)).to.equal(true);
70
+ });
71
+
72
+ it('detects a copy intention when the platform restricted the operation to copy', () => {
73
+ const event = createDragEvent({ dropEffect: 'none', effectAllowed: 'copy' });
74
+ expect(DragDropUtility.isCopyModifierFromEvent(event)).to.equal(true);
75
+ });
76
+
77
+ it('ignores Ctrl', () => {
78
+ const event = createDragEvent({ dropEffect: 'move', ctrlKey: true });
79
+ expect(DragDropUtility.isCopyModifierFromEvent(event)).to.equal(false);
80
+ });
81
+ });
82
+ });
@@ -20,17 +20,13 @@ import type { DragTooltipMetadata } from '@typo3/backend/drag-tooltip';
20
20
  */
21
21
  export default class DragDropUtility {
22
22
  public static isCopyModifierFromEvent(event: DragEvent): boolean {
23
- if (event.dataTransfer.dropEffect === 'copy') {
24
- return true;
25
- }
26
-
27
- if (event.dataTransfer.dropEffect === 'move') {
28
- return false;
29
- }
30
-
31
- return navigator.userAgent.includes('Mac')
23
+ // Browsers may preset dropEffect to "move" regardless of pressed modifiers
24
+ // (e.g. Chrome on Windows), therefore the modifier takes precedence.
25
+ const isCopyModifierPressed = navigator.userAgent.includes('Mac')
32
26
  ? (event.dataTransfer.effectAllowed === 'copy' || event.altKey)
33
27
  : event.ctrlKey;
28
+
29
+ return isCopyModifierPressed || event.dataTransfer.dropEffect === 'copy';
34
30
  }
35
31
 
36
32
  public static updateEventAndTooltipToReflectCopyMoveIntention(event: DragEvent): void {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "typo3-typescript-sources",
3
- "version": "13.4.36",
3
+ "version": "13.4.39",
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.36",
31
+ "sourceTag": "v13.4.39",
32
32
  "sourcePath": "Build/Sources/TypeScript"
33
33
  }
34
34
  }