cornhsu-polymigrate 2.3.1 → 3.0.0
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/README.md +49 -16
- package/THIRD-PARTY-NOTICES.md +298 -40
- package/bin/polymigrate.js +29 -12
- package/package.json +7 -7
package/README.md
CHANGED
|
@@ -3,27 +3,39 @@
|
|
|
3
3
|
[](https://www.nuget.org/packages/Cornhsu.PolyMigrate)
|
|
4
4
|
[](https://www.nuget.org/packages/Cornhsu.PolyMigrate)
|
|
5
5
|
[](https://github.com/HSU-YU-MING/cornhsu-polymigrate/actions/workflows/ci.yml)
|
|
6
|
-
[](LICENSE)
|
|
6
|
+
[](https://github.com/HSU-YU-MING/cornhsu-polymigrate/blob/main/LICENSE)
|
|
7
7
|
|
|
8
8
|
> **The i18n-first static-site migrator** — the only site migrator that pairs your multilingual pages automatically.
|
|
9
9
|
|
|
10
|
-
**[Project write-up](https://cornhsu.com/polymigrate) · [NuGet](https://www.nuget.org/packages/Cornhsu.PolyMigrate) · [繁體中文說明](README.zh-Hant.md) · MIT**
|
|
10
|
+
**[Project write-up](https://cornhsu.com/polymigrate) · [NuGet](https://www.nuget.org/packages/Cornhsu.PolyMigrate) · [繁體中文說明](https://github.com/HSU-YU-MING/cornhsu-polymigrate/blob/main/README.zh-Hant.md) · MIT**
|
|
11
11
|
|
|
12
12
|
PolyMigrate turns legacy dynamic sites (old PHP sites and the like) into clean, static-site-ready
|
|
13
13
|
Markdown — and it treats multilingual content as a first-class concern, not an afterthought.
|
|
14
14
|
Config-driven, fully offline-rerunnable, built on .NET.
|
|
15
15
|
|
|
16
|
-
**Status:
|
|
16
|
+
**Status: 3.0.** The extraction pipeline, pairing, verification, thumbnails and orphan-page
|
|
17
17
|
recovery are complete and validated against a real full-site migration (see below). The **CLI
|
|
18
|
-
surface
|
|
19
|
-
the minor version, fixes bump the patch
|
|
18
|
+
surface, exit codes, Phase output contracts and YAML config are frozen within a major version**:
|
|
19
|
+
new features bump the minor version, fixes bump the patch, and anything that changes one of those
|
|
20
|
+
four surfaces waits for a major. **3.0 is such a release** — it changes exit codes in a few cases
|
|
21
|
+
so they follow the 0 / 1 / 2 / 130 contract (an orphan probe that got no usable answer, a failed
|
|
22
|
+
npm launcher and an interrupted command no longer look like success), gives each section its own
|
|
23
|
+
orphan slug list (`orphan_slugs.<section>.txt`), keeps animated GIF/WebP thumbnails animated, and
|
|
24
|
+
adds probe/fetch entry points and cancellable overloads to the library. Config fields, CSV columns
|
|
25
|
+
and frontmatter fields are unchanged, but a config with an invalid value (a CSS selector, a regex, a
|
|
26
|
+
path that isn't a single segment, a malformed URL or language tag, a key left without a value…) is now
|
|
27
|
+
rejected when it is loaded, by every command, instead of when some page or command happens to use it, and a probe in
|
|
28
|
+
which only some candidates got no answer exits 1 (the list is written, but may be incomplete).
|
|
29
|
+
**Read the 3.0 upgrade checklist in the CHANGELOG before upgrading**.
|
|
30
|
+
Earlier history: 2.0 was an engineering release — it narrowed the
|
|
20
31
|
`Cornhsu.PolyMigrate.Core` public .NET API to its intended entry points and removed unused
|
|
21
|
-
config fields; 2.1 fixed up the release pipeline (arm64 npm packages, symbol packages)
|
|
32
|
+
config fields; 2.1 fixed up the release pipeline (arm64 npm packages, symbol packages) — though
|
|
33
|
+
the npm launcher could only start the Windows/Linux arm64 builds from 2.3.1 on.
|
|
22
34
|
2.2 closed a blind spot in `verify` — pages nothing links to were reported as fine, because a
|
|
23
35
|
link-following audit never reaches them — and added `slugs` for keeping up with a source site
|
|
24
36
|
that is still being updated. **Upgrading to 2.2 can turn a passing `verify` into exit 1**.
|
|
25
37
|
2.3 reads the source site's own `hreflang` declarations (see below) and reports them in a new
|
|
26
|
-
`hreflang_map.csv`. See the [CHANGELOG](CHANGELOG.md) for the migration notes.
|
|
38
|
+
`hreflang_map.csv`. See the [CHANGELOG](https://github.com/HSU-YU-MING/cornhsu-polymigrate/blob/main/CHANGELOG.md) for the migration notes.
|
|
27
39
|
|
|
28
40
|
## Why
|
|
29
41
|
|
|
@@ -62,6 +74,8 @@ A declaration is only used for pairing if it:
|
|
|
62
74
|
- resolves to a page actually in your mirror — **same host included**, since plenty of sites put
|
|
63
75
|
the English version on `en.example.org`, where a path-only comparison would make a page its
|
|
64
76
|
own translation,
|
|
77
|
+
- has a content page at both ends — neither end is a site-level page (a language picker and the
|
|
78
|
+
like, which isn't anyone's translation),
|
|
65
79
|
- and **isn't one of many same-language pages claiming the same target**. This is the classic
|
|
66
80
|
failure: one `<link>` pasted into the site-wide template, so every Chinese page declares the
|
|
67
81
|
English homepage as its English version. One page cannot be the translation of three others,
|
|
@@ -74,7 +88,7 @@ Everything declared — including the rejected ones — is written to `hreflang_
|
|
|
74
88
|
Pairs are still only ever *suggested*: `hreflang` raises the evidence quality, it does not
|
|
75
89
|
switch the tool into merging pages on its own. That is a deliberate call, not an unfinished
|
|
76
90
|
one — the measurement behind it, and what would have to change to revisit it, are recorded in
|
|
77
|
-
[docs/hreflang_量測與決策.md](docs/hreflang_
|
|
91
|
+
[docs/hreflang_量測與決策.md](https://github.com/HSU-YU-MING/cornhsu-polymigrate/blob/main/docs/hreflang_%E9%87%8F%E6%B8%AC%E8%88%87%E6%B1%BA%E7%AD%96.md).
|
|
78
92
|
|
|
79
93
|
## Battle-tested defaults
|
|
80
94
|
|
|
@@ -123,7 +137,7 @@ Two channels — pick whichever runtime you already have. **Same tool, same beha
|
|
|
123
137
|
|
|
124
138
|
```
|
|
125
139
|
npx cornhsu-polymigrate extract site.yaml # Node — no .NET install needed
|
|
126
|
-
dotnet tool install -g Cornhsu.PolyMigrate # .NET
|
|
140
|
+
dotnet tool install -g Cornhsu.PolyMigrate # .NET 10
|
|
127
141
|
```
|
|
128
142
|
|
|
129
143
|
> The npm build ships a self-contained native binary and only downloads the one
|
|
@@ -134,13 +148,24 @@ dotnet tool install -g Cornhsu.PolyMigrate # .NET
|
|
|
134
148
|
```
|
|
135
149
|
dotnet tool install -g Cornhsu.PolyMigrate
|
|
136
150
|
polymigrate extract site.yaml # mirror HTML -> frontmatter Markdown + inventories
|
|
137
|
-
polymigrate verify
|
|
151
|
+
polymigrate verify . # link/media/frontmatter/unlinked-page audit, CI exit codes
|
|
138
152
|
polymigrate thumbs site.yaml # EXIF-corrected, width-capped thumbnails
|
|
139
|
-
polymigrate probe-orphans site.yaml --section news --years 2021-2023
|
|
140
|
-
polymigrate fetch-orphans site.yaml --section news
|
|
153
|
+
polymigrate probe-orphans site.yaml --section news --years 2021-2023 # -> orphan_slugs.news.txt
|
|
154
|
+
polymigrate fetch-orphans site.yaml --section news # reads orphan_slugs.news.txt
|
|
141
155
|
polymigrate slugs . --section news # slugs already mirrored under ./raw (pipeable)
|
|
142
156
|
```
|
|
143
157
|
|
|
158
|
+
> **Animated GIF/WebP thumbnails keep every frame — within limits.** Scaling an animation frame by
|
|
159
|
+
> frame costs memory and time in proportion to frames × width × height (measured: a 400-frame
|
|
160
|
+
> 1300×900 GIF took 39 s and 3.2 GB). So an animation over **50 megapixels** in total, or one whose
|
|
161
|
+
> animated thumbnail would be larger than the original, gets a first-frame thumbnail instead — the
|
|
162
|
+
> same result as before 3.0 (an animation that needs no scaling is copied as-is instead). At the limit it takes about 6 s and a 250–400 MB memory peak, depending on the content
|
|
163
|
+
> (two 100-frame 1000×500 GIFs measured 250 MB and 384 MB). The `thumbs` summary lists
|
|
164
|
+
> which files got a first frame and why; neither case is a failure or changes the exit code.
|
|
165
|
+
> Still images get a limit too: one over **179 megapixels** (Pillow's decompression-bomb threshold —
|
|
166
|
+
> a 270 KB GIF can declare 20000×20000, and decoding it took 14.8 s and 1.6 GB) is not decoded at all and
|
|
167
|
+
> counts as a failed thumbnail (exit 1). 100-megapixel camera originals are well within it.
|
|
168
|
+
|
|
144
169
|
> **`raw/` is the one thing you cannot regenerate.** Re-crawling a site takes hours at a
|
|
145
170
|
> polite request rate, and the source site may be switched off the moment you finish
|
|
146
171
|
> migrating — at which point your mirror is the only copy left. No PolyMigrate command
|
|
@@ -148,10 +173,10 @@ polymigrate slugs . --section news # slugs already mirrored under ./raw
|
|
|
148
173
|
> off, and back them up if the source is going away.
|
|
149
174
|
|
|
150
175
|
> No .NET? Every command above also runs with **zero install** via npm — just prefix it:
|
|
151
|
-
> `npx cornhsu-polymigrate extract site.yaml`, `npx cornhsu-polymigrate verify
|
|
176
|
+
> `npx cornhsu-polymigrate extract site.yaml`, `npx cornhsu-polymigrate verify .`, and so on.
|
|
152
177
|
|
|
153
178
|
One YAML config per site describes everything site-specific — see
|
|
154
|
-
[examples/ibps-austin.yaml](examples/ibps-austin.yaml) for a fully-annotated real example.
|
|
179
|
+
[examples/ibps-austin.yaml](https://github.com/HSU-YU-MING/cornhsu-polymigrate/blob/main/examples/ibps-austin.yaml) for a fully-annotated real example.
|
|
155
180
|
|
|
156
181
|
```yaml
|
|
157
182
|
config_version: 1
|
|
@@ -185,8 +210,16 @@ if (report.HasErrors) { /* unsafe paths were skipped; see path_issues.csv */ }
|
|
|
185
210
|
|
|
186
211
|
var verify = PolyMigrator.Verify("out/"); // no config needed; reads Phase 2 output only
|
|
187
212
|
Console.WriteLine($"{verify.Errors} errors, {verify.Warnings} warnings");
|
|
213
|
+
|
|
214
|
+
// Orphan pages (probe-orphans / fetch-orphans). Nothing is written until you decide to.
|
|
215
|
+
var probe = await migrator.ProbeOrphansAsync("out/", "news", 2021, 2023);
|
|
216
|
+
if (probe.NoUsableAnswers) { /* the site never answered: an empty list means nothing */ }
|
|
217
|
+
else { await migrator.FetchOrphansAsync("out/", "news", probe.Found); }
|
|
188
218
|
```
|
|
189
219
|
|
|
220
|
+
Extract, Verify and GenerateThumbnails also have overloads that take a `CancellationToken`
|
|
221
|
+
(the probe/fetch methods take one as their last parameter).
|
|
222
|
+
|
|
190
223
|
## Layout
|
|
191
224
|
|
|
192
225
|
| Path | Contents |
|
|
@@ -214,9 +247,9 @@ signals in priority order, why "just read `hreflang`" often misses on real legac
|
|
|
214
247
|
(measured on one: 528 pages, **0** declarations, sitemap 404), the five gates a declaration has to
|
|
215
248
|
pass before it is usable at all, and why URL string similarity is the wrong tool for this job.
|
|
216
249
|
|
|
217
|
-
License: [MIT](LICENSE). All dependencies are MIT/BSD/Apache-2.0
|
|
250
|
+
License: [MIT](https://github.com/HSU-YU-MING/cornhsu-polymigrate/blob/main/LICENSE). All dependencies are MIT/BSD/Apache-2.0
|
|
218
251
|
(imaging via **Magick.NET**; ImageSharp was dropped when its 4.x line began requiring a
|
|
219
|
-
license key at build time). See [THIRD-PARTY-NOTICES](THIRD-PARTY-NOTICES.md).
|
|
252
|
+
license key at build time). See [THIRD-PARTY-NOTICES](https://github.com/HSU-YU-MING/cornhsu-polymigrate/blob/main/THIRD-PARTY-NOTICES.md).
|
|
220
253
|
|
|
221
254
|
PolyMigrate fetches pages from the site you point it at, and can be configured to send
|
|
222
255
|
cookies past a bot challenge. **It assumes the site is yours, or that you are migrating
|
package/THIRD-PARTY-NOTICES.md
CHANGED
|
@@ -1,49 +1,307 @@
|
|
|
1
1
|
# Third-party notices
|
|
2
2
|
|
|
3
3
|
PolyMigrate itself is licensed under the [MIT License](LICENSE). It builds on the
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
third-party components below. All of their licences are compatible with MIT, and none
|
|
5
|
+
of them are copyleft. The full licence texts are at the end of this file.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
## What each channel ships
|
|
8
|
+
|
|
9
|
+
Whether a channel redistributes a component — and so has to carry its notices — depends
|
|
10
|
+
on how it is packaged:
|
|
11
|
+
|
|
12
|
+
| Channel | What is inside | Notices shipped with it |
|
|
8
13
|
|---|---|---|
|
|
9
|
-
|
|
|
10
|
-
|
|
|
11
|
-
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
14
|
+
| **`Cornhsu.PolyMigrate`** — .NET tool on NuGet | `PackAsTool` puts the whole publish output into the package (`tools/net10.0/any/`): every dependency DLL **and** Magick.NET's native libraries for all platforms (`runtimes/*/native/Magick.Native-Q8-*`, which contain ImageMagick). The tool package itself is a redistribution of all of them. | `NOTICE.txt` (Magick.NET's `Notice.txt`, verbatim) and this file, at the package root |
|
|
15
|
+
| **`Cornhsu.PolyMigrate.Core`** — library on NuGet | `PolyMigrate.Core.dll` only. Its dependencies are declared, not bundled: NuGet resolves them on the consumer's side, and each package carries its own licence. | Nothing further is required |
|
|
16
|
+
| **npm** — `cornhsu-polymigrate` and `@cornhsu/polymigrate-<os>-<cpu>` | Each platform package is a self-contained executable: every dependency DLL, the `Magick.Native-Q8-*` for that platform, **and the .NET runtime**. The main package holds only the launcher script. | Platform packages: `NOTICE.txt`, this file and `LICENSE`. Main package: this file and `LICENSE` |
|
|
17
|
+
|
|
18
|
+
## Components
|
|
19
|
+
|
|
20
|
+
| Component | Licence | Copyright | Project | Shipped in |
|
|
21
|
+
|---|---|---|---|---|
|
|
22
|
+
| AngleSharp | MIT | Copyright (c) 2013 - 2026 AngleSharp | https://anglesharp.github.io/ | tool, npm |
|
|
23
|
+
| ReverseMarkdown | MIT | Copyright (c) 2015 Babu Annamalai | https://github.com/mysticmind/reversemarkdown-net | tool, npm |
|
|
24
|
+
| YamlDotNet | MIT | Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014 Antoine Aubry and contributors | https://github.com/aaubry/YamlDotNet | tool, npm |
|
|
25
|
+
| Magick.NET (`Magick.NET-Q8-AnyCPU`, `Magick.NET.Core` and the native `Magick.Native-Q8-*`) | Apache-2.0 | Copyright 2013-2026 Dirk Lemstra | https://github.com/dlemstra/Magick.NET | tool, npm |
|
|
26
|
+
| ImageMagick and the libraries built into `Magick.Native-Q8-*` | ImageMagick License; each bundled library under its own licence | ImageMagick Studio LLC and the respective authors — see `NOTICE.txt` | https://imagemagick.org/ | tool, npm |
|
|
27
|
+
| .NET runtime | MIT | Copyright (c) .NET Foundation and Contributors | https://github.com/dotnet/runtime | npm only |
|
|
28
|
+
|
|
29
|
+
The copyright lines are taken from each project's own licence file (Magick.NET: its package
|
|
30
|
+
metadata) at the versions this release resolves: AngleSharp 1.7.2, ReverseMarkdown 6.2.1,
|
|
31
|
+
YamlDotNet 18.1.0, Magick.NET 14.16.0. The exact versions inside a given package are listed
|
|
32
|
+
in its `polymigrate.deps.json`.
|
|
33
|
+
|
|
34
|
+
The .NET runtime contains third-party code of its own; its notices are at
|
|
35
|
+
https://github.com/dotnet/runtime/blob/main/THIRD-PARTY-NOTICES.TXT.
|
|
36
|
+
|
|
37
|
+
## Magick.NET and ImageMagick: `NOTICE.txt`
|
|
38
|
+
|
|
39
|
+
Magick.NET is Apache-2.0 and its package includes a `Notice.txt`, so section 4(d) of the
|
|
40
|
+
Apache License applies: whoever redistributes it must pass that notice on. The file also
|
|
41
|
+
reproduces the ImageMagick License and the licence of every library built into the native
|
|
42
|
+
binaries, for the exact ImageMagick version of that Magick.NET release — which is why the
|
|
43
|
+
packages ship the file itself, not a summary of it.
|
|
44
|
+
|
|
45
|
+
**This is automated, not a checklist item.** Both channels that redistribute Magick.NET
|
|
46
|
+
resolve the Magick.NET version that was actually restored, read `Notice.txt` from the NuGet
|
|
47
|
+
cache, and ship it as `NOTICE.txt` — **and fail if they cannot find it**:
|
|
48
|
+
|
|
49
|
+
- **tool package:** the `_PackMagickNotice` target in `src/PolyMigrate.Cli/PolyMigrate.Cli.csproj`
|
|
50
|
+
fails `dotnet pack`;
|
|
51
|
+
- **npm:** `npm/prepare.mjs` aborts, and `release.yml` then checks that every built package
|
|
52
|
+
really carries `NOTICE.txt` and this file.
|
|
53
|
+
|
|
54
|
+
A licence obligation that depends on someone remembering a checklist is one that will
|
|
43
55
|
eventually be missed.
|
|
44
56
|
|
|
45
57
|
## Keeping this current
|
|
46
58
|
|
|
47
|
-
This file
|
|
48
|
-
|
|
49
|
-
|
|
59
|
+
This file describes what the CLI's build output actually contains
|
|
60
|
+
(`src/PolyMigrate.Cli/bin/Release/net10.0`, listed in `polymigrate.deps.json`), not only what the
|
|
61
|
+
`.csproj` files reference: a build-time package can still leak a runtime DLL into the output.
|
|
62
|
+
**When a dependency is added, removed, or bumped, check the output and update this file in the
|
|
63
|
+
same commit** — Dependabot bumps will not do it for you.
|
|
64
|
+
|
|
65
|
+
## Licence texts
|
|
66
|
+
|
|
67
|
+
### MIT License
|
|
68
|
+
|
|
69
|
+
Applies to AngleSharp, ReverseMarkdown, YamlDotNet and the .NET runtime.
|
|
70
|
+
|
|
71
|
+
```text
|
|
72
|
+
MIT License
|
|
73
|
+
|
|
74
|
+
Copyright (c) 2013 - 2026 AngleSharp
|
|
75
|
+
Copyright (c) 2015 Babu Annamalai
|
|
76
|
+
Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014 Antoine Aubry and contributors
|
|
77
|
+
Copyright (c) .NET Foundation and Contributors
|
|
78
|
+
|
|
79
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
80
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
81
|
+
in the Software without restriction, including without limitation the rights
|
|
82
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
83
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
84
|
+
furnished to do so, subject to the following conditions:
|
|
85
|
+
|
|
86
|
+
The above copyright notice and this permission notice shall be included in all
|
|
87
|
+
copies or substantial portions of the Software.
|
|
88
|
+
|
|
89
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
90
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
91
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
92
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
93
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
94
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
95
|
+
SOFTWARE.
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Apache License 2.0
|
|
99
|
+
|
|
100
|
+
Applies to Magick.NET (`Magick.NET-Q8-AnyCPU`, `Magick.NET.Core` and the native
|
|
101
|
+
`Magick.Native-Q8-*`), Copyright 2013-2026 Dirk Lemstra. ImageMagick and the libraries built
|
|
102
|
+
into the native binaries are under their own licences, reproduced in full in `NOTICE.txt`.
|
|
103
|
+
|
|
104
|
+
```text
|
|
105
|
+
|
|
106
|
+
Apache License
|
|
107
|
+
Version 2.0, January 2004
|
|
108
|
+
http://www.apache.org/licenses/
|
|
109
|
+
|
|
110
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
111
|
+
|
|
112
|
+
1. Definitions.
|
|
113
|
+
|
|
114
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
115
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
116
|
+
|
|
117
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
118
|
+
the copyright owner that is granting the License.
|
|
119
|
+
|
|
120
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
121
|
+
other entities that control, are controlled by, or are under common
|
|
122
|
+
control with that entity. For the purposes of this definition,
|
|
123
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
124
|
+
direction or management of such entity, whether by contract or
|
|
125
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
126
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
127
|
+
|
|
128
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
129
|
+
exercising permissions granted by this License.
|
|
130
|
+
|
|
131
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
132
|
+
including but not limited to software source code, documentation
|
|
133
|
+
source, and configuration files.
|
|
134
|
+
|
|
135
|
+
"Object" form shall mean any form resulting from mechanical
|
|
136
|
+
transformation or translation of a Source form, including but
|
|
137
|
+
not limited to compiled object code, generated documentation,
|
|
138
|
+
and conversions to other media types.
|
|
139
|
+
|
|
140
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
141
|
+
Object form, made available under the License, as indicated by a
|
|
142
|
+
copyright notice that is included in or attached to the work
|
|
143
|
+
(an example is provided in the Appendix below).
|
|
144
|
+
|
|
145
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
146
|
+
form, that is based on (or derived from) the Work and for which the
|
|
147
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
148
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
149
|
+
of this License, Derivative Works shall not include works that remain
|
|
150
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
151
|
+
the Work and Derivative Works thereof.
|
|
152
|
+
|
|
153
|
+
"Contribution" shall mean any work of authorship, including
|
|
154
|
+
the original version of the Work and any modifications or additions
|
|
155
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
156
|
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
157
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
|
158
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
|
159
|
+
means any form of electronic, verbal, or written communication sent
|
|
160
|
+
to the Licensor or its representatives, including but not limited to
|
|
161
|
+
communication on electronic mailing lists, source code control systems,
|
|
162
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
|
163
|
+
Licensor for the purpose of discussing and improving the Work, but
|
|
164
|
+
excluding communication that is conspicuously marked or otherwise
|
|
165
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
|
166
|
+
|
|
167
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
168
|
+
on behalf of whom a Contribution has been received by Licensor and
|
|
169
|
+
subsequently incorporated within the Work.
|
|
170
|
+
|
|
171
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
172
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
173
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
174
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
175
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
176
|
+
Work and such Derivative Works in Source or Object form.
|
|
177
|
+
|
|
178
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
179
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
180
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
181
|
+
(except as stated in this section) patent license to make, have made,
|
|
182
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
183
|
+
where such license applies only to those patent claims licensable
|
|
184
|
+
by such Contributor that are necessarily infringed by their
|
|
185
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
|
186
|
+
with the Work to which such Contribution(s) was submitted. If You
|
|
187
|
+
institute patent litigation against any entity (including a
|
|
188
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
189
|
+
or a Contribution incorporated within the Work constitutes direct
|
|
190
|
+
or contributory patent infringement, then any patent licenses
|
|
191
|
+
granted to You under this License for that Work shall terminate
|
|
192
|
+
as of the date such litigation is filed.
|
|
193
|
+
|
|
194
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
195
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
196
|
+
modifications, and in Source or Object form, provided that You
|
|
197
|
+
meet the following conditions:
|
|
198
|
+
|
|
199
|
+
(a) You must give any other recipients of the Work or
|
|
200
|
+
Derivative Works a copy of this License; and
|
|
201
|
+
|
|
202
|
+
(b) You must cause any modified files to carry prominent notices
|
|
203
|
+
stating that You changed the files; and
|
|
204
|
+
|
|
205
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
206
|
+
that You distribute, all copyright, patent, trademark, and
|
|
207
|
+
attribution notices from the Source form of the Work,
|
|
208
|
+
excluding those notices that do not pertain to any part of
|
|
209
|
+
the Derivative Works; and
|
|
210
|
+
|
|
211
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
212
|
+
distribution, then any Derivative Works that You distribute must
|
|
213
|
+
include a readable copy of the attribution notices contained
|
|
214
|
+
within such NOTICE file, excluding those notices that do not
|
|
215
|
+
pertain to any part of the Derivative Works, in at least one
|
|
216
|
+
of the following places: within a NOTICE text file distributed
|
|
217
|
+
as part of the Derivative Works; within the Source form or
|
|
218
|
+
documentation, if provided along with the Derivative Works; or,
|
|
219
|
+
within a display generated by the Derivative Works, if and
|
|
220
|
+
wherever such third-party notices normally appear. The contents
|
|
221
|
+
of the NOTICE file are for informational purposes only and
|
|
222
|
+
do not modify the License. You may add Your own attribution
|
|
223
|
+
notices within Derivative Works that You distribute, alongside
|
|
224
|
+
or as an addendum to the NOTICE text from the Work, provided
|
|
225
|
+
that such additional attribution notices cannot be construed
|
|
226
|
+
as modifying the License.
|
|
227
|
+
|
|
228
|
+
You may add Your own copyright statement to Your modifications and
|
|
229
|
+
may provide additional or different license terms and conditions
|
|
230
|
+
for use, reproduction, or distribution of Your modifications, or
|
|
231
|
+
for any such Derivative Works as a whole, provided Your use,
|
|
232
|
+
reproduction, and distribution of the Work otherwise complies with
|
|
233
|
+
the conditions stated in this License.
|
|
234
|
+
|
|
235
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
236
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
237
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
238
|
+
this License, without any additional terms or conditions.
|
|
239
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
|
240
|
+
the terms of any separate license agreement you may have executed
|
|
241
|
+
with Licensor regarding such Contributions.
|
|
242
|
+
|
|
243
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
244
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
245
|
+
except as required for reasonable and customary use in describing the
|
|
246
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
|
247
|
+
|
|
248
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
249
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
250
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
251
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
252
|
+
implied, including, without limitation, any warranties or conditions
|
|
253
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
254
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
255
|
+
appropriateness of using or redistributing the Work and assume any
|
|
256
|
+
risks associated with Your exercise of permissions under this License.
|
|
257
|
+
|
|
258
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
259
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
260
|
+
unless required by applicable law (such as deliberate and grossly
|
|
261
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
|
262
|
+
liable to You for damages, including any direct, indirect, special,
|
|
263
|
+
incidental, or consequential damages of any character arising as a
|
|
264
|
+
result of this License or out of the use or inability to use the
|
|
265
|
+
Work (including but not limited to damages for loss of goodwill,
|
|
266
|
+
work stoppage, computer failure or malfunction, or any and all
|
|
267
|
+
other commercial damages or losses), even if such Contributor
|
|
268
|
+
has been advised of the possibility of such damages.
|
|
269
|
+
|
|
270
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
271
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
272
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
273
|
+
or other liability obligations and/or rights consistent with this
|
|
274
|
+
License. However, in accepting such obligations, You may act only
|
|
275
|
+
on Your own behalf and on Your sole responsibility, not on behalf
|
|
276
|
+
of any other Contributor, and only if You agree to indemnify,
|
|
277
|
+
defend, and hold each Contributor harmless for any liability
|
|
278
|
+
incurred by, or claims asserted against, such Contributor by reason
|
|
279
|
+
of your accepting any such warranty or additional liability.
|
|
280
|
+
|
|
281
|
+
END OF TERMS AND CONDITIONS
|
|
282
|
+
|
|
283
|
+
APPENDIX: How to apply the Apache License to your work.
|
|
284
|
+
|
|
285
|
+
To apply the Apache License to your work, attach the following
|
|
286
|
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
287
|
+
replaced with your own identifying information. (Don't include
|
|
288
|
+
the brackets!) The text should be enclosed in the appropriate
|
|
289
|
+
comment syntax for the file format. We also recommend that a
|
|
290
|
+
file or class name and description of purpose be included on the
|
|
291
|
+
same "printed page" as the copyright notice for easier
|
|
292
|
+
identification within third-party archives.
|
|
293
|
+
|
|
294
|
+
Copyright [yyyy] [name of copyright owner]
|
|
295
|
+
|
|
296
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
297
|
+
you may not use this file except in compliance with the License.
|
|
298
|
+
You may obtain a copy of the License at
|
|
299
|
+
|
|
300
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
301
|
+
|
|
302
|
+
Unless required by applicable law or agreed to in writing, software
|
|
303
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
304
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
305
|
+
See the License for the specific language governing permissions and
|
|
306
|
+
limitations under the License.
|
|
307
|
+
```
|
package/bin/polymigrate.js
CHANGED
|
@@ -34,13 +34,27 @@ const TARGETS = {
|
|
|
34
34
|
const key = `${process.platform} ${process.arch}`;
|
|
35
35
|
const target = TARGETS[key];
|
|
36
36
|
|
|
37
|
-
|
|
37
|
+
// 啟動腳本自己失敗 = PolyMigrate 根本沒有執行 = error,所以是 2(3.0 起)。
|
|
38
|
+
// 2.3.1 以前是 1,和 CLI 契約的「1 = 只有 warning」撞號:依「0/1 放行」的 CI 會把「工具沒跑」當成通過
|
|
39
|
+
// (2.1.0~2.3.0 的 arm64 事故走的就是這條路)。訊息用英文(與 CLI 其他輸出一致),明講工具沒有執行。
|
|
40
|
+
const LAUNCHER_FAILURE_EXIT = 2;
|
|
41
|
+
|
|
42
|
+
function fail(...lines) {
|
|
38
43
|
console.error(
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
44
|
+
[
|
|
45
|
+
`error: ${lines[0]} PolyMigrate did not run.`,
|
|
46
|
+
...lines.slice(1),
|
|
47
|
+
].join("\n")
|
|
48
|
+
);
|
|
49
|
+
process.exit(LAUNCHER_FAILURE_EXIT);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (!target) {
|
|
53
|
+
fail(
|
|
54
|
+
`no prebuilt binary for ${key}.`,
|
|
55
|
+
`Supported platforms: ${Object.keys(TARGETS).join(", ")}.`,
|
|
56
|
+
"On other platforms, use the .NET tool instead: dotnet tool install -g Cornhsu.PolyMigrate"
|
|
42
57
|
);
|
|
43
|
-
process.exit(1);
|
|
44
58
|
}
|
|
45
59
|
|
|
46
60
|
let binary;
|
|
@@ -50,19 +64,22 @@ try {
|
|
|
50
64
|
const manifest = require.resolve(`${target.pkg}/package.json`);
|
|
51
65
|
binary = path.join(path.dirname(manifest), "bin", target.bin);
|
|
52
66
|
} catch {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
67
|
+
fail(
|
|
68
|
+
`the platform package ${target.pkg} is not installed.`,
|
|
69
|
+
"It is an optional dependency: --no-optional / --omit=optional skips it, or the install was interrupted.",
|
|
70
|
+
"Reinstall: npm install cornhsu-polymigrate"
|
|
57
71
|
);
|
|
58
|
-
process.exit(1);
|
|
59
72
|
}
|
|
60
73
|
|
|
74
|
+
// Ctrl-C:主控台的 Ctrl-C 同時送給這個 node 行程與子行程(Windows 的主控台群組、Unix 的前景行程群組都是如此)。
|
|
75
|
+
// node 沒有 SIGINT 處理器的話會先被結束——Windows 上結束碼是 0xC000013A,子行程乾淨回的 130 傳不出去。
|
|
76
|
+
// 掛一個什麼都不做的處理器,讓 node 等子行程自己收尾,再原樣轉傳它的 exit code。
|
|
77
|
+
process.on("SIGINT", () => {});
|
|
78
|
+
|
|
61
79
|
const result = spawnSync(binary, process.argv.slice(2), { stdio: "inherit" });
|
|
62
80
|
|
|
63
81
|
if (result.error) {
|
|
64
|
-
|
|
65
|
-
process.exit(1);
|
|
82
|
+
fail(`could not start ${binary}: ${result.error.message}.`);
|
|
66
83
|
}
|
|
67
84
|
|
|
68
85
|
// 被訊號中斷時 status 會是 null;轉成慣例的 128+signal,別讓 CI 誤判為成功
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cornhsu-polymigrate",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"description": "The i18n-first static-site migrator — the only one that pairs your multilingual pages automatically. Mirrors a legacy site into frontmatter Markdown, auto-matches language versions, and honestly lists what it could not pair.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"i18n",
|
|
@@ -36,11 +36,11 @@
|
|
|
36
36
|
"node": ">=18"
|
|
37
37
|
},
|
|
38
38
|
"optionalDependencies": {
|
|
39
|
-
"@cornhsu/polymigrate-win32-x64": "
|
|
40
|
-
"@cornhsu/polymigrate-win32-arm64": "
|
|
41
|
-
"@cornhsu/polymigrate-linux-x64": "
|
|
42
|
-
"@cornhsu/polymigrate-linux-arm64": "
|
|
43
|
-
"@cornhsu/polymigrate-darwin-x64": "
|
|
44
|
-
"@cornhsu/polymigrate-darwin-arm64": "
|
|
39
|
+
"@cornhsu/polymigrate-win32-x64": "3.0.0",
|
|
40
|
+
"@cornhsu/polymigrate-win32-arm64": "3.0.0",
|
|
41
|
+
"@cornhsu/polymigrate-linux-x64": "3.0.0",
|
|
42
|
+
"@cornhsu/polymigrate-linux-arm64": "3.0.0",
|
|
43
|
+
"@cornhsu/polymigrate-darwin-x64": "3.0.0",
|
|
44
|
+
"@cornhsu/polymigrate-darwin-arm64": "3.0.0"
|
|
45
45
|
}
|
|
46
46
|
}
|