Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 58 additions & 9 deletions how-to-release.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
# Release Guide
**Publishing packages to NPM**

In `package.json` verify the name and update the version. Add additional files
if needed.
In `package.json` verify the name and update the version.

```json
{
Expand All @@ -11,15 +10,33 @@ if needed.
...
"files": [
"dist",
"*.md",
"Add more here if needed"
"LICENSE.md",
"README.md",
"CONTRIBUTING.md",
"RELEASE-NOTES-0.18.0.md"
]
}
```

Keep the `files` array as an explicit allowlist. Do **not** delete it: with no
`files` field, npm publishes the entire repo minus standard ignores (`src/`,
`test/`, configs, etc.), which bloats the package and leaks dev files. Avoid
globs like `"*.md"` here — they can sweep in transient files (e.g. per-release
notes) you did not intend to ship. Add a new entry only when a file genuinely
needs to ship, and prefer stable filenames over version-specific ones.

Release notes are **not** shipped in the npm tarball — they live on the GitHub
release (see "Preparing release notes" below), so there is nothing to add here
for them.

Note that when releasing on npm, you are distributing leaflet, proj4 etc., so
you need to distribute the text of their licenses with the dist folder.

Verify the exact contents of the tarball before publishing:
```bash
npm pack --dry-run
```

Open the command prompt and cd into the MapML.js project directory.

Type in –
Expand All @@ -35,17 +52,49 @@ When it publishes successfully you should see:
+@maps4html/mapml@X.X.X
```

**Preparing release notes**

Release notes live on the GitHub release, not in the repo or the npm package.
To write them ahead of time and still be able to edit before publishing, draft
them in a local, **uncommitted** scratch file (any name, e.g.
`RELEASE-NOTES-X.Y.Z.md`). Seed the file from the commit history since the last tag,
replacing `<previous-tag>` with the actual prior release tag (e.g. `v0.18.0`):

```bash
git log <previous-tag>..HEAD --pretty=format:'- %s (%h, %an)'
```

Edit that file freely — it is disposable and never committed or shipped.

**GitHub release procedure**

To create a new release on GitHub, visit the [release page](https://github.com/Maps4HTML/MapML.js/releases),
then click `Draft a new release`.
Create the release from the canonical `Maps4HTML/MapML.js` repository so the tag
and release are authoritative. Two options:

_Via the web UI:_ visit the [release page](https://github.com/Maps4HTML/MapML.js/releases)
and click `Draft a new release`. In the `Choose a tag` dropdown, type the new
`vX.Y.Z` tag (GitHub creates it on publish), set the target to the merged
release commit on `main`, paste in your notes, and publish.

_Via the GitHub CLI_ (lets you create an editable **draft** from your notes
file, then review/publish):
```bash
gh release create vX.Y.Z --draft --title "vX.Y.Z" --notes-file RELEASE-NOTES-X.Y.Z.md
```
Open the draft, make any final edits, then publish it. Publishing the release is
what creates and pushes the `vX.Y.Z` tag, so no separate `git push` of a tag is
required (useful when branch protection prevents pushing tags directly).

Enter the new release version in the `Choose a tag` dropdown, fill in the title and description
if needed, and then publish the release.
After the tag exists upstream, publish to npm from that tagged state:
```bash
git fetch upstream --tags
git checkout vX.Y.Z
npm ci && npm publish --access=public
```

**Publishing packages to GitHub**

Create a personal access token on [GitHub](https://github.com/settings/tokens/new)
Create a personal access (classic) token on [GitHub](https://github.com/settings/tokens/new)
and check `write:packages` and `delete:packages`.

Open the command prompt and cd into the MapML.js project directory. Enter:
Expand Down
17 changes: 16 additions & 1 deletion test/e2e/elements/map-link/map-link-security.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ test.describe('map-link security: XSS via <map-link rel=license|legend>', () =>
page =
context.pages().find((p) => p.url() === 'about:blank') ||
(await context.newPage());
await page.goto('map-link-security.html');
await page.goto('map-link-security.html', { waitUntil: "networkidle" });
// Give the viewer a beat to attach the malicious layers to the
// attribution / layer control before we probe.
await page.waitForSelector('mapml-viewer');
Expand Down Expand Up @@ -102,6 +102,21 @@ test.describe('map-link security: XSS via <map-link rel=license|legend>', () =>
test('legitimate https license still renders as an anchor', async () => {
// The `good_license` layer must produce a proper anchor in the
// attribution control, with the sanitised href and escaped title.
// The good_license layer is initialised asynchronously; on slower
// CI runners the anchor may not have been added to the attribution
// control by the time the earlier tests finish, so wait for it
// explicitly before probing.
await page.waitForFunction(() => {
const viewer = document.querySelector('mapml-viewer');
const container =
viewer && viewer._map && viewer._map.attributionControl
? viewer._map.attributionControl._container
: null;
if (!container) return false;
return Array.from(container.querySelectorAll('a')).some(
(a) => a.textContent && a.textContent.includes('Terms of service')
);
});
const legit = await page.evaluate(() => {
const container =
document.querySelector('mapml-viewer')._map.attributionControl
Expand Down
Loading