weleda-webcenter-text-export
Convert Esko Web Center GS1 XML exports into readable plain-text leaflets, in the browser
100K+
Converts a GS1 artwork_content:artworkContentMessage XML (the format
exported from Esko Web Center) into a readable plain-text leaflet — the
kind that's easy to paste into Word for layouting. With JavaScript on,
everything runs locally in the browser; no file ever leaves the
machine. With JavaScript off, the SSR container falls back to a server-
side conversion (see No-JavaScript fallback).
Four ways to load an XML:
<form> POST — picks the file in the dropzone and clicks the
Hochladen button that only appears when JavaScript is disabled.The published image serves the SSR build on port 3000.
You need Docker installed.
Pull and run the latest image:
docker run --rm -p 3000:3000 d3strukt0r/weleda-webcenter-text-export:latest
Then open http://localhost:3000.
Pin to a specific version (recommended for production):
docker run --rm -p 3000:3000 d3strukt0r/weleda-webcenter-text-export:2.1.2
Run on a different host port:
docker run --rm -p 8080:3000 d3strukt0r/weleda-webcenter-text-export:latest
Get a shell inside the container:
docker run --rm -it --entrypoint sh d3strukt0r/weleda-webcenter-text-export:latest
services:
web:
image: d3strukt0r/weleda-webcenter-text-export:latest
restart: unless-stopped
ports:
- "3000:3000"
PORT — port react-router-serve listens on. Default 3000.NODE_ENV — set to production in the image. Don't override.No secrets or per-deployment configuration — the converter has no backend state.
nonroot:65532)@react-router/serve (SSR)3000curl against / every 30 slinux/amd64, linux/arm64, linux/riscv64latest — highest published semver release (via flavor.latest=auto)<major>, <major>.<minor>, <major>.<minor>.<patch> — semver releasesdevelop — branch tip for the develop branch (pre-release / preview builds)master is not published as a branch tag — release tags from release.yml are the only path to :latest.
Full list at hub.docker.com/r/d3strukt0r/weleda-webcenter-text-export.
The image is built by flake.nix, not a Dockerfile. See
Development → Building the OCI image locally
for the full recipe (works on Windows / macOS / Linux via a throwaway
nixos/nix container; no host Nix install required).
The page works without JavaScript when running from the SSR image (the
GitHub Pages SPA build has no Node runtime, so it can only do client-
side conversion). With JS off you get the dropzone, the file picker,
and a Hochladen submit button that posts the file to a React Router
action on /?index; the server runs xmlToText and re-renders the
page with the converted result. After picking a file, the dropzone
shows a "✓ Datei ausgewählt" indicator via pure-CSS :has(input:valid)
— no inline JS.
Search, copy, and download require JavaScript; without it, the user can still read and select-copy the rendered text manually.
api: modern-compiler)app/locales/de.ymlfast-xml-parser
— pure JS, runs in browser + Node, deterministic for testspackageManager pinned)For working on the site itself (not just running the published image).
corepack enable) — pnpm is pinned via packageManager in
package.json.Or use one of the prebuilt environments below.
git clone [email protected]:D3strukt0r/weleda-webcenter-text-export.git
cd weleda-webcenter-text-export
pnpm install
pnpm dev
The dev server runs on http://localhost:5173 with HMR.
.devcontainer/devcontainer.json provisions Node 24, the DooD feature
(moby: false), act, common-utils. Open in VS Code → Reopen in
Container, then:
pnpm dev # Vite inside the devcontainer
# or
docker compose up dev # Vite in a sibling Nix container, host
# workspace bind-mounted via $LOCAL_WORKSPACE_FOLDER
.test hostname)Requires VirtualBox + Vagrant + mkcert
on the host (the Vagrantfile asks mkcert to mint local certs on first
boot).
vagrant up # provisions Debian 12, Docker, brings up Traefik + dev
# app reachable at https://weleda-webcenter-text-export.test
# Traefik dashboard at https://traefik.weleda-webcenter-text-export.test
compose.vm.dist.yml is the template; it's copied to compose.vm.yml
inside the VM (gitignored) so you can edit it without churning the
repo.
pnpm dev — Vite dev server (5173) with HMRpnpm build — production build → build/client/ + build/server/SSR=false pnpm build — static / SPA build → build/client/ onlypnpm preview — preview the static build locally on 4173pnpm typecheck — react-router typegen && tsc --noEmitpnpm lint / pnpm lint:fix — ESLintpnpm test / pnpm test:watch — VitestRun a single test by file or name:
pnpm test app/lib/xml-to-text/convert.test.ts
pnpm vitest run -t "preserves document order"
react-router.config.ts toggles SSR via the SSR env var:
pnpm build → SSR bundle, served
by react-router-serve on port 3000. Enables the no-JS form POST
path.SSR=false pnpm build → static
SPA in build/client/. The
deploy-gh-pages.yml workflow
uploads that folder via actions/deploy-pages. The no-JS form POST is
inert on GH Pages.The production image is Nix-built (flake.nix); there is no
Dockerfile. If you have Nix installed, nix build .#dockerImage is
enough. Otherwise — and on Windows in particular — run Nix inside a
throwaway nixos/nix container; everything else lives in your existing
Docker daemon.
PowerShell (Windows / macOS Docker Desktop):
docker run --rm `
-v "${PWD}:/work" -w /work `
nixos/nix:2.34.6 `
nix --extra-experimental-features "nix-command flakes" `
build .#dockerImage
docker load --input result
docker run --rm -p 3000:3000 d3strukt0r/weleda-webcenter-text-export:latest
Bash (Linux / WSL / macOS):
docker run --rm \
-v "$PWD:/work" -w /work \
nixos/nix:2.34.6 \
nix --extra-experimental-features "nix-command flakes" \
build .#dockerImage
docker load --input result
docker run --rm -p 3000:3000 d3strukt0r/weleda-webcenter-text-export:latest
For repeated builds, add -v nix-store:/nix to the docker run flags
so the Nix store survives across container restarts (mirrors what
compose.yml already does for the dev shell). First build: 5–10 min.
Subsequent rebuilds: seconds.
For a containerized dev server with HMR (no image build, just
pnpm run dev inside Nix), use compose.yml:
docker compose up --build
The converter walks every <textContent> subtree and emits one
paragraph per <p> or <li>. <b>, <i> etc. bubble through;
<br/> becomes a soft line break inside the same paragraph. The GS1
standard business document header and other metadata are ignored — the
output reads like a patient information leaflet, not an XML dump.
The full behaviour is locked down by a fixture-based Vitest spec at
app/lib/xml-to-text/convert.test.ts
plus __fixtures__/sample.xml
app/
assets/icons/ # per-icon SVGs imported via `?react` (svgr)
components/ # Topbar, Lede, Dropzone, DragOverlay, Result, Toast, AppFooter
hooks/ # useConverter, usePageDragDrop, usePasteXml, useToast, useTheme
lib/
xml-to-text/ # convert.ts + tests + fixtures
format.ts # size / number formatters, regex escape
locales/de.yml # all UI strings
routes/ # home.tsx (with server action), not-found.tsx
styles/ # main.scss (design tokens), tailwind.css
i18n.ts # i18next bootstrap
root.tsx
routes.ts # manifest
public/ # served from /, includes Weleda logo + robots.txt
fast-xml-parserPlease read CONTRIBUTING.md for details on our code of conduct and the process for submitting pull requests.
This project uses Conventional Commits.
We use SemVer for versioning. For available versions, see the tags on this repository.
See also the full list of contributors who participated in this project.
We're currently looking for contributions for the following:
For more information, please refer to our CONTRIBUTING.md guide.
This project is licensed under the MIT License - see the LICENSE.txt file for details.
This project currently uses no third-party libraries or copied code.
Content type
Image
Digest
sha256:2a736069f…
Size
94.4 MB
Last updated
6 days ago
docker pull d3strukt0r/weleda-webcenter-text-export:develop