Sign inSign up

d3strukt0r/weleda-webcenter-text-export

By d3strukt0r

•Updated about 9 hours ago

Convert Esko Web Center GS1 XML exports into readable plain-text leaflets, in the browser

Image
Web servers
0

100K+

d3strukt0r/weleda-webcenter-text-export repository overview

⁠Weleda Web Center XML to Text Converter

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:

  • Drop it anywhere on the page — the whole window is a drop target.
  • Click the dropzone — opens a regular file picker.
  • Ctrl/Cmd+V — paste either the file (copied with Ctrl+C in your file explorer) or the raw XML text directly.
  • <form> POST — picks the file in the dropzone and clicks the Hochladen button that only appears when JavaScript is disabled.

License Contributor Covenant Docker Stars Docker Pulls

CI Pages Docker

⁠Running the container

The published image serves the SSR build on port 3000.

⁠Prerequisites

You need Docker⁠ installed.

⁠Usage

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
⁠docker compose
services:
  web:
    image: d3strukt0r/weleda-webcenter-text-export:latest
    restart: unless-stopped
    ports:
      - "3000:3000"
⁠Environment variables
  • 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.

⁠Image details
  • Base: distroless (Nix-built, no shell as PID 1, runs as nonroot:65532)
  • Server: @react-router/serve (SSR)
  • Exposed port: 3000
  • Healthcheck: curl against / every 30 s
  • Architectures: linux/amd64, linux/arm64, linux/riscv64
⁠Tags
  • latest — highest published semver release (via flavor.latest=auto)
  • <major>, <major>.<minor>, <major>.<minor>.<patch> — semver releases
  • develop — 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⁠.

⁠Building your own image

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).

⁠No-JavaScript fallback

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.

⁠Stack

⁠Development

For working on the site itself (not just running the published image).

⁠Prerequisites

Or use one of the prebuilt environments below.

⁠Setup (host)
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 (Docker outside of Docker)

.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
⁠Vagrant VM (full HTTPS stack on a .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.

⁠Common commands
  • pnpm dev — Vite dev server (5173) with HMR
  • pnpm build — production build → build/client/ + build/server/
  • SSR=false pnpm build — static / SPA build → build/client/ only
  • pnpm preview — preview the static build locally on 4173
  • pnpm typecheck — react-router typegen && tsc --noEmit
  • pnpm lint / pnpm lint:fix — ESLint
  • pnpm test / pnpm test:watch — Vitest

Run a single test by file or name:

pnpm test app/lib/xml-to-text/convert.test.ts
pnpm vitest run -t "preserves document order"
⁠Build modes

react-router.config.ts toggles SSR via the SSR env var:

  • Docker / Node hosting (default): pnpm build → SSR bundle, served by react-router-serve on port 3000. Enables the no-JS form POST path.
  • GitHub Pages (no Node runtime): 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.
⁠Building the OCI image locally

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

⁠XML conversion

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⁠

⁠Project layout

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

⁠Built with

⁠Contributing

Please read CONTRIBUTING.md⁠ for details on our code of conduct and the process for submitting pull requests.

This project uses Conventional Commits⁠.

⁠Versioning

We use SemVer⁠ for versioning. For available versions, see the tags on this repository⁠.

⁠Authors

⁠Special thanks for all the people who had helped this project so far

See also the full list of contributors⁠ who participated in this project.

⁠I would like to join this list. How can I help the project?

We're currently looking for contributions for the following:

  • Bug fixes
  • Translations
  • etc...

For more information, please refer to our CONTRIBUTING.md⁠ guide.

⁠License

This project is licensed under the MIT License - see the LICENSE.txt⁠ file for details.

⁠Acknowledgments

This project currently uses no third-party libraries or copied code.

Tag summary

Content type

Image

Digest

sha256:c3c3e280a…

Size

93.7 MB

Last updated

3 months ago

docker pull d3strukt0r/weleda-webcenter-text-export