From b272fcb71330d8156eeb07f262667bccd76e07d1 Mon Sep 17 00:00:00 2001 From: Steffen Mecke Date: Tue, 12 Aug 2025 23:43:24 +0200 Subject: [PATCH 01/34] dynamic landing page --- index.njk | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/index.njk b/index.njk index d4d597c..3d0574b 100644 --- a/index.njk +++ b/index.njk @@ -3,20 +3,20 @@ layout: base-layout.njk title: Eressea Beispielpartie --- -
-

- Goblins -

-
+

Eressea Tutorial 2024

-
-

- Meermenschen -

-
+

Dies sind die Tagebücher der Parteien, die beim Tutorial 2024 mitgespielt haben. Vielen Dank an alle, die ihren +Bericht hier zur Verfügung stellen.

-
-

- Zwerge -

-
+

Some of these will be in English, some in German.

+ +{% for post in collections.race %} +
+

+ {{ post.data.title }} +

+ +
+{% else %} +

There is nothing here...

+{% endfor %} From b179b5383fa9d019f0e0a25ac102bdc4bc95c4e0 Mon Sep 17 00:00:00 2001 From: Steffen Mecke Date: Wed, 13 Aug 2025 01:29:31 +0200 Subject: [PATCH 02/34] created an example faction - created nogoblins directory (going to rename it to template) - added template/ to .eleventyignore - added pagination to base layout - added author field - updated README file for Tutorial authors --- .eleventyignore | 3 + README.md | 111 +++++++++++++++++++++++++++++++++++-- _includes/base-layout.njk | 31 +++++++++++ _includes/post-layout.njk | 6 +- css/site.css | 31 +++++++---- index.njk | 7 ++- nogoblins/Auswertung_01.md | 9 +++ nogoblins/Auswertung_02.md | 10 ++++ nogoblins/Auswertung_03.md | 8 +++ nogoblins/Auswertung_04.md | 8 +++ nogoblins/Auswertung_05.md | 8 +++ nogoblins/Auswertung_06.md | 8 +++ nogoblins/Auswertung_07.md | 9 +++ nogoblins/Auswertung_08.md | 9 +++ nogoblins/Auswertung_09.md | 9 +++ nogoblins/index.njk | 26 +++++++++ nogoblins/nogoblins.json | 5 ++ 17 files changed, 280 insertions(+), 18 deletions(-) create mode 100644 nogoblins/Auswertung_01.md create mode 100644 nogoblins/Auswertung_02.md create mode 100644 nogoblins/Auswertung_03.md create mode 100644 nogoblins/Auswertung_04.md create mode 100644 nogoblins/Auswertung_05.md create mode 100644 nogoblins/Auswertung_06.md create mode 100644 nogoblins/Auswertung_07.md create mode 100644 nogoblins/Auswertung_08.md create mode 100644 nogoblins/Auswertung_09.md create mode 100644 nogoblins/index.njk create mode 100644 nogoblins/nogoblins.json diff --git a/.eleventyignore b/.eleventyignore index ce9afc9..28ec6ef 100644 --- a/.eleventyignore +++ b/.eleventyignore @@ -1,5 +1,8 @@ # We don't want Eleventy to include the README.md as a website content file README.md +# template directory: help for authors +template/ + # Unit tests should be ignored by Eleventy tests/ diff --git a/README.md b/README.md index fae4954..7b790aa 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,117 @@ -# eleventy-blog -An example blog site using Eleventy that covers fundamental functionality. +# Eressea Tutorial 2024 -The following article accompanies this repo. +These are the diaries for the 2024 Eressea Tutorial. -## Creating A Blog With Eleventy +## How to add your diary + +### Create your own fork of the repository + +- Create a github account. + +- Fork this repository by clicking on the [Fork Link in Github](https://github.com/eressea/tutorials/fork). This will create your private copy of the whole thing. + +### Editing your content + +- You can edit it directly on github or *clone* it to your computer and edit it there. Cloning requires more steps, but is ultimately more flexible. It requires you to learn a bit about version control with [git](https://git-scm.com/docs/gittutorial) and [github](https://docs.github.com/en/get-started/start-your-journey/hello-world) + +- Create a subdirectory for your faction, for example 'dragonborn'. + +- Copy the file called 'index.njk' from the 'template' directory into your subdirectory: + +``` +--- +layout: base-layout.njk +title: Not Goblins! +override:tags: ["race"] +pagination: + data: collections.nogoblin + size: 8 + reverse: false + alias: posts +--- +{% for post in posts %} +... +``` + +Change the title as you wish. + +- If you want to create just one big file, replace everything below the second '---' with your content. This is not recommended if you want to add a lot of text. The content is [Markdown](https://www.markdownguide.org/), a text file format that let's you add basic formatting like headings, links, images. You could also use html directly. Then you would create an index.html file instead. HTML is less recommended. + +- If you have more to say, you should split your diary into multiple files. In that case, leave everything below the '---' as it is, at least for now. Also copy 'Auswertung_XX.md' from the template directory into your subdirectory. You may rename them as you wish, for example to week_01.md, week_02.md, ... and so forth. + +- Also copy the file nogoblins.json to your directory and rename it to yourdirectory.json. +``` +{ + "author": "enno", + "layout": "post-layout.njk", + "tags": "nogoblin" +} +``` +- Change the author to your name and "nogoblin" to "your_race". + +- Edit every Auswertung_XX.md: +``` +--- +title: "Dragonborn: Round 1" +date: 2024-03-17 +--- +# Round 1 + Lore ipsum ... +## Heading 1 + +... +``` + +This file consists of the 'front matter' between the lines starting with '---'. It contains some meta data that will be used for presenting your files nicely. + +- Change the title +- Change the date line. The files will be ordered by the 'date' field, so make sure to get that right. +- Write your text below the second '---' line + +- If you're editing directly in github, 'commit' your changes using the github interface. You can commit directly to your 'main' branch. + + +### Seeing your content + +- If you have cloned your repository and are using a Linux system, you can run +``` +npm install +npm run serve +``` +in a terminal. Watch the terminal for error messages. If all went well, you can then see the generated pages at [http://localhost:8080/](http://localhost:8080/) (your port may vary). + + +### Uploading your content + +- If you have cloned the repository to your computer, you must ['add'](https://git-scm.com/docs/gittutorial) and ['commit'](https://git-scm.com/docs/gittutorial) your changes, then 'push' them to your repository. + +- Optional: Activate github actions and github-pages. TODO + +- If you have pushed your changes or commited them on github and you are happy with them, create a ['pull request'](https://github.blog/developer-skills/github/beginners-guide-to-github-creating-a-pull-request/) for the actual eressea repository (sometimes called the 'upstream repository'). If you have changes, you should see a line like "This branch is 1 commit ahead of eressea/tutorials:main' on github. Use the 'contribute' button to 'Open a pull request'. Write a short comment explaining your changes and 'Create pull request'. This will notifiy the owners of the upstream repo to review your changes. If they like them, they will 'merge' them and they can be watched online. They may also have comments or questions or ask you for changes before actually merging them. + + + +### Done! + +You can see the current state of the tutorial on https://eressea.github.io/tutorials/. + + +## eleventy-blog + +We use [11ty](https://www.11ty.dev/) for creating the documentation. + +See here for an example using eleventy: + +### Creating A Blog With Eleventy [https://keepinguptodate.com/pages/2019/06/creating-blog-with-eleventy/](https://keepinguptodate.com/pages/2019/06/creating-blog-with-eleventy/) A demo of the blog is hosted on Netlify: [https://dazzling-almeida-ca0492.netlify.com/](https://dazzling-almeida-ca0492.netlify.com/) -## Branches +### Branches This repo contains several branches that allow you to checkout the code at various stages of development. -## How do I run the site? +### How do I run the site? ``` npm install npm run serve diff --git a/_includes/base-layout.njk b/_includes/base-layout.njk index 0176540..87b9a68 100644 --- a/_includes/base-layout.njk +++ b/_includes/base-layout.njk @@ -15,6 +15,37 @@
{{ content | safe }} + {%- set currentindex = 0 %} +{%- set lastindex = 0 %} +{%- set radius = 1 %} +{%- for pageEntry in pagination.pages %} +{%- if page.url == pagination.hrefs[ loop.index0 ] %} +{%- set currentindex = loop.index0 %} +{%- endif %} +{%- set lastindex = loop.index0 %} +{%- endfor %} + +{%- if lastindex > 0 %} + + +{% endif %}
© Eressea PBEM
diff --git a/_includes/post-layout.njk b/_includes/post-layout.njk index 66e0824..872cecb 100644 --- a/_includes/post-layout.njk +++ b/_includes/post-layout.njk @@ -3,6 +3,10 @@ layout: base-layout.njk ---

{{ title }}

+ {% if author %}{{author}},{% else %}N.N.,{% endif %} {{ content | safe }} -
\ No newline at end of file + +
+Tags: {{tags}} +
diff --git a/css/site.css b/css/site.css index f209ea0..0ad2f31 100644 --- a/css/site.css +++ b/css/site.css @@ -23,21 +23,22 @@ pre { header { display: flex; - align-items: center; /* Vertically align */ + align-items: center; + /* Vertically align */ padding: 5px 16px; color: white; background-color: #0747A6; border-radius: 8px; } -header > a:link, -header > a:visited, -header > a:hover { +header>a:link, +header>a:visited, +header>a:hover { color: white; text-decoration: none; } -header > a:hover { +header>a:hover { text-decoration: underline; } @@ -54,7 +55,7 @@ header > a:hover { main { padding: 5px 16px; - word-wrap:break-word; + word-wrap: break-word; } footer { @@ -74,12 +75,12 @@ h1 { font-size: 2em; } -h1 > a:link, -h1 > a:visited { +h1>a:link, +h1>a:visited { text-decoration: none; } -h1 > a:hover { +h1>a:hover { color: #20399daa; text-decoration: underline; } @@ -97,11 +98,21 @@ a:hover { color: #20399daa; } -time { +time, +author { color: #666666; } article img { width: 100%; height: auto; +} + +ol.navlist { + list-style: none; + padding-left: 0; +} + +ol.navlist li { + display: inline-block; } \ No newline at end of file diff --git a/index.njk b/index.njk index 3d0574b..596be84 100644 --- a/index.njk +++ b/index.njk @@ -1,6 +1,11 @@ --- layout: base-layout.njk title: Eressea Beispielpartie +pagination: + data: collections.race + size: 12 + reverse: false + alias: races ---

Eressea Tutorial 2024

@@ -10,7 +15,7 @@ Bericht hier zur Verfügung stellen.

Some of these will be in English, some in German.

-{% for post in collections.race %} +{% for post in races %}

{{ post.data.title }} diff --git a/nogoblins/Auswertung_01.md b/nogoblins/Auswertung_01.md new file mode 100644 index 0000000..88f5fc9 --- /dev/null +++ b/nogoblins/Auswertung_01.md @@ -0,0 +1,9 @@ +--- +author: "enno" +title: "Not Goblins: Runde 1" +date: 2024-03-17 +--- +# Runde 1 +## Die Auswertung + +Lore ipsum 1... \ No newline at end of file diff --git a/nogoblins/Auswertung_02.md b/nogoblins/Auswertung_02.md new file mode 100644 index 0000000..972f8d2 --- /dev/null +++ b/nogoblins/Auswertung_02.md @@ -0,0 +1,10 @@ +--- +title: "Not Goblins: Runde 2" +date: 2024-03-24 +--- +# Runde 2 + +## Die Auswertung + + +Lore ipsum 2 ... \ No newline at end of file diff --git a/nogoblins/Auswertung_03.md b/nogoblins/Auswertung_03.md new file mode 100644 index 0000000..7909e11 --- /dev/null +++ b/nogoblins/Auswertung_03.md @@ -0,0 +1,8 @@ +--- +title: "Not Goblins: Runde 3" +date: 2024-03-31 +--- +# Runde 3 +## Die Auswertung + +Lore ipsum 3 ... \ No newline at end of file diff --git a/nogoblins/Auswertung_04.md b/nogoblins/Auswertung_04.md new file mode 100644 index 0000000..cf7dc1b --- /dev/null +++ b/nogoblins/Auswertung_04.md @@ -0,0 +1,8 @@ +--- +title: "Not Goblins: Runde 4" +date: 2024-04-07 +--- +# Runde 4 +## Die Auswertung + +Lore ipsum 4 ... \ No newline at end of file diff --git a/nogoblins/Auswertung_05.md b/nogoblins/Auswertung_05.md new file mode 100644 index 0000000..4529d19 --- /dev/null +++ b/nogoblins/Auswertung_05.md @@ -0,0 +1,8 @@ +--- +title: "Not Goblins: Runde 5" +date: 2024-04-14 +--- +# Runde 5 +## Die Auswertung + +Lore ipsum 5 ... \ No newline at end of file diff --git a/nogoblins/Auswertung_06.md b/nogoblins/Auswertung_06.md new file mode 100644 index 0000000..4bcf079 --- /dev/null +++ b/nogoblins/Auswertung_06.md @@ -0,0 +1,8 @@ +--- +title: "Not Goblins: Runde 6" +date: 2024-04-21 +--- +# Runde 6 +## Die Auswertung + +Lore ipsum 6 ... \ No newline at end of file diff --git a/nogoblins/Auswertung_07.md b/nogoblins/Auswertung_07.md new file mode 100644 index 0000000..4ac6189 --- /dev/null +++ b/nogoblins/Auswertung_07.md @@ -0,0 +1,9 @@ +--- +title: "Not Goblins: Runde 7" +date: 2024-04-28 +--- +# Runde 7 +## Die Auswertung + + +Lore ipsum 7 ... \ No newline at end of file diff --git a/nogoblins/Auswertung_08.md b/nogoblins/Auswertung_08.md new file mode 100644 index 0000000..16a6f31 --- /dev/null +++ b/nogoblins/Auswertung_08.md @@ -0,0 +1,9 @@ +--- +title: "Not Goblins: Runde 8" +date: 2024-05-05 +--- +# Runde 8 +## Die Auswertung + + +Lore ipsum 8 ... \ No newline at end of file diff --git a/nogoblins/Auswertung_09.md b/nogoblins/Auswertung_09.md new file mode 100644 index 0000000..f971d02 --- /dev/null +++ b/nogoblins/Auswertung_09.md @@ -0,0 +1,9 @@ +--- +title: "Not Goblins: Runde 9" +date: 2024-05-12 +--- +# Runde 9 +## Die Auswertung + + +Lore ipsum 9 ... \ No newline at end of file diff --git a/nogoblins/index.njk b/nogoblins/index.njk new file mode 100644 index 0000000..d389817 --- /dev/null +++ b/nogoblins/index.njk @@ -0,0 +1,26 @@ +--- +layout: base-layout.njk +title: Not Goblins! +override:tags: ["race"] +pagination: + data: collections.nogoblin + size: 8 + reverse: false + alias: posts +--- +{% for post in posts %} +
+ +

+ {{ post.data.title }} +

+ + + + {% excerpt post %} + + Read more + +
+{% endfor %} + diff --git a/nogoblins/nogoblins.json b/nogoblins/nogoblins.json new file mode 100644 index 0000000..6544d3a --- /dev/null +++ b/nogoblins/nogoblins.json @@ -0,0 +1,5 @@ +{ + "author": "enno", + "layout": "post-layout.njk", + "tags": "nogoblin" +} \ No newline at end of file From 32f50978a5e38b107784e1839b1ef295947d59f3 Mon Sep 17 00:00:00 2001 From: Steffen Mecke Date: Thu, 14 Aug 2025 09:14:19 +0200 Subject: [PATCH 03/34] page title --- _includes/base-layout.njk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_includes/base-layout.njk b/_includes/base-layout.njk index 87b9a68..5b22c35 100644 --- a/_includes/base-layout.njk +++ b/_includes/base-layout.njk @@ -3,7 +3,7 @@ - Eressea Beispielpartie + Eressea Beispielpartie - {{title}} From 003636eecb5f3cbd2cf3a2a6298d8d5533adbadf Mon Sep 17 00:00:00 2001 From: Steffen Mecke Date: Thu, 14 Aug 2025 20:59:15 +0200 Subject: [PATCH 04/34] working cr to svg conversion --- .eleventy.js | 10 +- _includes/post-layout.njk | 2 + crs/crs-passthrough.js | 30 ++ crs/crs.js | 302 +++++++++++ images/active.svg | 96 ++++ images/akademie der kuenste.svg | 37 ++ images/akademie.svg | 26 + images/aktiver vulkan.svg | 298 +++++++++++ images/barke0.svg | 60 +++ images/barke1.svg | 60 +++ images/barke2.svg | 57 ++ images/barke3.svg | 57 ++ images/barke4.svg | 64 +++ images/barke5.svg | 60 +++ images/barke6.svg | 54 ++ images/befestigung.svg | 30 ++ images/berge.svg | 280 ++++++++++ images/bergwerk.svg | 41 ++ images/boat0.svg | 49 ++ images/boat1.svg | 43 ++ images/boat2.svg | 40 ++ images/boat3.svg | 35 ++ images/boat4.svg | 35 ++ images/boat5.svg | 36 ++ images/boat6.svg | 28 + images/boot0.svg | 49 ++ images/boot1.svg | 43 ++ images/boot2.svg | 40 ++ images/boot3.svg | 35 ++ images/boot4.svg | 35 ++ images/boot5.svg | 36 ++ images/boot6.svg | 28 + images/burg.svg | 48 ++ images/damm.svg | 35 ++ images/dichter nebel.svg | 165 ++++++ images/drachenschiff0.svg | 63 +++ images/drachenschiff1.svg | 61 +++ images/drachenschiff2.svg | 56 ++ images/drachenschiff3.svg | 46 ++ images/drachenschiff4.svg | 59 +++ images/drachenschiff5.svg | 64 +++ images/drachenschiff6.svg | 50 ++ images/dragonship0.svg | 63 +++ images/dragonship1.svg | 61 +++ images/dragonship2.svg | 56 ++ images/dragonship3.svg | 46 ++ images/dragonship4.svg | 59 +++ images/dragonship5.svg | 64 +++ images/dragonship6.svg | 50 ++ images/ebene.svg | 265 ++++++++++ images/einbaum0.svg | 65 +++ images/einbaum1.svg | 57 ++ images/einbaum2.svg | 51 ++ images/einbaum3.svg | 41 ++ images/einbaum4.svg | 48 ++ images/einbaum5.svg | 51 ++ images/einbaum6.svg | 45 ++ images/eisberg.svg | 332 ++++++++++++ images/eisscholle.svg | 287 ++++++++++ images/eisscholle2.svg | 258 +++++++++ images/festung.svg | 50 ++ images/feuerwand.svg | 226 ++++++++ images/feuerwand0.svg | 57 ++ images/feuerwand1.svg | 58 ++ images/feuerwand2.svg | 30 ++ images/feuerwand3.svg | 57 ++ images/feuerwand4.svg | 59 +++ images/feuerwand5.svg | 32 ++ images/floss0.svg | 57 ++ images/floss1.svg | 37 ++ images/floss2.svg | 33 ++ images/floss3.svg | 34 ++ images/floss4.svg | 40 ++ images/floss5.svg | 41 ++ images/floss6.svg | 38 ++ images/fregatte0.svg | 69 +++ images/fregatte1.svg | 71 +++ images/fregatte2.svg | 68 +++ images/fregatte3.svg | 62 +++ images/fregatte4.svg | 77 +++ images/fregatte5.svg | 74 +++ images/fregatte6.svg | 52 ++ images/galeone0.svg | 74 +++ images/galeone1.svg | 62 +++ images/galeone2.svg | 54 ++ images/galeone3.svg | 48 ++ images/galeone4.svg | 63 +++ images/galeone5.svg | 64 +++ images/galeone6.svg | 49 ++ images/gang.svg | 340 ++++++++++++ images/gebirge.svg | 280 ++++++++++ images/geruest.svg | 30 ++ images/gesegneter steinkreis.svg | 30 ++ images/gletscher.svg | 249 +++++++++ images/grundmauern.svg | 31 ++ images/hafen.svg | 44 ++ images/halle.svg | 340 ++++++++++++ images/handelsposten.svg | 31 ++ images/hochland.svg | 289 ++++++++++ images/irrlichter0.svg | 30 ++ images/irrlichter1.svg | 30 ++ images/irrlichter2.svg | 26 + images/irrlichter3.svg | 30 ++ images/irrlichter4.svg | 31 ++ images/irrlichter5.svg | 26 + images/karavelle0.svg | 67 +++ images/karavelle1.svg | 47 ++ images/karavelle2.svg | 42 ++ images/karavelle3.svg | 43 ++ images/karavelle30.svg | 68 +++ images/karavelle4.svg | 52 ++ images/karavelle5.svg | 53 ++ images/karavelle6.svg | 39 ++ images/karawane0.svg | 45 ++ images/karawanserei.svg | 29 + images/katamaran0.svg | 48 ++ images/katamaran1.svg | 42 ++ images/katamaran2.svg | 39 ++ images/katamaran3.svg | 36 ++ images/katamaran4.svg | 47 ++ images/katamaran5.svg | 47 ++ images/katamaran6.svg | 41 ++ images/koenigsbarke0.svg | 60 +++ images/koenigsbarke1.svg | 60 +++ images/koenigsbarke2.svg | 57 ++ images/koenigsbarke3.svg | 57 ++ images/koenigsbarke4.svg | 64 +++ images/koenigsbarke5.svg | 60 +++ images/koenigsbarke6.svg | 54 ++ images/kogge0.svg | 64 +++ images/kogge1.svg | 61 +++ images/kogge2.svg | 58 ++ images/kogge3.svg | 57 ++ images/kogge4.svg | 70 +++ images/kogge5.svg | 66 +++ images/kogge6.svg | 55 ++ images/korallenriff.svg | 333 ++++++++++++ images/kutter0.svg | 50 ++ images/kutter1.svg | 48 ++ images/kutter2.svg | 44 ++ images/kutter3.svg | 39 ++ images/kutter4.svg | 50 ++ images/kutter5.svg | 50 ++ images/kutter6.svg | 42 ++ images/langboot0.svg | 50 ++ images/langboot1.svg | 48 ++ images/langboot2.svg | 44 ++ images/langboot3.svg | 39 ++ images/langboot4.svg | 50 ++ images/langboot5.svg | 50 ++ images/langboot6.svg | 42 ++ images/leere.svg | 237 +++++++++ images/leuchtturm.svg | 32 ++ images/longboat0.svg | 50 ++ images/longboat1.svg | 48 ++ images/longboat2.svg | 44 ++ images/longboat3.svg | 39 ++ images/longboat4.svg | 50 ++ images/longboat5.svg | 50 ++ images/longboat6.svg | 42 ++ images/magierturm.svg | 40 ++ images/mahlstrom.svg | 297 +++++++++++ images/markt.svg | 37 ++ images/marktplatz.svg | 37 ++ images/monument.svg | 32 ++ images/nebel.svg | 70 +++ images/notype.svg | 9 + images/ozean.svg | 299 +++++++++++ images/packeis.svg | 348 ++++++++++++ images/pfeil0.svg | 86 +++ images/pfeil1.svg | 85 +++ images/pfeil2.svg | 124 +++++ images/pfeil3.svg | 86 +++ images/pfeil4.svg | 84 +++ images/pfeil5.svg | 126 +++++ images/pferdezucht.svg | 36 ++ images/portal.svg | 47 ++ images/regenwald.svg | 304 +++++++++++ images/saegewerk.svg | 36 ++ images/schemen.svg | 9 + images/schiff0.svg | 29 + images/schiff1.svg | 29 + images/schiff2.svg | 27 + images/schiff3.svg | 25 + images/schiff4.svg | 27 + images/schiff5.svg | 30 ++ images/schiff6.svg | 27 + images/schloss.svg | 43 ++ images/schmiede.svg | 31 ++ images/schoner0.svg | 73 +++ images/schoner1.svg | 67 +++ images/schoner2.svg | 59 +++ images/schoner3.svg | 50 ++ images/schoner4.svg | 65 +++ images/schoner5.svg | 68 +++ images/schoner6.svg | 52 ++ images/selected.svg | 84 +++ images/steinbruch.svg | 42 ++ images/steinkreis.svg | 47 ++ images/sumpf.svg | 312 +++++++++++ images/taverne.svg | 44 ++ images/trireme0.svg | 77 +++ images/trireme1.svg | 68 +++ images/trireme2.svg | 53 ++ images/trireme3.svg | 59 +++ images/trireme4.svg | 72 +++ images/trireme5.svg | 69 +++ images/trireme6.svg | 58 ++ images/tundra.svg | 167 ++++++ images/tunnel.svg | 42 ++ images/turm.svg | 29 + images/uebergang.svg | 91 ++++ images/unbekannt.svg | 9 + images/units.svg | 82 +++ images/vulkan.svg | 363 +++++++++++++ images/wachstube.svg | 30 ++ images/wachturm.svg | 37 ++ images/wald.svg | 365 +++++++++++++ images/wand.svg | 326 ++++++++++++ images/wueste.svg | 274 ++++++++++ images/zitadelle.svg | 55 ++ images/zweimast0.svg | 64 +++ nogoblins/Auswertung_01.md | 6 + nogoblins/crs/334-42.cr | 874 +++++++++++++++++++++++++++++++ 224 files changed, 18104 insertions(+), 3 deletions(-) create mode 100644 crs/crs-passthrough.js create mode 100644 crs/crs.js create mode 100644 images/active.svg create mode 100644 images/akademie der kuenste.svg create mode 100644 images/akademie.svg create mode 100644 images/aktiver vulkan.svg create mode 100644 images/barke0.svg create mode 100644 images/barke1.svg create mode 100644 images/barke2.svg create mode 100644 images/barke3.svg create mode 100644 images/barke4.svg create mode 100644 images/barke5.svg create mode 100644 images/barke6.svg create mode 100644 images/befestigung.svg create mode 100644 images/berge.svg create mode 100644 images/bergwerk.svg create mode 100644 images/boat0.svg create mode 100644 images/boat1.svg create mode 100644 images/boat2.svg create mode 100644 images/boat3.svg create mode 100644 images/boat4.svg create mode 100644 images/boat5.svg create mode 100644 images/boat6.svg create mode 100644 images/boot0.svg create mode 100644 images/boot1.svg create mode 100644 images/boot2.svg create mode 100644 images/boot3.svg create mode 100644 images/boot4.svg create mode 100644 images/boot5.svg create mode 100644 images/boot6.svg create mode 100644 images/burg.svg create mode 100644 images/damm.svg create mode 100644 images/dichter nebel.svg create mode 100644 images/drachenschiff0.svg create mode 100644 images/drachenschiff1.svg create mode 100644 images/drachenschiff2.svg create mode 100644 images/drachenschiff3.svg create mode 100644 images/drachenschiff4.svg create mode 100644 images/drachenschiff5.svg create mode 100644 images/drachenschiff6.svg create mode 100644 images/dragonship0.svg create mode 100644 images/dragonship1.svg create mode 100644 images/dragonship2.svg create mode 100644 images/dragonship3.svg create mode 100644 images/dragonship4.svg create mode 100644 images/dragonship5.svg create mode 100644 images/dragonship6.svg create mode 100644 images/ebene.svg create mode 100644 images/einbaum0.svg create mode 100644 images/einbaum1.svg create mode 100644 images/einbaum2.svg create mode 100644 images/einbaum3.svg create mode 100644 images/einbaum4.svg create mode 100644 images/einbaum5.svg create mode 100644 images/einbaum6.svg create mode 100644 images/eisberg.svg create mode 100644 images/eisscholle.svg create mode 100644 images/eisscholle2.svg create mode 100644 images/festung.svg create mode 100644 images/feuerwand.svg create mode 100644 images/feuerwand0.svg create mode 100644 images/feuerwand1.svg create mode 100644 images/feuerwand2.svg create mode 100644 images/feuerwand3.svg create mode 100644 images/feuerwand4.svg create mode 100644 images/feuerwand5.svg create mode 100644 images/floss0.svg create mode 100644 images/floss1.svg create mode 100644 images/floss2.svg create mode 100644 images/floss3.svg create mode 100644 images/floss4.svg create mode 100644 images/floss5.svg create mode 100644 images/floss6.svg create mode 100644 images/fregatte0.svg create mode 100644 images/fregatte1.svg create mode 100644 images/fregatte2.svg create mode 100644 images/fregatte3.svg create mode 100644 images/fregatte4.svg create mode 100644 images/fregatte5.svg create mode 100644 images/fregatte6.svg create mode 100644 images/galeone0.svg create mode 100644 images/galeone1.svg create mode 100644 images/galeone2.svg create mode 100644 images/galeone3.svg create mode 100644 images/galeone4.svg create mode 100644 images/galeone5.svg create mode 100644 images/galeone6.svg create mode 100644 images/gang.svg create mode 100644 images/gebirge.svg create mode 100644 images/geruest.svg create mode 100644 images/gesegneter steinkreis.svg create mode 100644 images/gletscher.svg create mode 100644 images/grundmauern.svg create mode 100644 images/hafen.svg create mode 100644 images/halle.svg create mode 100644 images/handelsposten.svg create mode 100644 images/hochland.svg create mode 100644 images/irrlichter0.svg create mode 100644 images/irrlichter1.svg create mode 100644 images/irrlichter2.svg create mode 100644 images/irrlichter3.svg create mode 100644 images/irrlichter4.svg create mode 100644 images/irrlichter5.svg create mode 100644 images/karavelle0.svg create mode 100644 images/karavelle1.svg create mode 100644 images/karavelle2.svg create mode 100644 images/karavelle3.svg create mode 100644 images/karavelle30.svg create mode 100644 images/karavelle4.svg create mode 100644 images/karavelle5.svg create mode 100644 images/karavelle6.svg create mode 100644 images/karawane0.svg create mode 100644 images/karawanserei.svg create mode 100644 images/katamaran0.svg create mode 100644 images/katamaran1.svg create mode 100644 images/katamaran2.svg create mode 100644 images/katamaran3.svg create mode 100644 images/katamaran4.svg create mode 100644 images/katamaran5.svg create mode 100644 images/katamaran6.svg create mode 100644 images/koenigsbarke0.svg create mode 100644 images/koenigsbarke1.svg create mode 100644 images/koenigsbarke2.svg create mode 100644 images/koenigsbarke3.svg create mode 100644 images/koenigsbarke4.svg create mode 100644 images/koenigsbarke5.svg create mode 100644 images/koenigsbarke6.svg create mode 100644 images/kogge0.svg create mode 100644 images/kogge1.svg create mode 100644 images/kogge2.svg create mode 100644 images/kogge3.svg create mode 100644 images/kogge4.svg create mode 100644 images/kogge5.svg create mode 100644 images/kogge6.svg create mode 100644 images/korallenriff.svg create mode 100644 images/kutter0.svg create mode 100644 images/kutter1.svg create mode 100644 images/kutter2.svg create mode 100644 images/kutter3.svg create mode 100644 images/kutter4.svg create mode 100644 images/kutter5.svg create mode 100644 images/kutter6.svg create mode 100644 images/langboot0.svg create mode 100644 images/langboot1.svg create mode 100644 images/langboot2.svg create mode 100644 images/langboot3.svg create mode 100644 images/langboot4.svg create mode 100644 images/langboot5.svg create mode 100644 images/langboot6.svg create mode 100644 images/leere.svg create mode 100644 images/leuchtturm.svg create mode 100644 images/longboat0.svg create mode 100644 images/longboat1.svg create mode 100644 images/longboat2.svg create mode 100644 images/longboat3.svg create mode 100644 images/longboat4.svg create mode 100644 images/longboat5.svg create mode 100644 images/longboat6.svg create mode 100644 images/magierturm.svg create mode 100644 images/mahlstrom.svg create mode 100644 images/markt.svg create mode 100644 images/marktplatz.svg create mode 100644 images/monument.svg create mode 100644 images/nebel.svg create mode 100644 images/notype.svg create mode 100644 images/ozean.svg create mode 100644 images/packeis.svg create mode 100644 images/pfeil0.svg create mode 100644 images/pfeil1.svg create mode 100644 images/pfeil2.svg create mode 100644 images/pfeil3.svg create mode 100644 images/pfeil4.svg create mode 100644 images/pfeil5.svg create mode 100644 images/pferdezucht.svg create mode 100644 images/portal.svg create mode 100644 images/regenwald.svg create mode 100644 images/saegewerk.svg create mode 100644 images/schemen.svg create mode 100644 images/schiff0.svg create mode 100644 images/schiff1.svg create mode 100644 images/schiff2.svg create mode 100644 images/schiff3.svg create mode 100644 images/schiff4.svg create mode 100644 images/schiff5.svg create mode 100644 images/schiff6.svg create mode 100644 images/schloss.svg create mode 100644 images/schmiede.svg create mode 100644 images/schoner0.svg create mode 100644 images/schoner1.svg create mode 100644 images/schoner2.svg create mode 100644 images/schoner3.svg create mode 100644 images/schoner4.svg create mode 100644 images/schoner5.svg create mode 100644 images/schoner6.svg create mode 100644 images/selected.svg create mode 100644 images/steinbruch.svg create mode 100644 images/steinkreis.svg create mode 100644 images/sumpf.svg create mode 100644 images/taverne.svg create mode 100644 images/trireme0.svg create mode 100644 images/trireme1.svg create mode 100644 images/trireme2.svg create mode 100644 images/trireme3.svg create mode 100644 images/trireme4.svg create mode 100644 images/trireme5.svg create mode 100644 images/trireme6.svg create mode 100644 images/tundra.svg create mode 100644 images/tunnel.svg create mode 100644 images/turm.svg create mode 100644 images/uebergang.svg create mode 100644 images/unbekannt.svg create mode 100644 images/units.svg create mode 100644 images/vulkan.svg create mode 100644 images/wachstube.svg create mode 100644 images/wachturm.svg create mode 100644 images/wald.svg create mode 100644 images/wand.svg create mode 100644 images/wueste.svg create mode 100644 images/zitadelle.svg create mode 100644 images/zweimast0.svg create mode 100644 nogoblins/crs/334-42.cr diff --git a/.eleventy.js b/.eleventy.js index 92a55e7..b888f29 100644 --- a/.eleventy.js +++ b/.eleventy.js @@ -1,3 +1,4 @@ +const crs = require('./crs/crs.js'); const moment = require('moment'); moment.locale('en'); @@ -11,9 +12,9 @@ module.exports = function (eleventyConfig) { // https://github.com/victornpb/eleventy-plugin-page-assets eleventyConfig.addPlugin(pageAssetsPlugin, { - mode: "parse", - assetsMatching: "*.png|*.PNG|*.jpg|*.JPG|*.gif|*.GIF", - postsMatching: "**/*.md", + mode: "parse", + assetsMatching: "*.png|*.PNG|*.jpg|*.JPG|*.gif|*.GIF", + postsMatching: "**/*.md", }); eleventyConfig.addFilter('dateIso', date => { @@ -28,6 +29,9 @@ module.exports = function (eleventyConfig) { // Folders to copy to output folder eleventyConfig.addPassthroughCopy("css"); + + crs(eleventyConfig); + }; module.exports.config = { diff --git a/_includes/post-layout.njk b/_includes/post-layout.njk index 872cecb..f3e88f3 100644 --- a/_includes/post-layout.njk +++ b/_includes/post-layout.njk @@ -1,6 +1,8 @@ --- layout: base-layout.njk --- + +

{{ title }}

{% if author %}{{author}},{% else %}N.N.,{% endif %} diff --git a/crs/crs-passthrough.js b/crs/crs-passthrough.js new file mode 100644 index 0000000..337907b --- /dev/null +++ b/crs/crs-passthrough.js @@ -0,0 +1,30 @@ +function showDescription(event, div_id, id) { + event.preventDefault(); + if (id) { + let element = document.getElementById(div_id); + let desc = document.getElementById(id).children[1].innerHTML; + element.innerHTML = desc; + element.style.display = "block"; + } + return false; +} + +function positionTooltip(event) { + const tooltip = document.getElementById('tooltip'); + const x = event.clientX; + const y = event.clientY; + tooltip.style.left = `${x}px`; + tooltip.style.top = `${y}px`; +} + +function showTooltip(event, text) { + const tooltip = document.getElementById('tooltip'); + tooltip.innerHTML = text; + tooltip.style.display = 'block'; + positionTooltip(event); +} + +function hideTooltip() { + const tooltip = document.getElementById('tooltip'); + tooltip.style.display = 'none'; +} \ No newline at end of file diff --git a/crs/crs.js b/crs/crs.js new file mode 100644 index 0000000..07da39d --- /dev/null +++ b/crs/crs.js @@ -0,0 +1,302 @@ +// crs.js + +const fs = require('fs'); +const path = require('path'); + +// Color and image mappings from PHP +const colors = { + 'default': 'grey', + 'Ozean': '#0000ff', + 'Ebene': '#ffff00', + 'Wald': '#00dd00', + 'Sumpf': '#226611', + 'Berge': '#777777', + 'Hochland': '#ffeeaa', + 'Wüste': '#ffcc55', + 'Gletscher': '#bbbbcc', + 'Eisberg': '#eeeeff', + 'Vulkan': '#bb0022', + 'Aktiver Vulkan': '#ee0022', + 'Feuerwand': '#ff0000', +}; + +const images = { + 'Ozean': 'ozean', + 'Ebene': 'ebene', + 'Wald': 'wald', + 'Sumpf': 'sumpf', + 'Berge': 'berge', + 'Hochland': 'hochland', + 'Wüste': 'wueste', + 'Gletscher': 'gletscher', + 'Eisberg': 'eisberg', + 'Vulkan': 'vulkan', + 'Aktiver Vulkan': 'aktiver vulkan', + 'Feuerwand': 'feuerwand', + 'Nebel': 'nebel', + 'Dichter Nebel': 'dichter nebel', + 'Packeis': 'packeis', + 'Gang': 'gang', + 'Halle': 'halle', + 'Wand': 'wand', +}; + +const defaultImage = 'region'; + + + +function getColor(terrain) { + return colors[terrain] || colors['default']; +} + +function getImage(terrain) { + return images[terrain] || null; +} + +const rwidth = 100; +const yoff = rwidth * 0.5; + +function transformx(region) { + return Math.round(region.x * rwidth + region.y * yoff); +} +function transformy(region) { + return Math.round(region.y * -rwidth * 3 / 4); +} + +function parseRegion(line, matches) { + const parts = line.trim().split(/\s+/); + const region = { tags: [], units: [] }; + region.x = parseInt(matches[1], 10); + region.y = parseInt(matches[2], 10); + if (matches[3]) region.z = parseInt(matches[3], 10); + console.log("found region ", region); + + return region; +} + +function outputRegion(region, bounds) { + if (!region) return ''; + if (!region.tags.Terrain) return ''; + let color = getColor(region.tags.Terrain); + let tag = getImage(region.tags.Terrain); + if (!tag) { + tag = defaultImage; + color = `fill=\"${color}\"`; + } else { + color = ''; + } + const xx = region.x; + const yy = region.y; + const x = transformx(region); + const y = transformy(region); + let tt = region.tags.Name ? region.tags.Name : region.tags.Terrain; + tt += ` (${xx}, ${yy})`; + let desc = ''; + console.log('tags ', region.tags); + + + desc = Object.entries(region.tags) + .map(([key, value]) => `${key}: ${value}
`) + .join('\n'); + + let id = 'r_'; + id += xx < 0 ? `m${-xx}` : xx; + id += yy < 0 ? `_m${-yy}` : `_${yy}`; + // Update bounds + bounds.xmin = Math.min(bounds.xmin, x); + bounds.ymin = Math.min(bounds.ymin, y); + bounds.xmax = Math.max(bounds.xmax, x); + bounds.ymax = Math.max(bounds.ymax, y); + // console.log(region.units); + let units = ''; + let udesc = ''; + if (region.units.length > 0) { + desc += `Units:
`; + Object.entries(region.units).forEach(([id, unit]) => { + console.log(`Unit ${id} skills:`, unit.skills); + const uid = `u_${unit.id}`; + udesc += `
`; + desc += `${unit.tags.Name} (${unit.id})
`; + udesc += `${unit.tags.Name} (${unit.id})`; + if (unit.skills) { + udesc += ' ' + Object.entries(unit.skills).map(([key, value]) => `${key} ${value}`).join(', '); + } + udesc += '
\n'; + udesc += Object.entries(unit.tags).filter(([key, value]) => key !== 'Name') + .map(([key, value]) => `${key}: ${value}
`) + .join('\n'); + udesc += `
`; + }); + + units = `${udesc}`; + } + + // onmousemove="showTooltip(evt, '${tt}');" + // onmouseout="hideTooltip();" + // onclick = "showDescription(event, '${desc}');" + return `` + + `${tt}${desc}\n` + + units + ``; + +} + + +function includeImage(image) { + // Looks for images/.svg and includes its content as a ... + const imgPath = path.resolve(process.cwd(), 'images', image + '.svg'); + if (fs.existsSync(imgPath)) { + let contents = fs.readFileSync(imgPath, 'utf8'); + // Extract only the inner SVG content (remove outer tags) + const match = contents.match(/]*>([\s\S]*?)<\/svg>/i); + contents = match ? match[1] : contents; + return ` ${contents} `; + } else { + // Optionally log a warning or just skip + // console.warn(`Warning: Image not found: ${imgPath}`); + return ` \n`; + } +} + +function outputFront(bounds) { + // SVG header and region polygon definition, plus terrain images + let svg = + `\n` + + `\n` + + ` \n` + + ` \n` + + ` \n` + + ` \n`; + // Include all terrain images + console.log(`Including terrain images...`); + for (const terrain in images) { + console.log(`Including terrain: ${terrain}`); + if (Object.prototype.hasOwnProperty.call(images, terrain)) { + svg += includeImage(images[terrain]); + } + } + svg += includeImage('units'); + svg += ` \n \n`; + return svg; +} + +function outputBack() { + return '\n'; +} + +function parseSkill(key) { + return parseInt(key.trim().split(/\s+/)[1], 10); +} + +function parseCrFile(filePath) { + console.log(`Processing CR file: ${filePath}`); + const content = fs.readFileSync(filePath, 'utf8'); + const lines = content.split(/\r?\n/); + const pregRegion = /^REGION (-?\d+) (-?\d+)(?: (-?\d+))?$/; + const pregTagq = /^"(.*)";(.*)$/; + const pregTag = /^(.*);(.*)$/; + const pregBlock = /^([A-Z]+)\s*(.*)$/; + const pregUnit = /^EINHEIT (\d+)$/; + let region = null; + let unit = null; + let block = null; + let svgContent = ''; + let bounds = { xmin: Infinity, ymin: Infinity, xmax: -Infinity, ymax: -Infinity }; + let regions = []; + for (let line of lines) { + let tag = null, value = null; + let matches; + if ((matches = pregRegion.exec(line))) { + if (region) regions.push(region); + block = 'REGION'; + region = parseRegion(line, matches); + } else if (region && (matches = pregUnit.exec(line))) { + block = 'UNIT'; + // Parse unit and add to current region + region.units = region.units || []; + let id = matches[1]; + unit = { + id: matches[1], + name: '???', + tags: [] + }; + region.units[id] = unit; + console.log(`Found unit ${unit.id} in region ${region.x}, ${region.y}`); + } else if ((matches = pregTagq.exec(line))) { + value = matches[1]; + tag = matches[2]; + console.log(`Found tag ${tag} with value ${value} in block ${block}`); + } else if ((matches = pregTag.exec(line))) { + value = matches[1]; + tag = matches[2]; + console.log(`Found tag ${tag} with value ${value} in block ${block}`); + } else if ((matches = pregBlock.exec(line))) { + block = matches[1]; + console.log(`Found block ${block}`); + } + + if (tag) { + if (block === "REGION" && region) { + region.tags[tag] = value; + } else if (block === "UNIT" && unit) { + unit.tags[tag] = value; + region.units[unit.id] = unit; + } + else if (block === "TALENTE" && region && unit) { + unit.skills = unit.skills || {}; + unit.skills[tag] = parseSkill(value); + // region.units[unit.id] = unit; + } + } + } + if (region) regions.push(region); + // Output regions and units + for (const reg of regions) { + svgContent += outputRegion(reg, bounds); + } + // // Output units as icons on top of regions + // for (const reg of regions) { + // if (reg.units && reg.units.length > 0) { + // console.log(`Outputting units for region: ${reg.Name}`); + // const x = transformx(reg); + // const y = transformy(reg); + // let ux = x + 50; // offset to center of hex + // let uy = y + 50; + + // for (const unit of reg.units.filter(Boolean)) { + // console.log(`Outputting unit for region ${reg.Name}: ${unit.name} [${unit.num}]`); + // } + // } + // } + svgContent = outputFront(bounds) + svgContent + outputBack(); + // console.log(`returning ${svgContent}`); + return svgContent; +} + +module.exports = function (eleventyConfig) { + eleventyConfig.addShortcode('crmap', function (file) { + // file is relative to the project root or input dir + try { + console.log(`Processing CR file: ${file}`); + const filePath = path.resolve(process.cwd(), file); + if (!fs.existsSync(filePath)) { + console.log(`File not found: ${filePath}`); + return `
File not found: ${file}
`; + } + const svg = parseCrFile(filePath); + return `
${svg}
\n` + + `
You need to enable Javascript for this to work.
\n` + + `
You need to enable Javascript for this to work.
`; + } catch (e) { + console.log(`Error processing file: ${filePath} `); + return `< div style = "max-width:100%; max-height:600px; overflow:auto; display:flex; align-items:center; justify-content:center; color:#a00; font-family:monospace; font-size:1.2em; min-height:200px;" > Error: ${e.message} `; + } + }); + + eleventyConfig.addPassthroughCopy("crs/crs-passthrough.js"); + +}; diff --git a/images/active.svg b/images/active.svg new file mode 100644 index 0000000..596bf6e --- /dev/null +++ b/images/active.svg @@ -0,0 +1,96 @@ + + + + diff --git a/images/akademie der kuenste.svg b/images/akademie der kuenste.svg new file mode 100644 index 0000000..7accb3e --- /dev/null +++ b/images/akademie der kuenste.svg @@ -0,0 +1,37 @@ + + + + diff --git a/images/akademie.svg b/images/akademie.svg new file mode 100644 index 0000000..45d0212 --- /dev/null +++ b/images/akademie.svg @@ -0,0 +1,26 @@ + + + + diff --git a/images/aktiver vulkan.svg b/images/aktiver vulkan.svg new file mode 100644 index 0000000..507578e --- /dev/null +++ b/images/aktiver vulkan.svg @@ -0,0 +1,298 @@ + + + + diff --git a/images/barke0.svg b/images/barke0.svg new file mode 100644 index 0000000..c52939b --- /dev/null +++ b/images/barke0.svg @@ -0,0 +1,60 @@ + + + + diff --git a/images/barke1.svg b/images/barke1.svg new file mode 100644 index 0000000..96cce66 --- /dev/null +++ b/images/barke1.svg @@ -0,0 +1,60 @@ + + + + diff --git a/images/barke2.svg b/images/barke2.svg new file mode 100644 index 0000000..635a307 --- /dev/null +++ b/images/barke2.svg @@ -0,0 +1,57 @@ + + + + diff --git a/images/barke3.svg b/images/barke3.svg new file mode 100644 index 0000000..8dbbc54 --- /dev/null +++ b/images/barke3.svg @@ -0,0 +1,57 @@ + + + + diff --git a/images/barke4.svg b/images/barke4.svg new file mode 100644 index 0000000..c0e5739 --- /dev/null +++ b/images/barke4.svg @@ -0,0 +1,64 @@ + + + + diff --git a/images/barke5.svg b/images/barke5.svg new file mode 100644 index 0000000..8888873 --- /dev/null +++ b/images/barke5.svg @@ -0,0 +1,60 @@ + + + + diff --git a/images/barke6.svg b/images/barke6.svg new file mode 100644 index 0000000..ae0ba1e --- /dev/null +++ b/images/barke6.svg @@ -0,0 +1,54 @@ + + + + diff --git a/images/befestigung.svg b/images/befestigung.svg new file mode 100644 index 0000000..762bb71 --- /dev/null +++ b/images/befestigung.svg @@ -0,0 +1,30 @@ + + + + diff --git a/images/berge.svg b/images/berge.svg new file mode 100644 index 0000000..637344a --- /dev/null +++ b/images/berge.svg @@ -0,0 +1,280 @@ + + + + diff --git a/images/bergwerk.svg b/images/bergwerk.svg new file mode 100644 index 0000000..b601368 --- /dev/null +++ b/images/bergwerk.svg @@ -0,0 +1,41 @@ + + + + diff --git a/images/boat0.svg b/images/boat0.svg new file mode 100644 index 0000000..7f8dcfb --- /dev/null +++ b/images/boat0.svg @@ -0,0 +1,49 @@ + + + + diff --git a/images/boat1.svg b/images/boat1.svg new file mode 100644 index 0000000..cfd2039 --- /dev/null +++ b/images/boat1.svg @@ -0,0 +1,43 @@ + + + + diff --git a/images/boat2.svg b/images/boat2.svg new file mode 100644 index 0000000..4efe8f8 --- /dev/null +++ b/images/boat2.svg @@ -0,0 +1,40 @@ + + + + diff --git a/images/boat3.svg b/images/boat3.svg new file mode 100644 index 0000000..4a1dd02 --- /dev/null +++ b/images/boat3.svg @@ -0,0 +1,35 @@ + + + + diff --git a/images/boat4.svg b/images/boat4.svg new file mode 100644 index 0000000..ea67e69 --- /dev/null +++ b/images/boat4.svg @@ -0,0 +1,35 @@ + + + + diff --git a/images/boat5.svg b/images/boat5.svg new file mode 100644 index 0000000..4e70b4d --- /dev/null +++ b/images/boat5.svg @@ -0,0 +1,36 @@ + + + + diff --git a/images/boat6.svg b/images/boat6.svg new file mode 100644 index 0000000..a3a916e --- /dev/null +++ b/images/boat6.svg @@ -0,0 +1,28 @@ + + + + diff --git a/images/boot0.svg b/images/boot0.svg new file mode 100644 index 0000000..7f8dcfb --- /dev/null +++ b/images/boot0.svg @@ -0,0 +1,49 @@ + + + + diff --git a/images/boot1.svg b/images/boot1.svg new file mode 100644 index 0000000..cfd2039 --- /dev/null +++ b/images/boot1.svg @@ -0,0 +1,43 @@ + + + + diff --git a/images/boot2.svg b/images/boot2.svg new file mode 100644 index 0000000..4efe8f8 --- /dev/null +++ b/images/boot2.svg @@ -0,0 +1,40 @@ + + + + diff --git a/images/boot3.svg b/images/boot3.svg new file mode 100644 index 0000000..2d05c82 --- /dev/null +++ b/images/boot3.svg @@ -0,0 +1,35 @@ + + + + diff --git a/images/boot4.svg b/images/boot4.svg new file mode 100644 index 0000000..7021b11 --- /dev/null +++ b/images/boot4.svg @@ -0,0 +1,35 @@ + + + + diff --git a/images/boot5.svg b/images/boot5.svg new file mode 100644 index 0000000..1c7e642 --- /dev/null +++ b/images/boot5.svg @@ -0,0 +1,36 @@ + + + + diff --git a/images/boot6.svg b/images/boot6.svg new file mode 100644 index 0000000..322f36f --- /dev/null +++ b/images/boot6.svg @@ -0,0 +1,28 @@ + + + + diff --git a/images/burg.svg b/images/burg.svg new file mode 100644 index 0000000..74fb864 --- /dev/null +++ b/images/burg.svg @@ -0,0 +1,48 @@ + + + + diff --git a/images/damm.svg b/images/damm.svg new file mode 100644 index 0000000..0d07e0e --- /dev/null +++ b/images/damm.svg @@ -0,0 +1,35 @@ + + + + diff --git a/images/dichter nebel.svg b/images/dichter nebel.svg new file mode 100644 index 0000000..3568eca --- /dev/null +++ b/images/dichter nebel.svg @@ -0,0 +1,165 @@ + + + + diff --git a/images/drachenschiff0.svg b/images/drachenschiff0.svg new file mode 100644 index 0000000..463e73f --- /dev/null +++ b/images/drachenschiff0.svg @@ -0,0 +1,63 @@ + + + + diff --git a/images/drachenschiff1.svg b/images/drachenschiff1.svg new file mode 100644 index 0000000..2e45f2c --- /dev/null +++ b/images/drachenschiff1.svg @@ -0,0 +1,61 @@ + + + + diff --git a/images/drachenschiff2.svg b/images/drachenschiff2.svg new file mode 100644 index 0000000..116827d --- /dev/null +++ b/images/drachenschiff2.svg @@ -0,0 +1,56 @@ + + + + diff --git a/images/drachenschiff3.svg b/images/drachenschiff3.svg new file mode 100644 index 0000000..b9f580e --- /dev/null +++ b/images/drachenschiff3.svg @@ -0,0 +1,46 @@ + + + + diff --git a/images/drachenschiff4.svg b/images/drachenschiff4.svg new file mode 100644 index 0000000..69c7abe --- /dev/null +++ b/images/drachenschiff4.svg @@ -0,0 +1,59 @@ + + + + diff --git a/images/drachenschiff5.svg b/images/drachenschiff5.svg new file mode 100644 index 0000000..b429019 --- /dev/null +++ b/images/drachenschiff5.svg @@ -0,0 +1,64 @@ + + + + diff --git a/images/drachenschiff6.svg b/images/drachenschiff6.svg new file mode 100644 index 0000000..b2b0361 --- /dev/null +++ b/images/drachenschiff6.svg @@ -0,0 +1,50 @@ + + + + diff --git a/images/dragonship0.svg b/images/dragonship0.svg new file mode 100644 index 0000000..a1d5b93 --- /dev/null +++ b/images/dragonship0.svg @@ -0,0 +1,63 @@ + + + + diff --git a/images/dragonship1.svg b/images/dragonship1.svg new file mode 100644 index 0000000..2e45f2c --- /dev/null +++ b/images/dragonship1.svg @@ -0,0 +1,61 @@ + + + + diff --git a/images/dragonship2.svg b/images/dragonship2.svg new file mode 100644 index 0000000..116827d --- /dev/null +++ b/images/dragonship2.svg @@ -0,0 +1,56 @@ + + + + diff --git a/images/dragonship3.svg b/images/dragonship3.svg new file mode 100644 index 0000000..4e36029 --- /dev/null +++ b/images/dragonship3.svg @@ -0,0 +1,46 @@ + + + + diff --git a/images/dragonship4.svg b/images/dragonship4.svg new file mode 100644 index 0000000..070c895 --- /dev/null +++ b/images/dragonship4.svg @@ -0,0 +1,59 @@ + + + + diff --git a/images/dragonship5.svg b/images/dragonship5.svg new file mode 100644 index 0000000..8b7c15d --- /dev/null +++ b/images/dragonship5.svg @@ -0,0 +1,64 @@ + + + + diff --git a/images/dragonship6.svg b/images/dragonship6.svg new file mode 100644 index 0000000..b26c746 --- /dev/null +++ b/images/dragonship6.svg @@ -0,0 +1,50 @@ + + + + diff --git a/images/ebene.svg b/images/ebene.svg new file mode 100644 index 0000000..425827b --- /dev/null +++ b/images/ebene.svg @@ -0,0 +1,265 @@ + + + + diff --git a/images/einbaum0.svg b/images/einbaum0.svg new file mode 100644 index 0000000..8ab564a --- /dev/null +++ b/images/einbaum0.svg @@ -0,0 +1,65 @@ + + + + diff --git a/images/einbaum1.svg b/images/einbaum1.svg new file mode 100644 index 0000000..d48bfe3 --- /dev/null +++ b/images/einbaum1.svg @@ -0,0 +1,57 @@ + + + + diff --git a/images/einbaum2.svg b/images/einbaum2.svg new file mode 100644 index 0000000..9c78db6 --- /dev/null +++ b/images/einbaum2.svg @@ -0,0 +1,51 @@ + + + + diff --git a/images/einbaum3.svg b/images/einbaum3.svg new file mode 100644 index 0000000..3aa44db --- /dev/null +++ b/images/einbaum3.svg @@ -0,0 +1,41 @@ + + + + diff --git a/images/einbaum4.svg b/images/einbaum4.svg new file mode 100644 index 0000000..33b6c6d --- /dev/null +++ b/images/einbaum4.svg @@ -0,0 +1,48 @@ + + + + diff --git a/images/einbaum5.svg b/images/einbaum5.svg new file mode 100644 index 0000000..3338a60 --- /dev/null +++ b/images/einbaum5.svg @@ -0,0 +1,51 @@ + + + + diff --git a/images/einbaum6.svg b/images/einbaum6.svg new file mode 100644 index 0000000..505c338 --- /dev/null +++ b/images/einbaum6.svg @@ -0,0 +1,45 @@ + + + + diff --git a/images/eisberg.svg b/images/eisberg.svg new file mode 100644 index 0000000..6bec21b --- /dev/null +++ b/images/eisberg.svg @@ -0,0 +1,332 @@ + + + + diff --git a/images/eisscholle.svg b/images/eisscholle.svg new file mode 100644 index 0000000..8f20dcb --- /dev/null +++ b/images/eisscholle.svg @@ -0,0 +1,287 @@ + + + + diff --git a/images/eisscholle2.svg b/images/eisscholle2.svg new file mode 100644 index 0000000..9fe0d5b --- /dev/null +++ b/images/eisscholle2.svg @@ -0,0 +1,258 @@ + + + + diff --git a/images/festung.svg b/images/festung.svg new file mode 100644 index 0000000..fee4c0f --- /dev/null +++ b/images/festung.svg @@ -0,0 +1,50 @@ + + + + diff --git a/images/feuerwand.svg b/images/feuerwand.svg new file mode 100644 index 0000000..76fd305 --- /dev/null +++ b/images/feuerwand.svg @@ -0,0 +1,226 @@ + + + + diff --git a/images/feuerwand0.svg b/images/feuerwand0.svg new file mode 100644 index 0000000..8ced269 --- /dev/null +++ b/images/feuerwand0.svg @@ -0,0 +1,57 @@ + + + + diff --git a/images/feuerwand1.svg b/images/feuerwand1.svg new file mode 100644 index 0000000..479f43b --- /dev/null +++ b/images/feuerwand1.svg @@ -0,0 +1,58 @@ + + + + diff --git a/images/feuerwand2.svg b/images/feuerwand2.svg new file mode 100644 index 0000000..139f68f --- /dev/null +++ b/images/feuerwand2.svg @@ -0,0 +1,30 @@ + + + + diff --git a/images/feuerwand3.svg b/images/feuerwand3.svg new file mode 100644 index 0000000..a99432b --- /dev/null +++ b/images/feuerwand3.svg @@ -0,0 +1,57 @@ + + + + diff --git a/images/feuerwand4.svg b/images/feuerwand4.svg new file mode 100644 index 0000000..be82606 --- /dev/null +++ b/images/feuerwand4.svg @@ -0,0 +1,59 @@ + + + + diff --git a/images/feuerwand5.svg b/images/feuerwand5.svg new file mode 100644 index 0000000..3f2f637 --- /dev/null +++ b/images/feuerwand5.svg @@ -0,0 +1,32 @@ + + + + diff --git a/images/floss0.svg b/images/floss0.svg new file mode 100644 index 0000000..8a5a8bd --- /dev/null +++ b/images/floss0.svg @@ -0,0 +1,57 @@ + + + + diff --git a/images/floss1.svg b/images/floss1.svg new file mode 100644 index 0000000..c2128a7 --- /dev/null +++ b/images/floss1.svg @@ -0,0 +1,37 @@ + + + + diff --git a/images/floss2.svg b/images/floss2.svg new file mode 100644 index 0000000..1e6c8d8 --- /dev/null +++ b/images/floss2.svg @@ -0,0 +1,33 @@ + + + + diff --git a/images/floss3.svg b/images/floss3.svg new file mode 100644 index 0000000..ca60be7 --- /dev/null +++ b/images/floss3.svg @@ -0,0 +1,34 @@ + + + + diff --git a/images/floss4.svg b/images/floss4.svg new file mode 100644 index 0000000..6f066ab --- /dev/null +++ b/images/floss4.svg @@ -0,0 +1,40 @@ + + + + diff --git a/images/floss5.svg b/images/floss5.svg new file mode 100644 index 0000000..4dbafb1 --- /dev/null +++ b/images/floss5.svg @@ -0,0 +1,41 @@ + + + + diff --git a/images/floss6.svg b/images/floss6.svg new file mode 100644 index 0000000..ac3e07c --- /dev/null +++ b/images/floss6.svg @@ -0,0 +1,38 @@ + + + + diff --git a/images/fregatte0.svg b/images/fregatte0.svg new file mode 100644 index 0000000..74e4661 --- /dev/null +++ b/images/fregatte0.svg @@ -0,0 +1,69 @@ + + + + diff --git a/images/fregatte1.svg b/images/fregatte1.svg new file mode 100644 index 0000000..9294deb --- /dev/null +++ b/images/fregatte1.svg @@ -0,0 +1,71 @@ + + + + diff --git a/images/fregatte2.svg b/images/fregatte2.svg new file mode 100644 index 0000000..cadec87 --- /dev/null +++ b/images/fregatte2.svg @@ -0,0 +1,68 @@ + + + + diff --git a/images/fregatte3.svg b/images/fregatte3.svg new file mode 100644 index 0000000..6221f3d --- /dev/null +++ b/images/fregatte3.svg @@ -0,0 +1,62 @@ + + + + diff --git a/images/fregatte4.svg b/images/fregatte4.svg new file mode 100644 index 0000000..eecc278 --- /dev/null +++ b/images/fregatte4.svg @@ -0,0 +1,77 @@ + + + + diff --git a/images/fregatte5.svg b/images/fregatte5.svg new file mode 100644 index 0000000..3ec9b3a --- /dev/null +++ b/images/fregatte5.svg @@ -0,0 +1,74 @@ + + + + diff --git a/images/fregatte6.svg b/images/fregatte6.svg new file mode 100644 index 0000000..e80117a --- /dev/null +++ b/images/fregatte6.svg @@ -0,0 +1,52 @@ + + + + diff --git a/images/galeone0.svg b/images/galeone0.svg new file mode 100644 index 0000000..1374ea7 --- /dev/null +++ b/images/galeone0.svg @@ -0,0 +1,74 @@ + + + + diff --git a/images/galeone1.svg b/images/galeone1.svg new file mode 100644 index 0000000..09ce9e7 --- /dev/null +++ b/images/galeone1.svg @@ -0,0 +1,62 @@ + + + + diff --git a/images/galeone2.svg b/images/galeone2.svg new file mode 100644 index 0000000..53e2d5f --- /dev/null +++ b/images/galeone2.svg @@ -0,0 +1,54 @@ + + + + diff --git a/images/galeone3.svg b/images/galeone3.svg new file mode 100644 index 0000000..4997c43 --- /dev/null +++ b/images/galeone3.svg @@ -0,0 +1,48 @@ + + + + diff --git a/images/galeone4.svg b/images/galeone4.svg new file mode 100644 index 0000000..76e77d9 --- /dev/null +++ b/images/galeone4.svg @@ -0,0 +1,63 @@ + + + + diff --git a/images/galeone5.svg b/images/galeone5.svg new file mode 100644 index 0000000..a06c6f9 --- /dev/null +++ b/images/galeone5.svg @@ -0,0 +1,64 @@ + + + + diff --git a/images/galeone6.svg b/images/galeone6.svg new file mode 100644 index 0000000..beab8ea --- /dev/null +++ b/images/galeone6.svg @@ -0,0 +1,49 @@ + + + + diff --git a/images/gang.svg b/images/gang.svg new file mode 100644 index 0000000..0727889 --- /dev/null +++ b/images/gang.svg @@ -0,0 +1,340 @@ + + + + diff --git a/images/gebirge.svg b/images/gebirge.svg new file mode 100644 index 0000000..bf1982a --- /dev/null +++ b/images/gebirge.svg @@ -0,0 +1,280 @@ + + + + diff --git a/images/geruest.svg b/images/geruest.svg new file mode 100644 index 0000000..a27035e --- /dev/null +++ b/images/geruest.svg @@ -0,0 +1,30 @@ + + + + diff --git a/images/gesegneter steinkreis.svg b/images/gesegneter steinkreis.svg new file mode 100644 index 0000000..4cd33ba --- /dev/null +++ b/images/gesegneter steinkreis.svg @@ -0,0 +1,30 @@ + + + + diff --git a/images/gletscher.svg b/images/gletscher.svg new file mode 100644 index 0000000..01e3f30 --- /dev/null +++ b/images/gletscher.svg @@ -0,0 +1,249 @@ + + + + diff --git a/images/grundmauern.svg b/images/grundmauern.svg new file mode 100644 index 0000000..3b09a9e --- /dev/null +++ b/images/grundmauern.svg @@ -0,0 +1,31 @@ + + + + diff --git a/images/hafen.svg b/images/hafen.svg new file mode 100644 index 0000000..27cc6df --- /dev/null +++ b/images/hafen.svg @@ -0,0 +1,44 @@ + + + + diff --git a/images/halle.svg b/images/halle.svg new file mode 100644 index 0000000..0ee83b8 --- /dev/null +++ b/images/halle.svg @@ -0,0 +1,340 @@ + + + + diff --git a/images/handelsposten.svg b/images/handelsposten.svg new file mode 100644 index 0000000..8fa4648 --- /dev/null +++ b/images/handelsposten.svg @@ -0,0 +1,31 @@ + + + + diff --git a/images/hochland.svg b/images/hochland.svg new file mode 100644 index 0000000..dddb610 --- /dev/null +++ b/images/hochland.svg @@ -0,0 +1,289 @@ + + + + diff --git a/images/irrlichter0.svg b/images/irrlichter0.svg new file mode 100644 index 0000000..1e66d2f --- /dev/null +++ b/images/irrlichter0.svg @@ -0,0 +1,30 @@ + + + + diff --git a/images/irrlichter1.svg b/images/irrlichter1.svg new file mode 100644 index 0000000..7e18c43 --- /dev/null +++ b/images/irrlichter1.svg @@ -0,0 +1,30 @@ + + + + diff --git a/images/irrlichter2.svg b/images/irrlichter2.svg new file mode 100644 index 0000000..b18c7c5 --- /dev/null +++ b/images/irrlichter2.svg @@ -0,0 +1,26 @@ + + + + diff --git a/images/irrlichter3.svg b/images/irrlichter3.svg new file mode 100644 index 0000000..010263e --- /dev/null +++ b/images/irrlichter3.svg @@ -0,0 +1,30 @@ + + + + diff --git a/images/irrlichter4.svg b/images/irrlichter4.svg new file mode 100644 index 0000000..01554aa --- /dev/null +++ b/images/irrlichter4.svg @@ -0,0 +1,31 @@ + + + + diff --git a/images/irrlichter5.svg b/images/irrlichter5.svg new file mode 100644 index 0000000..2d9b550 --- /dev/null +++ b/images/irrlichter5.svg @@ -0,0 +1,26 @@ + + + + diff --git a/images/karavelle0.svg b/images/karavelle0.svg new file mode 100644 index 0000000..00c2d6c --- /dev/null +++ b/images/karavelle0.svg @@ -0,0 +1,67 @@ + + + + diff --git a/images/karavelle1.svg b/images/karavelle1.svg new file mode 100644 index 0000000..c68d473 --- /dev/null +++ b/images/karavelle1.svg @@ -0,0 +1,47 @@ + + + + diff --git a/images/karavelle2.svg b/images/karavelle2.svg new file mode 100644 index 0000000..8bf18d7 --- /dev/null +++ b/images/karavelle2.svg @@ -0,0 +1,42 @@ + + + + diff --git a/images/karavelle3.svg b/images/karavelle3.svg new file mode 100644 index 0000000..a1f1742 --- /dev/null +++ b/images/karavelle3.svg @@ -0,0 +1,43 @@ + + + + diff --git a/images/karavelle30.svg b/images/karavelle30.svg new file mode 100644 index 0000000..12a6d4c --- /dev/null +++ b/images/karavelle30.svg @@ -0,0 +1,68 @@ + + + + diff --git a/images/karavelle4.svg b/images/karavelle4.svg new file mode 100644 index 0000000..cf27a81 --- /dev/null +++ b/images/karavelle4.svg @@ -0,0 +1,52 @@ + + + + diff --git a/images/karavelle5.svg b/images/karavelle5.svg new file mode 100644 index 0000000..481dac9 --- /dev/null +++ b/images/karavelle5.svg @@ -0,0 +1,53 @@ + + + + diff --git a/images/karavelle6.svg b/images/karavelle6.svg new file mode 100644 index 0000000..4aefa44 --- /dev/null +++ b/images/karavelle6.svg @@ -0,0 +1,39 @@ + + + + diff --git a/images/karawane0.svg b/images/karawane0.svg new file mode 100644 index 0000000..3c39c76 --- /dev/null +++ b/images/karawane0.svg @@ -0,0 +1,45 @@ + + + + diff --git a/images/karawanserei.svg b/images/karawanserei.svg new file mode 100644 index 0000000..5f387d8 --- /dev/null +++ b/images/karawanserei.svg @@ -0,0 +1,29 @@ + + + + diff --git a/images/katamaran0.svg b/images/katamaran0.svg new file mode 100644 index 0000000..08b666b --- /dev/null +++ b/images/katamaran0.svg @@ -0,0 +1,48 @@ + + + + diff --git a/images/katamaran1.svg b/images/katamaran1.svg new file mode 100644 index 0000000..31f23d8 --- /dev/null +++ b/images/katamaran1.svg @@ -0,0 +1,42 @@ + + + + diff --git a/images/katamaran2.svg b/images/katamaran2.svg new file mode 100644 index 0000000..99ba28d --- /dev/null +++ b/images/katamaran2.svg @@ -0,0 +1,39 @@ + + + + diff --git a/images/katamaran3.svg b/images/katamaran3.svg new file mode 100644 index 0000000..21273a3 --- /dev/null +++ b/images/katamaran3.svg @@ -0,0 +1,36 @@ + + + + diff --git a/images/katamaran4.svg b/images/katamaran4.svg new file mode 100644 index 0000000..fd65172 --- /dev/null +++ b/images/katamaran4.svg @@ -0,0 +1,47 @@ + + + + diff --git a/images/katamaran5.svg b/images/katamaran5.svg new file mode 100644 index 0000000..a414c06 --- /dev/null +++ b/images/katamaran5.svg @@ -0,0 +1,47 @@ + + + + diff --git a/images/katamaran6.svg b/images/katamaran6.svg new file mode 100644 index 0000000..abbd2b8 --- /dev/null +++ b/images/katamaran6.svg @@ -0,0 +1,41 @@ + + + + diff --git a/images/koenigsbarke0.svg b/images/koenigsbarke0.svg new file mode 100644 index 0000000..329db81 --- /dev/null +++ b/images/koenigsbarke0.svg @@ -0,0 +1,60 @@ + + + + diff --git a/images/koenigsbarke1.svg b/images/koenigsbarke1.svg new file mode 100644 index 0000000..458ba49 --- /dev/null +++ b/images/koenigsbarke1.svg @@ -0,0 +1,60 @@ + + + + diff --git a/images/koenigsbarke2.svg b/images/koenigsbarke2.svg new file mode 100644 index 0000000..037210a --- /dev/null +++ b/images/koenigsbarke2.svg @@ -0,0 +1,57 @@ + + + + diff --git a/images/koenigsbarke3.svg b/images/koenigsbarke3.svg new file mode 100644 index 0000000..1663782 --- /dev/null +++ b/images/koenigsbarke3.svg @@ -0,0 +1,57 @@ + + + + diff --git a/images/koenigsbarke4.svg b/images/koenigsbarke4.svg new file mode 100644 index 0000000..116424b --- /dev/null +++ b/images/koenigsbarke4.svg @@ -0,0 +1,64 @@ + + + + diff --git a/images/koenigsbarke5.svg b/images/koenigsbarke5.svg new file mode 100644 index 0000000..d2fe14e --- /dev/null +++ b/images/koenigsbarke5.svg @@ -0,0 +1,60 @@ + + + + diff --git a/images/koenigsbarke6.svg b/images/koenigsbarke6.svg new file mode 100644 index 0000000..9bb256e --- /dev/null +++ b/images/koenigsbarke6.svg @@ -0,0 +1,54 @@ + + + + diff --git a/images/kogge0.svg b/images/kogge0.svg new file mode 100644 index 0000000..c4174cc --- /dev/null +++ b/images/kogge0.svg @@ -0,0 +1,64 @@ + + + + diff --git a/images/kogge1.svg b/images/kogge1.svg new file mode 100644 index 0000000..346b217 --- /dev/null +++ b/images/kogge1.svg @@ -0,0 +1,61 @@ + + + + diff --git a/images/kogge2.svg b/images/kogge2.svg new file mode 100644 index 0000000..b619a34 --- /dev/null +++ b/images/kogge2.svg @@ -0,0 +1,58 @@ + + + + diff --git a/images/kogge3.svg b/images/kogge3.svg new file mode 100644 index 0000000..3b922ef --- /dev/null +++ b/images/kogge3.svg @@ -0,0 +1,57 @@ + + + + diff --git a/images/kogge4.svg b/images/kogge4.svg new file mode 100644 index 0000000..4fd8be1 --- /dev/null +++ b/images/kogge4.svg @@ -0,0 +1,70 @@ + + + + diff --git a/images/kogge5.svg b/images/kogge5.svg new file mode 100644 index 0000000..6fa9fd2 --- /dev/null +++ b/images/kogge5.svg @@ -0,0 +1,66 @@ + + + + diff --git a/images/kogge6.svg b/images/kogge6.svg new file mode 100644 index 0000000..4666398 --- /dev/null +++ b/images/kogge6.svg @@ -0,0 +1,55 @@ + + + + diff --git a/images/korallenriff.svg b/images/korallenriff.svg new file mode 100644 index 0000000..081f193 --- /dev/null +++ b/images/korallenriff.svg @@ -0,0 +1,333 @@ + + + + diff --git a/images/kutter0.svg b/images/kutter0.svg new file mode 100644 index 0000000..2b689b3 --- /dev/null +++ b/images/kutter0.svg @@ -0,0 +1,50 @@ + + + + diff --git a/images/kutter1.svg b/images/kutter1.svg new file mode 100644 index 0000000..39c5baf --- /dev/null +++ b/images/kutter1.svg @@ -0,0 +1,48 @@ + + + + diff --git a/images/kutter2.svg b/images/kutter2.svg new file mode 100644 index 0000000..ebbfd49 --- /dev/null +++ b/images/kutter2.svg @@ -0,0 +1,44 @@ + + + + diff --git a/images/kutter3.svg b/images/kutter3.svg new file mode 100644 index 0000000..c3ad19e --- /dev/null +++ b/images/kutter3.svg @@ -0,0 +1,39 @@ + + + + diff --git a/images/kutter4.svg b/images/kutter4.svg new file mode 100644 index 0000000..cc2c80f --- /dev/null +++ b/images/kutter4.svg @@ -0,0 +1,50 @@ + + + + diff --git a/images/kutter5.svg b/images/kutter5.svg new file mode 100644 index 0000000..5badace --- /dev/null +++ b/images/kutter5.svg @@ -0,0 +1,50 @@ + + + + diff --git a/images/kutter6.svg b/images/kutter6.svg new file mode 100644 index 0000000..2b2fba1 --- /dev/null +++ b/images/kutter6.svg @@ -0,0 +1,42 @@ + + + + diff --git a/images/langboot0.svg b/images/langboot0.svg new file mode 100644 index 0000000..687ad98 --- /dev/null +++ b/images/langboot0.svg @@ -0,0 +1,50 @@ + + + + diff --git a/images/langboot1.svg b/images/langboot1.svg new file mode 100644 index 0000000..f8dc672 --- /dev/null +++ b/images/langboot1.svg @@ -0,0 +1,48 @@ + + + + diff --git a/images/langboot2.svg b/images/langboot2.svg new file mode 100644 index 0000000..332a1ea --- /dev/null +++ b/images/langboot2.svg @@ -0,0 +1,44 @@ + + + + diff --git a/images/langboot3.svg b/images/langboot3.svg new file mode 100644 index 0000000..47b49fe --- /dev/null +++ b/images/langboot3.svg @@ -0,0 +1,39 @@ + + + + diff --git a/images/langboot4.svg b/images/langboot4.svg new file mode 100644 index 0000000..ed17dbf --- /dev/null +++ b/images/langboot4.svg @@ -0,0 +1,50 @@ + + + + diff --git a/images/langboot5.svg b/images/langboot5.svg new file mode 100644 index 0000000..5badace --- /dev/null +++ b/images/langboot5.svg @@ -0,0 +1,50 @@ + + + + diff --git a/images/langboot6.svg b/images/langboot6.svg new file mode 100644 index 0000000..c0a38d5 --- /dev/null +++ b/images/langboot6.svg @@ -0,0 +1,42 @@ + + + + diff --git a/images/leere.svg b/images/leere.svg new file mode 100644 index 0000000..42aae26 --- /dev/null +++ b/images/leere.svg @@ -0,0 +1,237 @@ + + + + diff --git a/images/leuchtturm.svg b/images/leuchtturm.svg new file mode 100644 index 0000000..abdf312 --- /dev/null +++ b/images/leuchtturm.svg @@ -0,0 +1,32 @@ + + + + diff --git a/images/longboat0.svg b/images/longboat0.svg new file mode 100644 index 0000000..5323dce --- /dev/null +++ b/images/longboat0.svg @@ -0,0 +1,50 @@ + + + + diff --git a/images/longboat1.svg b/images/longboat1.svg new file mode 100644 index 0000000..b2b3f4e --- /dev/null +++ b/images/longboat1.svg @@ -0,0 +1,48 @@ + + + + diff --git a/images/longboat2.svg b/images/longboat2.svg new file mode 100644 index 0000000..332a1ea --- /dev/null +++ b/images/longboat2.svg @@ -0,0 +1,44 @@ + + + + diff --git a/images/longboat3.svg b/images/longboat3.svg new file mode 100644 index 0000000..1d85cf3 --- /dev/null +++ b/images/longboat3.svg @@ -0,0 +1,39 @@ + + + + diff --git a/images/longboat4.svg b/images/longboat4.svg new file mode 100644 index 0000000..cc2c80f --- /dev/null +++ b/images/longboat4.svg @@ -0,0 +1,50 @@ + + + + diff --git a/images/longboat5.svg b/images/longboat5.svg new file mode 100644 index 0000000..5badace --- /dev/null +++ b/images/longboat5.svg @@ -0,0 +1,50 @@ + + + + diff --git a/images/longboat6.svg b/images/longboat6.svg new file mode 100644 index 0000000..2b2fba1 --- /dev/null +++ b/images/longboat6.svg @@ -0,0 +1,42 @@ + + + + diff --git a/images/magierturm.svg b/images/magierturm.svg new file mode 100644 index 0000000..2842df2 --- /dev/null +++ b/images/magierturm.svg @@ -0,0 +1,40 @@ + + + + diff --git a/images/mahlstrom.svg b/images/mahlstrom.svg new file mode 100644 index 0000000..bf8cb47 --- /dev/null +++ b/images/mahlstrom.svg @@ -0,0 +1,297 @@ + + + + diff --git a/images/markt.svg b/images/markt.svg new file mode 100644 index 0000000..aea1ad4 --- /dev/null +++ b/images/markt.svg @@ -0,0 +1,37 @@ + + + + diff --git a/images/marktplatz.svg b/images/marktplatz.svg new file mode 100644 index 0000000..0c2712c --- /dev/null +++ b/images/marktplatz.svg @@ -0,0 +1,37 @@ + + + + diff --git a/images/monument.svg b/images/monument.svg new file mode 100644 index 0000000..c742c06 --- /dev/null +++ b/images/monument.svg @@ -0,0 +1,32 @@ + + + + diff --git a/images/nebel.svg b/images/nebel.svg new file mode 100644 index 0000000..da3da53 --- /dev/null +++ b/images/nebel.svg @@ -0,0 +1,70 @@ + + + + diff --git a/images/notype.svg b/images/notype.svg new file mode 100644 index 0000000..a15c601 --- /dev/null +++ b/images/notype.svg @@ -0,0 +1,9 @@ + + + + diff --git a/images/ozean.svg b/images/ozean.svg new file mode 100644 index 0000000..6c62e11 --- /dev/null +++ b/images/ozean.svg @@ -0,0 +1,299 @@ + + + + diff --git a/images/packeis.svg b/images/packeis.svg new file mode 100644 index 0000000..8d21ee6 --- /dev/null +++ b/images/packeis.svg @@ -0,0 +1,348 @@ + + + + diff --git a/images/pfeil0.svg b/images/pfeil0.svg new file mode 100644 index 0000000..084ffa4 --- /dev/null +++ b/images/pfeil0.svg @@ -0,0 +1,86 @@ + + + + diff --git a/images/pfeil1.svg b/images/pfeil1.svg new file mode 100644 index 0000000..2dbb805 --- /dev/null +++ b/images/pfeil1.svg @@ -0,0 +1,85 @@ + + + + diff --git a/images/pfeil2.svg b/images/pfeil2.svg new file mode 100644 index 0000000..2bf14ce --- /dev/null +++ b/images/pfeil2.svg @@ -0,0 +1,124 @@ + + + + diff --git a/images/pfeil3.svg b/images/pfeil3.svg new file mode 100644 index 0000000..8ee45a4 --- /dev/null +++ b/images/pfeil3.svg @@ -0,0 +1,86 @@ + + + + diff --git a/images/pfeil4.svg b/images/pfeil4.svg new file mode 100644 index 0000000..b3b9bd1 --- /dev/null +++ b/images/pfeil4.svg @@ -0,0 +1,84 @@ + + + + diff --git a/images/pfeil5.svg b/images/pfeil5.svg new file mode 100644 index 0000000..ae7908f --- /dev/null +++ b/images/pfeil5.svg @@ -0,0 +1,126 @@ + + + + diff --git a/images/pferdezucht.svg b/images/pferdezucht.svg new file mode 100644 index 0000000..abff5e3 --- /dev/null +++ b/images/pferdezucht.svg @@ -0,0 +1,36 @@ + + + + diff --git a/images/portal.svg b/images/portal.svg new file mode 100644 index 0000000..f7f7c9f --- /dev/null +++ b/images/portal.svg @@ -0,0 +1,47 @@ + + + + diff --git a/images/regenwald.svg b/images/regenwald.svg new file mode 100644 index 0000000..1c00d1f --- /dev/null +++ b/images/regenwald.svg @@ -0,0 +1,304 @@ + + + + diff --git a/images/saegewerk.svg b/images/saegewerk.svg new file mode 100644 index 0000000..61c6545 --- /dev/null +++ b/images/saegewerk.svg @@ -0,0 +1,36 @@ + + + + diff --git a/images/schemen.svg b/images/schemen.svg new file mode 100644 index 0000000..279bf96 --- /dev/null +++ b/images/schemen.svg @@ -0,0 +1,9 @@ + + + + diff --git a/images/schiff0.svg b/images/schiff0.svg new file mode 100644 index 0000000..d8d2697 --- /dev/null +++ b/images/schiff0.svg @@ -0,0 +1,29 @@ + + + + diff --git a/images/schiff1.svg b/images/schiff1.svg new file mode 100644 index 0000000..6d79c18 --- /dev/null +++ b/images/schiff1.svg @@ -0,0 +1,29 @@ + + + + diff --git a/images/schiff2.svg b/images/schiff2.svg new file mode 100644 index 0000000..6c7f9f1 --- /dev/null +++ b/images/schiff2.svg @@ -0,0 +1,27 @@ + + + + diff --git a/images/schiff3.svg b/images/schiff3.svg new file mode 100644 index 0000000..9bdf0a7 --- /dev/null +++ b/images/schiff3.svg @@ -0,0 +1,25 @@ + + + + diff --git a/images/schiff4.svg b/images/schiff4.svg new file mode 100644 index 0000000..81a853f --- /dev/null +++ b/images/schiff4.svg @@ -0,0 +1,27 @@ + + + + diff --git a/images/schiff5.svg b/images/schiff5.svg new file mode 100644 index 0000000..894944a --- /dev/null +++ b/images/schiff5.svg @@ -0,0 +1,30 @@ + + + + diff --git a/images/schiff6.svg b/images/schiff6.svg new file mode 100644 index 0000000..4117444 --- /dev/null +++ b/images/schiff6.svg @@ -0,0 +1,27 @@ + + + + diff --git a/images/schloss.svg b/images/schloss.svg new file mode 100644 index 0000000..9469de3 --- /dev/null +++ b/images/schloss.svg @@ -0,0 +1,43 @@ + + + + diff --git a/images/schmiede.svg b/images/schmiede.svg new file mode 100644 index 0000000..afe736f --- /dev/null +++ b/images/schmiede.svg @@ -0,0 +1,31 @@ + + + + diff --git a/images/schoner0.svg b/images/schoner0.svg new file mode 100644 index 0000000..dc97e87 --- /dev/null +++ b/images/schoner0.svg @@ -0,0 +1,73 @@ + + + + diff --git a/images/schoner1.svg b/images/schoner1.svg new file mode 100644 index 0000000..2f52b2d --- /dev/null +++ b/images/schoner1.svg @@ -0,0 +1,67 @@ + + + + diff --git a/images/schoner2.svg b/images/schoner2.svg new file mode 100644 index 0000000..8b64e7d --- /dev/null +++ b/images/schoner2.svg @@ -0,0 +1,59 @@ + + + + diff --git a/images/schoner3.svg b/images/schoner3.svg new file mode 100644 index 0000000..50dd62d --- /dev/null +++ b/images/schoner3.svg @@ -0,0 +1,50 @@ + + + + diff --git a/images/schoner4.svg b/images/schoner4.svg new file mode 100644 index 0000000..c5eb345 --- /dev/null +++ b/images/schoner4.svg @@ -0,0 +1,65 @@ + + + + diff --git a/images/schoner5.svg b/images/schoner5.svg new file mode 100644 index 0000000..f14ca17 --- /dev/null +++ b/images/schoner5.svg @@ -0,0 +1,68 @@ + + + + diff --git a/images/schoner6.svg b/images/schoner6.svg new file mode 100644 index 0000000..0531d06 --- /dev/null +++ b/images/schoner6.svg @@ -0,0 +1,52 @@ + + + + diff --git a/images/selected.svg b/images/selected.svg new file mode 100644 index 0000000..04e2f40 --- /dev/null +++ b/images/selected.svg @@ -0,0 +1,84 @@ + + + + diff --git a/images/steinbruch.svg b/images/steinbruch.svg new file mode 100644 index 0000000..e84e7f7 --- /dev/null +++ b/images/steinbruch.svg @@ -0,0 +1,42 @@ + + + + diff --git a/images/steinkreis.svg b/images/steinkreis.svg new file mode 100644 index 0000000..6505dec --- /dev/null +++ b/images/steinkreis.svg @@ -0,0 +1,47 @@ + + + + diff --git a/images/sumpf.svg b/images/sumpf.svg new file mode 100644 index 0000000..ad38c1f --- /dev/null +++ b/images/sumpf.svg @@ -0,0 +1,312 @@ + + + + diff --git a/images/taverne.svg b/images/taverne.svg new file mode 100644 index 0000000..7762bc5 --- /dev/null +++ b/images/taverne.svg @@ -0,0 +1,44 @@ + + + + diff --git a/images/trireme0.svg b/images/trireme0.svg new file mode 100644 index 0000000..7807583 --- /dev/null +++ b/images/trireme0.svg @@ -0,0 +1,77 @@ + + + + diff --git a/images/trireme1.svg b/images/trireme1.svg new file mode 100644 index 0000000..e619108 --- /dev/null +++ b/images/trireme1.svg @@ -0,0 +1,68 @@ + + + + diff --git a/images/trireme2.svg b/images/trireme2.svg new file mode 100644 index 0000000..9697fbc --- /dev/null +++ b/images/trireme2.svg @@ -0,0 +1,53 @@ + + + + diff --git a/images/trireme3.svg b/images/trireme3.svg new file mode 100644 index 0000000..73d1a51 --- /dev/null +++ b/images/trireme3.svg @@ -0,0 +1,59 @@ + + + + diff --git a/images/trireme4.svg b/images/trireme4.svg new file mode 100644 index 0000000..70eee7e --- /dev/null +++ b/images/trireme4.svg @@ -0,0 +1,72 @@ + + + + diff --git a/images/trireme5.svg b/images/trireme5.svg new file mode 100644 index 0000000..25d2ef1 --- /dev/null +++ b/images/trireme5.svg @@ -0,0 +1,69 @@ + + + + diff --git a/images/trireme6.svg b/images/trireme6.svg new file mode 100644 index 0000000..62066ca --- /dev/null +++ b/images/trireme6.svg @@ -0,0 +1,58 @@ + + + + diff --git a/images/tundra.svg b/images/tundra.svg new file mode 100644 index 0000000..fd0a444 --- /dev/null +++ b/images/tundra.svg @@ -0,0 +1,167 @@ + + + + diff --git a/images/tunnel.svg b/images/tunnel.svg new file mode 100644 index 0000000..8251b68 --- /dev/null +++ b/images/tunnel.svg @@ -0,0 +1,42 @@ + + + + diff --git a/images/turm.svg b/images/turm.svg new file mode 100644 index 0000000..8db198e --- /dev/null +++ b/images/turm.svg @@ -0,0 +1,29 @@ + + + + diff --git a/images/uebergang.svg b/images/uebergang.svg new file mode 100644 index 0000000..da6ce3e --- /dev/null +++ b/images/uebergang.svg @@ -0,0 +1,91 @@ + + + + diff --git a/images/unbekannt.svg b/images/unbekannt.svg new file mode 100644 index 0000000..a15c601 --- /dev/null +++ b/images/unbekannt.svg @@ -0,0 +1,9 @@ + + + + diff --git a/images/units.svg b/images/units.svg new file mode 100644 index 0000000..cf120fd --- /dev/null +++ b/images/units.svg @@ -0,0 +1,82 @@ + + + diff --git a/images/vulkan.svg b/images/vulkan.svg new file mode 100644 index 0000000..19d367e --- /dev/null +++ b/images/vulkan.svg @@ -0,0 +1,363 @@ + + + + diff --git a/images/wachstube.svg b/images/wachstube.svg new file mode 100644 index 0000000..12b74d6 --- /dev/null +++ b/images/wachstube.svg @@ -0,0 +1,30 @@ + + + + diff --git a/images/wachturm.svg b/images/wachturm.svg new file mode 100644 index 0000000..84870a6 --- /dev/null +++ b/images/wachturm.svg @@ -0,0 +1,37 @@ + + + + diff --git a/images/wald.svg b/images/wald.svg new file mode 100644 index 0000000..5d4e5f0 --- /dev/null +++ b/images/wald.svg @@ -0,0 +1,365 @@ + + + + diff --git a/images/wand.svg b/images/wand.svg new file mode 100644 index 0000000..fcdce15 --- /dev/null +++ b/images/wand.svg @@ -0,0 +1,326 @@ + + + + diff --git a/images/wueste.svg b/images/wueste.svg new file mode 100644 index 0000000..5a75ea0 --- /dev/null +++ b/images/wueste.svg @@ -0,0 +1,274 @@ + + + + diff --git a/images/zitadelle.svg b/images/zitadelle.svg new file mode 100644 index 0000000..dd0adb0 --- /dev/null +++ b/images/zitadelle.svg @@ -0,0 +1,55 @@ + + + + diff --git a/images/zweimast0.svg b/images/zweimast0.svg new file mode 100644 index 0000000..1f21930 --- /dev/null +++ b/images/zweimast0.svg @@ -0,0 +1,64 @@ + + + + diff --git a/nogoblins/Auswertung_01.md b/nogoblins/Auswertung_01.md index 88f5fc9..2a59217 100644 --- a/nogoblins/Auswertung_01.md +++ b/nogoblins/Auswertung_01.md @@ -6,4 +6,10 @@ date: 2024-03-17 # Runde 1 ## Die Auswertung +Map: +{% crmap './nogoblins/crs/334-42.cr' %} + +No Map +{% crmap './nogoblins/crs/334-424242.cr' %} + Lore ipsum 1... \ No newline at end of file diff --git a/nogoblins/crs/334-42.cr b/nogoblins/crs/334-42.cr new file mode 100644 index 0000000..6fb5643 --- /dev/null +++ b/nogoblins/crs/334-42.cr @@ -0,0 +1,874 @@ +VERSION 69 +"UTF-8";charset +"de";locale +1;noskillpoints +1693565514;date +"Eressea";Spiel +"Standard";Konfiguration +"Hex";Koordinaten +2500;max_units +36;Basis +334;Runde +2;Zeitalter +"28.4.0-06a187397";Build +"eressea-server@kn-bremen.de";mailto +"ERESSEA 2 BEFEHLE";mailcmd +PARTEI 146 +"de";locale +1;age +599;Optionen +"Menschen";Typ +75;Rekrutierungskosten +2019;Anzahl Personen +"gray";Magiegebiet +0;Anzahl Immigranten +32;Max. Immigranten +29;max_heroes +"Partei 6tap";Parteiname +"fex@eressea.de";email +OPTIONEN +1;AUSWERTUNG +1;COMPUTER +1;ZUGVORLAGE +1;STATISTIK +0;DEBUG +1;ZIPPED +0;ZEITUNG +1;ADRESSEN +0;BZIP2 +0;PUNKTE +0;SHOWSKCHANGE +MESSAGE 417008016 +107552268;type +"economy";section +"Einheit 8uz4 (8uz4) bezahlt den Unterhalt von Leuchtturm (3s4x).";rendered +413392;unit +176433;building +MESSAGE 414364096 +2026874001;type +"movement";section +"Die Karavelle (b0ae) segelt von Susot (-2011,2) nach Susot (-2011,2).";rendered +513590;ship +-2011 2 0;from +-2011 2 0;to +MESSAGE 417640736 +829394366;type +"events";section +"Einheit u4fh (u4fh) in Susot (-2011,2) wird durch unzureichende Nahrung geschwächt.";rendered +1405421;unit +-2011 2 0;region +MESSAGE 417671280 +829394366;type +"events";section +"Einheit cfe2 (cfe2) in Susot (-2011,2) wird durch unzureichende Nahrung geschwächt.";rendered +579818;unit +-2011 2 0;region +MESSAGE 417617936 +829394366;type +"events";section +"Einheit 5a5n (5a5n) in Susot (-2011,2) wird durch unzureichende Nahrung geschwächt.";rendered +246443;unit +-2011 2 0;region +MESSAGE 417672096 +829394366;type +"events";section +"Einheit ehp6 (ehp6) in Susot (-2011,2) wird durch unzureichende Nahrung geschwächt.";rendered +676122;unit +-2011 2 0;region +MESSAGE 417548768 +829394366;type +"events";section +"Einheit 13ii (13ii) in Susot (-2011,2) wird durch unzureichende Nahrung geschwächt.";rendered +51210;unit +-2011 2 0;region +MESSAGE 417530656 +829394366;type +"events";section +"Einheit d19j (d19j) in Susot (-2011,2) wird durch unzureichende Nahrung geschwächt.";rendered +608167;unit +-2011 2 0;region +MESSAGE 417651360 +829394366;type +"events";section +"Einheit fa66 (fa66) in Susot (-2011,2) wird durch unzureichende Nahrung geschwächt.";rendered +713022;unit +-2011 2 0;region +MESSAGE 417212016 +829394366;type +"events";section +"Einheit rtqa (rtqa) in Susot (-2011,2) wird durch unzureichende Nahrung geschwächt.";rendered +1298242;unit +-2011 2 0;region +BATTLE -2011 0 +MESSAGE 416979280 +26679501;type +"battle";section +"Der Kampf wurde ausgelöst von Partei 6tap (42).";rendered +"Partei 6tap (42)";factions +MESSAGE 416337728 +1801908756;type +"battle";section +"Heer 0: Partei 6tap (42)";rendered +0;index +"Partei 6tap (42)";name +146;faction +MESSAGE 417406320 +1803906635;type +"battle";section +"Kämpft gegen: Heer 1 (17pd)";rendered +"Kämpft gegen: Heer 1 (17pd)";string +MESSAGE 417288352 +1803906635;type +"battle";section +"Attacke gegen: Heer 1(17pd)";rendered +"Attacke gegen: Heer 1(17pd)";string +MESSAGE 417292720 +1684814935;type +"battle";section +"... in der 1. Kampflinie:";rendered +1;row +MESSAGE 417684592 +2144337409;type +"battle";section +" * Einheit xda9 (xda9), 1000 Menschen, aggressiv, bewacht die Region, Talente: Hiebwaffen 20, Ausdauer 10, hat: 100000 Silber, 1000 Plattenpanzer, 1000 Schilde, 1000 Schwerter.";rendered +" * Einheit xda9 (xda9), 1000 Menschen, aggressiv, bewacht die Region, Talente: Hiebwaffen 20, Ausdauer 10, hat: 100000 Silber, 1000 Plattenpanzer, 1000 Schilde, 1000 Schwerter.";string +1556865;unit +MESSAGE 417418416 +1684814935;type +"battle";section +"... in der 2. Kampflinie:";rendered +2;row +MESSAGE 417479120 +2144337409;type +"battle";section +" * Einheit z2b9 (z2b9), 1 Mensch, hinten, Talente: Magie Gwyrrd 10. Aura 1000/105, Zauber: Mauern der Ewigkeit, Hagel, Kampfzauber: keiner, Hagel(8), keiner.";rendered +" * Einheit z2b9 (z2b9), 1 Mensch, hinten, Talente: Magie Gwyrrd 10. Aura 1000/105, Zauber: Mauern der Ewigkeit, Hagel, Kampfzauber: keiner, Hagel(8), keiner.";string +1635957;unit +MESSAGE 415904064 +2144337409;type +"battle";section +" * Einheit fwpq (fwpq), 1000 Menschen, hinten, Talente: Bogenschießen 20, Ausdauer 10, hat: 1000 Bögen, 100000 Silber, 1000 Schilde.";rendered +" * Einheit fwpq (fwpq), 1000 Menschen, hinten, Talente: Bogenschießen 20, Ausdauer 10, hat: 1000 Bögen, 100000 Silber, 1000 Schilde.";string +742238;unit +MESSAGE 417700848 +1801908756;type +"battle";section +"Heer 1: Partei 17pd (17pd)";rendered +1;index +"Partei 17pd (17pd)";name +56641;faction +MESSAGE 417389296 +1803906635;type +"battle";section +"Kämpft gegen: Heer 0 (42)";rendered +"Kämpft gegen: Heer 0 (42)";string +MESSAGE 417572320 +1684814935;type +"battle";section +"... in der 1. Kampflinie:";rendered +1;row +MESSAGE 417065776 +2144337409;type +"battle";section +" - Einheit 2uph (2uph), 1000 Menschen, aggressiv, hat: 1000 Plattenpanzer, 1000 Schilde, 1000 Schwerter.";rendered +" - Einheit 2uph (2uph), 1000 Menschen, aggressiv, hat: 1000 Plattenpanzer, 1000 Schilde, 1000 Schwerter.";string +133109;unit +MESSAGE 417300912 +1684814935;type +"battle";section +"... in der 2. Kampflinie:";rendered +2;row +MESSAGE 415903856 +2144337409;type +"battle";section +" - Einheit d3o0 (d3o0), 1000 Menschen, hinten, hat: 1000 Armbrüste, 1000 Schilde.";rendered +" - Einheit d3o0 (d3o0), 1000 Menschen, hinten, hat: 1000 Armbrüste, 1000 Schilde.";string +611280;unit +MESSAGE 417290928 +564544796;type +"battle";section +"Einheiten vor der 1. Runde:";rendered +1;turn +MESSAGE 417017424 +1803906635;type +"battle";section +"Heer 0(42): 1000+1001, Heer 1(17pd): 1000+1000";rendered +"Heer 0(42): 1000+1001, Heer 1(17pd): 1000+1000";string +MESSAGE 417653936 +450463848;type +"battle";section +"Einheit z2b9 (z2b9) zaubert Hagel: 0 Krieger wurden getötet.";rendered +1635957;mage +"Hagel";spell +0;dead +MESSAGE 415906272 +564544796;type +"battle";section +"Einheiten vor der 2. Runde:";rendered +2;turn +MESSAGE 417568096 +1803906635;type +"battle";section +"Heer 0(42): 1000+1000, Heer 1(17pd): 1000+1000";rendered +"Heer 0(42): 1000+1000, Heer 1(17pd): 1000+1000";string +MESSAGE 417325168 +564544796;type +"battle";section +"Einheiten vor der 3. Runde:";rendered +3;turn +MESSAGE 415905104 +1803906635;type +"battle";section +"Heer 0(42): 1000+999, Heer 1(17pd): 1000+1000";rendered +"Heer 0(42): 1000+999, Heer 1(17pd): 1000+1000";string +MESSAGE 415905872 +564544796;type +"battle";section +"Einheiten vor der 4. Runde:";rendered +4;turn +MESSAGE 417672784 +1803906635;type +"battle";section +"Heer 0(42): 1000+999, Heer 1(17pd): 1000+1000";rendered +"Heer 0(42): 1000+999, Heer 1(17pd): 1000+1000";string +MESSAGE 416251696 +564544796;type +"battle";section +"Einheiten vor der 5. Runde:";rendered +5;turn +MESSAGE 416377728 +1803906635;type +"battle";section +"Heer 0(42): 998+996, Heer 1(17pd): 999+1000";rendered +"Heer 0(42): 998+996, Heer 1(17pd): 999+1000";string +MESSAGE 416373216 +564544796;type +"battle";section +"Einheiten vor der 6. Runde:";rendered +6;turn +MESSAGE 416184544 +1803906635;type +"battle";section +"Heer 0(42): 997+995, Heer 1(17pd): 998+1000";rendered +"Heer 0(42): 997+995, Heer 1(17pd): 998+1000";string +MESSAGE 416315536 +1436762363;type +"battle";section +"Einheit z2b9 (z2b9) erzielte 116 Treffer und tötete 0 Gegner.";rendered +1635957;unit +116;hits +0;kills +MESSAGE 416264608 +1436762363;type +"battle";section +"Einheit fwpq (fwpq) erzielte 2917 Treffer und tötete 0 Gegner.";rendered +742238;unit +2917;hits +0;kills +MESSAGE 416183744 +1436762363;type +"battle";section +"Einheit xda9 (xda9) erzielte 1338 Treffer und tötete 2 Gegner.";rendered +1556865;unit +1338;hits +2;kills +MESSAGE 414353376 +804883071;type +"battle";section +"Einheit z2b9 (z2b9) verlor 1 Personen.";rendered +1635957;unit +1;fallen +0;alive +0;run +MESSAGE 414340864 +804883071;type +"battle";section +"Einheit fwpq (fwpq) verlor 3 Personen, 997 überlebten.";rendered +742238;unit +3;fallen +997;alive +0;run +MESSAGE 416235600 +804883071;type +"battle";section +"Einheit xda9 (xda9) verlor 3 Personen, 997 überlebten.";rendered +1556865;unit +3;fallen +997;alive +0;run +MESSAGE 416183280 +804883071;type +"battle";section +"Einheit 2uph (2uph) verlor 2 Personen, 998 überlebten.";rendered +133109;unit +2;fallen +998;alive +0;run +MESSAGE 416210976 +1109807897;type +"battle";section +"Heer 0(42): 7 Tote, 0 Geflohene, 1994 Überlebende.";rendered +0;index +"42";abbrev +7;dead +0;fled +1994;survived +MESSAGE 416211328 +1109807897;type +"battle";section +"Heer 1(17pd): 2 Tote, 0 Geflohene, 1998 Überlebende.";rendered +1;index +"17pd";abbrev +2;dead +0;fled +1998;survived +PARTEI 56641 +"Partei 17pd";Parteiname +"war@eressea.de";email +"de";locale +REGION -2011 0 +889912896;id +"Vosal";Name +"Ebene";Terrain +5004;Bauern +44;Pferde +64949;Silber +3247;Unterh +125;Rekruten +11;Lohn +RESOURCE 347593380 +"Bauern";type +5004;number +RESOURCE 210060480 +"Silber";type +64949;number +RESOURCE 200695649 +"Pferde";type +44;number +PREISE +12;Balsam +20;Gewürz +-7;Juwel +10;Myrrhe +3;Öl +30;Seide +12;Weihrauch +BURG 979180 +"Leuchtturm";Typ +"Leuchtturm";Name +10;Groesse +BURG 1256726 +"Bergwerk";Typ +"Bergwerk";Name +10;Groesse +BURG 797904 +"Steinbruch";Typ +"Steinbruch";Name +10;Groesse +BURG 385129 +"Sägewerk";Typ +"Sägewerk";Name +10;Groesse +BURG 536986 +"Schmiede";Typ +"Schmiede";Name +10;Groesse +BURG 535462 +"Pferdezucht";Typ +"Pferdezucht";Name +10;Groesse +BURG 311133 +"Hafen";Typ +"Hafen";Name +10;Groesse +BURG 989382 +"Karawanserei";Typ +"Karawanserei";Name +25;Groesse +BURG 1105804 +"Akademie";Typ +"Akademie";Name +25;Groesse +BURG 176434 +"Magierturm";Typ +"Magierturm";Name +50;Groesse +BURG 1011788 +"Damm";Typ +"Damm";Name +50;Groesse +BURG 1364079 +"Tunnel";Typ +"Tunnel";Name +100;Groesse +BURG 1496338 +"Taverne";Typ +"Taverne";Name +10;Groesse +BURG 955640 +"Monument";Typ +"Monument";Name +10;Groesse +BURG 1328968 +"Steinkreis";Typ +"Steinkreis";Name +100;Groesse +EINHEIT 133109 +"Einheit 2uph";Name +56641;Partei +998;Anzahl +"Menschen";Typ +GEGENSTAENDE +999;Plattenpanzer +999;Schild +998;Schwert +EINHEIT 1556865 +"Einheit xda9";Name +146;Partei +997;Anzahl +"Menschen";Typ +1;bewacht +0;Kampfstatus +1686929;weight +"erschöpft";hp +COMMANDS +TALENTE +6281100 20;Hiebwaffen +1645050 10;Ausdauer +GEGENSTAENDE +90029;Silber +1000;Plattenpanzer +1000;Schild +999;Schwert +EINHEIT 742238 +"Einheit fwpq";Name +146;Partei +997;Anzahl +"Menschen";Typ +2;Kampfstatus +1286929;weight +"erschöpft";hp +COMMANDS +TALENTE +6281100 20;Bogenschießen +1645050 10;Ausdauer +GEGENSTAENDE +1000;Bogen +90029;Silber +999;Schild +EINHEIT 611280 +"Einheit d3o0";Name +56641;Partei +1000;Anzahl +"Menschen";Typ +GEGENSTAENDE +1000;Armbrust +1000;Schild +REGION -2010 0 +1758876736;id +"Sanwopavor";Name +"Sumpf";Terrain +1122;Bauern +0;Pferde +17900;Silber +895;Unterh +28;Rekruten +11;Lohn +RESOURCE 347593380 +"Bauern";type +1122;number +RESOURCE 210060480 +"Silber";type +17900;number +PREISE +8;Balsam +25;Gewürz +28;Juwel +25;Myrrhe +-3;Öl +12;Seide +16;Weihrauch +MESSAGE 417262368 +2110306401;type +"events";section +"Eine Botschaft von Einheit 8uz4 (8uz4): 'Hey, Welt'";rendered +413392;unit +"Hey, Welt";message +BURG 176433 +"Leuchtturm";Typ +"Leuchtturm";Name +10;Groesse +413392;Besitzer +146;Partei +EINHEIT 413392 +"Einheit 8uz4";Name +146;Partei +1;Anzahl +"Menschen";Typ +176433;Burg +0;Kampfstatus +1890;weight +COMMANDS +TALENTE +1650 10;Wahrnehmung +GEGENSTAENDE +890;Silber +REGION -2011 1 +580554208;id +"Ruvaskon";Name +"Berge";Terrain +"lighthouse";visibility +574;Bauern +RESOURCE 347593380 +"Bauern";type +574;number +REGION -2012 1 +159292901;id +"Garvufyd";Name +"Hochland";Terrain +"lighthouse";visibility +2323;Bauern +RESOURCE 347593380 +"Bauern";type +2323;number +REGION -2012 0 +718757703;id +"Batsosbur";Name +"Wüste";Terrain +"lighthouse";visibility +226;Bauern +RESOURCE 347593380 +"Bauern";type +226;number +REGION -2011 -1 +1969236227;id +"Povos";Name +"Gletscher";Terrain +"lighthouse";visibility +100;Bauern +RESOURCE 347593380 +"Bauern";type +100;number +REGION -2010 -1 +316495505;id +"Gygarod";Name +"Vulkan";Terrain +"lighthouse";visibility +177;Bauern +18;Baeume +4;Schoesslinge +RESOURCE 347593380 +"Bauern";type +177;number +RESOURCE 6035652 +"Bäume";type +18;number +RESOURCE 1352714618 +"Schößlinge";type +4;number +REGION -2009 0 +385138274;id +"Ozean";Terrain +"lighthouse";visibility +REGION -2010 1 +1601752705;id +"Ozean";Terrain +"lighthouse";visibility +REGION -2008 0 +694297240;id +"Feuerwand";Terrain +"lighthouse";visibility +REGION -2007 0 +162890060;id +"Gusvokabud";Name +"Wand";Terrain +"neighbour";visibility +REGION -2011 2 +159704196;id +"Susot";Name +"Wald";Terrain +5083;Bauern +122;Pferde +69800;Silber +3490;Unterh +127;Rekruten +11;Lohn +600;Baeume +60;Schoesslinge +RESOURCE 347593380 +"Bauern";type +5083;number +RESOURCE 6035652 +"Bäume";type +600;number +RESOURCE 1352714618 +"Schößlinge";type +60;number +RESOURCE 210060480 +"Silber";type +69800;number +RESOURCE 200695649 +"Pferde";type +122;number +PREISE +20;Balsam +5;Gewürz +-7;Juwel +25;Myrrhe +6;Öl +24;Seide +20;Weihrauch +SCHIFF 548842 +"Boot";Name +"Boot";Typ +1;Anzahl +5;Groesse +1405421;Kapitaen +146;Partei +5000;capacity +3000;cargo +2;speed +SCHIFF 1088880 +"Langboot";Name +"Langboot";Typ +1;Anzahl +50;Groesse +579818;Kapitaen +146;Partei +50000;capacity +3000;cargo +3;speed +SCHIFF 1013629 +"Drachenschiff";Name +"Drachenschiff";Typ +1;Anzahl +100;Groesse +246443;Kapitaen +146;Partei +100000;capacity +3000;cargo +7;speed +SCHIFF 1365078 +"Karavelle";Name +"Karavelle";Typ +1;Anzahl +250;Groesse +676122;Kapitaen +146;Partei +300000;capacity +3000;cargo +5;speed +SCHIFF 1332456 +"Trireme";Name +"Trireme";Typ +1;Anzahl +200;Groesse +51210;Kapitaen +146;Partei +200000;capacity +3000;cargo +7;speed +SCHIFF 172012 +"Galeone";Name +"Galeone";Typ +1;Anzahl +2000;Groesse +608167;Kapitaen +146;Partei +2000000;capacity +3000;cargo +5;speed +SCHIFF 513590 +"Karavelle";Name +"Karavelle";Typ +1;Anzahl +250;Groesse +1298242;Kapitaen +146;Partei +300000;capacity +3000;cargo +5;speed +1;Kueste +SCHIFF 352849 +"Karavelle";Name +"Karavelle";Typ +1;Anzahl +250;Groesse +1;Schaden +713022;Kapitaen +146;Partei +299640;capacity +3000;cargo +5;speed +EINHEIT 1405421 +"Einheit u4fh";Name +146;Partei +3;Anzahl +"Menschen";Typ +548842;Schiff +0;Kampfstatus +3000;weight +"verwundet";hp +1;hunger +COMMANDS +TALENTE +114750 50;Segeln +EINHEIT 579818 +"Einheit cfe2";Name +146;Partei +3;Anzahl +"Menschen";Typ +1088880;Schiff +0;Kampfstatus +3000;weight +"schwer verwundet";hp +1;hunger +COMMANDS +TALENTE +114750 50;Segeln +EINHEIT 246443 +"Einheit 5a5n";Name +146;Partei +3;Anzahl +"Menschen";Typ +1013629;Schiff +0;Kampfstatus +3000;weight +"verwundet";hp +1;hunger +COMMANDS +TALENTE +114750 50;Segeln +EINHEIT 676122 +"Einheit ehp6";Name +146;Partei +3;Anzahl +"Menschen";Typ +1365078;Schiff +0;Kampfstatus +3000;weight +"verwundet";hp +1;hunger +COMMANDS +TALENTE +114750 50;Segeln +EINHEIT 51210 +"Einheit 13ii";Name +146;Partei +3;Anzahl +"Menschen";Typ +1332456;Schiff +0;Kampfstatus +3000;weight +"schwer verwundet";hp +1;hunger +COMMANDS +TALENTE +114750 50;Segeln +EINHEIT 608167 +"Einheit d19j";Name +146;Partei +3;Anzahl +"Menschen";Typ +172012;Schiff +0;Kampfstatus +3000;weight +"verwundet";hp +1;hunger +COMMANDS +TALENTE +114750 50;Segeln +EINHEIT 1298242 +"Einheit rtqa";Name +146;Partei +3;Anzahl +"Menschen";Typ +513590;Schiff +0;Kampfstatus +3000;weight +"schwer verwundet";hp +1;hunger +COMMANDS +TALENTE +114750 50;Segeln +EINHEIT 713022 +"Einheit fa66";Name +146;Partei +3;Anzahl +"Menschen";Typ +352849;Schiff +0;Kampfstatus +3000;weight +"verwundet";hp +1;hunger +COMMANDS +TALENTE +114750 50;Segeln +REGION -2013 0 +1476172623;id +"Ozean";Terrain +"neighbour";visibility +REGION -2013 1 +903266434;id +"Ozean";Terrain +"neighbour";visibility +REGION -2013 2 +198871871;id +"Ozean";Terrain +"neighbour";visibility +REGION -2013 3 +1630461357;id +"Ozean";Terrain +"neighbour";visibility +REGION -2012 -1 +1132208834;id +"Ozean";Terrain +"neighbour";visibility +REGION -2012 2 +665941722;id +"Ozean";Terrain +"lighthouse";visibility +REGION -2012 3 +661947569;id +"Ozean";Terrain +"neighbour";visibility +REGION -2011 -2 +550328667;id +"Ozean";Terrain +"neighbour";visibility +REGION -2011 3 +2080041580;id +"Ozean";Terrain +"travel";visibility +DURCHSCHIFFUNG +"Karavelle (b0ae)" +REGION -2010 -2 +1469279136;id +"Ozean";Terrain +"lighthouse";visibility +REGION -2010 2 +1211809502;id +"Ozean";Terrain +"travel";visibility +DURCHSCHIFFUNG +"Karavelle (b0ae)" +REGION -2010 3 +853321833;id +"Ozean";Terrain +"neighbour";visibility +REGION -2009 -2 +1519201686;id +"Ozean";Terrain +"lighthouse";visibility +REGION -2009 -1 +1420501750;id +"Ozean";Terrain +"lighthouse";visibility +REGION -2009 1 +1894631067;id +"Ozean";Terrain +"lighthouse";visibility +REGION -2009 2 +852913341;id +"Ozean";Terrain +"neighbour";visibility From e2ddb4a5ebd433b94e7abb16643b241813c1562b Mon Sep 17 00:00:00 2001 From: Steffen Mecke Date: Fri, 15 Aug 2025 10:49:43 +0200 Subject: [PATCH 05/34] multiple crs per page --- crs/crs-passthrough.js | 40 ++++++++++++++++++--------- crs/crs.js | 56 +++++++++++++++++--------------------- nogoblins/Auswertung_01.md | 4 +++ 3 files changed, 56 insertions(+), 44 deletions(-) diff --git a/crs/crs-passthrough.js b/crs/crs-passthrough.js index 337907b..63c7493 100644 --- a/crs/crs-passthrough.js +++ b/crs/crs-passthrough.js @@ -9,22 +9,36 @@ function showDescription(event, div_id, id) { return false; } -function positionTooltip(event) { - const tooltip = document.getElementById('tooltip'); - const x = event.clientX; - const y = event.clientY; +function showTooltip(event, id, text) { + const tooltip = document.getElementById(id); + tooltip.style.display = 'block'; + tooltip.innerHTML = text; + tooltip.style.display = 'block'; + const x = event.clientX + 10; + const y = event.clientY - 10; tooltip.style.left = `${x}px`; tooltip.style.top = `${y}px`; } -function showTooltip(event, text) { - const tooltip = document.getElementById('tooltip'); - tooltip.innerHTML = text; - tooltip.style.display = 'block'; - positionTooltip(event); +function hideTooltip(id) { + const tooltip = document.getElementById(id); + tooltip.style.display = 'none'; } -function hideTooltip() { - const tooltip = document.getElementById('tooltip'); - tooltip.style.display = 'none'; -} \ No newline at end of file +function initDiv(element) { + + if (element.id === 'rdetails') { + element.innerHTML = 'Select a region to see details here.'; + } +} + +// document.addEventListener('DOMContentLoaded', function () { +// const rdetails = document.getElementById('rdetails'); +// const udetails = document.getElementById('udetails'); +// if (rdetails) { +// rdetails.innerHTML = 'Select a region to see details here.'; +// } +// if (udetails) { +// udetails.innerHTML = 'Select a unit to see details here.'; +// } +// }); \ No newline at end of file diff --git a/crs/crs.js b/crs/crs.js index 07da39d..f9ca8c2 100644 --- a/crs/crs.js +++ b/crs/crs.js @@ -1,5 +1,4 @@ // crs.js - const fs = require('fs'); const path = require('path'); @@ -43,7 +42,8 @@ const images = { const defaultImage = 'region'; - +let crids = []; +let cridCounter = 0; function getColor(terrain) { return colors[terrain] || colors['default']; @@ -74,7 +74,7 @@ function parseRegion(line, matches) { return region; } -function outputRegion(region, bounds) { +function outputRegion(region, bounds, crid) { if (!region) return ''; if (!region.tags.Terrain) return ''; let color = getColor(region.tags.Terrain); @@ -92,7 +92,7 @@ function outputRegion(region, bounds) { let tt = region.tags.Name ? region.tags.Name : region.tags.Terrain; tt += ` (${xx}, ${yy})`; let desc = ''; - console.log('tags ', region.tags); + // console.log('tags ', region.tags); desc = Object.entries(region.tags) @@ -102,6 +102,7 @@ function outputRegion(region, bounds) { let id = 'r_'; id += xx < 0 ? `m${-xx}` : xx; id += yy < 0 ? `_m${-yy}` : `_${yy}`; + id += `_${crid}`; // Update bounds bounds.xmin = Math.min(bounds.xmin, x); bounds.ymin = Math.min(bounds.ymin, y); @@ -113,10 +114,10 @@ function outputRegion(region, bounds) { if (region.units.length > 0) { desc += `Units:
`; Object.entries(region.units).forEach(([id, unit]) => { - console.log(`Unit ${id} skills:`, unit.skills); - const uid = `u_${unit.id}`; + // console.log(`Unit ${id} skills:`, unit.skills); + const uid = `u_${unit.id}_${crid}`; udesc += `
`; - desc += `${unit.tags.Name} (${unit.id})
`; + desc += `${unit.tags.Name} (${unit.id})
`; udesc += `${unit.tags.Name} (${unit.id})`; if (unit.skills) { udesc += ' ' + Object.entries(unit.skills).map(([key, value]) => `${key} ${value}`).join(', '); @@ -134,7 +135,7 @@ function outputRegion(region, bounds) { // onmousemove="showTooltip(evt, '${tt}');" // onmouseout="hideTooltip();" // onclick = "showDescription(event, '${desc}');" - return `` + + return `` + `${tt}${desc}\n` + units + ``; @@ -192,7 +193,7 @@ function parseSkill(key) { return parseInt(key.trim().split(/\s+/)[1], 10); } -function parseCrFile(filePath) { +function parseCrFile(filePath, crid) { console.log(`Processing CR file: ${filePath}`); const content = fs.readFileSync(filePath, 'utf8'); const lines = content.split(/\r?\n/); @@ -229,11 +230,11 @@ function parseCrFile(filePath) { } else if ((matches = pregTagq.exec(line))) { value = matches[1]; tag = matches[2]; - console.log(`Found tag ${tag} with value ${value} in block ${block}`); + // console.log(`Found tag ${tag} with value ${value} in block ${block}`); } else if ((matches = pregTag.exec(line))) { value = matches[1]; tag = matches[2]; - console.log(`Found tag ${tag} with value ${value} in block ${block}`); + // console.log(`Found tag ${tag} with value ${value} in block ${block}`); } else if ((matches = pregBlock.exec(line))) { block = matches[1]; console.log(`Found block ${block}`); @@ -256,24 +257,11 @@ function parseCrFile(filePath) { if (region) regions.push(region); // Output regions and units for (const reg of regions) { - svgContent += outputRegion(reg, bounds); + svgContent += outputRegion(reg, bounds, crid); } - // // Output units as icons on top of regions - // for (const reg of regions) { - // if (reg.units && reg.units.length > 0) { - // console.log(`Outputting units for region: ${reg.Name}`); - // const x = transformx(reg); - // const y = transformy(reg); - // let ux = x + 50; // offset to center of hex - // let uy = y + 50; - // for (const unit of reg.units.filter(Boolean)) { - // console.log(`Outputting unit for region ${reg.Name}: ${unit.name} [${unit.num}]`); - // } - // } - // } svgContent = outputFront(bounds) + svgContent + outputBack(); - // console.log(`returning ${svgContent}`); + return svgContent; } @@ -281,16 +269,22 @@ module.exports = function (eleventyConfig) { eleventyConfig.addShortcode('crmap', function (file) { // file is relative to the project root or input dir try { - console.log(`Processing CR file: ${file}`); + const crid = ++cridCounter; + console.log(`Processing CR file ${crid}: ${file}`); const filePath = path.resolve(process.cwd(), file); if (!fs.existsSync(filePath)) { console.log(`File not found: ${filePath}`); return `
File not found: ${file}
`; } - const svg = parseCrFile(filePath); - return `
${svg}
\n` + - `
You need to enable Javascript for this to work.
\n` + - `
You need to enable Javascript for this to work.
`; + const svg = parseCrFile(filePath, crid); + + crids.push(crid); + + return ` +{% endif %} + diff --git a/_includes/post-layout.njk b/_includes/post-layout.njk index f3e88f3..872cecb 100644 --- a/_includes/post-layout.njk +++ b/_includes/post-layout.njk @@ -1,8 +1,6 @@ --- layout: base-layout.njk --- - -

{{ title }}

{% if author %}{{author}},{% else %}N.N.,{% endif %} diff --git a/crs/crs-passthrough.js b/crs/crs-passthrough.js index 3f868be..72aff50 100644 --- a/crs/crs-passthrough.js +++ b/crs/crs-passthrough.js @@ -154,21 +154,20 @@ function hideTooltip(id) { if (window.__crMapBound) return; // avoid rebinding on partial reloads window.__crMapBound = true; document.addEventListener('mousemove', function (e) { - const target = e.target.closest('.cr-region-link'); + const target = e.target?.closest?.('.cr-region-link') || null; if (target && target.dataset.tooltipId && target.dataset.tooltip) { showTooltip(e, target.dataset.tooltipId, target.dataset.tooltip); } }, true); document.addEventListener('mouseout', function (e) { const rel = e.relatedTarget; - if (!e.currentTarget) return; - const link = e.target.closest('.cr-region-link'); + const link = e.target?.closest?.('.cr-region-link') || null; if (link && (!rel || !rel.closest('.cr-region-link')) && link.dataset.tooltipId) { hideTooltip(link.dataset.tooltipId); } }, true); document.addEventListener('click', function (e) { - const regionLink = e.target.closest('.cr-region-link'); + const regionLink = e.target?.closest?.('.cr-region-link') || null; if (regionLink && regionLink.dataset.regionId && regionLink.dataset.regionTarget) { showDescription(e, regionLink.dataset.regionTarget, regionLink.dataset.regionId); e.preventDefault(); diff --git a/crs/crs.js b/crs/crs.js index 074f252..7bf3edc 100644 --- a/crs/crs.js +++ b/crs/crs.js @@ -524,6 +524,8 @@ module.exports = function (eleventyConfig) { caption = report.name + (report.owner ? `, ${report.owner.tags.Parteiname} (${report.owner.id})` : ''); } + // window.crids = ${JSON.stringify(crids)};<\/script>\n` + `
` + `
${svg}
` + From 6c595ce06e5b72d47563303802a2858fa0e10c16 Mon Sep 17 00:00:00 2001 From: Steffen Mecke Date: Mon, 18 Aug 2025 13:55:48 +0200 Subject: [PATCH 16/34] resolved code-review issues: - crid tracked by page, no global state - argument to to crmap is now always a JSON string - use of reg.id removed - use of unit.faction is fine - use of ellipsis is fine --- _includes/base-layout.njk | 2 +- crs/crs.js | 191 +++++++++++++++++--------------------- template/Auswertung_01.md | 6 +- 3 files changed, 87 insertions(+), 112 deletions(-) diff --git a/_includes/base-layout.njk b/_includes/base-layout.njk index 0799bd3..a146879 100644 --- a/_includes/base-layout.njk +++ b/_includes/base-layout.njk @@ -43,7 +43,7 @@ {% elif currentindex - loop.index0 <= radius and loop.index0 - currentindex <= radius %}
  • {{ loop.index }}
  • {% elif currentindex - loop.index0 <= radius + 1 and loop.index0 - currentindex <= radius + 1 %} -
  • ....
  • +
  • {% endif %} {%- endfor %} {% if pagination.href.next %}
  • {% endif %} diff --git a/crs/crs.js b/crs/crs.js index 7bf3edc..c57a6a6 100644 --- a/crs/crs.js +++ b/crs/crs.js @@ -55,11 +55,7 @@ function escapeHtml(str) { .replace(/'/g, '''); } -let crids = []; -let cridCounter = 0; -let cridOwners = {}; // crid -> template inputPath -let lastCrid = null; // Track last used crid for crmap_* - +// Validation helper (stateless) function validateCrid(id) { if (typeof id !== 'string') return { ok: false, message: 'crid must be a string' }; if (id !== id.toLowerCase()) return { ok: false, message: `crid '${id}' must be lowercase` }; @@ -105,7 +101,7 @@ function parseRegion(line, matches) { region.x = parseInt(matches[1], 10); region.y = parseInt(matches[2], 10); if (matches[3]) region.z = parseInt(matches[3], 10); else region.z = 0; - debug("found region", region); + debug(`found region (${region.x},${region.y}, ${region.z})`); return region; } @@ -113,12 +109,13 @@ function parseRegion(line, matches) { function parseUnit(line, matches) { const parts = line.trim().split(/\s+/); const unit = { id: itoa36(parseInt(matches[1], 10)), name: '???', tags: {}, skills: {}, items: {}, commands: [] }; - debug("found unit", unit); + debug("found unit", unit.id); return unit; } function outputRegion(region, bounds, crid, withDetails, ownerFactionId) { + debug('writing region ', region); if (!region) return ''; if (!region.tags.Terrain) return ''; let color = getColor(region.tags.Terrain); @@ -171,6 +168,7 @@ function outputRegion(region, bounds, crid, withDetails, ownerFactionId) { // Keep a single for units icon location unitsMarkup = ``; } + debug(`found units for region ${id}:`, unitsData); const escAttr = s => String(s).replace(/&/g, '&').replace(/"/g, '"'); const regionDataAttr2 = withDetails ? ` data-region="${encodeURIComponent(JSON.stringify(regionData))}" data-region-target="rdetails_${crid}" data-region-id="${id}"` : ''; @@ -288,7 +286,7 @@ class Report { currentFaction = null; currentUnit = null; const reg = parseRegion(line, matches); - debug(`parsing region ${reg.id} with z=${reg.z}, needs to match ${zFilter}`); + debug(`parsing region (${reg.x},${reg.y}) with z=${reg.z}, needs to match ${zFilter}`); if ((reg.z || 0) === (zFilter || 0)) { currentRegion = report.addRegion(reg); } else { @@ -387,23 +385,21 @@ class Report { } module.exports = function (eleventyConfig) { - // Usage examples (positional order: file, id, details, layer, caption): - // {% crmap 'path/to/file.cr' %} -> auto numeric crid, details true, layer 0 - // {% crmap 'path/to/file.cr' 'map1' %} -> explicit crid - // {% crmap 'path/to/file.cr' 'map1' false %} -> explicit crid, no details (tooltips only) - // {% crmap 'path/to/file.cr' 'map1' true 2 %} -> explicit crid, details, layer z=2 (auto caption) - // {% crmap 'path/to/file.cr' 'map1' true 2 'My Caption'%} -> custom caption - // {% crmap 'path/to/file.cr' 'map1' true 2 false %} -> omit caption entirely - // {% crmap 'path/to/file.cr' '' true 1 %} -> auto crid, details, layer z=1 (empty id) - // Object/options form (backwards compatible): - // {% crmap 'path/to/file.cr' { crid: 'map1', details: false, z: 1, caption: 'Custom' } %} - // {% crmap 'path/to/file.cr' { caption: false } %} -> omit caption - // Notes: - // - layer (z) defaults to 0; regions without z are treated as z=0. - // - id (crid) must be lowercase a-z 0-9 _ - ; empty string means auto. - // - details:false omits region/unit descriptions and links but keeps tooltips. - // - caption: string for custom text; false to omit figcaption. - // - Previous two-argument usage (file, optionsObject|stringId) still works. + // Usage: SECOND ARGUMENT IS OPTIONAL JSON OPTIONS STRING. + // {% crmap 'path/to/file.cr' %} -> defaults (auto crid, details true, z 0, auto caption) + // {% crmap 'path/to/file.cr' '{}' %} -> same as defaults + // {% crmap 'path/to/file.cr' '{"crid":"map1"}' %} -> explicit crid + // {% crmap 'path/to/file.cr' '{"details":false}' %} -> no details (tooltips only) + // {% crmap 'path/to/file.cr' '{"layer":2}' %} -> layer z=2 + // {% crmap 'path/to/file.cr' '{"caption":"My Caption"}' %} -> custom caption + // {% crmap 'path/to/file.cr' '{"caption":false}' %} -> omit caption + // {% crmap 'path/to/file.cr' '{"crid":"m1","details":false,"layer":1,"caption":false}' %} + // Option keys: crid (string), details (boolean), layer (integer), caption (string|false) + // Rules: + // - crid must match /^[a-z0-9_-]+$/; if omitted => auto numeric. + // - details:false removes detail panels but keeps tooltips. + // - caption:false omits figcaption; caption:string sets custom text. + // - Unrecognized keys are ignored. // Optional detail containers (place anywhere after the map): // {% crmap_rdetails 'map1' 'Optional placeholder text' %} -> region details target div // {% crmap_udetails 'map1' 'Optional placeholder text' %} -> unit details target div @@ -412,72 +408,54 @@ module.exports = function (eleventyConfig) { // - crid must be lowercase a-z 0-9 _ - // - Duplicate custom crid returns an inline error. // - details:false omits region/unit descriptions and links but keeps tooltips. - eleventyConfig.addShortcode('crmap', function (file, idArg, detailsArg, layerArg, captionArg) { + eleventyConfig.addShortcode('crmap', function (file, optionsJson) { try { let requestedCrid; // explicit id let detailsOption = true; // default include details let zOption = 0; // default layer 0 let captionOption; // undefined -> auto, string -> custom, false -> omit - // Backward compatibility: if idArg is a JSON-like options string or object, treat as options - if (idArg && typeof idArg === 'string' && idArg.trim().startsWith('{')) { - let raw = idArg.trim(); - try { - const normalized = raw - .replace(/([,{]\s*)([a-zA-Z_][a-zA-Z0-9_]*)\s*:/g, '$1"$2":') - .replace(/'/g, '"'); - idArg = JSON.parse(normalized); - } catch (e) { - return `
    Invalid options object: ${e.message}
    `; - } - } - if (idArg && typeof idArg === 'object') { - requestedCrid = idArg.crid || idArg.id || ''; - if (Object.prototype.hasOwnProperty.call(idArg, 'details')) { - detailsOption = idArg.details !== false; - } - if (Object.prototype.hasOwnProperty.call(idArg, 'z')) { - const zv = idArg.z; - if (/^-?\d+$/.test(zv.toString())) zOption = parseInt(zv, 10); - } - if (Object.prototype.hasOwnProperty.call(idArg, 'caption')) { - const c = idArg.caption; - if (c === false) captionOption = false; else if (typeof c === 'string') captionOption = c; + // Acquire per-page state (unique per template render) + // Structure: { crids: Set, counter: number, lastCrid: string|null } + let pageState; + if (this && this.page) { + this.ctx._crmapState = this.ctx._crmapState || {}; + pageState = this.ctx._crmapState; + if (!pageState.crids) { + pageState.crids = new Set(); + pageState.counter = 0; + pageState.lastCrid = null; } } else { - // Positional parsing: file, id, details, layer - if (typeof idArg === 'string') { - requestedCrid = idArg; // may be '' meaning auto - } else if (idArg === false) { - detailsOption = false; - } - // details argument - if (typeof detailsArg !== 'undefined') { - if (detailsArg === false || detailsArg === 'false') detailsOption = false; - else if (detailsArg === true || detailsArg === 'true') detailsOption = true; - else if (typeof detailsArg === 'number') { - // If number given in details slot, treat as layer when layerArg missing - zOption = parseInt(detailsArg, 10) || 0; - } else if (typeof detailsArg === 'string' && !/^-?\d+$/.test(detailsArg) && detailsArg !== 'true' && detailsArg !== 'false') { - // Treat as caption if a free-form string - captionOption = detailsArg; + // Fallback isolated state (should be rare) + pageState = { crids: new Set(), counter: 0, lastCrid: null }; + } + + // Treat missing or blank argument as '{}' + if (typeof optionsJson === 'undefined' || (typeof optionsJson === 'string' && optionsJson.trim() === '')) { + optionsJson = '{}'; + } + if (typeof optionsJson === 'string') { + try { + const opts = JSON.parse(optionsJson); + if (opts && typeof opts === 'object') { + if (typeof opts.crid === 'string') requestedCrid = opts.crid; + if (Object.prototype.hasOwnProperty.call(opts, 'details')) detailsOption = opts.details !== false; + if (Object.prototype.hasOwnProperty.call(opts, 'layer')) { + const layerValue = opts.layer; + if (/^-?\d+$/.test(String(layerValue))) zOption = parseInt(layerValue, 10); + } + if (Object.prototype.hasOwnProperty.call(opts, 'caption')) { + if (opts.caption === false) captionOption = false; else if (typeof opts.caption === 'string') captionOption = opts.caption; + } } + } catch (e) { + return `
    Invalid JSON options: ${escapeHtml(e.message)}
    `; } - // layer argument - if (typeof layerArg !== 'undefined') { - if (/^-?\d+$/.test(layerArg.toString())) zOption = parseInt(layerArg, 10); - else if (layerArg === false) captionOption = false; - else if (typeof layerArg === 'string') captionOption = layerArg; - } - // explicit caption fifth param - if (typeof captionArg !== 'undefined') { - if (captionArg === false) captionOption = false; - else if (typeof captionArg === 'string') captionOption = captionArg; - } - } - if (requestedCrid === '') { - requestedCrid = undefined; // force auto + } else { + return `
    Options must be a JSON string
    `; } + if (requestedCrid === '') requestedCrid = undefined; // force auto let crid; if (requestedCrid) { @@ -487,26 +465,19 @@ module.exports = function (eleventyConfig) { console.warn(valid.message); return `
    ${valid.message}
    `; } - if (crids.includes(crid)) { - const owner = cridOwners[crid]; - const current = this && this.page ? this.page.inputPath : 'unknown'; - if (owner && owner !== current) { - const msg = `Duplicate crid '${crid}' already used by ${owner} (current: ${current})`; - console.warn(msg); - return `
    ${msg}
    `; - } - // Same template rebuilding: allow silently + if (pageState.crids.has(crid)) { + const msg = `Duplicate crid '${crid}' already used on this page.`; + console.warn(msg); + return `
    ${msg}
    `; } debug(`Processing CR file with provided crid=${crid}: ${file}`); } else { - crid = (++cridCounter).toString(); + // Incremental auto id per page + crid = (++pageState.counter).toString(); debug(`Processing CR file ${crid}: ${file}`); } - if (!crids.includes(crid)) crids.push(crid); - if (this && this.page) { - cridOwners[crid] = this.page.inputPath; - } - lastCrid = crid; + pageState.crids.add(crid); + pageState.lastCrid = crid; const filePath = path.resolve(process.cwd(), file); if (!fs.existsSync(filePath)) { debug(`File not found: ${filePath}`); @@ -526,7 +497,7 @@ module.exports = function (eleventyConfig) { // window.crids = ${JSON.stringify(crids)};<\/script>\n` + + return ` {% endif %} diff --git a/crs/crs.css b/crs/crs.css index d49ee13..f52a068 100644 --- a/crs/crs.css +++ b/crs/crs.css @@ -58,4 +58,65 @@ .cr-error { color: #a00; font-family: monospace; +} + +/* Orderfile styling */ +.orderfile { + font-family: monospace; + font-size: 0.95em; +} + +.order-line { + padding: 0.08em 0.25em; + margin: 0; + line-height: 1.15; +} + +.order-line+.order-line { + margin-top: 0.08em; +} + +.order-line.empty { + height: 0.4em; +} + +/* Comments: lighter, slightly indented, italic */ +.order-line.comment { + background: rgba(200, 200, 200, 0.03); + color: #555; + padding-left: 0.5em; + font-family: sans-serif; + border-left: 2px solid rgba(0, 0, 0, 0.06); +} + +.order-line.comment+.order-line.comment { + margin-top: 0.06em; +} + +/* Orders: more prominent */ +.order-line.order { + background: rgba(0, 0, 0, 0.02); + color: #111; + padding-left: 0.25em; +} + +.order-line.order .order-keyword { + font-weight: 600; + color: #0b5394; + text-decoration: none; +} + +.order-line.order+.order-line.order { + margin-top: 0.06em; +} + +/* Some orders (diagnostics) are rendered as 'order' but without auto-link */ +.order-line.no-link { + color: #222; +} + +/* Slightly reduce spacing before and after the whole block */ +.orderfile { + margin-top: 0.2em; + margin-bottom: 0.2em; } \ No newline at end of file diff --git a/crs/crs.js b/crs/crs.js index 01cf25f..8bf0b94 100644 --- a/crs/crs.js +++ b/crs/crs.js @@ -423,6 +423,7 @@ module.exports = function (eleventyConfig) { let detailsOption = true; // default include details let zOption = 0; // default layer 0 let captionOption; // undefined -> auto, string -> custom, false -> omit + let fileLinkOption = true; // include a link to the source file in the caption by default // Acquire per-page state (unique per template render) // Structure: { crids: Set, counter: number, lastCrid: string|null } @@ -457,6 +458,9 @@ module.exports = function (eleventyConfig) { if (Object.prototype.hasOwnProperty.call(opts, 'caption')) { if (opts.caption === false) captionOption = false; else if (typeof opts.caption === 'string') captionOption = opts.caption; } + if (Object.prototype.hasOwnProperty.call(opts, 'fileLink')) { + fileLinkOption = !!opts.fileLink; + } } } catch (e) { return `
    Invalid JSON options: ${escapeHtml(e.message)}
    `; @@ -504,13 +508,27 @@ module.exports = function (eleventyConfig) { caption = report.name + (report.owner ? `, ${report.owner.tags.Parteiname} (${report.owner.id})` : ''); } + // Build figcaption HTML (may include a link to the input file) + let figcaptionHtml = ''; + if (caption !== null && typeof caption !== 'undefined') { + const captionEsc = escapeHtml(caption); + if (fileLinkOption) { + const href = escapeHtml(encodeURI(file)); + const fileDisplay = escapeHtml(path.basename(file)); + figcaptionHtml = `
    ${captionEsc}, source: ${fileDisplay}
    `; + } else { + figcaptionHtml = `
    ${captionEsc}
    `; + } + } + // \n` + - `
    ` + - `
    ${svg}
    ` + - (caption ? `
    ${escapeHtml(caption)}
    ` : '') + - `
    ` + + // include marker classes so the layout can detect whether to add CSS/JS + `
    ` + + `
    ${svg}
    ` + + (figcaptionHtml ? figcaptionHtml : '') + + `
    ` + `
    `; } catch (e) { debug(`Error processing file: ${filePath} `, e); @@ -579,6 +597,219 @@ module.exports = function (eleventyConfig) { return `
    ${placeholder}
    `; }); + // Shortcode to output order file contents line by line + // Usage: {% orderfile 'path/to/file.nr' %} or {% orderfile 'path' '{"markdownInComments":true}' %} + // + // Options (passed as JSON string, optional): + // markdownInComments: boolean (default: true) + // - When true, lines starting with ';' are rendered as comment lines and + // the comment text is processed with markdown-it (inline rendering) + // if available. When false, comments are escaped plain text. + // fileLink: boolean (default: true) + // - When true, the rendered block will include a small header linking to + // the source file (basename shown). Set to false to omit the file link. + // commentsAsOrders: boolean (default: false) + // - When true, lines that start with ';' are treated as orders instead of + // comment blocks. They will be rendered as order lines with class + // `order no-link` (escaped text, no wiki link on the first token). + // + // Examples: + // {% orderfile 'reports/orcs/orders-demo-02.txt' %} + // {% orderfile 'reports/orcs/orders-demo-02.txt' '{"fileLink":false}' %} + // {% orderfile 'reports/orcs/orders-demo-02.txt' '{"commentsAsOrders":true}' %} + const renderOrderFile = function (fileName, optionsJson) { + const fs = require('fs'); + const path = require('path'); + if (!fileName || typeof fileName !== 'string') { + return '
    orderfile: missing file name
    '; + } + // parse options + const opts = { markdownInComments: true, fileLink: true, commentsAsOrders: false }; + if (typeof optionsJson === 'string' && optionsJson.trim() !== '') { + try { + const parsed = JSON.parse(optionsJson); + if (parsed && typeof parsed === 'object') { + if (Object.prototype.hasOwnProperty.call(parsed, 'markdownInComments')) opts.markdownInComments = !!parsed.markdownInComments; + if (Object.prototype.hasOwnProperty.call(parsed, 'fileLink')) opts.fileLink = !!parsed.fileLink; + if (Object.prototype.hasOwnProperty.call(parsed, 'commentsAsOrders')) opts.commentsAsOrders = !!parsed.commentsAsOrders; + } + } catch (e) { + return `
    orderfile: invalid options JSON: ${escapeHtml(e.message)}
    `; + } + } + + const fullPath = path.resolve(process.cwd(), fileName); + if (!fs.existsSync(fullPath)) { + return `
    orderfile: file not found: ${escapeHtml(fileName)}
    `; + } + const content = fs.readFileSync(fullPath, 'utf8'); + const rawLines = content.split(/\r?\n/); + // Detect locale from lines like: "en";locale -- default to 'de' if not found + let locale = 'de'; + for (const l of rawLines) { + const m = l.match(/^locale\s*([a-z]{2})/i); + if (m) { locale = m[1].toLowerCase(); break; } + } + + // Translation table: map English keyword -> German wiki target + // Edit this table as needed; shown here with likely translations. + const translations = { + // core nouns + 'ERESSEA': 'ERESSEA', + 'UNIT': 'EINHEIT', + 'REGION': 'REGION', + + // common commands (English -> German wiki page target) + 'WORK': 'ARBEITE', + 'ATTACK': 'ATTACKIERE', + 'BANNER': 'BANNER', + 'CLAIM': 'BEANSPRUCHE', + 'PROMOTE': 'BEFÖRDERE', + 'STEAL': 'BEKLAUE', + 'NAME': 'BENENNE', + 'USE': 'BENUTZE', + 'DESCRIBE': 'BESCHREIBE', + 'ENTER': 'BETRETE', + 'GUARD': 'BEWACHE', + 'PAY': 'BEZAHLE', + 'MESSAGE': 'BOTSCHAFT', + 'DEFAULT': 'DEFAULT', + 'EMAIL': 'EMAIL', + 'END': 'ENDE', + 'RIDE': 'FAHRE', + 'FOLLOW': 'FOLGE', + 'RESEARCH': 'FORSCHE', + 'GIVE': 'GIB', + 'GROUP': 'GRUPPE', + 'HELP': 'HELFE', + 'COMBAT': 'KÄMPFE', + 'BUY': 'KAUFE', + 'CONTACT': 'KONTAKTIERE', + 'TEACH': 'LEHRE', + 'LEARN': 'LERNE', + 'LOCALE': 'LOCALE', + 'MAKE': 'MACHE', + 'MOVE': 'NACH', + 'NEXT': 'NÄCHSTER', + 'NUMBER': 'NUMMER', + 'OPTION': 'OPTION', + 'PASSWORD': 'PASSWORT', + 'PLANT': 'PFLANZE', + 'PIRACY': 'PIRATERIE', + 'PREFIX': 'PRÄFIX', + 'RECRUIT': 'REKRUTIERE', + 'RESERVE': 'RESERVIERE', + 'ROUTE': 'ROUTE', + 'SPY': 'SPIONIERE', + 'LANGUAGE': 'SPRACHE', + 'QUIT': 'STIRB', + 'HIDE': 'TARNUNG', + 'CARRY': 'TRANSPORTIERE', + 'TAX': 'TREIBE', + 'ENTERTAIN': 'UNTERHALTE', + 'ORIGIN': 'URSPRUNG', + 'FORGET': 'VERGISS', + 'SELL': 'VERKAUFE', + 'LEAVE': 'VERLASSE', + 'CAST': 'ZAUBERE', + 'SHOW': 'ZEIGE', + 'DESTROY': 'ZERSTÖRE', + 'GROW': 'ZÜCHTE', + + }; + + // Join lines that end with a backslash (continuation marker) + const lines = []; + for (let i = 0; i < rawLines.length; i++) { + let line = rawLines[i]; + // While this line ends with a backslash, remove it and append the next line (trimmed) + while (/\\\s*$/.test(line) && i + 1 < rawLines.length) { + line = line.replace(/\\\s*$/, ''); + i++; + // append the next physical line trimmed, join with a single space + line += rawLines[i].trim(); + } + lines.push(line); + } + + // try to load markdown-it for comment rendering; fall back to plain text + let md = null; + try { md = require('markdown-it')(); } catch (e) { md = null; } + + // Transform each (possibly-joined) line, wrap in div + const inner = lines.map(rawLine => { + let line = rawLine || ''; + if (line.trim() === '') return '
    '; + // Special-case: treat certain diagnostic/comment prefixes as orders (no link) + const specialPrefixes = [/^TIMESTAMP\b/i, /^Magellan version/i, /^ECheck\b/i]; + const pureLine = line.replace(/^;\s*/, ''); + const isSpecial = specialPrefixes.some(rx => rx.test(pureLine)); + console.log(isSpecial ? 'special' : 'normal' + ': ' + line); + if (isSpecial) { + // render these special diagnostic lines in the same style as comment-as-order + + const txt = escapeHtml(line); + return `
    ${txt}
    `; + } + if (/^\/\//.test(line.trim())) { + // lines beginning with // are a special "comment" command that should link to the + // wiki page 'KOMMENTAR' — support both '//' and '//foo' as the first token. + const parts = line.trim().split(/\s+/); + const keyword = parts.shift(); + const rest = parts.join(' '); + const kwEsc = escapeHtml(keyword); + const wikiUrl = `https://wiki.eressea.de/KOMMENTAR`; + const linked = `${kwEsc}`; + const contentRest = rest ? ' ' + escapeHtml(rest) : ''; + return `
    ${linked}${contentRest}
    `; + } + if (line.startsWith(';')) { + if (opts.commentsAsOrders) { + const commentText = opts.markdownInComments ? md.renderInline(line) : escapeHtml(line); + return `
    ${(commentText)}
    `; + } else { + const commentText = line.replace(/^;\s*/, ''); + // default behavior: comment line - render markdown if enabled + if (opts.markdownInComments && md) { + return `
    ${md.renderInline(commentText)}
    `; + } else { + return `
    ${escapeHtml(commentText)}
    `; + } + } + } + // order line: link first word to wiki + const parts = line.trim().split(/\s+/); + const keyword = parts.shift(); + const rest = parts.join(' '); + const kwEsc = escapeHtml(keyword); + const upper = keyword.toUpperCase(); + let target = upper; + if (locale === 'en') { + if (translations[upper]) target = translations[upper].toUpperCase(); + else { + const joined = line.trim().toUpperCase(); + for (const k in translations) { + if (Object.prototype.hasOwnProperty.call(translations, k)) { + const keyUpper = k.toUpperCase(); + if (joined.startsWith(keyUpper)) { target = translations[k].toUpperCase(); break; } + } + } + } + } + const wikiUrl = `https://wiki.eressea.de/${encodeURIComponent(target)}`; + const linked = `${kwEsc}`; + const contentRest = rest ? ' ' + escapeHtml(rest) : ''; + return `
    ${linked}${contentRest}
    `; + }).join(''); + // Optional file link header + const fileHeader = opts.fileLink ? `` : ''; + return `
    ${fileHeader}${inner}
    `; + }; + + eleventyConfig.addShortcode('orderfile', function (fileName, optionsJson) { + return renderOrderFile.call(this, fileName, optionsJson); + }); + eleventyConfig.addPassthroughCopy("crs/crs-passthrough.js"); eleventyConfig.addPassthroughCopy({ "crs/crs.css": "css/crs.css" }); diff --git a/reports/template/befehle-42.txt b/reports/template/befehle-42.txt new file mode 100644 index 0000000..67a3594 --- /dev/null +++ b/reports/template/befehle-42.txt @@ -0,0 +1,43 @@ +ERESSEA 42 "123" +;TIMESTAMP 1755601343839 +;Magellan Version 2.1.0-788.rc +; ECHECK -r75 -s -l -w4 -v4.3.2 +LOCALE de +REGION -2011,0 ; Vosal +; ECheck Lohn 11 +EINHEIT xda9; Einheit xda9 [997,90029$] +; Feinde attackieren! +ATTACKIERE 2uph ;Einheit 2uph +ATTACKIERE d3o0 ;Einheit d3o0 +LERNE Unterhaltung + +EINHEIT fwpq; Einheit fwpq [997,90029$] +ATTACKIERE 2uph ;Einheit 2uph +ATTACKIERE d3o0 ;Einheit d3o0 +LERNE Unterhaltung +REGION -2010,0 ; Sanwopavor +; ECheck Lohn 11 +EINHEIT 8uz4; Einheit 8uz4 [1,890$,U100] +LERNE Wahrnehmung +REGION -2011,2 ; Susot +; ECheck Lohn 11 +EINHEIT u4fh; Einheit u4fh [3,0$,Sbrhm] +ARBEITE +EINHEIT cfe2; Einheit cfe2 [3,0$,Snc6o] +; Ups, kein Silber ... +ARBEITE +EINHEIT 5a5n; Einheit 5a5n [3,0$,SLq4d] +; Ups, kein Silber! +LERNE Unterhaltung +EINHEIT ehp6; Einheit ehp6 [3,0$,St9au] +ARBEITE +EINHEIT 13ii; Einheit 13ii [3,0$,Ssk4o] +; **Auf zu neuen Abenteuern!** +NACH no o so o +EINHEIT d19j; Einheit d19j [3,0$,S3oq4] +ARBEITE +EINHEIT rtqa; Einheit rtqa [3,0$,Sb0ae] +ARBEITE +EINHEIT fa66; Einheit fa66 [3,0$,S7k9d] +ARBEITE +NÄCHSTER diff --git a/template/Auswertung_01.md b/template/Auswertung_01.md index 0e92c5a..59cfc33 100644 --- a/template/Auswertung_01.md +++ b/template/Auswertung_01.md @@ -31,3 +31,8 @@ Orders: ### Map not found error: {% crmap './reports/template/334-424242.cr' %} + + +### Include an order file with automatic comment formatting and wiki links + +{% orderfile './reports/template/befehle-42.txt' %} From 50cadb6c6f8b95763bdf623e90c31afc21f5d191 Mon Sep 17 00:00:00 2001 From: Steffen Mecke Date: Tue, 19 Aug 2025 16:07:10 +0200 Subject: [PATCH 20/34] refactored: moved things around in module.exports --- crs/crs.js | 861 +++++++++++++++++++++++++++-------------------------- 1 file changed, 441 insertions(+), 420 deletions(-) diff --git a/crs/crs.js b/crs/crs.js index 8bf0b94..5abd527 100644 --- a/crs/crs.js +++ b/crs/crs.js @@ -2,422 +2,476 @@ const fs = require('fs'); const path = require('path'); -// Color and image mappings from PHP -const colors = { - 'default': 'grey', - 'Ozean': '#0000ff', - 'Ebene': '#ffff00', - 'Wald': '#00dd00', - 'Sumpf': '#226611', - 'Berge': '#777777', - 'Hochland': '#ffeeaa', - 'Wüste': '#ffcc55', - 'Gletscher': '#bbbbcc', - 'Eisberg': '#eeeeff', - 'Vulkan': '#bb0022', - 'Aktiver Vulkan': '#ee0022', - 'Feuerwand': '#ff0000', -}; +// Library version (update when changing public shortcode behavior) +const CRS_VERSION = '0.1.0'; +// Export version for external use (e.g., in layouts via require) and add as global data below +module.exports.CRS_VERSION = CRS_VERSION; -const images = { - 'Ozean': 'ozean', - 'Ebene': 'ebene', - 'Wald': 'wald', - 'Sumpf': 'sumpf', - 'Berge': 'berge', - 'Hochland': 'hochland', - 'Wüste': 'wueste', - 'Gletscher': 'gletscher', - 'Eisberg': 'eisberg', - 'Vulkan': 'vulkan', - 'Aktiver Vulkan': 'aktiver vulkan', - 'Feuerwand': 'feuerwand', - 'Nebel': 'nebel', - 'Dichter Nebel': 'dichter nebel', - 'Packeis': 'packeis', - 'Gang': 'gang', - 'Halle': 'halle', - 'Wand': 'wand', -}; +module.exports = function (eleventyConfig) { + // Provide version to all templates as 'crmapVersion' + if (eleventyConfig.addGlobalData) { + eleventyConfig.addGlobalData('crmapVersion', CRS_VERSION); + } + + // crmap: render a CR file to an interactive SVG map. + // Usage: SECOND ARGUMENT IS OPTIONAL JSON OPTIONS STRING. + // {% crmap 'path/to/file.cr' %} -> defaults (auto crid, details true, z 0, auto caption) + // {% crmap 'path/to/file.cr' '{}' %} -> same as defaults + // {% crmap 'path/to/file.cr' '{"crid":"map1"}' %} -> explicit crid + // {% crmap 'path/to/file.cr' '{"details":false}' %} -> no details (tooltips only) + // {% crmap 'path/to/file.cr' '{"layer":2}' %} -> layer z=2 + // {% crmap 'path/to/file.cr' '{"caption":"My Caption"}' %} -> custom caption + // {% crmap 'path/to/file.cr' '{"caption":false}' %} -> omit caption + // {% crmap 'path/to/file.cr' '{"crid":"m1","details":false,"layer":1,"caption":false}' %} + // Option keys: crid (string), details (boolean), layer (integer), caption (string|false) + // Rules: + // - crid must match /^[a-z0-9_-]+$/; if omitted => auto numeric. + // - details:false removes detail panels but keeps tooltips. + // - caption:false omits figcaption; caption:string sets custom text. + // - Unrecognized keys are ignored. + // Optional detail containers (place anywhere after the map): + // {% crmap_rdetails 'map1' 'Optional placeholder text' %} -> region details target div + // {% crmap_udetails 'map1' 'Optional placeholder text' %} -> unit details target div + // {% crmap_commands 'map1' 'Optional placeholder text' %} -> unit commands target div + // Notes: + // - crid must be lowercase a-z 0-9 _ - + // - Duplicate custom crid returns an inline error. + // - details:false omits region/unit descriptions and links but keeps tooltips. -const defaultImage = 'region'; + eleventyConfig.addShortcode('crmap', function (file, optionsJson) { + return crmapShortcode.call(this, file, optionsJson); + }); -// Debug flag (enable with environment variable CRS_DEBUG=1) -const DEBUG = process.env.CRS_DEBUG === '1'; -function debug(...args) { if (DEBUG) console.log('[crs]', ...args); } + // Shortcode to output region details container for a given (or last created) crid + eleventyConfig.addShortcode('crmap_rdetails', function (crid, placeholder = null) { + return crmapRdetailsShortcode.call(this, crid, placeholder); + }); -function escapeHtml(str) { - return String(str) - .replace(/&/g, '&') - .replace(//g, '>') - .replace(/"/g, '"') - .replace(/'/g, '''); -} + // Shortcode to output unit details container for a given (or last created) crid + eleventyConfig.addShortcode('crmap_udetails', function (crid, placeholder = null) { + return crmapUdetailsShortcode.call(this, crid, placeholder); + }); -// Library version (update when changing public shortcode behavior) -const CRS_VERSION = '0.1.0'; -// Export version for external use (e.g., in layouts via require) and add as global data below -module.exports.CRS_VERSION = CRS_VERSION; + // Shortcode to output command details container for a given (or last created) crid + eleventyConfig.addShortcode('crmap_commands', function (crid, placeholder = null) { + return crmapCommandsShortcode.call(this, crid, placeholder); + }); -// Validation helper (stateless) -function validateCrid(id) { - if (typeof id !== 'string') return { ok: false, message: 'crid must be a string' }; - if (id !== id.toLowerCase()) return { ok: false, message: `crid '${id}' must be lowercase` }; - if (!/^[a-z0-9_-]+$/.test(id)) return { ok: false, message: `crid '${id}' contains invalid characters (allowed: a-z 0-9 _ -)` }; - return { ok: true }; -} - -function getColor(terrain) { - return colors[terrain] || colors['default']; -} - -function getImage(terrain) { - return images[terrain] || null; -} - -const rwidth = 100; -const yoff = rwidth * 0.5; - -function transformx(region) { - return Math.round(region.x * rwidth + region.y * yoff); -} -function transformy(region) { - return Math.round(region.y * -rwidth * 3 / 4); -} - -function itoa36(num) { - return num.toString(36); -} - -function parseFaction(line, matches) { - const parts = line.trim().split(/\s+/); - const numid = parseInt(matches[1], 10); - const faction = { id: itoa36(numid), numid, tags: {} }; - debug("found faction", faction); - - return faction; -} - -function parseRegion(line, matches) { - const parts = line.trim().split(/\s+/); - // Use plain objects for tags & units (units keyed by id) - const region = { tags: {}, units: {} }; - region.x = parseInt(matches[1], 10); - region.y = parseInt(matches[2], 10); - if (matches[3]) region.z = parseInt(matches[3], 10); else region.z = 0; - debug(`found region (${region.x},${region.y}, ${region.z})`); - - return region; -} - -function parseUnit(line, matches) { - const parts = line.trim().split(/\s+/); - const unit = { id: itoa36(parseInt(matches[1], 10)), name: '???', tags: {}, skills: {}, items: {}, commands: [] }; - debug("found unit", unit.id); - - return unit; -} - -function outputRegion(region, bounds, crid, withDetails, ownerFactionId) { - debug('writing region ', region); - if (!region) return ''; - if (!region.tags.Terrain) return ''; - let color = getColor(region.tags.Terrain); - let tag = getImage(region.tags.Terrain); - if (!tag) { - tag = defaultImage; - color = `fill=\"${color}\"`; - } else { - color = ''; + // Shortcode to output order file contents line by line + // Usage: {% orderfile 'path/to/file.nr' %} or {% orderfile 'path' '{"markdownInComments":true}' %} + // + // Options (passed as JSON string, optional): + // markdownInComments: boolean (default: true) + // - When true, lines starting with ';' are rendered as comment lines and + // the comment text is processed with markdown-it (inline rendering) + // if available. When false, comments are escaped plain text. + // fileLink: boolean (default: true) + // - When true, the rendered block will include a small header linking to + // the source file (basename shown). Set to false to omit the file link. + // commentsAsOrders: boolean (default: false) + // - When true, lines that start with ';' are treated as orders instead of + // comment blocks. They will be rendered as order lines with class + // `order no-link` (escaped text, no wiki link on the first token). + // + // Examples: + // {% orderfile 'reports/orcs/orders-demo-02.txt' %} + // {% orderfile 'reports/orcs/orders-demo-02.txt' '{"fileLink":false}' %} + // {% orderfile 'reports/orcs/orders-demo-02.txt' '{"commentsAsOrders":true}' %} + eleventyConfig.addShortcode('orderfile', function (fileName, optionsJson) { + return renderOrderFile.call(this, fileName, optionsJson); + }); + + // Passthrough assets + eleventyConfig.addPassthroughCopy("crs/crs-passthrough.js"); + eleventyConfig.addPassthroughCopy({ "crs/crs.css": "css/crs.css" }); + + // Color and image mappings from PHP + const colors = { + 'default': 'grey', + 'Ozean': '#0000ff', + 'Ebene': '#ffff00', + 'Wald': '#00dd00', + 'Sumpf': '#226611', + 'Berge': '#777777', + 'Hochland': '#ffeeaa', + 'Wüste': '#ffcc55', + 'Gletscher': '#bbbbcc', + 'Eisberg': '#eeeeff', + 'Vulkan': '#bb0022', + 'Aktiver Vulkan': '#ee0022', + 'Feuerwand': '#ff0000', + }; + + const images = { + 'Ozean': 'ozean', + 'Ebene': 'ebene', + 'Wald': 'wald', + 'Sumpf': 'sumpf', + 'Berge': 'berge', + 'Hochland': 'hochland', + 'Wüste': 'wueste', + 'Gletscher': 'gletscher', + 'Eisberg': 'eisberg', + 'Vulkan': 'vulkan', + 'Aktiver Vulkan': 'aktiver vulkan', + 'Feuerwand': 'feuerwand', + 'Nebel': 'nebel', + 'Dichter Nebel': 'dichter nebel', + 'Packeis': 'packeis', + 'Gang': 'gang', + 'Halle': 'halle', + 'Wand': 'wand', + }; + + const defaultImage = 'region'; + + // Debug flag (enable with environment variable CRS_DEBUG=1) + const DEBUG = process.env.CRS_DEBUG === '1'; + function debug(...args) { if (DEBUG) console.log('[crs]', ...args); } + + function escapeHtml(str) { + return String(str) + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"') + .replace(/'/g, '''); } - const xx = region.x; - const yy = region.y; - const x = transformx(region); - const y = transformy(region); - let tt = region.tags.Name ? region.tags.Name : region.tags.Terrain; - tt += ` (${xx}, ${yy})`; - - // Prepare JSON payloads - let regionData = {}; - if (withDetails) { - regionData = { x: region.x, y: region.y, tags: region.tags }; + + + // Validation helper (stateless) + function validateCrid(id) { + if (typeof id !== 'string') return { ok: false, message: 'crid must be a string' }; + if (id !== id.toLowerCase()) return { ok: false, message: `crid '${id}' must be lowercase` }; + if (!/^[a-z0-9_-]+$/.test(id)) return { ok: false, message: `crid '${id}' contains invalid characters (allowed: a-z 0-9 _ -)` }; + return { ok: true }; } - let id = 'r_'; - id += xx < 0 ? `m${-xx}` : xx; - id += yy < 0 ? `_m${-yy}` : `_${yy}`; - id += `_${crid}`; - - bounds.xmin = Math.min(bounds.xmin, x); - bounds.ymin = Math.min(bounds.ymin, y); - bounds.xmax = Math.max(bounds.xmax, x); - bounds.ymax = Math.max(bounds.ymax, y); - - let unitsMarkup = ''; - let unitsData = []; - if (withDetails && Object.keys(region.units).length > 0) { - unitsData = Object.entries(region.units).map(([id, unit]) => { - return { - id: unit.id, - name: unit.tags.Name || unit.id, - faction: unit.faction ? unit.faction.id : null, - factionName: unit.factionName || null, - isOwner: ownerFactionId && unit.faction && unit.faction.id === ownerFactionId ? true : false, - tags: unit.tags, - skills: unit.skills || {}, - items: unit.items || {}, - commands: unit.commands || [] - }; - }); - // Keep a single for units icon location - unitsMarkup = ``; + function getColor(terrain) { + return colors[terrain] || colors['default']; } - debug(`found units for region ${id}:`, unitsData); - - const escAttr = s => String(s).replace(/&/g, '&').replace(/"/g, '"'); - const regionDataAttr2 = withDetails ? ` data-region="${encodeURIComponent(JSON.stringify(regionData))}" data-region-target="rdetails_${crid}" data-region-id="${id}"` : ''; - return `` + - `${tt}\n` + - unitsMarkup + ``; -} - -function includeImage(image) { - // Looks for images/.svg and includes its content as a ... - const imgPath = path.resolve(process.cwd(), 'images', image + '.svg'); - if (fs.existsSync(imgPath)) { - let contents = fs.readFileSync(imgPath, 'utf8'); - // Extract only the inner SVG content (remove outer tags) - const match = contents.match(/]*>([\s\S]*?)<\/svg>/i); - contents = match ? match[1] : contents; - return ` ${contents} `; - } else { - return ` \n`; + + function getImage(terrain) { + return images[terrain] || null; } -} - -function outputFront(bounds) { - // SVG header and region polygon definition, plus terrain images - let svg = - `\n` + - `\n` + - ` \n` + - ` \n` + - ` \n` + - ` \n`; - for (const terrain in images) { - if (Object.prototype.hasOwnProperty.call(images, terrain)) { - svg += includeImage(images[terrain]); - } + + const rwidth = 100; + const yoff = rwidth * 0.5; + + function transformx(region) { + return Math.round(region.x * rwidth + region.y * yoff); + } + function transformy(region) { + return Math.round(region.y * -rwidth * 3 / 4); } - svg += includeImage('units'); - svg += ` \n \n`; - return svg; -} - -function outputBack() { - return '\n'; -} - -function parseSkill(key) { - return parseInt(key.trim().split(/\s+/)[1], 10); -} - -function parseItem(key) { - return parseInt(key.trim(), 10); -} - -// Report class encapsulating all regions and their units -class Report { - constructor(crid, name, withDetails = true) { - this.crid = crid; - this.name = name || `Report ${crid}`; - this.tags = {}; - this.owner = null; - this.regions = []; - this.factions = []; - this.withDetails = withDetails; + + function itoa36(num) { + return num.toString(36); } - addFaction(faction) { - this.factions.push(faction); + function parseFaction(line, matches) { + const parts = line.trim().split(/\s+/); + const numid = parseInt(matches[1], 10); + const faction = { id: itoa36(numid), numid, tags: {} }; + debug("found faction", faction); + return faction; } - addRegion(region) { - this.regions.push(region); + function parseRegion(line, matches) { + const parts = line.trim().split(/\s+/); + // Use plain objects for tags & units (units keyed by id) + const region = { tags: {}, units: {} }; + region.x = parseInt(matches[1], 10); + region.y = parseInt(matches[2], 10); + if (matches[3]) region.z = parseInt(matches[3], 10); else region.z = 0; + debug(`found region (${region.x},${region.y}, ${region.z})`); + return region; } - addUnit(region, unit) { - region.units[unit.id] = unit; + function parseUnit(line, matches) { + const parts = line.trim().split(/\s+/); + const unit = { id: itoa36(parseInt(matches[1], 10)), name: '???', tags: {}, skills: {}, items: {}, commands: [] }; + debug("found unit", unit.id); + return unit; } - static parse(filePath, crid, name, withDetails = true, zFilter = 0) { - debug(`Processing CR file: ${filePath}`); - const content = fs.readFileSync(filePath, 'utf8'); - const lines = content.split(/\r?\n/); - const pregRegion = /^REGION (-?\d+) (-?\d+)(?: (-?\d+))?$/; - const pregTagq = /^"(.*)";(.*)$/; - const pregTag = /^(.*);(.*)$/; - const pregBlock = /^([A-Z]+)\s*(.*)$/; - const pregQString = /^"(.*)"$/; - const pregUnit = /^EINHEIT (\d+)$/; - const pregFaction = /^PARTEI (\d+)$/; - - const report = new Report(crid, name, withDetails); - let block = 'ERESSEA'; - let currentUnit = null, currentRegion = null, currentFaction = null; - for (let line of lines) { - let tag = null, value = null, matches; - if ((matches = pregFaction.exec(line))) { - block = 'FACTION'; - currentRegion = null; - currentUnit = null; - currentFaction = report.addFaction(parseFaction(line, matches)); - if (!report.owner) { - report.owner = currentFaction; - } - continue; + function outputRegion(region, bounds, crid, withDetails, ownerFactionId) { + debug('writing region ', region); + if (!region) return ''; + if (!region.tags.Terrain) return ''; + let color = getColor(region.tags.Terrain); + let tag = getImage(region.tags.Terrain); + if (!tag) { + tag = defaultImage; + color = `fill=\"${color}\"`; + } else { + color = ''; + } + const xx = region.x; + const yy = region.y; + const x = transformx(region); + const y = transformy(region); + let tt = region.tags.Name ? region.tags.Name : region.tags.Terrain; + tt += ` (${xx}, ${yy})`; + + // Prepare JSON payloads + let regionData = {}; + if (withDetails) { + regionData = { x: region.x, y: region.y, tags: region.tags }; + } + + let id = 'r_'; + id += xx < 0 ? `m${-xx}` : xx; + id += yy < 0 ? `_m${-yy}` : `_${yy}`; + id += `_${crid}`; + + bounds.xmin = Math.min(bounds.xmin, x); + bounds.ymin = Math.min(bounds.ymin, y); + bounds.xmax = Math.max(bounds.xmax, x); + bounds.ymax = Math.max(bounds.ymax, y); + + let unitsMarkup = ''; + let unitsData = []; + if (withDetails && Object.keys(region.units).length > 0) { + unitsData = Object.entries(region.units).map(([id, unit]) => { + return { + id: unit.id, + name: unit.tags.Name || unit.id, + faction: unit.faction ? unit.faction.id : null, + factionName: unit.factionName || null, + isOwner: ownerFactionId && unit.faction && unit.faction.id === ownerFactionId ? true : false, + tags: unit.tags, + skills: unit.skills || {}, + items: unit.items || {}, + commands: unit.commands || [] + }; + }); + // Keep a single for units icon location + unitsMarkup = ``; + } + debug(`found units for region ${id}:`, unitsData); + + const escAttr = s => String(s).replace(/&/g, '&').replace(/"/g, '"'); + const regionDataAttr2 = withDetails ? ` data-region="${encodeURIComponent(JSON.stringify(regionData))}" data-region-target="rdetails_${crid}" data-region-id="${id}"` : ''; + return `` + + `${tt}\n` + + unitsMarkup + ``; + } + + function includeImage(image) { + // Looks for images/.svg and includes its content as a ... + const imgPath = path.resolve(process.cwd(), 'images', image + '.svg'); + if (fs.existsSync(imgPath)) { + let contents = fs.readFileSync(imgPath, 'utf8'); + // Extract only the inner SVG content (remove outer tags) + const match = contents.match(/]*>([\s\S]*?)<\/svg>/i); + contents = match ? match[1] : contents; + return ` ${contents} `; + } else { + return ` \n`; + } + } + + function outputFront(bounds) { + // SVG header and region polygon definition, plus terrain images + let svg = + `\n` + + `\n` + + ` \n` + + ` \n` + + ` \n` + + ` \n`; + for (const terrain in images) { + if (Object.prototype.hasOwnProperty.call(images, terrain)) { + svg += includeImage(images[terrain]); } - if ((matches = pregRegion.exec(line))) { - block = 'REGION'; - currentFaction = null; - currentUnit = null; - const reg = parseRegion(line, matches); - debug(`parsing region (${reg.x},${reg.y}) with z=${reg.z}, needs to match ${zFilter}`); - if ((reg.z || 0) === (zFilter || 0)) { - currentRegion = report.addRegion(reg); - } else { - // Skip this region's subsequent UNIT/TAG blocks by keeping currentRegion null + } + svg += includeImage('units'); + svg += ` \n \n`; + return svg; + } + + function outputBack() { + return '\n'; + } + + function parseSkill(key) { + return parseInt(key.trim().split(/\s+/)[1], 10); + } + + function parseItem(key) { + return parseInt(key.trim(), 10); + } + + // Report class encapsulating all regions and their units + class Report { + constructor(crid, name, withDetails = true) { + this.crid = crid; + this.name = name || `Report ${crid}`; + this.tags = {}; + this.owner = null; + this.regions = []; + this.factions = []; + this.withDetails = withDetails; + } + + addFaction(faction) { + this.factions.push(faction); + return faction; + } + + addRegion(region) { + this.regions.push(region); + return region; + } + + addUnit(region, unit) { + region.units[unit.id] = unit; + return unit; + } + + static parse(filePath, crid, name, withDetails = true, zFilter = 0) { + debug(`Processing CR file: ${filePath}`); + const content = fs.readFileSync(filePath, 'utf8'); + const lines = content.split(/\r?\n/); + const pregRegion = /^REGION (-?\d+) (-?\d+)(?: (-?\d+))?$/; + const pregTagq = /^"(.*)";(.*)$/; + const pregTag = /^(.*);(.*)$/; + const pregBlock = /^([A-Z]+)\s*(.*)$/; + const pregQString = /^"(.*)"$/; + const pregUnit = /^EINHEIT (\d+)$/; + const pregFaction = /^PARTEI (\d+)$/; + + const report = new Report(crid, name, withDetails); + let block = 'ERESSEA'; + let currentUnit = null, currentRegion = null, currentFaction = null; + for (let line of lines) { + let tag = null, value = null, matches; + if ((matches = pregFaction.exec(line))) { + block = 'FACTION'; currentRegion = null; + currentUnit = null; + currentFaction = report.addFaction(parseFaction(line, matches)); + if (!report.owner) { + report.owner = currentFaction; + } + continue; + } + if ((matches = pregRegion.exec(line))) { + block = 'REGION'; + currentFaction = null; + currentUnit = null; + const reg = parseRegion(line, matches); + debug(`parsing region (${reg.x},${reg.y}) with z=${reg.z}, needs to match ${zFilter}`); + if ((reg.z || 0) === (zFilter || 0)) { + currentRegion = report.addRegion(reg); + } else { + // Skip this region's subsequent UNIT/TAG blocks by keeping currentRegion null + currentRegion = null; + } + continue; } - continue; - } - if (currentRegion && (matches = pregUnit.exec(line))) { - block = 'UNIT'; - currentUnit = report.addUnit(currentRegion, parseUnit(line, matches)); + if (currentRegion && (matches = pregUnit.exec(line))) { + block = 'UNIT'; + currentUnit = report.addUnit(currentRegion, parseUnit(line, matches)); - continue; - } - if ((matches = pregQString.exec(line))) { - tag = true; - value = matches[1]; - } else if ((matches = pregTagq.exec(line))) { - value = matches[1]; tag = matches[2]; - } else if ((matches = pregTag.exec(line))) { - value = matches[1]; tag = matches[2]; - } else if ((matches = pregBlock.exec(line))) { - block = matches[1]; - continue; - } - if (!tag) continue; - if (block === 'ERESSEA') { - report.tags[tag] = value; - } else if (block == 'FACTION' && currentFaction) { - currentFaction.tags[tag] = value; - } else if (block === 'REGION' && currentRegion) { - currentRegion.tags[tag] = value; - } else if (block === 'UNIT' && currentUnit && currentRegion) { - currentUnit.tags[tag] = value; - currentRegion.units[currentUnit.id] = currentUnit; - } else if (block === 'TALENTE' && currentUnit) { - currentUnit.skills = currentUnit.skills || {}; - currentUnit.skills[tag] = parseSkill(value); - } else if (block === 'GEGENSTAENDE' && currentUnit) { - currentUnit.items = currentUnit.items || {}; - currentUnit.items[tag] = parseItem(value); - } else if (block === 'COMMANDS' && currentUnit) { - currentUnit.commands = currentUnit.commands || []; - // Remove surrounding quotes if present - let cmd = value; - if (cmd.length > 1 && ((cmd.startsWith('"') && cmd.endsWith('"')) || (cmd.startsWith("'") && cmd.endsWith("'")))) { - cmd = cmd.slice(1, -1); + continue; + } + if ((matches = pregQString.exec(line))) { + tag = true; + value = matches[1]; + } else if ((matches = pregTagq.exec(line))) { + value = matches[1]; tag = matches[2]; + } else if ((matches = pregTag.exec(line))) { + value = matches[1]; tag = matches[2]; + } else if ((matches = pregBlock.exec(line))) { + block = matches[1]; + continue; + } + if (!tag) continue; + if (block === 'ERESSEA') { + report.tags[tag] = value; + } else if (block == 'FACTION' && currentFaction) { + currentFaction.tags[tag] = value; + } else if (block === 'REGION' && currentRegion) { + currentRegion.tags[tag] = value; + } else if (block === 'UNIT' && currentUnit && currentRegion) { + currentUnit.tags[tag] = value; + currentRegion.units[currentUnit.id] = currentUnit; + } else if (block === 'TALENTE' && currentUnit) { + currentUnit.skills = currentUnit.skills || {}; + currentUnit.skills[tag] = parseSkill(value); + } else if (block === 'GEGENSTAENDE' && currentUnit) { + currentUnit.items = currentUnit.items || {}; + currentUnit.items[tag] = parseItem(value); + } else if (block === 'COMMANDS' && currentUnit) { + currentUnit.commands = currentUnit.commands || []; + // Remove surrounding quotes if present + let cmd = value; + if (cmd.length > 1 && ((cmd.startsWith('"') && cmd.endsWith('"')) || (cmd.startsWith("'") && cmd.endsWith("'")))) { + cmd = cmd.slice(1, -1); + } + currentUnit.commands.push(cmd); } - currentUnit.commands.push(cmd); } - } - // Resolve unit factions (Partei tag) to actual faction objects & names - const factionIndexByNum = {}; - for (const f of report.factions) factionIndexByNum[f.numid] = f; - for (const region of report.regions) { - for (const unit of Object.values(region.units)) { - if (unit.tags && unit.tags.Partei) { - const fid = parseInt(unit.tags.Partei, 10); - if (!isNaN(fid) && factionIndexByNum[fid]) { - unit.faction = factionIndexByNum[fid]; - unit.factionName = factionIndexByNum[fid].tags.Parteiname || factionIndexByNum[fid].id; + // Resolve unit factions (Partei tag) to actual faction objects & names + const factionIndexByNum = {}; + for (const f of report.factions) factionIndexByNum[f.numid] = f; + for (const region of report.regions) { + for (const unit of Object.values(region.units)) { + if (unit.tags && unit.tags.Partei) { + const fid = parseInt(unit.tags.Partei, 10); + if (!isNaN(fid) && factionIndexByNum[fid]) { + unit.faction = factionIndexByNum[fid]; + unit.factionName = factionIndexByNum[fid].tags.Parteiname || factionIndexByNum[fid].id; + } } } } + return report; } - return report; - } - computeBounds() { - const bounds = { xmin: Infinity, ymin: Infinity, xmax: -Infinity, ymax: -Infinity }; - for (const r of this.regions) { - const x = transformx(r); - const y = transformy(r); - bounds.xmin = Math.min(bounds.xmin, x); - bounds.ymin = Math.min(bounds.ymin, y); - bounds.xmax = Math.max(bounds.xmax, x); - bounds.ymax = Math.max(bounds.ymax, y); - } - if (!isFinite(bounds.xmin)) { // empty safeguard - bounds.xmin = bounds.ymin = 0; - bounds.xmax = bounds.ymax = 100; + computeBounds() { + const bounds = { xmin: Infinity, ymin: Infinity, xmax: -Infinity, ymax: -Infinity }; + for (const r of this.regions) { + const x = transformx(r); + const y = transformy(r); + bounds.xmin = Math.min(bounds.xmin, x); + bounds.ymin = Math.min(bounds.ymin, y); + bounds.xmax = Math.max(bounds.xmax, x); + bounds.ymax = Math.max(bounds.ymax, y); + } + if (!isFinite(bounds.xmin)) { // empty safeguard + bounds.xmin = bounds.ymin = 0; + bounds.xmax = bounds.ymax = 100; + } + return bounds; } - return bounds; - } - toSVG() { - const bounds = this.computeBounds(); - let body = ''; - const ownerFactionId = this.owner ? this.owner.id : null; - for (const r of this.regions) { - body += outputRegion(r, bounds, this.crid, this.withDetails, ownerFactionId); + toSVG() { + const bounds = this.computeBounds(); + let body = ''; + const ownerFactionId = this.owner ? this.owner.id : null; + for (const r of this.regions) { + body += outputRegion(r, bounds, this.crid, this.withDetails, ownerFactionId); + } + return outputFront(bounds) + body + outputBack(); } - return outputFront(bounds) + body + outputBack(); } -} -module.exports = function (eleventyConfig) { - // Provide version to all templates as 'crmapVersion' - if (eleventyConfig.addGlobalData) { - eleventyConfig.addGlobalData('crmapVersion', CRS_VERSION); - } - // Usage: SECOND ARGUMENT IS OPTIONAL JSON OPTIONS STRING. - // {% crmap 'path/to/file.cr' %} -> defaults (auto crid, details true, z 0, auto caption) - // {% crmap 'path/to/file.cr' '{}' %} -> same as defaults - // {% crmap 'path/to/file.cr' '{"crid":"map1"}' %} -> explicit crid - // {% crmap 'path/to/file.cr' '{"details":false}' %} -> no details (tooltips only) - // {% crmap 'path/to/file.cr' '{"layer":2}' %} -> layer z=2 - // {% crmap 'path/to/file.cr' '{"caption":"My Caption"}' %} -> custom caption - // {% crmap 'path/to/file.cr' '{"caption":false}' %} -> omit caption - // {% crmap 'path/to/file.cr' '{"crid":"m1","details":false,"layer":1,"caption":false}' %} - // Option keys: crid (string), details (boolean), layer (integer), caption (string|false) - // Rules: - // - crid must match /^[a-z0-9_-]+$/; if omitted => auto numeric. - // - details:false removes detail panels but keeps tooltips. - // - caption:false omits figcaption; caption:string sets custom text. - // - Unrecognized keys are ignored. - // Optional detail containers (place anywhere after the map): - // {% crmap_rdetails 'map1' 'Optional placeholder text' %} -> region details target div - // {% crmap_udetails 'map1' 'Optional placeholder text' %} -> unit details target div - // {% crmap_commands 'map1' 'Optional placeholder text' %} -> unit commands target div - // Notes: - // - crid must be lowercase a-z 0-9 _ - - // - Duplicate custom crid returns an inline error. - // - details:false omits region/unit descriptions and links but keeps tooltips. - eleventyConfig.addShortcode('crmap', function (file, optionsJson) { + + // ================= Shortcode function implementations ================= + + function crmapShortcode(file, optionsJson) { try { let requestedCrid; // explicit id let detailsOption = true; // default include details @@ -534,11 +588,9 @@ module.exports = function (eleventyConfig) { debug(`Error processing file: ${filePath} `, e); return `
    Error: ${escapeHtml(e.message)}
    `; } - }); - - // Shortcode to output region details container for a given crid + } - eleventyConfig.addShortcode('crmap_rdetails', function (crid, placeholder = null) { + function crmapRdetailsShortcode(crid, placeholder = null) { // Access per-page state let pageState = this && this.ctx ? this.ctx._crmapState : null; let useCrid = crid; @@ -555,11 +607,9 @@ module.exports = function (eleventyConfig) { placeholder = ''; } return `
    ${placeholder}
    `; - }); - - // Shortcode to output unit details container for a given crid + } - eleventyConfig.addShortcode('crmap_udetails', function (crid, placeholder = null) { + function crmapUdetailsShortcode(crid, placeholder = null) { let pageState = this && this.ctx ? this.ctx._crmapState : null; let useCrid = crid; if (!useCrid && pageState) useCrid = pageState.lastCrid; @@ -575,11 +625,9 @@ module.exports = function (eleventyConfig) { placeholder = ''; } return `
    ${placeholder}
    `; - }); - - // Shortcode to output unit commands container for a given crid + } - eleventyConfig.addShortcode('crmap_commands', function (crid, placeholder = null) { + function crmapCommandsShortcode(crid, placeholder = null) { let pageState = this && this.ctx ? this.ctx._crmapState : null; let useCrid = crid; if (!useCrid && pageState) useCrid = pageState.lastCrid; @@ -595,29 +643,9 @@ module.exports = function (eleventyConfig) { placeholder = ''; } return `
    ${placeholder}
    `; - }); + } - // Shortcode to output order file contents line by line - // Usage: {% orderfile 'path/to/file.nr' %} or {% orderfile 'path' '{"markdownInComments":true}' %} - // - // Options (passed as JSON string, optional): - // markdownInComments: boolean (default: true) - // - When true, lines starting with ';' are rendered as comment lines and - // the comment text is processed with markdown-it (inline rendering) - // if available. When false, comments are escaped plain text. - // fileLink: boolean (default: true) - // - When true, the rendered block will include a small header linking to - // the source file (basename shown). Set to false to omit the file link. - // commentsAsOrders: boolean (default: false) - // - When true, lines that start with ';' are treated as orders instead of - // comment blocks. They will be rendered as order lines with class - // `order no-link` (escaped text, no wiki link on the first token). - // - // Examples: - // {% orderfile 'reports/orcs/orders-demo-02.txt' %} - // {% orderfile 'reports/orcs/orders-demo-02.txt' '{"fileLink":false}' %} - // {% orderfile 'reports/orcs/orders-demo-02.txt' '{"commentsAsOrders":true}' %} - const renderOrderFile = function (fileName, optionsJson) { + function renderOrderFile(fileName, optionsJson) { const fs = require('fs'); const path = require('path'); if (!fileName || typeof fileName !== 'string') { @@ -802,15 +830,8 @@ module.exports = function (eleventyConfig) { return `
    ${linked}${contentRest}
    `; }).join(''); // Optional file link header - const fileHeader = opts.fileLink ? `` : ''; + const fileHeader = opts.fileLink ? `` : ''; + // include marker classes so the layout can detect whether to add CSS/JS return `
    ${fileHeader}${inner}
    `; - }; - - eleventyConfig.addShortcode('orderfile', function (fileName, optionsJson) { - return renderOrderFile.call(this, fileName, optionsJson); - }); - - eleventyConfig.addPassthroughCopy("crs/crs-passthrough.js"); - eleventyConfig.addPassthroughCopy({ "crs/crs.css": "css/crs.css" }); - + } }; From 4e3c512d2f57681374f71da0701d32c8471202d3 Mon Sep 17 00:00:00 2001 From: Steffen Mecke Date: Tue, 19 Aug 2025 16:35:47 +0200 Subject: [PATCH 21/34] sorting out path usage --- crs/crs.js | 65 +++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 52 insertions(+), 13 deletions(-) diff --git a/crs/crs.js b/crs/crs.js index 5abd527..5402f46 100644 --- a/crs/crs.js +++ b/crs/crs.js @@ -138,6 +138,41 @@ module.exports = function (eleventyConfig) { .replace(/'/g, '''); } + // Resolve a user-supplied path argument used in shortcodes. + // Supports two forms: + // 1. Root-relative (starts with '/'): resolved against project root (Eleventy's input dir) + // 2. Relative: resolved against the directory of the calling template file + // Returns { fsPath, publicPath, relPath } or { error } + // publicPath is prefixed with optional deployment path prefix (env ELEVENTY_PATH_PREFIX) and always begins with '/'. + function resolveUserPath(spec, ctx) { + if (!spec || typeof spec !== 'string') return { error: 'missing path' }; + // Normalize Windows backslashes just in case + spec = spec.replace(/\\/g, '/'); + let pathPrefix = process.env.ELEVENTY_PATH_PREFIX || ''; + if (pathPrefix && pathPrefix !== '/' && pathPrefix.endsWith('/')) pathPrefix = pathPrefix.slice(0, -1); + if (pathPrefix === '/') pathPrefix = ''; + const projectRoot = process.cwd(); + // Base directory derived from the template invoking the shortcode + let baseDir = projectRoot; + try { + if (ctx && ctx.page && ctx.page.inputPath) { + const tplPath = path.resolve(projectRoot, ctx.page.inputPath); + baseDir = path.dirname(tplPath); + } + } catch (_) { /* ignore */ } + const isRootRel = spec.startsWith('/'); + const cleaned = isRootRel ? spec.replace(/^\/+/, '') : spec; + const candidateFs = path.resolve(isRootRel ? projectRoot : baseDir, cleaned); + // Prevent escaping project root + const rootWithSep = projectRoot.endsWith(path.sep) ? projectRoot : projectRoot + path.sep; + if (!candidateFs.startsWith(rootWithSep)) { + return { error: 'path escapes project root' }; + } + const relPath = path.relative(projectRoot, candidateFs).split(path.sep).join('/'); + const publicPath = (pathPrefix ? pathPrefix : '') + '/' + relPath; + return { fsPath: candidateFs, publicPath, relPath }; + } + // Validation helper (stateless) function validateCrid(id) { @@ -545,13 +580,16 @@ module.exports = function (eleventyConfig) { } pageState.crids.add(crid); pageState.lastCrid = crid; - const filePath = path.resolve(process.cwd(), file); - if (!fs.existsSync(filePath)) { - debug(`File not found: ${filePath}`); + const resolved = resolveUserPath(file, this); + if (resolved.error) { + return `
    Path error: ${escapeHtml(resolved.error)} (${escapeHtml(file)})
    `; + } + if (!fs.existsSync(resolved.fsPath)) { + debug(`File not found: ${resolved.fsPath}`); return `
    File not found: ${escapeHtml(file)}
    `; } - const reportName = path.basename(filePath, path.extname(filePath)); - const report = Report.parse(filePath, crid, reportName, detailsOption, zOption); + const reportName = path.basename(resolved.fsPath, path.extname(resolved.fsPath)); + const report = Report.parse(resolved.fsPath, crid, reportName, detailsOption, zOption); const svg = report.toSVG(); let caption = ''; if (captionOption === false) { @@ -567,9 +605,9 @@ module.exports = function (eleventyConfig) { if (caption !== null && typeof caption !== 'undefined') { const captionEsc = escapeHtml(caption); if (fileLinkOption) { - const href = escapeHtml(encodeURI(file)); const fileDisplay = escapeHtml(path.basename(file)); - figcaptionHtml = `
    ${captionEsc}, source: ${fileDisplay}
    `; + const href = escapeHtml(encodeURI(resolved.publicPath)); + figcaptionHtml = `
    ${captionEsc}, source: ${fileDisplay}
    `; } else { figcaptionHtml = `
    ${captionEsc}
    `; } @@ -646,8 +684,6 @@ module.exports = function (eleventyConfig) { } function renderOrderFile(fileName, optionsJson) { - const fs = require('fs'); - const path = require('path'); if (!fileName || typeof fileName !== 'string') { return '
    orderfile: missing file name
    '; } @@ -666,11 +702,14 @@ module.exports = function (eleventyConfig) { } } - const fullPath = path.resolve(process.cwd(), fileName); - if (!fs.existsSync(fullPath)) { + const resolved = resolveUserPath(fileName, this); + if (resolved.error) { + return `
    orderfile: path error: ${escapeHtml(resolved.error)} (${escapeHtml(fileName)})
    `; + } + if (!fs.existsSync(resolved.fsPath)) { return `
    orderfile: file not found: ${escapeHtml(fileName)}
    `; } - const content = fs.readFileSync(fullPath, 'utf8'); + const content = fs.readFileSync(resolved.fsPath, 'utf8'); const rawLines = content.split(/\r?\n/); // Detect locale from lines like: "en";locale -- default to 'de' if not found let locale = 'de'; @@ -830,7 +869,7 @@ module.exports = function (eleventyConfig) { return `
    ${linked}${contentRest}
    `; }).join(''); // Optional file link header - const fileHeader = opts.fileLink ? `` : ''; + const fileHeader = opts.fileLink ? `` : ''; // include marker classes so the layout can detect whether to add CSS/JS return `
    ${fileHeader}${inner}
    `; } From 3bcd5fcf4845d3dbfe43fac7bf71db2906aa78f2 Mon Sep 17 00:00:00 2001 From: Steffen Mecke Date: Wed, 20 Aug 2025 12:14:05 +0200 Subject: [PATCH 22/34] feature: show NRs; select sections, line ranges - show sections of the nr like the intro, events, a region, a unit - you can even display line ranges of arbitrary text files - with or without line numbers - see template/Auswertung_01.md for usage examples --- crs/crs.css | 75 +++++++ crs/crs.js | 388 ++++++++++++++++++++++++++++++++++++- reports/template/334-42.nr | 365 ++++++++++++++++++++++++++++++++++ template/Auswertung_01.md | 76 ++++++-- 4 files changed, 885 insertions(+), 19 deletions(-) create mode 100644 reports/template/334-42.nr diff --git a/crs/crs.css b/crs/crs.css index f52a068..9148ced 100644 --- a/crs/crs.css +++ b/crs/crs.css @@ -61,6 +61,7 @@ } /* Orderfile styling */ + .orderfile { font-family: monospace; font-size: 0.95em; @@ -119,4 +120,78 @@ .orderfile { margin-top: 0.2em; margin-bottom: 0.2em; +} + +/* shownr / nr helpers: render in same monospace font and spacing as orderfile/order-line */ +.shownr-wrapper { + display: block; +} + +.nr-registered { + font-family: monospace; + font-size: 0.95em; +} + +.shownr { + font-family: monospace; + font-size: 0.8em; + overflow-x: auto; + padding: 0.35em; + border: 1px solid rgba(0, 0, 0, 0.06); + background: #fbfbfb; + border-radius: 6px; +} + +.shownr-line { + font-family: monospace; + padding: 0.08em 0.25em; + margin: 0; + line-height: 1.15; + white-space: pre; + tab-size: 4; +} + +.shownr-line+.shownr-line { + margin-top: 0.08em; +} + +/* nicer scrollbars on WebKit/Blink */ +.shownr::-webkit-scrollbar { + height: 10px; + background: transparent; +} + +.shownr::-webkit-scrollbar-thumb { + background: rgba(0, 0, 0, 0.12); + border-radius: 6px; +} + +.shownr::-webkit-scrollbar-thumb:hover { + background: rgba(0, 0, 0, 0.18); +} + +/* Firefox scrollbar width hint */ +.shownr { + scrollbar-width: thin; + scrollbar-color: rgba(0, 0, 0, 0.12) transparent; +} + +.shownr-file { + font-family: inherit; + /* use site default font */ + font-size: 0.95em; + color: #333; + margin-bottom: 0.25em; +} + +.nr-registered { + display: none; +} + +.shownr-linenr { + display: inline-block; + width: 2em; + text-align: right; + color: #999; + padding-right: 0.5em; } \ No newline at end of file diff --git a/crs/crs.js b/crs/crs.js index 5402f46..6923b6c 100644 --- a/crs/crs.js +++ b/crs/crs.js @@ -1,6 +1,7 @@ // crs.js const fs = require('fs'); const path = require('path'); +const { start } = require('repl'); // Library version (update when changing public shortcode behavior) const CRS_VERSION = '0.1.0'; @@ -72,6 +73,8 @@ module.exports = function (eleventyConfig) { // - When true, lines that start with ';' are treated as orders instead of // comment blocks. They will be rendered as order lines with class // `order no-link` (escaped text, no wiki link on the first token). + // renderSpecial: boolean (default: false) + // - When true, lines that match specialPrefixes are rendered. // // Examples: // {% orderfile 'reports/orcs/orders-demo-02.txt' %} @@ -81,6 +84,24 @@ module.exports = function (eleventyConfig) { return renderOrderFile.call(this, fileName, optionsJson); }); + // Usage examples for the .nr helpers: + // {% readnr 'reports/orcs/orders-demo-02.nr' %} -> registers file, auto nrid + // {% readnr 'reports/orcs/orders-demo-02.nr' '{"nrid":"r1"}' %} -> register with explicit nrid + // {% shownr 'list' %} -> show a list of all bookmarks from last readnr + // {% shownr 'header' %} -> show 'header' bookmark from last readnr + // {% shownr 'r1' 'battles' %} -> show 'battles' bookmark from nrid r1 + // {% shownr '10-20' %} -> show lines 10..20 from last nrid + // {% shownr '{"nrid":"r1","range":"5-15", "lineNumbers":true }' %} -> JSON form + // {% shownr 'r1' 'unit_abc123' %} -> show the unit with id 'abc123' inside region + // {% shownr '{"bookmark":"heading_ereignisse","maxHeight":300}' %} -> show heading with max 300px height + // Shortcodes for reading and showing .nr (order/report) files with bookmarks + eleventyConfig.addShortcode('readnr', function (file, optionsJson) { + return readnrShortcode.call(this, file, optionsJson); + }); + eleventyConfig.addShortcode('shownr', function (arg1, arg2) { + return shownrShortcode.call(this, arg1, arg2); + }); + // Passthrough assets eleventyConfig.addPassthroughCopy("crs/crs-passthrough.js"); eleventyConfig.addPassthroughCopy({ "crs/crs.css": "css/crs.css" }); @@ -688,7 +709,7 @@ module.exports = function (eleventyConfig) { return '
    orderfile: missing file name
    '; } // parse options - const opts = { markdownInComments: true, fileLink: true, commentsAsOrders: false }; + const opts = { markdownInComments: true, fileLink: true, commentsAsOrders: false, renderSpecial: false }; if (typeof optionsJson === 'string' && optionsJson.trim() !== '') { try { const parsed = JSON.parse(optionsJson); @@ -696,6 +717,7 @@ module.exports = function (eleventyConfig) { if (Object.prototype.hasOwnProperty.call(parsed, 'markdownInComments')) opts.markdownInComments = !!parsed.markdownInComments; if (Object.prototype.hasOwnProperty.call(parsed, 'fileLink')) opts.fileLink = !!parsed.fileLink; if (Object.prototype.hasOwnProperty.call(parsed, 'commentsAsOrders')) opts.commentsAsOrders = !!parsed.commentsAsOrders; + if (Object.prototype.hasOwnProperty.call(parsed, 'renderSpecial')) opts.renderSpecial = !!parsed.renderSpecial; } } catch (e) { return `
    orderfile: invalid options JSON: ${escapeHtml(e.message)}
    `; @@ -808,15 +830,18 @@ module.exports = function (eleventyConfig) { let line = rawLine || ''; if (line.trim() === '') return '
    '; // Special-case: treat certain diagnostic/comment prefixes as orders (no link) - const specialPrefixes = [/^TIMESTAMP\b/i, /^Magellan version/i, /^ECheck\b/i]; + const specialPrefixes = [/^TIMESTAMP\b/i, /^Magellan version/i, /^ECheck\b/i, /^bestaetigt\s*$/]; const pureLine = line.replace(/^;\s*/, ''); const isSpecial = specialPrefixes.some(rx => rx.test(pureLine)); - console.log(isSpecial ? 'special' : 'normal' + ': ' + line); + if (isSpecial) { // render these special diagnostic lines in the same style as comment-as-order - - const txt = escapeHtml(line); - return `
    ${txt}
    `; + if (opts.renderSpecial) { + const txt = escapeHtml(line); + return `
    ${txt}
    `; + } else { + return ''; + } } if (/^\/\//.test(line.trim())) { // lines beginning with // are a special "comment" command that should link to the @@ -835,7 +860,7 @@ module.exports = function (eleventyConfig) { const commentText = opts.markdownInComments ? md.renderInline(line) : escapeHtml(line); return `
    ${(commentText)}
    `; } else { - const commentText = line.replace(/^;\s*/, ''); + const commentText = line; // .replace(/^;\s*/, ''); // default behavior: comment line - render markdown if enabled if (opts.markdownInComments && md) { return `
    ${md.renderInline(commentText)}
    `; @@ -873,4 +898,353 @@ module.exports = function (eleventyConfig) { // include marker classes so the layout can detect whether to add CSS/JS return `
    ${fileHeader}${inner}
    `; } + + // ----------------- readnr / shownr implementations ----------------- + + function _getPageNrState(ctxThis) { + if (ctxThis && ctxThis.ctx) { + ctxThis.ctx._nrState = ctxThis.ctx._nrState || {}; + const s = ctxThis.ctx._nrState; + if (!s.nrids) { s.nrids = new Set(); s.counter = 0; s.lastNrid = null; s.nrFiles = {}; } + return s; + } + return { nrids: new Set(), counter: 0, lastNrid: null, nrFiles: {} }; + } + + function readnrShortcode(file, optionsJson) { + const separator = /^\s*-+\s*$/; + + const fs = require('fs'); + const path = require('path'); + let opts = {}; + if (typeof optionsJson === 'string' && optionsJson.trim() !== '') { + try { opts = JSON.parse(optionsJson); } catch (e) { return `
    readnr: invalid options JSON: ${escapeHtml(e.message)}
    `; } + } + const requestedNrid = opts && typeof opts.nrid === 'string' && opts.nrid !== '' ? opts.nrid : undefined; + const pageState = _getPageNrState(this); + // determine nrid + let nrid; + if (requestedNrid) { + const v = validateCrid(requestedNrid); + if (!v.ok) return `
    ${escapeHtml(v.message)}
    `; + if (pageState.nrids.has(requestedNrid)) return `
    readnr: duplicate nrid '${escapeHtml(requestedNrid)}' on this page
    `; + nrid = requestedNrid; + } else { + nrid = (++pageState.counter).toString(); + } + const resolved = resolveUserPath(file, this); + if (resolved.error) return `
    readnr: path error: ${escapeHtml(resolved.error)} (${escapeHtml(file)})
    `; + if (!fs.existsSync(resolved.fsPath)) return `
    readnr: file not found: ${escapeHtml(file)}
    `; + const content = fs.readFileSync(resolved.fsPath, 'utf8'); + const rawLines = content.split(/\r?\n/); + const bookmarks = {}; + const startIndices = []; + + const language = /.*Report for .*/.test(rawLines[0]) ? 'en' : 'de'; // crude language detection based on first line + + // Find the section separator (a line containing only hyphens) that marks the start of regions + let regionSectionStart = null; + for (let i = 0; i < rawLines.length; i++) { + if (separator.test(rawLines[i])) { regionSectionStart = i; break; } + } + + // Header detection: detect only the specifically requested headings (exact match, case-insensitive) + // These headers (if present) become bookmarks and capture the header line itself and everything + // up to (but not including) the next header occurrence. + const HEADER_TITLES = { + // active sections: + // events + // errors + // magic + // production + // study + // economy + // movement + // battle + // mail + // nr + // + // newspells + // newpotions + + de: [ + 'Ereignisse', + 'Warnungen und Fehler', + 'Magie und Artefakte', + 'Rohstoffe und Produktion', + 'Lehren und Lernen', + 'Wirtschaft und Handel', + 'Reisen und Bewegung', + 'Kämpfe', + 'Botschaften', + 'Neue Zauber', + 'Neue Tränke', + 'Verschiedenes', + 'Hinweise' + ], + en: [ + 'Events', + 'Warnings and Errors', + 'Magic and Artefacts', + 'Resources and Production', + 'Learning and Teaching', + 'Economy and Trade', + 'Movement and Travel', + 'Battles', + 'Dispatches', + 'New Spells', + 'New Potions', + 'Miscellaneous', + 'Notifications' + ] + + + }; + // helper to sanitize a header into a bookmark name + function sanitizeToken(tok) { + return String(tok).trim().replace(/\s+/g, '_').replace(/[^A-Za-z0-9_\-\p{L}]/gu, ''); + } + + function startIndicesToBookmarks(startIndices, rawLines, bookmarks) { + startIndices.sort((a, b) => a.index - b.index); + for (let s = 0; s < startIndices.length; s++) { + const cur = startIndices[s]; + const next = startIndices[s + 1]; + const start = cur.index; + const end = next ? next.index - 1 : rawLines.length - 1; + bookmarks[cur.name] = { start: start + 1, end: end + 1 }; + } + } + + if (regionSectionStart !== null) { + bookmarks['header'] = { start: 1, end: regionSectionStart }; + } + + let firstHeader = 0; + for (let i = 0; i < rawLines.length; i++) { + const trimmed = rawLines[i].trim(); + if (!trimmed) continue; + for (const ht of HEADER_TITLES[language]) { + if (trimmed.toLowerCase() === ht.toLowerCase()) { + const nm = `heading_${(sanitizeToken(ht))}`; + startIndices.push({ name: nm, index: i }); + if (firstHeader === 0) firstHeader = i; + break; + } + } + } + + + if (regionSectionStart !== null) { + bookmarks['intro'] = { start: 1, end: firstHeader > 0 ? startIndices[0].index : regionSectionStart }; + startIndices.push({ name: 'regions', index: regionSectionStart }); + } + startIndicesToBookmarks(startIndices, rawLines, bookmarks); + startIndices.length = 0; + + // findAllHeaders + if (firstHeader > 0) { + for (let i = firstHeader; i <= regionSectionStart; i++) { + const trimmed = rawLines[i].trim(); + if (!trimmed) continue; + if (/^\s{5}.*/.test(rawLines[i])) { + const nm = `heading_${(sanitizeToken(trimmed))}`; + if (!bookmarks[nm]) { + startIndices.push({ name: nm, index: i }); + } + } + } + startIndices.push({ name: 'regions', index: regionSectionStart }); + startIndicesToBookmarks(startIndices, rawLines, bookmarks); + } + + let regionSectionEnd = regionSectionStart; + + // Region detection: after the separator, parse region sections. + // A region section starts with a line "Name (x,y)" or "Name (x,y,z)" and + // continues until the next separator line (a line that contains only hyphens). + if (regionSectionStart !== null) { + for (let i = regionSectionStart + 1; i < rawLines.length;) { + const raw = rawLines[i]; + // skip empty lines and repeated separators + if (!raw || separator.test(raw) || raw.trim() === '') { i++; continue; } + + // match "Name (x,y)" or "Name (x,y,z)" -- assume name does not contain parentheses + const m = raw.trim().match(/^([^()]+)\s*\(([^)]+)\)/); + if (!m) { i++; continue; } + + const namePart = m[1].trim(); + const coords = m[2].split(',').map(s => s.trim()); + if (coords.length >= 2) { + const x = parseInt(coords[0], 10); + const y = parseInt(coords[1], 10); + const ztok = coords[2] ? coords[2] : null; + + // find the end of this region: the next separator line (hyphens) or EOF + let j = i + 1; + while (j < rawLines.length && !separator.test(rawLines[j])) j++; + const endIdx = j < rawLines.length ? j - 1 : rawLines.length - 1; + + const key = ztok ? `region_${x}_${y}_${sanitizeToken(ztok)}` : `region_${x}_${y}`; + // store bookmark spanning from this header line through the line before the separator + bookmarks[key] = { start: i + 1, end: endIdx + 1 }; + // startIndices.push({ name: key, index: i }); + + // detect unit sub-sections inside this region and add unit bookmarks --- + // Unit lines have the form (indented) " - Name (ID)" (leading two spaces, a marker, name, then ID in parentheses). + // They end at the next empty line or separator line (we stop at endIdx). + for (let k = i + 1; k <= endIdx;) { + const lineK = rawLines[k]; + if (!lineK || separator.test(lineK) || lineK.trim() === '') { k++; continue; } + // Match unit header lines: two (or more) spaces, one of + * - marker, space, name (no parentheses), space, (ID) + const um = lineK.match(/^\s{2,}[+\-*]\s+([^()]+)\s*\(([^()\s]+)\)/); + if (!um) { k++; continue; } + const unitName = um[1].trim(); + const unitIdRaw = um[2].trim(); + // sanitize unit id for bookmark key (keep readable and safe) + const unitId = sanitizeToken(unitIdRaw) || unitIdRaw.replace(/[^a-z0-9_-]/ig, '_'); + // find unit end: next empty line or separator or endIdx + let j2 = k + 1; + while (j2 <= endIdx && rawLines[j2].trim() !== '' && !separator.test(rawLines[j2])) j2++; + const unitEnd = j2 <= endIdx ? j2 : endIdx; + const unitKey = `unit_${unitId}`; + bookmarks[unitKey] = { start: k + 1, end: unitEnd + 1 }; + // startIndices.push({ name: unitKey, index: k }); + // continue scanning after this unit block + k = j2 + 1; + } + // --- end unit detection --- + regionSectionEnd = j; + + // continue after the separator (if any) + i = j + 1; + } else { + i++; + } + } + } + + startIndicesToBookmarks(startIndices, rawLines, bookmarks); + if (regionSectionStart != regionSectionEnd) { + bookmarks.regions = { + start: regionSectionStart + 2, + end: regionSectionEnd + 1 + }; + } + if (regionSectionEnd) { + bookmarks.outro = { + start: regionSectionEnd + 1, + end: rawLines.length + }; + } + + bookmarks.all = { start: 1, end: rawLines.length }; + + console.log(regionSectionStart); + console.log(startIndices); + console.log(bookmarks); + + // store + pageState.nrids.add(nrid); + pageState.lastNrid = nrid; + pageState.nrFiles[nrid] = { + fsPath: resolved.fsPath, + publicPath: resolved.publicPath, + relPath: resolved.relPath, + lines: rawLines, + bookmarks: bookmarks, + sourceName: path.basename(resolved.fsPath) + }; + return `
    NR registered: ${escapeHtml(nrid)} (source: ${escapeHtml(path.basename(resolved.fsPath))})
    `; + } + + function shownrShortcode(arg1, arg2) { + const pageState = _getPageNrState(this); + let opts = {}; + function parseRangeString(s) { + const m = String(s).trim().match(/^(\d+)(?:-(\d+))?$/); + if (!m) return null; + const a = parseInt(m[1], 10); + const b = m[2] ? parseInt(m[2], 10) : a; + return { start: Math.min(a, b), end: Math.max(a, b) }; + } + if (typeof arg2 === 'undefined') { + if (typeof arg1 === 'string' && arg1.trim().startsWith('{')) { + try { opts = JSON.parse(arg1); } catch (e) { return `
    shownr: invalid JSON: ${escapeHtml(e.message)}
    `; } + } else if (typeof arg1 === 'string' && parseRangeString(arg1)) { + opts.range = parseRangeString(arg1); + } else if (typeof arg1 === 'string') { + opts.bookmark = arg1; + } else { + return `
    shownr: invalid arguments
    `; + } + } else { + if (typeof arg1 === 'string' && validateCrid(arg1).ok) { + opts.nrid = arg1; + if (typeof arg2 === 'string' && arg2.trim().startsWith('{')) { + try { Object.assign(opts, JSON.parse(arg2)); } catch (e) { return `
    shownr: invalid JSON: ${escapeHtml(e.message)}
    `; } + } else if (parseRangeString(arg2)) { + opts.range = parseRangeString(arg2); + } else { opts.bookmark = arg2; } + } else if (typeof arg2 === 'string' && validateCrid(arg2).ok) { + opts.nrid = arg2; + if (parseRangeString(arg1)) opts.range = parseRangeString(arg1); else opts.bookmark = arg1; + } else { + if (typeof arg2 === 'string' && arg2.trim().startsWith('{')) { + try { Object.assign(opts, JSON.parse(arg2)); } catch (e) { return `
    shownr: invalid JSON: ${escapeHtml(e.message)}
    `; } + if (!opts.nrid && typeof arg1 === 'string') { if (parseRangeString(arg1)) opts.range = parseRangeString(arg1); else opts.bookmark = arg1; } + } else { + if (typeof arg1 === 'string' && validateCrid(arg1).ok) opts.nrid = arg1; else opts.bookmark = arg1; + if (typeof arg2 === 'string' && parseRangeString(arg2)) opts.range = parseRangeString(arg2); + } + } + } + if (!opts.range && parseRangeString(opts.bookmark)) { + opts.range = parseRangeString(opts.bookmark); opts.bookmark = undefined; + } + // parse maxHeight option (number -> px or CSS size string) + let maxHeight = undefined; + if (Object.prototype.hasOwnProperty.call(opts, 'maxHeight')) maxHeight = opts.maxHeight; + else if (Object.prototype.hasOwnProperty.call(opts, 'max_height')) maxHeight = opts.max_height; + if (typeof maxHeight === 'number' && !isNaN(maxHeight)) maxHeight = `${maxHeight}px`; + if (typeof maxHeight === 'string') maxHeight = maxHeight.trim() || undefined; + + let nrid = opts.nrid; + if (!nrid) nrid = pageState.lastNrid; + if (!nrid) return `
    shownr: no nrid specified and no previous readnr on this page
    `; + if (!pageState.nrFiles || !pageState.nrFiles[nrid]) return `
    shownr: unknown nrid '${escapeHtml(nrid)}' (did you call readnr first?)
    `; + + let lineNumbers = opts.lineNumbers || false; + + const fileInfo = pageState.nrFiles[nrid]; + const totalLines = fileInfo.lines.length; + let start = 1, end = totalLines; + if (opts.bookmark) { + if (opts.bookmark === 'list') { + const bookmarks = Object.keys(fileInfo.bookmarks || {}); + if (bookmarks.length === 0) return `
    shownr: no bookmarks available for nrid '${escapeHtml(nrid)}'
    `; + const listItems = + bookmarks.map(bm => { + const b = fileInfo.bookmarks[bm]; + return `
  • ${escapeHtml(bm)}: ${b.start} - ${b.end}
  • `; + }).join(''); + return `
      ${listItems}
    `; + } + const bm = fileInfo.bookmarks && fileInfo.bookmarks[opts.bookmark]; + if (!bm) return `
    shownr: unknown bookmark '${escapeHtml(opts.bookmark)}' for nrid '${escapeHtml(nrid)}'
    `; + start = bm.start; end = bm.end; + } else if (opts.range) { + start = Math.max(1, opts.range.start); end = Math.min(totalLines, opts.range.end); + if (start > end) return `
    shownr: invalid range ${start}-${end}
    `; + } + const slice = fileInfo.lines.slice(start - 1, end); + const inner = slice.map((ln, idx) => { + const linenr = lineNumbers ? `${start + idx}` : ''; + return `
    ${linenr}${escapeHtml(ln)}
    `; + }).join(''); + const header = `
    Source: ${escapeHtml(fileInfo.sourceName)} - lines ${start}-${end}
    `; + const shownrStyle = maxHeight ? ` style=\"max-height:${escapeHtml(maxHeight)}; overflow:auto;\"` : ''; + return `
    ${header}
    ${inner}
    `; + } + }; diff --git a/reports/template/334-42.nr b/reports/template/334-42.nr new file mode 100644 index 0000000..d36e6c1 --- /dev/null +++ b/reports/template/334-42.nr @@ -0,0 +1,365 @@ + Report für Eressea, Thursday, 08. September 2022, 15:44 + Wir schreiben die erste Woche des Monats Schneebann im Jahre 6 des zweiten + Zeitalters. Es ist Winter. + + Partei z5w4 (42), Menschen/Kein Magiegebiet (fex@eressea.de) + Bitte denke daran, deine Befehle mit dem Betreff ERESSEA 2 BEFEHLE an + eressea-server@kn-bremen.de zu senden. + + Deine Partei hat 2021 Personen in 11 von maximal 2500 Einheiten. + Deine Partei hat 0 Migranten und kann maximal 32 Migranten aufnehmen. + Deine Partei hat 0 Helden und kann maximal 29 Helden ernennen. + + Optionen: AUSWERTUNG COMPUTER ZUGVORLAGE STATISTIK ZIPPED ADRESSEN + + Ereignisse + +Einheit 8w39 (8w39) in Cikanpat (-2005,2) wird durch unzureichende Nahrung + geschwächt. +Einheit 14Lf (14Lf) in Cikanpat (-2005,2) wird durch unzureichende Nahrung + geschwächt. +Einheit mrv4 (mrv4) in Cikanpat (-2005,2) wird durch unzureichende Nahrung + geschwächt. +Einheit pmb6 (pmb6) in Cikanpat (-2005,2) wird durch unzureichende Nahrung + geschwächt. +Einheit qt2q (qt2q) in Cikanpat (-2005,2) wird durch unzureichende Nahrung + geschwächt. +Einheit 67tv (67tv) in Cikanpat (-2005,2) wird durch unzureichende Nahrung + geschwächt. +Einheit 47zq (47zq) in Cikanpat (-2005,2) wird durch unzureichende Nahrung + geschwächt. +Einheit ryhp (ryhp) in Cikanpat (-2005,2) wird durch unzureichende Nahrung + geschwächt. + + Warnungen und Fehler + +Deine Partei hat letzte Runde keinen Zug abgegeben! + + Wirtschaft und Handel + +Einheit rgoi (rgoi) bezahlt den Unterhalt von Leuchtturm (b5im). + + Reisen und Bewegung + +Die Karavelle 1n6o (1n6o) segelt von Cikanpat (-2005,2) nach Cikanpat + (-2005,2). + + Kämpfe + + In Cibifar (-2005,0) findet ein Kampf statt. + +Der Kampf wurde ausgelöst von Partei z5w4 (42). + +Heer 0: Partei z5w4 (42) +Kämpft gegen: Heer 1 (ym2e) +Attacke gegen: Heer 1(ym2e) +... in der 1. Kampflinie: + * Einheit xpb2 (xpb2), 1000 Menschen, aggressiv, bewacht die Region, + Talente: Hiebwaffen 20, Ausdauer 10, hat: 100000 Silber, 1000 + Plattenpanzer, 1000 Schilde, 1000 Schwerter. +... in der 2. Kampflinie: + * Einheit jfg3 (jfg3), 1 Mensch, hinten, Talente: Magie Gwyrrd 10. Aura + 1000/105, Zauber: Mauern der Ewigkeit, Hagel, Kampfzauber: keiner, + Hagel(8), keiner. + * Einheit c1sr (c1sr), 1000 Menschen, hinten, Talente: Bogenschießen 20, + Ausdauer 10, hat: 1000 Bögen, 100000 Silber, 1000 Schilde. + +Heer 1: Partei ym2e (ym2e) +Kämpft gegen: Heer 0 (42) +... in der 1. Kampflinie: + - Einheit 2aLf (2aLf), 1000 Menschen, aggressiv, hat: 1000 Plattenpanzer, + 1000 Schilde, 1000 Schwerter. +... in der 2. Kampflinie: + - Einheit ycr7 (ycr7), 1000 Menschen, hinten, hat: 1000 Armbrüste, 1000 + Schilde. + +Einheiten vor der 1. Runde: +Heer 0(42): 1000+1001, Heer 1(ym2e): 1000+1000 +Einheit jfg3 (jfg3) zaubert Hagel: 0 Krieger wurden getötet. + +Einheiten vor der 2. Runde: +Heer 0(42): 1000+1000, Heer 1(ym2e): 1000+1000 +Einheit jfg3 (jfg3) zaubert Hagel: 0 Krieger wurden getötet. + +Einheiten vor der 3. Runde: +Heer 0(42): 1000+998, Heer 1(ym2e): 1000+999 +Einheit jfg3 (jfg3) zaubert Hagel: 0 Krieger wurden getötet. + +Einheiten vor der 4. Runde: +Heer 0(42): 1000+998, Heer 1(ym2e): 1000+999 +Einheit jfg3 (jfg3) zaubert Hagel: 0 Krieger wurden getötet. + +Einheiten vor der 5. Runde: +Heer 0(42): 999+994, Heer 1(ym2e): 999+999 + +Einheiten vor der 6. Runde: +Heer 0(42): 998+993, Heer 1(ym2e): 999+997 +Einheit jfg3 (jfg3) erzielte 408 Treffer und tötete 0 Gegner. +Einheit c1sr (c1sr) erzielte 3009 Treffer und tötete 2 Gegner. +Einheit xpb2 (xpb2) erzielte 1282 Treffer und tötete 1 Gegner. +Einheit jfg3 (jfg3) verlor 1 Personen. +Einheit c1sr (c1sr) verlor 2 Personen, 998 überlebten. +Einheit xpb2 (xpb2) verlor 2 Personen, 998 überlebten. +Einheit 2aLf (2aLf) verlor 1 Personen, 999 überlebten. +Einheit ycr7 (ycr7) verlor 2 Personen, 998 überlebten. +Heer 0(42): 5 Tote, 0 Geflohene, 1996 Überlebende. +Heer 1(ym2e): 3 Tote, 0 Geflohene, 1997 Überlebende. + + +------------------------------------------------------------------------------ + +Cibifar (-2005,0), Wald, 530/132 Bäume, 3194 Bauern, 44633 Silber, 28 Pferde. +Im Nordwesten der Region liegt das Hochland von Gisudar (-2006,1), im +Nordosten das Bergland von Pybul (-2005,1), im Osten der Sumpf von Sivel +(-2004,0), im Südosten der Vulkan von Covus (-2004,-1), im Südwesten der +Gletscher von Vusderet (-2005,-1) und im Westen die Wüste von Centoditol +(-2006,0). + +Auf dem Markt wird für Weihrauch 4 Silber verlangt. Geboten wird für Balsam +16 Silber, für Gewürze 30 Silber, für Juwelen 14 Silber, für Myrrhe 10 +Silber, für Öl 3 Silber und für Seide 18 Silber. + +Die Region wird von Partei z5w4 (42) bewacht. + +Statistik für Cibifar (-2005,0): + + Unterhaltung: max. 2231 Silber + Lohn für Arbeit: 10 Silber + Rekruten: max. 79 Bauern + Luxusgüter zum angegebenen Preis: 31 + Personen: 1996 + Bögen: 999 + Silber: 180038 + Plattenpanzer: 1000 + Schilde: 1998 + Schwerter: 1000 + + Leuchtturm (ujew), Größe 10, Leuchtturm. + + Bergwerk (auty), Größe 10, Bergwerk. + + Steinbruch (wj9w), Größe 10, Steinbruch. + + Sägewerk (3r1L), Größe 10, Sägewerk. + + Schmiede (ambe), Größe 10, Schmiede. + + Pferdezucht (3xr4), Größe 10, Pferdezucht. + + Hafen (s6zt), Größe 10, Hafen (im Bau). + + Karawanserei (set9), Größe 25, Karawanserei. + + Akademie (yg07), Größe 25, Akademie. + + Magierturm (a0cm), Größe 50, Magierturm. + + Damm (a636), Größe 50, Damm. + + Tunnel (bknd), Größe 100, Tunnel. + + Taverne (fynu), Größe 10, Taverne. + + Monument (2at4), Größe 10, Monument. + + Steinkreis (f4w6), Größe 100, Steinkreis. + + - Einheit 2aLf (2aLf), Partei ym2e (ym2e), 999 Menschen, hat: 1000 + Plattenpanzer, 1000 Schilde, 999 Schwerter. + + * Einheit xpb2 (xpb2), 998 Menschen, aggressiv (erschöpft), bewacht die + Region, Talente: Hiebwaffen 20, Ausdauer 10, hat: 90019 Silber, 1000 + Plattenpanzer, 1000 Schilde, 1000 Schwerter. + + * Einheit c1sr (c1sr), 998 Menschen, hinten (erschöpft), Talente: + Bogenschießen 20, Ausdauer 10, hat: 999 Bögen, 90019 Silber, 998 Schilde. + + - Einheit ycr7 (ycr7), Partei ym2e (ym2e), 998 Menschen, hat: 1000 + Armbrüste, 999 Schilde. +------------------------------------------------------------------------------ + +Sivel (-2004,0), Sumpf, 1001 Bauern, 15990 Silber. Im Nordwesten der Region +liegt das Bergland von Pybul (-2005,1), im Nordosten Ozean (-2004,1), im Osten +Ozean (-2003,0), im Südosten Ozean (-2003,-1), im Südwesten der Vulkan von +Covus (-2004,-1) und im Westen der Wald von Cibifar (-2005,0). + +Auf dem Markt wird für Weihrauch 4 Silber verlangt. Geboten wird für Balsam +4 Silber, für Gewürze 25 Silber, für Juwelen 35 Silber, für Myrrhe 25 +Silber, für Öl 6 Silber und für Seide 30 Silber. + +Statistik für Sivel (-2004,0): + + Unterhaltung: max. 799 Silber + Lohn für Arbeit: 10 Silber + Rekruten: max. 25 Bauern + Luxusgüter zum angegebenen Preis: 10 + Personen: 1 + Silber: 890 + +Eine Botschaft von Einheit rgoi (rgoi): 'Hey, Welt' + + Leuchtturm (b5im), Größe 10, Leuchtturm. + + * Einheit rgoi (rgoi), 1 Mensch, aggressiv, Talente: Wahrnehmung 10, hat: + 890 Silber. +------------------------------------------------------------------------------ + +Pybul (-2005,1) (vom Turm erblickt), Berge, 61/15 Bäume, 396 Bauern. Im +Nordwesten der Region liegt Ozean (-2006,2), im Nordosten der Wald von +Cikanpat (-2005,2), im Osten Ozean (-2004,1), im Südosten der Sumpf von Sivel +(-2004,0), im Südwesten der Wald von Cibifar (-2005,0) und im Westen das +Hochland von Gisudar (-2006,1). +------------------------------------------------------------------------------ + +Gisudar (-2006,1) (vom Turm erblickt), Hochland, 276/69 Bäume, 654 Bauern. Im +Nordwesten der Region liegt Ozean (-2007,2), im Nordosten Ozean (-2006,2), im +Osten das Bergland von Pybul (-2005,1), im Südosten der Wald von Cibifar +(-2005,0), im Südwesten die Wüste von Centoditol (-2006,0) und im Westen +Ozean (-2007,1). +------------------------------------------------------------------------------ + +Centoditol (-2006,0) (vom Turm erblickt), Wüste, 212 Bauern. Im Nordwesten +der Region liegt Ozean (-2007,1), im Nordosten das Hochland von Gisudar +(-2006,1), im Osten der Wald von Cibifar (-2005,0), im Südosten der Gletscher +von Vusderet (-2005,-1), im Südwesten Ozean (-2006,-1) und im Westen Ozean +(-2007,0). +------------------------------------------------------------------------------ + +Vusderet (-2005,-1) (vom Turm erblickt), Gletscher, 100 Bauern. Im Nordwesten +der Region liegt die Wüste von Centoditol (-2006,0), im Nordosten der Wald +von Cibifar (-2005,0), im Osten der Vulkan von Covus (-2004,-1), im Südosten +Ozean (-2004,-2), im Südwesten Ozean (-2005,-2) und im Westen Ozean +(-2006,-1). +------------------------------------------------------------------------------ + +Covus (-2004,-1) (vom Turm erblickt), Vulkan, 256 Bauern. Im Nordwesten der +Region liegt der Wald von Cibifar (-2005,0), im Nordosten der Sumpf von Sivel +(-2004,0), im Osten Ozean (-2003,-1), im Südosten Ozean (-2003,-2), im +Südwesten Ozean (-2004,-2) und im Westen der Gletscher von Vusderet +(-2005,-1). +------------------------------------------------------------------------------ + +Ozean (-2003,0) (vom Turm erblickt), Ozean. Im Nordwesten der Region liegt +Ozean (-2004,1), im Nordosten Ozean (-2003,1), im Osten eine Feuerwand +(-2002,0), im Südwesten Ozean (-2003,-1) und im Westen der Sumpf von Sivel +(-2004,0). +------------------------------------------------------------------------------ + +Ozean (-2004,1) (vom Turm erblickt), Ozean. Im Nordwesten der Region liegt der +Wald von Cikanpat (-2005,2), im Nordosten Ozean (-2004,2), im Osten Ozean +(-2003,1), im Südosten Ozean (-2003,0), im Südwesten der Sumpf von Sivel +(-2004,0) und im Westen das Bergland von Pybul (-2005,1). +------------------------------------------------------------------------------ + +Feuerwand (-2002,0) (vom Turm erblickt), Feuerwand. Im Nordwesten der Region +liegt Ozean (-2003,1), im Osten Fofyvol (-2001,0) und im Westen Ozean +(-2003,0). +------------------------------------------------------------------------------ + +Cikanpat (-2005,2), Wald, 600/60 Bäume, 6185 Bauern, 73390 Silber, 33 Pferde. +Im Nordwesten der Region liegt Ozean (-2006,3), im Nordosten Ozean (-2005,3), +im Osten Ozean (-2004,2), im Südosten Ozean (-2004,1), im Südwesten das +Bergland von Pybul (-2005,1) und im Westen Ozean (-2006,2). + +Auf dem Markt wird für Öl 3 Silber verlangt. Geboten wird für Balsam 16 +Silber, für Gewürze 20 Silber, für Juwelen 21 Silber, für Myrrhe 5 Silber, +für Seide 12 Silber und für Weihrauch 16 Silber. + +Statistik für Cikanpat (-2005,2): + + Unterhaltung: max. 3669 Silber + Lohn für Arbeit: 10 Silber + Rekruten: max. 154 Bauern + Luxusgüter zum angegebenen Preis: 61 + Personen: 24 + + Boot 66nx (66nx), 1 Boot, (30/50). + + * Einheit 8w39 (8w39), 3 Menschen, aggressiv (verwundet, hungert), + Talente: Segeln 50. + + Langboot w6xv (w6xv), 1 Langboot, (30/500). + + * Einheit 14Lf (14Lf), 3 Menschen, aggressiv (schwer verwundet, hungert), + Talente: Segeln 50. + + Drachenschiff 7zoc (7zoc), 1 Drachenschiff, (30/1000). + + * Einheit mrv4 (mrv4), 3 Menschen, aggressiv (verwundet, hungert), + Talente: Segeln 50. + + Karavelle 5dco (5dco), 1 Karavelle, (30/3000). + + * Einheit pmb6 (pmb6), 3 Menschen, aggressiv (schwer verwundet, hungert), + Talente: Segeln 50. + + Trireme 3ewr (3ewr), 1 Trireme, (30/2000). + + * Einheit qt2q (qt2q), 3 Menschen, aggressiv (schwer verwundet, hungert), + Talente: Segeln 50. + + Galeone 7c3i (7c3i), 1 Galeone, (30/20000). + + * Einheit 67tv (67tv), 3 Menschen, aggressiv (schwer verwundet, hungert), + Talente: Segeln 50. + + Karavelle 1n6o (1n6o), 1 Karavelle, (30/3000), Nordostküste. + + * Einheit ryhp (ryhp), 3 Menschen, aggressiv (verwundet, hungert), + Talente: Segeln 50. + + Karavelle xuht (xuht), 1 Karavelle, (30/2996), 1% beschädigt. + + * Einheit 47zq (47zq), 3 Menschen, aggressiv (verwundet, hungert), + Talente: Segeln 50. +------------------------------------------------------------------------------ + +Ozean (-2006,2) (vom Turm erblickt), Ozean. Im Nordwesten der Region liegt +Ozean (-2007,3), im Nordosten Ozean (-2006,3), im Osten der Wald von Cikanpat +(-2005,2), im Südosten das Bergland von Pybul (-2005,1), im Südwesten das +Hochland von Gisudar (-2006,1) und im Westen Ozean (-2007,2). +------------------------------------------------------------------------------ + +Ozean (-2005,3) (durchgereist), Ozean. Im Osten der Region liegt Ozean +(-2004,3), im Südosten Ozean (-2004,2), im Südwesten der Wald von Cikanpat +(-2005,2) und im Westen Ozean (-2006,3). + +Die Region wurde durchquert von Karavelle 1n6o (1n6o). +------------------------------------------------------------------------------ + +Ozean (-2004,-2) (vom Turm erblickt), Ozean. Im Nordwesten der Region liegt +der Gletscher von Vusderet (-2005,-1), im Nordosten der Vulkan von Covus +(-2004,-1), im Osten Ozean (-2003,-2) und im Westen Ozean (-2005,-2). +------------------------------------------------------------------------------ + +Ozean (-2004,2) (durchgereist), Ozean. Im Nordwesten der Region liegt Ozean +(-2005,3), im Nordosten Ozean (-2004,3), im Osten Ozean (-2003,2), im +Südosten Ozean (-2003,1), im Südwesten Ozean (-2004,1) und im Westen der +Wald von Cikanpat (-2005,2). + +Die Region wurde durchquert von Karavelle 1n6o (1n6o). +------------------------------------------------------------------------------ + +Ozean (-2003,-2) (vom Turm erblickt), Ozean. Im Nordwesten der Region liegt +der Vulkan von Covus (-2004,-1), im Nordosten Ozean (-2003,-1) und im Westen +Ozean (-2004,-2). +------------------------------------------------------------------------------ + +Ozean (-2003,-1) (vom Turm erblickt), Ozean. Im Nordwesten der Region liegt +der Sumpf von Sivel (-2004,0), im Nordosten Ozean (-2003,0), im Südwesten +Ozean (-2003,-2) und im Westen der Vulkan von Covus (-2004,-1). +------------------------------------------------------------------------------ + +Ozean (-2003,1) (vom Turm erblickt), Ozean. Im Nordwesten der Region liegt +Ozean (-2004,2), im Nordosten Ozean (-2003,2), im Südosten eine Feuerwand +(-2002,0), im Südwesten Ozean (-2003,0) und im Westen Ozean (-2004,1). +------------------------------------------------------------------------------ + + Aktueller Status + +------------------------------------------------------------------------------ + + Liste aller Adressen + + * Partei z5w4 (42): fex@eressea.de; + - Partei ym2e (ym2e): war@eressea.de; diff --git a/template/Auswertung_01.md b/template/Auswertung_01.md index 59cfc33..62cae75 100644 --- a/template/Auswertung_01.md +++ b/template/Auswertung_01.md @@ -4,10 +4,13 @@ date: 2024-03-17 --- ## Die Auswertung -Some examples to demonstrate the crmap shortcode. +Beispiele für die Darstellung von Karten, NRs, Befehlen mit crmap Shortcodes. -### Map with details: -{% crmap './reports/template/1234-bLa.cr' %} +## Karte mit Details + +Relative Pfade funktionieren, aber die Quelldateien werden nicht automatisch zur erzeugten Seite kopiert, weswegen der Link zur cr-Datei tot ist. + +{% crmap './reports/1234-bLa.cr' %} {% crmap_rdetails %} ... @@ -15,12 +18,15 @@ Some examples to demonstrate the crmap shortcode. Orders: {% crmap_commands%} -### Map only: -{% crmap './reports/template/334-42.cr' '{ "crid": "map1", "details": false }' %} +### Karte alleine + +Alle Dateien in /reports werden im Projekt automatisch zur erzeugten Seite kopiert ()`.eleventy.js: eleventyConfig.addPassthroughCopy("reports");`) Hier funktioniert der Link. -### Another Map: -{% crmap './reports/template/1000-demo.cr' '{ "crid": "eressea_1000" }' %} -{% crmap './reports/template/1000-demo.cr' '{ "crid": "astral", "layer": 1, "caption": "Astralraum" }' %} +{% crmap '/reports/template/334-42.cr' '{ "crid": "map1", "details": false }' %} + +### Noch eine Karte mit Astralraum +{% crmap '/reports/template/1000-demo.cr' '{ "crid": "eressea_1000" }' %} +{% crmap '/reports/template/1000-demo.cr' '{ "crid": "astral", "layer": 1, "caption": "Astralraum" }' %} {% crmap_rdetails 'eressea_1000' '' %} @@ -29,10 +35,56 @@ Orders: {% crmap_rdetails 'astral' '' %} -### Map not found error: -{% crmap './reports/template/334-424242.cr' %} +### Fehlermeldungen, falls datei nicht vorhanden +{% crmap '/reports/template/334-424242.cr' %} + + +## Befehlsdateien mit Formatierung der Kommentare und Wikilinks + +{% orderfile '/reports/template/befehle-42.txt' %} + +... oder ohne Formatierung + +{% orderfile '/reports/template/befehle-42.txt' '{ "commentsAsOrders": true, "markdownInComments": false }' %} + + +## NR-Abschnitte + +Einlesen: + +{% readnr '/reports/template/334-42.nr' %} + +#### Liste aller gefundenen Abschnitte anzeigen + +{% shownr 'list' %} + +#### Headers / Regions / Outro +{% shownr 'intro' %} + +{% shownr '{ "bookmark": "header", "maxHeight" : "15em" }' %} + +{% shownr '{ "bookmark": "regions", "maxHeight" : "15em" }' %} + +{% shownr 'outro' %} + +#### Abschnitte +{% shownr 'heading_Ereignisse' %} + +{% shownr 'heading_Kämpfe' %} + +{% shownr 'heading_In_Cibifar_-20050_findet_ein_Kampf_statt' %} + +#### Zeilen +{% shownr '10-20' %} +#### Region +{% shownr 'region_-2005_0' %} + +#### Einheit +{% shownr 'unit_mrv4' %} -### Include an order file with automatic comment formatting and wiki links +### Beliebige Dateien -{% orderfile './reports/template/befehle-42.txt' %} +Wir können sogar beliebige Textdateien anzeigen. +{% readnr './reports/1234-bLa.cr' %} +{% shownr '{ "bookmark": "21-33", "lineNumbers" : true }' %} From e5e02e7c20de6e4c0482743ff199a2b5c0a15c0a Mon Sep 17 00:00:00 2001 From: Steffen Mecke Date: Thu, 21 Aug 2025 11:01:16 +0200 Subject: [PATCH 23/34] amend debug output --- crs/crs.js | 13 +++++++++---- template/Auswertung_01.md | 6 +++--- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/crs/crs.js b/crs/crs.js index 6923b6c..dd67341 100644 --- a/crs/crs.js +++ b/crs/crs.js @@ -942,11 +942,14 @@ module.exports = function (eleventyConfig) { const language = /.*Report for .*/.test(rawLines[0]) ? 'en' : 'de'; // crude language detection based on first line + debug(`Scanning ${file} for language ${language}`); + // Find the section separator (a line containing only hyphens) that marks the start of regions let regionSectionStart = null; for (let i = 0; i < rawLines.length; i++) { if (separator.test(rawLines[i])) { regionSectionStart = i; break; } } + debug("region section start: ", regionSectionStart); // Header detection: detect only the specifically requested headings (exact match, case-insensitive) // These headers (if present) become bookmarks and capture the header line itself and everything @@ -1027,6 +1030,7 @@ module.exports = function (eleventyConfig) { for (const ht of HEADER_TITLES[language]) { if (trimmed.toLowerCase() === ht.toLowerCase()) { const nm = `heading_${(sanitizeToken(ht))}`; + debug(`Found pre-defined header ${ht} at ${i}`); startIndices.push({ name: nm, index: i }); if (firstHeader === 0) firstHeader = i; break; @@ -1050,6 +1054,7 @@ module.exports = function (eleventyConfig) { if (/^\s{5}.*/.test(rawLines[i])) { const nm = `heading_${(sanitizeToken(trimmed))}`; if (!bookmarks[nm]) { + debug(`Found other header ${nm} at ${i}`); startIndices.push({ name: nm, index: i }); } } @@ -1087,6 +1092,7 @@ module.exports = function (eleventyConfig) { const key = ztok ? `region_${x}_${y}_${sanitizeToken(ztok)}` : `region_${x}_${y}`; // store bookmark spanning from this header line through the line before the separator + debug(`Found region ${key} from ${i + 1} to ${endIdx + 1}`); bookmarks[key] = { start: i + 1, end: endIdx + 1 }; // startIndices.push({ name: key, index: i }); @@ -1108,6 +1114,7 @@ module.exports = function (eleventyConfig) { while (j2 <= endIdx && rawLines[j2].trim() !== '' && !separator.test(rawLines[j2])) j2++; const unitEnd = j2 <= endIdx ? j2 : endIdx; const unitKey = `unit_${unitId}`; + debug(`Found unit ${unitKey} from ${k + 1} to ${unitEnd + 1}`); bookmarks[unitKey] = { start: k + 1, end: unitEnd + 1 }; // startIndices.push({ name: unitKey, index: k }); // continue scanning after this unit block @@ -1125,6 +1132,8 @@ module.exports = function (eleventyConfig) { } startIndicesToBookmarks(startIndices, rawLines, bookmarks); + debug(`Found regions / outro at ${regionSectionStart} and ${regionSectionEnd}`); + if (regionSectionStart != regionSectionEnd) { bookmarks.regions = { start: regionSectionStart + 2, @@ -1140,10 +1149,6 @@ module.exports = function (eleventyConfig) { bookmarks.all = { start: 1, end: rawLines.length }; - console.log(regionSectionStart); - console.log(startIndices); - console.log(bookmarks); - // store pageState.nrids.add(nrid); pageState.lastNrid = nrid; diff --git a/template/Auswertung_01.md b/template/Auswertung_01.md index 62cae75..203903f 100644 --- a/template/Auswertung_01.md +++ b/template/Auswertung_01.md @@ -8,9 +8,9 @@ Beispiele für die Darstellung von Karten, NRs, Befehlen mit crmap Shortcodes. ## Karte mit Details -Relative Pfade funktionieren, aber die Quelldateien werden nicht automatisch zur erzeugten Seite kopiert, weswegen der Link zur cr-Datei tot ist. +Relative Pfade funktionieren, Quelldateien sollten automatisch zur erzeugten Seite kopiert werden, wenn nicht ist der Link zur cr-Datei tot. -{% crmap './reports/1234-bLa.cr' %} +{% crmap './reports/1234-bLa.cr' %} {% crmap_rdetails %} ... @@ -20,7 +20,7 @@ Orders: ### Karte alleine -Alle Dateien in /reports werden im Projekt automatisch zur erzeugten Seite kopiert ()`.eleventy.js: eleventyConfig.addPassthroughCopy("reports");`) Hier funktioniert der Link. +Alle Dateien in /reports werden im Projekt automatisch zur erzeugten Seite kopiert (`.eleventy.js: eleventyConfig.addPassthroughCopy("reports");`) Hier funktioniert der Link. {% crmap '/reports/template/334-42.cr' '{ "crid": "map1", "details": false }' %} From 8c566d4ae8291724ea5385e1007703aaf9a5e9b8 Mon Sep 17 00:00:00 2001 From: Steffen Mecke Date: Wed, 20 Aug 2025 13:00:08 +0200 Subject: [PATCH 24/34] updated version to 0.2.0 --- crs/crs.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crs/crs.js b/crs/crs.js index dd67341..52fa51a 100644 --- a/crs/crs.js +++ b/crs/crs.js @@ -4,7 +4,7 @@ const path = require('path'); const { start } = require('repl'); // Library version (update when changing public shortcode behavior) -const CRS_VERSION = '0.1.0'; +const CRS_VERSION = '0.2.0'; // Export version for external use (e.g., in layouts via require) and add as global data below module.exports.CRS_VERSION = CRS_VERSION; From 87e57c42834438438e3ec2a623459c27918aed5c Mon Sep 17 00:00:00 2001 From: Steffen Mecke Date: Wed, 20 Aug 2025 15:39:15 +0200 Subject: [PATCH 25/34] inserted prev/next links in post layout --- _includes/post-layout.njk | 44 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/_includes/post-layout.njk b/_includes/post-layout.njk index 872cecb..3f47892 100644 --- a/_includes/post-layout.njk +++ b/_includes/post-layout.njk @@ -10,3 +10,47 @@ layout: base-layout.njk
    Tags: {{tags}}
    + +{# Determine the collection that contains this page (skip generic 'all') #} +{% set raceCollectionName = null %} +{% for colName, colItems in collections %} + {% if colName != 'all' and colItems and colItems | length > 0 %} + {% for it in colItems %} + {% if it.inputPath == page.inputPath %} + {% set raceCollectionName = colName %} + {% endif %} + {% endfor %} + {% endif %} +{% endfor %} + +{% if raceCollectionName %} + {% set coll = collections[raceCollectionName] | sort(attribute='date') %} + {# Find next in this collection #} + {% set found = false %} + {% set next = null %} + {% set previous = null %} + {% for item in coll %} + {% if found and next == null %} + {% set next = item %} + {% endif %} + {% if item.inputPath == page.inputPath %} + {% set found = true %} + {% elif found == false %} + {% set previous = item %} + {% endif %} + {% endfor %} + {% if previous %} + + {% endif %} + {% endif %} + {% if next %} + {% if not previous %} + + {% endif %} +{% endif %} From 72a54a3545b300c9306d393791be3c4879d8afb3 Mon Sep 17 00:00:00 2001 From: Steffen Mecke Date: Wed, 20 Aug 2025 17:15:06 +0200 Subject: [PATCH 26/34] set default layout to de; fixed dates --- .eleventy.js | 23 +++++++++++++++++------ README.md | 5 ++++- _data/site.json | 3 +++ _includes/post-layout.njk | 2 +- template/template.json | 3 ++- 5 files changed, 27 insertions(+), 9 deletions(-) create mode 100644 _data/site.json diff --git a/.eleventy.js b/.eleventy.js index 9815077..2377f77 100644 --- a/.eleventy.js +++ b/.eleventy.js @@ -1,7 +1,5 @@ const crs = require('./crs/crs.js'); -const moment = require('moment'); - -moment.locale('en'); +const { DateTime } = require('luxon'); const pageAssetsPlugin = require('eleventy-plugin-page-assets'); @@ -18,11 +16,24 @@ module.exports = function (eleventyConfig) { }); eleventyConfig.addFilter('dateIso', date => { - return moment(date).toISOString(); + if (!date) return ''; + try { + const dt = date instanceof Date ? DateTime.fromJSDate(date) : DateTime.fromISO(String(date)); + if (dt.isValid) return dt.toUTC().toISO(); + // fallback to native parse + const d2 = new Date(String(date)); + return isNaN(d2) ? '' : DateTime.fromJSDate(d2).toUTC().toISO(); + } catch (e) { return ''; } }); - eleventyConfig.addFilter('dateReadable', date => { - return moment(date).utc().format('LL'); // E.g. May 31, 2019 + // dateReadable: server-side formatted date using the provided locale (e.g. page.locale) + // Usage: {{ page.date | dateReadable(page.locale) }} — falls back to 'de' + eleventyConfig.addFilter('dateReadable', (date, locale) => { + if (!date) return ''; + let dt = date instanceof Date ? DateTime.fromJSDate(date) : DateTime.fromISO(String(date)); + if (!dt.isValid) dt = DateTime.fromJSDate(new Date(String(date))); + const useLocale = locale || 'en'; + return dt.setLocale(useLocale).toLocaleString(DateTime.DATE_FULL); }); eleventyConfig.addShortcode('excerpt', article => extractExcerpt(article)); diff --git a/README.md b/README.md index a2f3579..6e05333 100644 --- a/README.md +++ b/README.md @@ -44,11 +44,14 @@ Change the title as you wish and 'nogoblin' to 'dragonborns'. { "author": "enno", "layout": "post-layout.njk", - "tags": "nogoblin" + "tags": "nogoblin", + "locale": "de" } ``` - Change the author to your name and "nogoblin" to "dragonborns". +- Change the locale to en if you want to write in English. + - Edit every Auswertung_XX.md: ``` --- diff --git a/_data/site.json b/_data/site.json new file mode 100644 index 0000000..72ea19d --- /dev/null +++ b/_data/site.json @@ -0,0 +1,3 @@ +{ + "locale": "de" +} \ No newline at end of file diff --git a/_includes/post-layout.njk b/_includes/post-layout.njk index 3f47892..6ef9a68 100644 --- a/_includes/post-layout.njk +++ b/_includes/post-layout.njk @@ -4,7 +4,7 @@ layout: base-layout.njk

    {{ title }}

    {% if author %}{{author}},{% else %}N.N.,{% endif %} - + {{ content | safe }}
    diff --git a/template/template.json b/template/template.json index 8da134b..e6505f8 100644 --- a/template/template.json +++ b/template/template.json @@ -1,5 +1,6 @@ { "author": "stm", "layout": "post-layout.njk", - "tags": "nogoblin" + "tags": "nogoblin", + "locale": "de" } From 54d1079aa9ee3d246932166ade3a587bdf0b8952 Mon Sep 17 00:00:00 2001 From: Steffen Mecke Date: Thu, 21 Aug 2025 10:11:41 +0200 Subject: [PATCH 27/34] fixed elevent-plugin-page-assets in directory mode with patch-package package is not maintained fixed bug in directory mode fixed typos added "silent" option --- package-lock.json | 1987 ++++++----------- package.json | 6 +- .../eleventy-plugin-page-assets+0.3.0.patch | 122 + 3 files changed, 762 insertions(+), 1353 deletions(-) create mode 100644 patches/eleventy-plugin-page-assets+0.3.0.patch diff --git a/package-lock.json b/package-lock.json index 295e988..07475d5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,9 +7,11 @@ "": { "name": "eressea-tutorials", "version": "1.1.0", + "hasInstallScript": true, "license": "MIT", "dependencies": { - "@jest/globals": "latest" + "@jest/globals": "latest", + "patch-package": "^8.0.0" }, "devDependencies": { "@11ty/eleventy": "^3.1.0", @@ -866,21 +868,6 @@ "node": ">= 10.14.2" } }, - "node_modules/@jest/console/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/@jest/console/node_modules/chalk": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", @@ -897,45 +884,6 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@jest/console/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/@jest/console/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/@jest/console/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/console/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/@jest/core": { "version": "26.6.3", "resolved": "https://registry.npmjs.org/@jest/core/-/core-26.6.3.tgz", @@ -984,21 +932,6 @@ "node": ">=8" } }, - "node_modules/@jest/core/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/@jest/core/node_modules/chalk": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", @@ -1015,33 +948,6 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@jest/core/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/@jest/core/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/@jest/core/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/@jest/core/node_modules/rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -1070,18 +976,6 @@ "node": ">=8" } }, - "node_modules/@jest/core/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/@jest/environment": { "version": "26.6.2", "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-26.6.2.tgz", @@ -1193,20 +1087,6 @@ "node": ">=8" } }, - "node_modules/@jest/globals/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/@jest/globals/node_modules/braces": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", @@ -1233,22 +1113,6 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@jest/globals/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/@jest/globals/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, "node_modules/@jest/globals/node_modules/diff-sequences": { "version": "26.6.2", "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-26.6.2.tgz", @@ -1289,14 +1153,6 @@ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==" }, - "node_modules/@jest/globals/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "engines": { - "node": ">=8" - } - }, "node_modules/@jest/globals/node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -1419,17 +1275,6 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.1.tgz", "integrity": "sha512-NAnt2iGDXohE5LI7uBnLnqvLQMtzhkiAOLXTmv+qnF9Ky7xAPcX8Up/xWIhxvLVGJvuLiNc4xQLtuqDRzb4fSA==" }, - "node_modules/@jest/globals/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/@jest/globals/node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -1479,21 +1324,6 @@ "node-notifier": "^8.0.0" } }, - "node_modules/@jest/reporters/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/@jest/reporters/node_modules/chalk": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", @@ -1510,45 +1340,6 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@jest/reporters/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/@jest/reporters/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/@jest/reporters/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/reporters/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/@jest/source-map": { "version": "26.6.2", "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-26.6.2.tgz", @@ -1620,21 +1411,6 @@ "node": ">= 10.14.2" } }, - "node_modules/@jest/transform/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/@jest/transform/node_modules/chalk": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", @@ -1651,45 +1427,6 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@jest/transform/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/@jest/transform/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/@jest/transform/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/transform/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/@jest/types": { "version": "26.6.2", "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.6.2.tgz", @@ -1706,21 +1443,6 @@ "node": ">= 10.14.2" } }, - "node_modules/@jest/types/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/@jest/types/node_modules/chalk": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", @@ -1737,45 +1459,6 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@jest/types/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/@jest/types/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/@jest/types/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/types/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/@sindresorhus/slugify": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/@sindresorhus/slugify/-/slugify-2.2.1.tgz", @@ -1959,6 +1642,12 @@ "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-15.0.0.tgz", "integrity": "sha512-FA/BWv8t8ZWJ+gEOnLLd8ygxH/2UFbAvgEonyfN6yWGLKc7zVjbpl2Y4CTjid9h2RfgPP6SEt6uHwEOply00yw==" }, + "node_modules/@yarnpkg/lockfile": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", + "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", + "license": "BSD-2-Clause" + }, "node_modules/a-sync-waterfall": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/a-sync-waterfall/-/a-sync-waterfall-1.0.1.tgz", @@ -2047,6 +1736,39 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/ansi-styles/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/ansi-styles/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, "node_modules/anymatch": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", @@ -2189,6 +1911,15 @@ "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", "dev": true }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "license": "ISC", + "engines": { + "node": ">= 4.0.0" + } + }, "node_modules/atob": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", @@ -2238,21 +1969,6 @@ "@babel/core": "^7.0.0" } }, - "node_modules/babel-jest/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/babel-jest/node_modules/chalk": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", @@ -2269,45 +1985,6 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/babel-jest/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/babel-jest/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/babel-jest/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/babel-jest/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/babel-plugin-istanbul": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.0.0.tgz", @@ -2381,8 +2058,7 @@ "node_modules/balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" }, "node_modules/base": { "version": "0.11.2", @@ -2522,7 +2198,6 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -2532,7 +2207,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, "dependencies": { "fill-range": "^7.0.1" }, @@ -2604,6 +2278,53 @@ "node": ">=0.10.0" } }, + "node_modules/call-bind": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", + "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.0", + "es-define-property": "^1.0.0", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -2832,8 +2553,7 @@ "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, "node_modules/convert-source-map": { "version": "1.7.0", @@ -2998,6 +2718,23 @@ "node": ">=0.10.0" } }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/define-property": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", @@ -3189,6 +2926,20 @@ "url": "https://github.com/fb55/domutils?sponsor=1" } }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", @@ -3298,6 +3049,36 @@ "is-arrayish": "^0.2.1" } }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", @@ -3507,39 +3288,6 @@ "node": ">= 10.14.2" } }, - "node_modules/expect/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/expect/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/expect/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -3679,7 +3427,6 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, "dependencies": { "to-regex-range": "^5.0.1" }, @@ -3729,6 +3476,15 @@ "node": ">=8" } }, + "node_modules/find-yarn-workspace-root": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz", + "integrity": "sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ==", + "license": "Apache-2.0", + "dependencies": { + "micromatch": "^4.0.2" + } + }, "node_modules/for-in": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", @@ -3783,11 +3539,34 @@ "node": ">= 0.8" } }, + "node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "license": "MIT", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/fs-extra/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, "node_modules/fsevents": { "version": "2.3.2", @@ -3804,10 +3583,13 @@ } }, "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/gensync": { "version": "1.0.0-beta.2", @@ -3827,6 +3609,30 @@ "node": "6.* || 8.* || >= 10.*" } }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/get-package-type": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", @@ -3836,10 +3642,23 @@ "node": ">=8.0.0" } }, - "node_modules/get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", "dev": true, "dependencies": { "pump": "^3.0.0" @@ -3871,7 +3690,6 @@ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -3909,11 +3727,22 @@ "node": ">=4" } }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/graceful-fs": { "version": "4.2.6", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", - "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==", - "dev": true + "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==" }, "node_modules/gray-matter": { "version": "4.0.3", @@ -3981,6 +3810,30 @@ "node": ">=4" } }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/has-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", @@ -4044,6 +3897,18 @@ "node": ">=0.10.0" } }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/hosted-git-info": { "version": "2.8.8", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", @@ -4194,7 +4059,6 @@ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", - "dev": true, "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -4203,8 +4067,7 @@ "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "node_modules/is-accessor-descriptor": { "version": "0.1.6", @@ -4368,8 +4231,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.1.1.tgz", "integrity": "sha512-ZOoqiXfEwtGknTiuDEy8pN2CfE3TxMHprvNer1mXiqwkOT77Rw3YVrUQ52EqAOU3QAWDQ+bQdx7HJzrv7LS2Hw==", - "dev": true, - "optional": true, "bin": { "is-docker": "cli.js" }, @@ -4441,7 +4302,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, "engines": { "node": ">=0.12.0" } @@ -4488,11 +4348,28 @@ "node": ">=0.10.0" } }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "license": "MIT", + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "license": "MIT" + }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" }, "node_modules/iso-639-1": { "version": "3.1.5", @@ -4566,27 +4443,6 @@ "node": ">=8" } }, - "node_modules/istanbul-lib-report/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-report/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/istanbul-lib-source-maps": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.0.tgz", @@ -4800,21 +4656,6 @@ } } }, - "node_modules/jest-config/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/jest-config/node_modules/chalk": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", @@ -4831,45 +4672,6 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/jest-config/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/jest-config/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/jest-config/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-config/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/jest-diff": { "version": "26.6.2", "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-26.6.2.tgz", @@ -4885,21 +4687,6 @@ "node": ">= 10.14.2" } }, - "node_modules/jest-diff/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/jest-diff/node_modules/chalk": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", @@ -4916,45 +4703,6 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/jest-diff/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/jest-diff/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/jest-diff/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-diff/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/jest-docblock": { "version": "26.0.0", "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-26.0.0.tgz", @@ -4983,21 +4731,6 @@ "node": ">= 10.14.2" } }, - "node_modules/jest-each/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/jest-each/node_modules/chalk": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", @@ -5014,45 +4747,6 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/jest-each/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/jest-each/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/jest-each/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-each/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/jest-environment-jsdom": { "version": "26.6.2", "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-26.6.2.tgz", @@ -5153,21 +4847,6 @@ "node": ">= 10.14.2" } }, - "node_modules/jest-jasmine2/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/jest-jasmine2/node_modules/chalk": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", @@ -5184,56 +4863,17 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/jest-jasmine2/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/jest-leak-detector": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-26.6.2.tgz", + "integrity": "sha512-i4xlXpsVSMeKvg2cEKdfhh0H39qlJlP5Ex1yQxwF9ubahboQYMgTtz5oML35AVA3B4Eu+YsmwaiKVev9KCvLxg==", "dev": true, "dependencies": { - "color-name": "~1.1.4" + "jest-get-type": "^26.3.0", + "pretty-format": "^26.6.2" }, "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/jest-jasmine2/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/jest-jasmine2/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-jasmine2/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-leak-detector": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-26.6.2.tgz", - "integrity": "sha512-i4xlXpsVSMeKvg2cEKdfhh0H39qlJlP5Ex1yQxwF9ubahboQYMgTtz5oML35AVA3B4Eu+YsmwaiKVev9KCvLxg==", - "dev": true, - "dependencies": { - "jest-get-type": "^26.3.0", - "pretty-format": "^26.6.2" - }, - "engines": { - "node": ">= 10.14.2" + "node": ">= 10.14.2" } }, "node_modules/jest-matcher-utils": { @@ -5251,21 +4891,6 @@ "node": ">= 10.14.2" } }, - "node_modules/jest-matcher-utils/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/jest-matcher-utils/node_modules/chalk": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", @@ -5282,45 +4907,6 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/jest-matcher-utils/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/jest-matcher-utils/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/jest-matcher-utils/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-matcher-utils/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/jest-message-util": { "version": "26.6.2", "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-26.6.2.tgz", @@ -5341,21 +4927,6 @@ "node": ">= 10.14.2" } }, - "node_modules/jest-message-util/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/jest-message-util/node_modules/chalk": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", @@ -5372,45 +4943,6 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/jest-message-util/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/jest-message-util/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/jest-message-util/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-message-util/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/jest-mock": { "version": "26.6.2", "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-26.6.2.tgz", @@ -5482,21 +5014,6 @@ "node": ">= 10.14.2" } }, - "node_modules/jest-resolve/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/jest-resolve/node_modules/chalk": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", @@ -5513,45 +5030,6 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/jest-resolve/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/jest-resolve/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/jest-resolve/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-resolve/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/jest-runner": { "version": "26.6.3", "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-26.6.3.tgz", @@ -5583,21 +5061,6 @@ "node": ">= 10.14.2" } }, - "node_modules/jest-runner/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/jest-runner/node_modules/chalk": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", @@ -5614,45 +5077,6 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/jest-runner/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/jest-runner/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/jest-runner/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-runner/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/jest-runtime": { "version": "26.6.3", "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-26.6.3.tgz", @@ -5694,21 +5118,6 @@ "node": ">= 10.14.2" } }, - "node_modules/jest-runtime/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/jest-runtime/node_modules/chalk": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", @@ -5725,45 +5134,6 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/jest-runtime/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/jest-runtime/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/jest-runtime/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-runtime/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/jest-serializer": { "version": "26.6.2", "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-26.6.2.tgz", @@ -5803,75 +5173,21 @@ "engines": { "node": ">= 10.14.2" } - }, - "node_modules/jest-snapshot/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-snapshot/node_modules/chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-snapshot/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/jest-snapshot/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/jest-snapshot/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-snapshot/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + }, + "node_modules/jest-snapshot/node_modules/chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", "dev": true, "dependencies": { - "has-flag": "^4.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, "node_modules/jest-util": { @@ -5891,21 +5207,6 @@ "node": ">= 10.14.2" } }, - "node_modules/jest-util/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/jest-util/node_modules/chalk": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", @@ -5922,45 +5223,6 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/jest-util/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/jest-util/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/jest-util/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-util/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/jest-validate": { "version": "26.6.2", "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-26.6.2.tgz", @@ -5978,21 +5240,6 @@ "node": ">= 10.14.2" } }, - "node_modules/jest-validate/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/jest-validate/node_modules/camelcase": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", @@ -6021,45 +5268,6 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/jest-validate/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/jest-validate/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/jest-validate/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-validate/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/jest-watcher": { "version": "26.6.2", "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-26.6.2.tgz", @@ -6078,21 +5286,6 @@ "node": ">= 10.14.2" } }, - "node_modules/jest-watcher/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/jest-watcher/node_modules/chalk": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", @@ -6109,45 +5302,6 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/jest-watcher/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/jest-watcher/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/jest-watcher/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-watcher/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/jest-worker": { "version": "26.6.2", "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", @@ -6162,42 +5316,6 @@ "node": ">= 10.13.0" } }, - "node_modules/jest-worker/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-worker/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/jest/node_modules/chalk": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", @@ -6214,33 +5332,6 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/jest/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/jest/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/jest/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/jest/node_modules/jest-cli": { "version": "26.6.3", "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-26.6.3.tgz", @@ -6268,18 +5359,6 @@ "node": ">= 10.14.2" } }, - "node_modules/jest/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -6391,6 +5470,25 @@ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true }, + "node_modules/json-stable-stringify": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.3.0.tgz", + "integrity": "sha512-qtYiSSFlwot9XHtF9bD9c7rwKjr+RecWT//ZnPvSmEjpV5mmPOCN4j8UjY5hbjNkOwZ/jQv3J6R1/pL7RwgMsg==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "isarray": "^2.0.5", + "jsonify": "^0.0.1", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", @@ -6412,6 +5510,36 @@ "node": ">=6" } }, + "node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsonfile/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/jsonify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.1.tgz", + "integrity": "sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg==", + "license": "Public Domain", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/jsprim": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", @@ -6446,6 +5574,15 @@ "node": ">=0.10.0" } }, + "node_modules/klaw-sync": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/klaw-sync/-/klaw-sync-6.0.0.tgz", + "integrity": "sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.1.11" + } + }, "node_modules/kleur": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", @@ -6641,6 +5778,15 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/maximatch": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/maximatch/-/maximatch-0.1.0.tgz", @@ -6674,7 +5820,6 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", - "dev": true, "dependencies": { "braces": "^3.0.1", "picomatch": "^2.0.5" @@ -6730,7 +5875,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -6742,7 +5886,6 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" @@ -6901,19 +6044,6 @@ "which": "^2.0.2" } }, - "node_modules/node-notifier/node_modules/is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "dev": true, - "optional": true, - "dependencies": { - "is-docker": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/node-notifier/node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -7105,6 +6235,15 @@ "node": ">=0.10.0" } }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/object-visit": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", @@ -7146,7 +6285,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, "dependencies": { "wrappy": "1" } @@ -7166,6 +6304,22 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/open": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", + "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", + "license": "MIT", + "dependencies": { + "is-docker": "^2.0.0", + "is-wsl": "^2.1.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/optionator": { "version": "0.8.3", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", @@ -7183,6 +6337,15 @@ "node": ">= 0.8.0" } }, + "node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/p-each-series": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-2.2.0.tgz", @@ -7290,6 +6453,135 @@ "node": ">=0.10.0" } }, + "node_modules/patch-package": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/patch-package/-/patch-package-8.0.0.tgz", + "integrity": "sha512-da8BVIhzjtgScwDJ2TtKsfT5JFWz1hYoBl9rUQ1f38MC2HwnEIkK8VN3dKMKcP7P7bvvgzNDbfNHtx3MsQb5vA==", + "license": "MIT", + "dependencies": { + "@yarnpkg/lockfile": "^1.1.0", + "chalk": "^4.1.2", + "ci-info": "^3.7.0", + "cross-spawn": "^7.0.3", + "find-yarn-workspace-root": "^2.0.0", + "fs-extra": "^9.0.0", + "json-stable-stringify": "^1.0.2", + "klaw-sync": "^6.0.0", + "minimist": "^1.2.6", + "open": "^7.4.2", + "rimraf": "^2.6.3", + "semver": "^7.5.3", + "slash": "^2.0.0", + "tmp": "^0.0.33", + "yaml": "^2.2.2" + }, + "bin": { + "patch-package": "index.js" + }, + "engines": { + "node": ">=14", + "npm": ">5" + } + }, + "node_modules/patch-package/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/patch-package/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/patch-package/node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/patch-package/node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/patch-package/node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/patch-package/node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/patch-package/node_modules/slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/patch-package/node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -7303,7 +6595,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -7468,39 +6759,6 @@ "node": ">=8" } }, - "node_modules/pretty-format/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/pretty-format/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/pretty-format/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, "node_modules/prompts": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.1.tgz", @@ -7863,6 +7121,19 @@ "node": ">=0.12" } }, + "node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, "node_modules/rsvp": { "version": "4.8.5", "resolved": "https://registry.npmjs.org/rsvp/-/rsvp-4.8.5.tgz", @@ -8115,7 +7386,6 @@ "version": "7.7.2", "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", - "dev": true, "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -8189,6 +7459,23 @@ "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/set-value": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", @@ -8731,6 +8018,27 @@ "node": ">=6" } }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-color/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/supports-hyperlinks": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.1.0.tgz", @@ -8753,18 +8061,6 @@ "node": ">=8" } }, - "node_modules/supports-hyperlinks/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/symbol-tree": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", @@ -8852,6 +8148,18 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "license": "MIT", + "dependencies": { + "os-tmpdir": "~1.0.2" + }, + "engines": { + "node": ">=0.6.0" + } + }, "node_modules/tmpl": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz", @@ -8910,7 +8218,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, "dependencies": { "is-number": "^7.0.0" }, @@ -9318,8 +8625,7 @@ "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "node_modules/write-file-atomic": { "version": "3.0.3", @@ -9366,6 +8672,18 @@ "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", "dev": true }, + "node_modules/yaml": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.1.tgz", + "integrity": "sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==", + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + } + }, "node_modules/yargs": { "version": "15.4.1", "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", @@ -9397,21 +8715,6 @@ "node": ">=8" } }, - "node_modules/yargs/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/yargs/node_modules/cliui": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", @@ -9423,24 +8726,6 @@ "wrap-ansi": "^6.2.0" } }, - "node_modules/yargs/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/yargs/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, "node_modules/yargs/node_modules/strip-ansi": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", diff --git a/package.json b/package.json index 2f9392c..b694b5c 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,8 @@ "build-gh": "env NODE_ENV=production npx eleventy --pathprefix tutorials", "serve": "npx eleventy --serve", "debug": "DEBUG=* npx eleventy", - "test": "jest" + "test": "jest", + "postinstall": "patch-package" }, "repository": { "type": "git", @@ -26,6 +27,7 @@ "moment": "^2.29.1" }, "dependencies": { - "@jest/globals": "latest" + "@jest/globals": "latest", + "patch-package": "^8.0.0" } } diff --git a/patches/eleventy-plugin-page-assets+0.3.0.patch b/patches/eleventy-plugin-page-assets+0.3.0.patch new file mode 100644 index 0000000..a4001b7 --- /dev/null +++ b/patches/eleventy-plugin-page-assets+0.3.0.patch @@ -0,0 +1,122 @@ +diff --git a/node_modules/eleventy-plugin-page-assets/src/plugin.js b/node_modules/eleventy-plugin-page-assets/src/plugin.js +index 72875cc..77bed09 100644 +--- a/node_modules/eleventy-plugin-page-assets/src/plugin.js ++++ b/node_modules/eleventy-plugin-page-assets/src/plugin.js +@@ -16,6 +16,8 @@ const pluginOptions = { + postsMatching: "*.md", + assetsMatching: "*.png|*.jpg|*.gif", + ++ silent: false, ++ + recursive: false, // only mode:directory + + hashAssets: true, // only mode:parse +@@ -38,53 +40,56 @@ async function transformParser(content, outputPath) { + const templateDir = path.dirname(template.inputPath); + const outputDir = path.dirname(outputPath); + +- // parse +- const dom = new JSDOM(content); +- const elms = [...dom.window.document.querySelectorAll("img")]; //TODO: handle different tags ++ // parse ++ const dom = new JSDOM(content); ++ const elms = [...dom.window.document.querySelectorAll("img")]; //TODO: handle different tags + ++ if (pluginOptions.silent !== true) + console.log(LOG_PREFIX, `Found ${elms.length} assets in ${outputPath} from template ${inputPath}`); +- await Promise.all(elms.map(async (img) => { ++ await Promise.all(elms.map(async (img) => { + +- const src = img.getAttribute("src"); +- if (isRelative(src) && pm.isMatch(src, pluginOptions.assetsMatching, { contains: true })) { ++ const src = img.getAttribute("src"); ++ if (isRelative(src) && pm.isMatch(src, pluginOptions.assetsMatching, { contains: true })) { + +- const assetPath = path.join(templateDir, src); +- const assetSubdir = path.relative(templateDir, path.dirname(assetPath)); +- const assetBasename = path.basename(assetPath); ++ const assetPath = path.join(templateDir, src); ++ const assetSubdir = path.relative(templateDir, path.dirname(assetPath)); ++ const assetBasename = path.basename(assetPath); + +- let destDir = path.join(outputDir, assetSubdir); +- let destPath = path.join(destDir, assetBasename); +- let destPathRelativeToPage = path.join('./', assetSubdir, assetBasename); ++ let destDir = path.join(outputDir, assetSubdir); ++ let destPath = path.join(destDir, assetBasename); ++ let destPathRelativeToPage = path.join('./', assetSubdir, assetBasename); + +- // resolve asset +- if (await resolveFile(assetPath)) { ++ // resolve asset ++ if (await resolveFile(assetPath)) { + +- // calculate hash +- if (pluginOptions.hashAssets) { +- const hash = await hashFile(assetPath, pluginOptions.hashingAlg, pluginOptions.hashingDigest); +- if (pluginOptions.addIntegrityAttribute) +- img.setAttribute("integrity", `${pluginOptions.hashingAlg}-${hash}`); ++ // calculate hash ++ if (pluginOptions.hashAssets) { ++ const hash = await hashFile(assetPath, pluginOptions.hashingAlg, pluginOptions.hashingDigest); ++ if (pluginOptions.addIntegrityAttribute) ++ img.setAttribute("integrity", `${pluginOptions.hashingAlg}-${hash}`); + +- // rewrite paths +- destDir = outputDir; // flatten subdir +- destPath = path.join(destDir, hash + path.extname(assetBasename)) +- destPathRelativeToPage = './' + path.join(hash + path.extname(assetBasename)) +- img.setAttribute("src", destPathRelativeToPage); +- } ++ // rewrite paths ++ destDir = outputDir; // flatten subdir ++ destPath = path.join(destDir, hash + path.extname(assetBasename)) ++ destPathRelativeToPage = './' + path.join(hash + path.extname(assetBasename)) ++ img.setAttribute("src", destPathRelativeToPage); ++ } + +- console.log(LOG_PREFIX, `Writting ./${destPath} from ./${assetPath}`); +- fs.mkdirSync(destDir, { recursive: true }); +- await fs.promises.copyFile(assetPath, destPath); ++ if (pluginOptions.silent !== true) ++ console.log(LOG_PREFIX, `Writing ./${destPath} from ./${assetPath}`); ++ fs.mkdirSync(destDir, { recursive: true }); ++ await fs.promises.copyFile(assetPath, destPath); + +- } else { +- throw new Error(`${LOG_PREFIX} Cannot resolve asset "${src}" in "${outputPath}" from template "${inputPath}"!`); +- } ++ } else { ++ throw new Error(`${LOG_PREFIX} Cannot resolve asset "${src}" in "${outputPath}" from template "${inputPath}"!`); + } ++ } + +- })); ++ })); + ++ if (pluginOptions.silent !== true) + console.log(LOG_PREFIX, `Processed ${elms.length} images in "${outputPath}" from template "${inputPath}"`); +- content = dom.serialize(); ++ content = dom.serialize(); + } + } + return content; +@@ -101,7 +106,7 @@ async function transformDirectoryWalker(content, outputPath) { + const templateDir = path.dirname(template.inputPath); + const outputDir = path.dirname(outputPath); + +- const assets = []; ++ let assets = []; + if (pluginOptions.recursive) { + for await (const file of walk(templateDir)) { + assets.push(file); +@@ -121,7 +126,8 @@ async function transformDirectoryWalker(content, outputPath) { + const destDir = path.join(outputDir, relativeSubDir); + const dest = path.join(destDir, basename); + +- console.log(LOG_PREFIX, `Writting ./${dest} from ./${from}`); ++ if (pluginOptions.silent !== true) ++ console.log(LOG_PREFIX, `Writing ./${dest} from ./${from}`); + fs.mkdirSync(destDir, { recursive: true }); + await fs.promises.copyFile(from, dest); + } From 27f9b6c014fca3d59979ac3fec9f5602359aa286 Mon Sep 17 00:00:00 2001 From: Steffen Mecke Date: Thu, 21 Aug 2025 11:13:58 +0200 Subject: [PATCH 28/34] changed page-assets options to include .cr/.nr/.txt --- .eleventy.js | 7 +- crs/crs.js | 2 +- template/reports/1234-bLa.cr | 386 +++++++++++++++++++++++++++++++++++ 3 files changed, 392 insertions(+), 3 deletions(-) create mode 100644 template/reports/1234-bLa.cr diff --git a/.eleventy.js b/.eleventy.js index 2377f77..36b4c68 100644 --- a/.eleventy.js +++ b/.eleventy.js @@ -10,9 +10,12 @@ module.exports = function (eleventyConfig) { // https://github.com/victornpb/eleventy-plugin-page-assets eleventyConfig.addPlugin(pageAssetsPlugin, { - mode: "parse", - assetsMatching: "*.png|*.PNG|*.jpg|*.JPG|*.gif|*.GIF", + mode: "directory", + assetsMatching: "*.png|*.PNG|*.jpg|*.JPG|*.gif|*.GIF|*.cr|*.nr|*.txt", postsMatching: "**/*.md", + hashAssets: false, + recursive: true, + silent: true, }); eleventyConfig.addFilter('dateIso', date => { diff --git a/crs/crs.js b/crs/crs.js index 52fa51a..364309d 100644 --- a/crs/crs.js +++ b/crs/crs.js @@ -190,7 +190,7 @@ module.exports = function (eleventyConfig) { return { error: 'path escapes project root' }; } const relPath = path.relative(projectRoot, candidateFs).split(path.sep).join('/'); - const publicPath = (pathPrefix ? pathPrefix : '') + '/' + relPath; + const publicPath = isRootRel ? (pathPrefix ? pathPrefix : '') + '/' + relPath : spec; return { fsPath: candidateFs, publicPath, relPath }; } diff --git a/template/reports/1234-bLa.cr b/template/reports/1234-bLa.cr new file mode 100644 index 0000000..4e37fc9 --- /dev/null +++ b/template/reports/1234-bLa.cr @@ -0,0 +1,386 @@ +VERSION 69 +"UTF-8";charset +"de";locale +1;noskillpoints +1659958813;date +"eressea";Spiel +"Java-Tools";Konfiguration +"Hex";Koordinaten +36;Basis +1;Umlaute +0;curTempID +1234;Runde +2;Zeitalter +"eressea-server@kn-bremen.de";mailto +"ERESSEA 2 BEFEHLE";mailcmd +15022;reportowner +"27.1.2-2-g5645d9678";Build +2500;max_units +COORDTRANS 15022 +0 0;translation +PARTEI 15022 +"de";locale +599;Optionen +"Orks";Typ +70;Rekrutierungskosten +1;Anzahl Personen +1;age +"gray";Magiegebiet +"Partei bLa";Parteiname +"max.mustermann@example.com";email +OPTIONEN +1;REPORT +1;COMPUTER +1;ZUGVORLAGE +0;SILBERPOOL +1;STATISTIK +0;DEBUG +1;ZIPPED +0;ZEITUNG +0;MATERIALPOOL +1;ADRESSEN +0;BZIP2 +0;PUNKTE +0;TALENTVERSCHIEBUNGEN +MESSAGE 971112208 +198804487;type +"Deine Partei hat letzte Runde keinen Zug abgegeben!";rendered +MESSAGE 1063819696 +771334452;type +"Einheit 5ac0 (5ac0) verdient in Rilmodciget (0, 0) 10 Silber.";rendered +246672;unit +0 0 0;region +10;amount +10;wanted +0;mode +MESSAGE 761101056 +1784377885;type +"Das Passwort für diese Partei lautet keinpasswort";rendered +"keinpasswort";value +MESSAGE 751019600 +1593006007;type +"Deine Partei ist noch die nächsten 6 Wochen immun gegen Angriffe.";rendered +6;turns +REGION -1 0 +6231171415;id +"Ozean";Terrain +"neighbour";visibility +REGION 0 -1 +943437574;id +"Ozean";Terrain +"neighbour";visibility +REGION 0 0 +1102578064;id +"Gusras";Name +"Wald";Terrain +"";Beschr +500;Baeume +100;Schoesslinge +4004;Bauern +51;Pferde +83960;Silber +4198;Unterh +100;Rekruten +11;Lohn +1;aktiveRegion +RESOURCE 347593380 +"Bauern";type +4004;number +1234;Runde +RESOURCE 6035652 +"Bäume";type +500;number +1234;Runde +RESOURCE 1352714618 +"Schößlinge";type +100;number +1234;Runde +RESOURCE 210060480 +"Silber";type +83960;number +1234;Runde +RESOURCE 200695649 +"Pferde";type +51;number +1234;Runde +PREISE +8;Balsam +25;Gewürz +-7;Juwel +20;Myrrhe +12;Öl +24;Seide +20;Weihrauch +EINHEIT 246672 +"Einheit 5ac0";Name +15022;Partei +1;Anzahl +"Orks";Typ +0;Kampfstatus +32500;weight +COMMANDS +"; Befehle, die mit Semicolon beginnen, sind Kommentare." +"; Die Standardeinstellungen von Magellan sorgen dafür, dass sie vor dem " +"; Versand an den Server entfernt werden. Magellan sorgt auch dafür, dass zu lange Zeilen wie diese hier umgebrochen werden und auf dem Server keine Probleme machen." +"; Wir nutzen die Kommentare hier, um dir die Befehle zu erklären." +"; " +"; Wir wollen eine schöne, passende Nummer (ID) für unsere Partei sichern." +"; IDs Bestehen aus einer Kombination von 4 Zahlen oder Buchstaben." +"; Die IDs für Parteien, Einheiten, Gebäuden und Schiffen kommen jeweils" +"; aus einem eigenen Pool." +"NUMMER PARTEI demo" +"; Es ist also möglich dieser Einheit die gleiche Nummer wie die der Partei" +"; zu geben" +"NUMMER EINHEIT demo" +"; Zurück zur Partei. Wir wollen unserer Partei einen guten Namen und eine" +"; hübsche Beschreibung geben. Eressea spielt man mit anderen zusammen." +"; Schöne Beschreibungen erhöhen den Spielspaß für alle und vermindern die " +"; Wahrscheinlichkeit von seinen Nachbarn früh abgeschlachtet zu werden. " +"; Wirklich wahr." +"BENENNE PARTEI \"Die DEMOrkraten\"" +"BANNER \"Wir glauben an demorkratische Werte. Sie sind der beste Weg für ein gutes Zusammenleben. Wenn ihr das auch denkt, schreibt uns doch eine Nachricht an demo@example.com!\"" +"BENENNE EINHEIT \"Erster Demorkrat\"" +"BESCHREIBE EINHEIT \"Tritt für Gewaltenteilung ein. Also zumindest für Gewalt. Und Teilung.\"" +"; " +"; Wir ändern noch rasch den Kampfstatus. Im Moment ist das streng genommen" +"; nicht nötig, aber so vergessen wir es später nicht. Für Kundschafter und" +"; andere Unbewaffnete ist FLIEHE eine gute Wahl: für den Fall, dass wir" +"; von unliebsamen Nachbarn oder Monstern angegriffen werden, können wir uns" +"; noch nicht wirksam verteidigen. Stattdessen vergrößern wir unsere Chancen" +"; zu überleben UND verlieren außerdem unseren Bewegungsbefehl nicht." +"; Win-Win!" +"KÄMPFE FLIEHE" +";" +"; Der Rest der Befehle dieser Einheit besteht nur aus Übergaben an" +"; TEMP-Einheiten und der Erzeugung von TEMP-Einheiten." +"; Gelogen! Wir sichern uns noch schnell Silber, um wenigstens die nächsten" +"; 4 Runden überleben zu können." +"RESERVIERE 40 Silber" +";" +"; Überhaupt Silber. Wir haben 2500 und so bald stehen keine Einnahmen ins" +"; Haus. Wir sind schließlich keine Halblinge, die ab Runde zwei fette" +"; Einnahmen haben, weil die Bauern sie sooo lustig finden und ihnen" +"; freiwillig Geld in den ... Ich schweife ab. " +"; Was können wir tun?" +"; 2500 Silber, also rekrutieren wir 35 Orks zu je 70 Silber, richtig?" +"; Falsch natürlich, das führt in die sichere Katastrophe: Wir brauchen ja" +"; auch 10 Silber Unterhalt pro Runde." +"; Unsere ersten Einnahmen stehen frühestens in Runde 3 an: " +"; Runde 1: Einheit 1 lernt Waffenbau" +"; Runde 2: Einheit 1 macht Holz zu Speeren, Einheit 2 lernt Treiben" +"; Runde 3: Einheit 2 schappt sich die Speere und treibt. Bis dahin haben" +"; sie wahrscheinlich nur je eine Talentstufe gelernt, dazu kommt unser " +"; Rassenbonus von +1 auf Steuereintreiben." +"; Macht also (Stufe 2 * 20 Silber pro Stufe) = 40 Silber pro Runde." +"; Effizienter ist wahrscheinlich Folgendes: Wir lassen eine Person " +"; Steuereintreiben lernen. Die benutzen wir in der nächsten Runde als" +"; Lehrer für unsere ersten 10 Treiber." +"; Durch diesen Trick sparen wir das Unterhaltssilber für die 10 Treiber in" +"; der ersten Runde beim gleichen Ergebnis. Vielleicht ist es auch" +"; sinnvoller, sie dann gleich noch eine Runde lernen zu lassen. Auf diese" +"; Weise werden sie wahrscheinlich Stufe 2 erreichen und können dann gleich" +"; 60 Silber pro Runde machen. Bis dahin braucht jede Person also 30 Silber" +"; Unterhalt. Genaues Rechnen lohnt sich. Ist es sinnvoll, die" +"; Steuereintreiber trotzdem schon diese Runde zu rekrutieren und etwas" +"; anderes lernen zu lassen?" +";" +"; Wir übergeben das Rekrutierungssilber plus drei Runden Unterhalt. Das ist" +"; nicht unbedingt nötig, weil die Einheit sich das Silber auch aus dem " +"; Silberpool nimmt." +"; Aufgrund der Übersichtlichkeit ist es aber eine gute Praxis." +"; Orks sind billig, wir können also wenigsten viel mehr Einheiten " +"; rekrutieren als zum Beispiel Elfen. Bäh!" +"; 1 Treiberlehrer" +"GIB TEMP de00 100 Silber" +"; 3 oder 4 Waffenbauer" +"GIB TEMP de01 400 Silber" +"; 1 Tarner" +"GIB TEMP de02 100 Silber" +"; 1 Wahrnehmer" +"GIB TEMP de03 100 Silber" +"; Unsere Späher bekommen neben dem Rekrutierungssilber noch 50 Silber," +"; um als Kundschafter 5 Runden durch die Lande ziehen zu können. Plus 120" +"; Silber, um einen weiteren Kundschafter in der Nachbarregion rekrutieren" +"; zu können." +"GIB TEMP de04 240 Silber" +"GIB TEMP de05 240 Silber" +"; weitere Einheiten" +"GIB TEMP de06 100 Silber" +"GIB TEMP de07 100 Silber" +"GIB TEMP de08 200 Silber" +"; Dies ist der letzte Befehl. Wir übergeben alles, was wir noch haben, an" +"; unser Depot." +"; Wir behalten nur reservierte Gegenstände. Das ist eine gute Angewohnheit," +"; um nicht aufgrund von Denkfehlern überladen zu werden." +"GIB TEMP de02 ALLES" +"; Aha! Wir haben selber noch keinen langen Befehl bekommen. Nun, da wir" +"; schon einen Talentvorsprung haben, können wir als Ausbilder für unsere" +"; zukünftigen Treiber / Krieger dienen." +"; Die Frage ist nur, ob wir Hieb- oder Stangenwaffen lernen." +"LERNE AUTO Hiebwaffen" +"; Das war's! Wir könnten noch Pferdedresseure (super wichtig für;" +"; Steintransport und den Krieg), Segler und Schiffbauer (schließlich haben" +"; wir 4 Ozeanregionen) anstellen." +"; Hätten wir keinen Malus auf Magie, würden wir wahrscheinlich auch 1 oder" +"; 4 Magier ausbilden. Aber die brauchen bei uns drei Wochen und 500 Silber," +"; bis sie auch nur Stufe 1 erreicht haben. Wir warten lieber. Das hat" +"; wenigstens den Vorteil, dass wir uns noch länger Zeit lassen können, ein" +"; Magiegebiet zu wählen." +";" +"; Wir belassen es dabei. Wir haben schon 14 Personen und jede weitere" +"; verlangsamt unseren Start, da wir weniger Steuereintreiber einsetzen" +"; können. Dafür bleiben uns jetzt noch etwa 950 Silber." +"; " +"; Allzu oft fragt man sich: Was habe ich mir letzte Runde wohl dabei" +"; gedacht? //-Kommentare erscheinen nächste Woche im Report und sind" +"; deshalb ein guter Weg, um Pläne über mehrere Wochen nicht zu vergessen." +"// Plan für Woche 1235:" +"// 10 Steuereintreiber rekrutieren und lehren lassen" +"// Speere bauen" +"// Plan für Woche 1236:" +"// Treiber lernen, mehr Speere" +"// Plan für Woche 1237:" +"// Profit!" +"; Vielleicht ist das noch nicht der beste Plan. Es lohnt sich, gerade in" +"; den ersten Runden alles Schritt für Schritt vorauszudenken. Wie genau" +"; sieht die Situation nächte Woche aus?" +"; Wie in zwei, drei oder zehn Wochen? Wir wollen dann nicht merken, dass wir" +"; etwas Wichtiges versäumt haben!" +";" +"; Die Befehle MACHE TEMP und ENDE zur Erzeugung von TEMP-Einheiten, fügt" +"; Magellan netterweise selbständig hinzu, wenn wir dort eine TEMP-Einheit" +"; anlegen" +"MACHE TEMP de00" +"; Unser zukünftiger Lehrer" +"BENENNE EINHEIT \"Demorkratieverwalter\"" +"; Haben wir an das Silber zum Rekrutieren gedacht? Haben wir." +"; Magellan würde auch eine Warnung in der Offene-Probleme-Ansicht geben," +"; falls wir es vergessen." +"REKRUTIERE 1" +"; Durch LERNE AUTO müssen wir nicht von Hand Lehrer auf Schüler verteilen." +"; Wir können theoretisch nächste Runde nur 8 Steuereintreiber rekrutieren" +"; und mit LERNE AUTO Steuereintreiben lernen lassen (jedoch nicht einfach" +"; LERNE Steuereintreiben!)" +"; Die 2 \"fehlenden\" Schüler nutzt unser Lehrer dann, um selber zu lernen." +"LERNE AUTO Steuereintreiben" +"ENDE" +"MACHE TEMP de01" +"; Das werden unsere Speerbauer" +"// Runde 1235: mit T3 6 Speere pro Runde bauen" +"BENENNE EINHEIT \"Kunsthandwerker\"" +"REKRUTIERE 4" +"LERNE AUTO Waffenbau" +"ENDE" +"MACHE TEMP de02" +"; Eine Depoteinheit, die alle unsere nicht benötigten Gegenstände bekommt" +"; und Tarnung lernt. Auf diese Weise verringern wir die Informationen, die" +"; feindliche Späher über unsere Partei bekommen." +"; Gleichzeitig haben Einheiten mit Tarnung eine bessere Fluchtchance, falls" +"; wir überfallen werden." +"; Vor dem Beklautwerden schützt dies leider nicht, weil blöde Goblindiebe" +"; aus dem Silberpool klauen." +"BENENNE EINHEIT \"DEpot\"" +"REKRUTIERE 1" +"; Tarnung und Wahrnehmung sind mit die wichtigsten Talente. Deshalb lohnt" +"; es sich wahrscheinlich, sie ab Runde 1 zu lernen!" +"LERNE AUTO Tarnung" +"ENDE" +"MACHE TEMP de03" +"; Wir lernen auch Wahrnehmung ab Runde 1. Wir möchten ja nicht von Goblins" +"; und Katzen totgeklaut werden!" +"BENENNE EINHEIT \"Wächter der Demorkratie\"" +"REKRUTIERE 1" +"LERNE AUTO Wahrnehmung" +"ENDE" +"MACHE TEMP de04" +"; Wir wollen uns so früh wie möglich unsere Umgebung anschauen. " +"; Der Berg im Osten scheint uns besonders interessant. Dahinter wird es" +"; hoffentlich weitere Regionen geben, also wollen wir dort nächste Runde" +"; einen zweiten Botschafter rekrutieren." +"BENENNE EINHEIT \"Botschafter der Demorkratie\"" +"BESCHREIBE EINHEIT \"Der Botschafter trägt fröhliche schwarz-rot-goldene Klamotten\"" +"REKRUTIERE 1" +"NACH o" +"ENDE" +"MACHE TEMP de05" +"; Die nächsten 2 Botschafter schicken wir nach Südosten" +"BENENNE EINHEIT \"Botschafter der Demorkratie\"" +"BESCHREIBE EINHEIT \"Der Botschafter trägt fröhliche schwarz-rot-goldene Klamotten\"" +"REKRUTIERE 1" +"NACH so" +"ENDE" +"MACHE TEMP de06" +"; Das ist wichtig. Für die meisten Völker ist Unterhaltung das bessere" +"; Talent, um die Wirtschaft aufzubauen. Wir haben aber -2 auf Unterhaltung," +"; also kostet es uns 6 Wochen, überhaupt funktionsfähige Unterhalter" +"; auszubilden. Steuereintreiber brauchen thoeretisch nur eine Woche:" +"; eine für Steuereintreiben, das Waffentalent bringen sie schon mit. Nur " +"; brauchen sie dann noch eine Waffe." +"; Am Anfang werden das Speere sein. Holz ist super knapp in Eressea. In " +"; der Region gibt es 500 Bäume und 100 Schößlinge. Also ist unser Plan," +"; schnell Eisen zu finden, damit ein Sägewerk zu bauen, so dass wir daraus" +"; 1200 Holz machen können. Das reicht für bis zu 1200 Treiber und Krieger," +"; um uns Respekt zu verschaffen. Die Produktion dauert aber und der Betrieb eines" +"; Sägewerks ist teuer. Hoffentlich sind wir bis dahin nicht von einem aggressiven" +"; Insekten- oder einem boomenden Halblingsvolk überrannt worden!" +";" +"; Schritt 1 ist: Eisen finden für das Sägewerk." +"; Vielleicht gibt es Eisen oder Stein in unserer Startregion. Sonst müssen" +"; wir den Berg ausbeuten und hoffen, dass sich dort noch kein Z ... kein Zw" +"; ... Boah, das kommt mir schwer über die Lippen ... Keiner unserer" +"; vertikal benachteiligten Zeitgenossen breit gemacht hat." +"; Mittel- und langfristig sollten wir nicht auf Stangenwaffen, sondern auf" +"; Hiebwaffen setzen." +"; Die sind fast immer besser bei gleichen Ressourcen und wir können unser" +"; Holz für Gebäude, Schiffe und Wagen benutzen." +"BENENNE EINHEIT \"Kumpel\"" +"REKRUTIERE 1" +"LERNE AUTO Bergbau" +"ENDE" +"MACHE TEMP de07" +"; Steine sind auch wichtig für Handelsposten (okay, am Anfang eher nicht" +"; für uns), Burgen zur Verteidiung und Sägewerke, Bergwerke und" +"; Steinbrüche." +"BENENNE EINHEIT \"Kumpel\"" +"REKRUTIERE 1" +"LERNE AUTO Steinbau" +"ENDE" +"MACHE TEMP de08" +"; Wir rekrutieren auch noch ein paar Holzfäller, damit unsere Waffenbauer" +"; auch in Zukunft was zu tun haben." +"BENENNE EINHEIT \"Landschaftspfleger\"" +"REKRUTIERE 2" +"LERNE AUTO Holzfällen" +"ENDE" +"; Den Befehl NÄCHSTER am Ende unserer Befehle fügt Magellan auch" +"; automatisch hinzu. Achte darauf, dass du vor dem Absenden oben das richtige" +"; Passwort einträgst." +TALENTE +300 4;Armbrustschießen +300 4;Bogenschießen +300 4;Katapultbedienung +300 4;Hiebwaffen +300 4;Stangenwaffen +GEGENSTAENDE +10;Holz +2500;Silber +4;Stein +REGION 1 -1 +6811631996;id +"Gytsosuncun";Name +"Wüste";Terrain +"neighbour";visibility +REGION 1 0 +5061153169;id +"Tanpeldoddod";Name +"Berge";Terrain +"neighbour";visibility +REGION -1 1 +233888444;id +"Ozean";Terrain +"neighbour";visibility +REGION 0 1 +6874843160;id +"Ozean";Terrain +"neighbour";visibility +TRANSLATION From b02b6b16c99f64e8fa5998218cd2e144758c9e87 Mon Sep 17 00:00:00 2001 From: Steffen Mecke Date: Thu, 21 Aug 2025 23:33:27 +0200 Subject: [PATCH 29/34] got rid of deprecated | url filter in favor of HTMLBase --- .eleventy.js | 14 +++++++++++--- _includes/base-layout.njk | 10 +++++----- crs/crs.js | 18 +++++++++--------- goblins/index.njk | 4 ++-- index.njk | 2 +- template/index.njk | 4 ++-- 6 files changed, 30 insertions(+), 22 deletions(-) diff --git a/.eleventy.js b/.eleventy.js index 36b4c68..a97680f 100644 --- a/.eleventy.js +++ b/.eleventy.js @@ -1,13 +1,15 @@ const crs = require('./crs/crs.js'); const { DateTime } = require('luxon'); -const pageAssetsPlugin = require('eleventy-plugin-page-assets'); - -module.exports = function (eleventyConfig) { +module.exports = async function (eleventyConfig) { // https://www.11ty.dev/docs/languages/markdown/#indented-code-blocks eleventyConfig.amendLibrary("md", (mdLib) => mdLib.enable("code")); + // const pageAssetsPlugin = require('eleventy-plugin-page-assets'); + let pageAssetsPlugin = await import('eleventy-plugin-page-assets'); + pageAssetsPlugin = pageAssetsPlugin.default || pageAssetsPlugin; + // https://github.com/victornpb/eleventy-plugin-page-assets eleventyConfig.addPlugin(pageAssetsPlugin, { mode: "directory", @@ -18,6 +20,12 @@ module.exports = function (eleventyConfig) { silent: true, }); + // This replaces the {{ xyz | url }} filter by applying pathPrefix properly + let { HtmlBasePlugin } = await import("@11ty/eleventy"); + HtmlBasePlugin = HtmlBasePlugin.default || HtmlBasePlugin; + eleventyConfig.addPlugin(HtmlBasePlugin); + + eleventyConfig.addFilter('dateIso', date => { if (!date) return ''; try { diff --git a/_includes/base-layout.njk b/_includes/base-layout.njk index 880ab22..b61c9af 100644 --- a/_includes/base-layout.njk +++ b/_includes/base-layout.njk @@ -5,20 +5,20 @@ Eressea Beispielpartie - {{title}} - + {% if content.indexOf('crs-requires-css') !== -1 %} - + {% endif %} {% if content.indexOf('crs-requires-js') !== -1 %} - + {% endif %}
    - Beispielpartie - Up + Beispielpartie + Up
    {{ content | safe }} diff --git a/crs/crs.js b/crs/crs.js index 364309d..df9ab01 100644 --- a/crs/crs.js +++ b/crs/crs.js @@ -164,14 +164,11 @@ module.exports = function (eleventyConfig) { // 1. Root-relative (starts with '/'): resolved against project root (Eleventy's input dir) // 2. Relative: resolved against the directory of the calling template file // Returns { fsPath, publicPath, relPath } or { error } - // publicPath is prefixed with optional deployment path prefix (env ELEVENTY_PATH_PREFIX) and always begins with '/'. + // publicPath is a root-relative path beginning with '/' suitable for use in generated HTML. function resolveUserPath(spec, ctx) { if (!spec || typeof spec !== 'string') return { error: 'missing path' }; // Normalize Windows backslashes just in case - spec = spec.replace(/\\/g, '/'); - let pathPrefix = process.env.ELEVENTY_PATH_PREFIX || ''; - if (pathPrefix && pathPrefix !== '/' && pathPrefix.endsWith('/')) pathPrefix = pathPrefix.slice(0, -1); - if (pathPrefix === '/') pathPrefix = ''; + spec = spec.replace(/\\/g, '/').trim(); const projectRoot = process.cwd(); // Base directory derived from the template invoking the shortcode let baseDir = projectRoot; @@ -181,6 +178,7 @@ module.exports = function (eleventyConfig) { baseDir = path.dirname(tplPath); } } catch (_) { /* ignore */ } + const isRootRel = spec.startsWith('/'); const cleaned = isRootRel ? spec.replace(/^\/+/, '') : spec; const candidateFs = path.resolve(isRootRel ? projectRoot : baseDir, cleaned); @@ -190,11 +188,14 @@ module.exports = function (eleventyConfig) { return { error: 'path escapes project root' }; } const relPath = path.relative(projectRoot, candidateFs).split(path.sep).join('/'); - const publicPath = isRootRel ? (pathPrefix ? pathPrefix : '') + '/' + relPath : spec; + // publicPath: always root-relative and start with '/' + const publicPath = spec; // '/' + relPath; + + console.log(`rup ${spec} `, ctx?.page?.inputPath, candidateFs, publicPath, relPath); + console.log({ fsPath: candidateFs, publicPath, relPath }); return { fsPath: candidateFs, publicPath, relPath }; } - // Validation helper (stateless) function validateCrid(id) { if (typeof id !== 'string') return { ok: false, message: 'crid must be a string' }; @@ -524,7 +525,6 @@ module.exports = function (eleventyConfig) { } } - // ================= Shortcode function implementations ================= function crmapShortcode(file, optionsJson) { @@ -644,7 +644,7 @@ module.exports = function (eleventyConfig) { `
    ` + `
    `; } catch (e) { - debug(`Error processing file: ${filePath} `, e); + debug(`Error processing file: ${file} `, e); return `
    Error: ${escapeHtml(e.message)}
    `; } } diff --git a/goblins/index.njk b/goblins/index.njk index 0549004..14ddd9a 100644 --- a/goblins/index.njk +++ b/goblins/index.njk @@ -14,14 +14,14 @@ pagination:

    - {{ post.data.title }} + {{ post.data.title }}

    {% excerpt post %} - Read more + Read more
    {% endfor %} diff --git a/index.njk b/index.njk index 596be84..57fc179 100644 --- a/index.njk +++ b/index.njk @@ -18,7 +18,7 @@ Bericht hier zur Verfügung stellen.

    {% for post in races %} diff --git a/template/index.njk b/template/index.njk index 65a00ba..363cff0 100644 --- a/template/index.njk +++ b/template/index.njk @@ -16,14 +16,14 @@ Goblins sind die besten, yada, yada, yada ...

    - {{ post.data.title }} + {{ post.data.title }}

    {% excerpt post %} - Read more + Read more
    {% endfor %} From beb368f0623a9d50ce83f042c6d6ffe3ae4fbe93 Mon Sep 17 00:00:00 2001 From: Steffen Mecke Date: Thu, 21 Aug 2025 23:35:45 +0200 Subject: [PATCH 30/34] fallback to site.locale in dateReadable --- .eleventy.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.eleventy.js b/.eleventy.js index a97680f..74339b3 100644 --- a/.eleventy.js +++ b/.eleventy.js @@ -38,12 +38,14 @@ module.exports = async function (eleventyConfig) { }); // dateReadable: server-side formatted date using the provided locale (e.g. page.locale) - // Usage: {{ page.date | dateReadable(page.locale) }} — falls back to 'de' + // Usage: {{ page.date | dateReadable(page.locale) }} — falls back to site locale or 'en' eleventyConfig.addFilter('dateReadable', (date, locale) => { if (!date) return ''; let dt = date instanceof Date ? DateTime.fromJSDate(date) : DateTime.fromISO(String(date)); if (!dt.isValid) dt = DateTime.fromJSDate(new Date(String(date))); - const useLocale = locale || 'en'; + + const site = require('./_data/site.json'); + const useLocale = locale || site.locale || 'en'; return dt.setLocale(useLocale).toLocaleString(DateTime.DATE_FULL); }); From 36507074ea1f3c0269e653a693954f158f8cf778 Mon Sep 17 00:00:00 2001 From: Steffen Mecke Date: Thu, 21 Aug 2025 23:50:36 +0200 Subject: [PATCH 31/34] created overview-layout for race landing pages --- _includes/overview-layout.njk | 21 +++++++++++++++++++++ aquarians/index.njk | 20 ++------------------ goblins/index.njk | 18 +----------------- template/index.njk | 19 +------------------ 4 files changed, 25 insertions(+), 53 deletions(-) create mode 100644 _includes/overview-layout.njk diff --git a/_includes/overview-layout.njk b/_includes/overview-layout.njk new file mode 100644 index 0000000..1497016 --- /dev/null +++ b/_includes/overview-layout.njk @@ -0,0 +1,21 @@ +--- +layout: base-layout.njk +--- +{{ content | safe }} + +{% for post in posts %} +
    + +

    + {{ post.data.title }} +

    + + + + {% excerpt post %} + + Read more + +
    +{% endfor %} + diff --git a/aquarians/index.njk b/aquarians/index.njk index 094026d..fcb697c 100644 --- a/aquarians/index.njk +++ b/aquarians/index.njk @@ -1,5 +1,5 @@ --- -layout: base-layout.njk +layout: overview-layout.njk title: Meermenschen override:tags: ["race"] pagination: @@ -9,20 +9,4 @@ pagination: alias: posts --- -

    Home of the Aquarian Tutorial!

    - -{% for post in posts %} -
    - -

    - {{ post.data.title }} -

    - - - - {% excerpt post %} - - Read more - -
    -{% endfor %} +

    Home of the Aquarian Tutorial!

    \ No newline at end of file diff --git a/goblins/index.njk b/goblins/index.njk index 14ddd9a..c349987 100644 --- a/goblins/index.njk +++ b/goblins/index.njk @@ -1,5 +1,5 @@ --- -layout: base-layout.njk +layout: overview-layout.njk title: Goblins override:tags: ["race"] pagination: @@ -9,19 +9,3 @@ pagination: alias: posts ---

    Das Goblin-Tutorial

    - -{% for post in posts %} -
    - -

    - {{ post.data.title }} -

    - - - - {% excerpt post %} - - Read more - -
    -{% endfor %} diff --git a/template/index.njk b/template/index.njk index 363cff0..0c747bf 100644 --- a/template/index.njk +++ b/template/index.njk @@ -1,5 +1,5 @@ --- -layout: base-layout.njk +layout: overview-layout.njk title: Not Goblins! override:tags: ["race"] pagination: @@ -11,20 +11,3 @@ pagination:

    Das ist nicht das Goblin-Tutorial!

    Goblins sind die besten, yada, yada, yada ... - -{% for post in posts %} -
    - -

    - {{ post.data.title }} -

    - - - - {% excerpt post %} - - Read more - -
    -{% endfor %} - From dd3b0f3a5c6334d7d066ffaa4b55b17e32e59851 Mon Sep 17 00:00:00 2001 From: Steffen Mecke Date: Thu, 21 Aug 2025 23:51:24 +0200 Subject: [PATCH 32/34] bumped version and updated README --- README.md | 24 ++++++++++++++---------- crs/crs.js | 2 +- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 6e05333..c38e670 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ These are the diaries for the 2024 Eressea Tutorial. ``` --- -layout: base-layout.njk +layout: overview-layout.njk title: Not Goblins! override:tags: ["race"] pagination: @@ -29,7 +29,6 @@ pagination: reverse: false alias: posts --- -{% for post in posts %} ... ``` @@ -37,7 +36,7 @@ Change the title as you wish and 'nogoblin' to 'dragonborns'. - If you want to create just one big file, replace everything below the second '---' with your content. This is not recommended if you want to add a lot of text. The content is [Markdown](https://www.markdownguide.org/), a text file format that let's you add basic formatting like headings, links, images. You could also use html directly. Then you would create an index.html file instead. HTML is less recommended. -- If you have more to say, you should split your diary into multiple files. In that case, leave everything below the '---' as it is, at least for now. Also copy 'Auswertung_XX.md' from the template directory into your subdirectory. You may rename them as you wish, for example to week_01.md, week_02.md, ... and so forth. +- If you have more to say, you should split your diary into multiple files. In that case, just add a short intro below the '---'. Also copy 'Auswertung_XX.md' from the template directory into your subdirectory. You may rename them as you wish, for example to week_01.md, week_02.md, ... and so forth. - Also copy the file template.json to your directory and rename it to dragonborns.json. ``` @@ -58,10 +57,9 @@ Change the title as you wish and 'nogoblin' to 'dragonborns'. title: "Dragonborn: Round 1" date: 2024-03-17 --- -# Round 1 - Lore ipsum ... -## Heading 1 - +## Was passiert ist +... +## Unser Plan ... ``` @@ -75,16 +73,22 @@ This file consists of the 'front matter' between the lines starting with '---'. ### Including links to files -If you want to link to, for example, a report file, create a subdirectory `/reports/dragonborns` and copy them there. Now they get copied to the site and you can link to them as `[my first report](/reports/dragonborns/1-drag.cr)`. +If you use images, .cr, .nr, or .txt files in your text they should be automatically handled. + +If this does not work, it may help to instead create a subdirectory `/reports/dragonborns` (at the project root, not inside your dragonborns directory) and copy them there. Now they get copied to the site and you can link to them as `[my first report](/reports/dragonborns/1-drag.cr)`. ### Including cr maps -With the 'shortcode' crmap you can include a cr directly into your file like so: +With the 'shortcode' crmap, readnr, showorders etc. you can include a cr directly into your file like so: {% crmap './reports/dragonborns/123-drag.cr' %} -See template/Auswertung_01.md for more details and examples. + {% orderfile '/reports/template/befehle-42.txt' %} + + {% readnr '/reports/template/334-42.nr' %} + {% shownr 'intro' %} +See template/Auswertung_01.md for more details and examples. ### Seeing your content diff --git a/crs/crs.js b/crs/crs.js index df9ab01..16aead7 100644 --- a/crs/crs.js +++ b/crs/crs.js @@ -4,7 +4,7 @@ const path = require('path'); const { start } = require('repl'); // Library version (update when changing public shortcode behavior) -const CRS_VERSION = '0.2.0'; +const CRS_VERSION = '0.2.1'; // Export version for external use (e.g., in layouts via require) and add as global data below module.exports.CRS_VERSION = CRS_VERSION; From bc1499daf8ab0edf000681559678e45961a791a3 Mon Sep 17 00:00:00 2001 From: Steffen Mecke Date: Fri, 22 Aug 2025 12:33:55 +0200 Subject: [PATCH 33/34] transform links to relative paths (works with files and path prefixes) --- .eleventy.js | 73 +++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 70 insertions(+), 3 deletions(-) diff --git a/.eleventy.js b/.eleventy.js index 74339b3..499a608 100644 --- a/.eleventy.js +++ b/.eleventy.js @@ -21,10 +21,13 @@ module.exports = async function (eleventyConfig) { }); // This replaces the {{ xyz | url }} filter by applying pathPrefix properly - let { HtmlBasePlugin } = await import("@11ty/eleventy"); - HtmlBasePlugin = HtmlBasePlugin.default || HtmlBasePlugin; - eleventyConfig.addPlugin(HtmlBasePlugin); + // let { HtmlBasePlugin } = await import("@11ty/eleventy"); + // HtmlBasePlugin = HtmlBasePlugin.default || HtmlBasePlugin; + // eleventyConfig.addPlugin(HtmlBasePlugin); + // This currently works best + // It replaces all links with links relative to the current file + eleventyConfig.addPlugin(relativeLinks); eleventyConfig.addFilter('dateIso', date => { if (!date) return ''; @@ -95,3 +98,67 @@ function extractExcerpt(article) { return excerpt; } + + +/** Referring to HtmlBasePlugin.js + * + * This plugin tries to make all URLs in the HTML output relative to the page. + * + * Useful for: + * * browsing via file:// + * * gh-pages in subdirectory repo + * * unsure where in the directory structure the site will be hosted + * + * We're expecting the internal links to start with "/" + * + * todo? + * * option to include "index.html" for those directory links, for extra file:// compat + * + */ + +// import path from "path"; +const path = require("path"); + +function relativeLinks(eleventyConfig) { + // Apply to all HTML output in your project + eleventyConfig.htmlTransformer.addUrlTransform( + "html", + function makeUrlRelative(urlInMarkup) { + // Skip empty URLs, non-root-relative URLs, and dev server image transform URLs + if ( + !urlInMarkup + || !urlInMarkup.startsWith("/") + || urlInMarkup.startsWith("/.11ty/") + || urlInMarkup.startsWith("//") + ) { + if (urlInMarkup.endsWith("/") && urlInMarkup.startsWith("/")) { + return urlInMarkup + 'index.html'; + } + if (urlInMarkup === "..") return "../index.html"; + return urlInMarkup; + } + + // Get base directory path (keep trailing slash for index pages) + const fromDir = this.url.endsWith("/") ? this.url : path.dirname(this.url); + + let relativePath = path.relative(fromDir, urlInMarkup); + + // Add ./ for same-directory references + if (!relativePath.startsWith(".")) { + relativePath = "./" + relativePath; + } + + // Preserve trailing slash from original URL + if (urlInMarkup.endsWith("/") && !relativePath.endsWith("/")) { + relativePath += "/"; + } + if (relativePath.endsWith("/")) + return relativePath + "index.html"; + + return relativePath; + }, + { + priority: -1, // run last last (after PathToUrl) + }, + ); +} \ No newline at end of file From 56624c9229bb7a18ce45e1e25d927c938e5cc23c Mon Sep 17 00:00:00 2001 From: Steffen Mecke Date: Fri, 22 Aug 2025 14:00:07 +0200 Subject: [PATCH 34/34] unified warnings --- crs/crs.js | 122 +++++++++++++++++++++++++++++++++++------------------ 1 file changed, 81 insertions(+), 41 deletions(-) diff --git a/crs/crs.js b/crs/crs.js index 16aead7..34f4a85 100644 --- a/crs/crs.js +++ b/crs/crs.js @@ -4,7 +4,7 @@ const path = require('path'); const { start } = require('repl'); // Library version (update when changing public shortcode behavior) -const CRS_VERSION = '0.2.1'; +const CRS_VERSION = '0.2.2'; // Export version for external use (e.g., in layouts via require) and add as global data below module.exports.CRS_VERSION = CRS_VERSION; @@ -150,6 +150,13 @@ module.exports = function (eleventyConfig) { const DEBUG = process.env.CRS_DEBUG === '1'; function debug(...args) { if (DEBUG) console.log('[crs]', ...args); } + // warn(msg[, html_msg]) -> logs a console warning and returns an error HTML string. + function warn(msg, html_msg) { + try { console.warn('[crs]', msg); } catch (e) { /* ignore */ } + html_msg = html_msg || String(msg); + return `
    ${escapeHtml(String(html_msg))}
    `; + } + function escapeHtml(str) { return String(str) .replace(/&/g, '&') @@ -191,8 +198,6 @@ module.exports = function (eleventyConfig) { // publicPath: always root-relative and start with '/' const publicPath = spec; // '/' + relPath; - console.log(`rup ${spec} `, ctx?.page?.inputPath, candidateFs, publicPath, relPath); - console.log({ fsPath: candidateFs, publicPath, relPath }); return { fsPath: candidateFs, publicPath, relPath }; } @@ -573,10 +578,10 @@ module.exports = function (eleventyConfig) { } } } catch (e) { - return `
    Invalid JSON options: ${escapeHtml(e.message)}
    `; + return warn(`crmap: invalid JSON options: ${e.message}`); } } else { - return `
    Options must be a JSON string
    `; + return warn('crmap: options must be a JSON string'); } if (requestedCrid === '') requestedCrid = undefined; // force auto @@ -585,13 +590,11 @@ module.exports = function (eleventyConfig) { crid = requestedCrid.toString(); const valid = validateCrid(crid); if (!valid.ok) { - console.warn(valid.message); - return `
    ${valid.message}
    `; + return warn('crmap: ' + valid.message); } if (pageState.crids.has(crid)) { - const msg = `Duplicate crid '${crid}' already used on this page.`; - console.warn(msg); - return `
    ${msg}
    `; + const msg = `crmap: Duplicate crid '${crid}' already used on this page.`; + return warn(msg); } debug(`Processing CR file with provided crid=${crid}: ${file}`); } else { @@ -603,11 +606,10 @@ module.exports = function (eleventyConfig) { pageState.lastCrid = crid; const resolved = resolveUserPath(file, this); if (resolved.error) { - return `
    Path error: ${escapeHtml(resolved.error)} (${escapeHtml(file)})
    `; + return warn(`crmap: path error: ${resolved.error} ${file}`); } if (!fs.existsSync(resolved.fsPath)) { - debug(`File not found: ${resolved.fsPath}`); - return `
    File not found: ${escapeHtml(file)}
    `; + return warn(`crmap: file not found: ${file} -> ${resolved.fsPath}`, `crmap: file not found: ${file}`); } const reportName = path.basename(resolved.fsPath, path.extname(resolved.fsPath)); const report = Report.parse(resolved.fsPath, crid, reportName, detailsOption, zOption); @@ -644,8 +646,7 @@ module.exports = function (eleventyConfig) { `
    ` + `
    `; } catch (e) { - debug(`Error processing file: ${file} `, e); - return `
    Error: ${escapeHtml(e.message)}
    `; + return warn(`crmap: error processing file: ${file} ${e && e.message ? e.message : ''}`); } } @@ -654,11 +655,15 @@ module.exports = function (eleventyConfig) { let pageState = this && this.ctx ? this.ctx._crmapState : null; let useCrid = crid; if (!useCrid && pageState) useCrid = pageState.lastCrid; - if (!useCrid) return '
    crmap_rdetails: missing crid (no crmap rendered yet)
    '; + if (!useCrid) { + return warn('crmap_rdetails: missing crid (no crmap rendered yet)'); + } const v = validateCrid(useCrid.toString()); - if (!v.ok) return `
    ${v.message}
    `; + if (!v.ok) { + return warn(`crmap_rdetails: ${v.message}`); + } if (!pageState || !pageState.crids.has(useCrid.toString())) { - return `
    Unknown crid '${useCrid}' (render map first)
    `; + return warn(`crmap_rdetails: unknown crid '${useCrid}' (render map first)`); } if (placeholder === null || placeholder === true) { placeholder = 'Select a region for details.'; @@ -672,11 +677,15 @@ module.exports = function (eleventyConfig) { let pageState = this && this.ctx ? this.ctx._crmapState : null; let useCrid = crid; if (!useCrid && pageState) useCrid = pageState.lastCrid; - if (!useCrid) return '
    crmap_udetails: missing crid (no crmap rendered yet)
    '; + if (!useCrid) { + return warn('crmap_udetails: missing crid (no crmap rendered yet)'); + } const v = validateCrid(useCrid.toString()); - if (!v.ok) return `
    ${v.message}
    `; + if (!v.ok) { + return warn(`crmap_udetails: ${v.message}`); + } if (!pageState || !pageState.crids.has(useCrid.toString())) { - return `
    Unknown crid '${useCrid}' (render map first)
    `; + return warn(`crmap_udetails: unknown crid '${useCrid}' (render map first)`); } if (placeholder === null || placeholder === true) { placeholder = 'Select a unit.'; @@ -690,11 +699,15 @@ module.exports = function (eleventyConfig) { let pageState = this && this.ctx ? this.ctx._crmapState : null; let useCrid = crid; if (!useCrid && pageState) useCrid = pageState.lastCrid; - if (!useCrid) return '
    crmap_commands: missing crid (no crmap rendered yet)
    '; + if (!useCrid) { + return warn('crmap_commands: missing crid (no crmap rendered yet)'); + } const v = validateCrid(useCrid.toString()); - if (!v.ok) return `
    ${v.message}
    `; + if (!v.ok) { + return warn(`crmap_commands: ${v.message}`); + } if (!pageState || !pageState.crids.has(useCrid.toString())) { - return `
    Unknown crid '${useCrid}' (render map first)
    `; + return warn(`crmap_commands: unknown crid '${useCrid}' (render map first)`); } if (placeholder === null || placeholder === true) { placeholder = 'Select a unit for commands.'; @@ -706,7 +719,7 @@ module.exports = function (eleventyConfig) { function renderOrderFile(fileName, optionsJson) { if (!fileName || typeof fileName !== 'string') { - return '
    orderfile: missing file name
    '; + return warn('orderfile: missing file name'); } // parse options const opts = { markdownInComments: true, fileLink: true, commentsAsOrders: false, renderSpecial: false }; @@ -720,16 +733,16 @@ module.exports = function (eleventyConfig) { if (Object.prototype.hasOwnProperty.call(parsed, 'renderSpecial')) opts.renderSpecial = !!parsed.renderSpecial; } } catch (e) { - return `
    orderfile: invalid options JSON: ${escapeHtml(e.message)}
    `; + return warn(`orderfile: invalid options JSON: ${e.message}`); } } const resolved = resolveUserPath(fileName, this); if (resolved.error) { - return `
    orderfile: path error: ${escapeHtml(resolved.error)} (${escapeHtml(fileName)})
    `; + return warn(`orderfile : path error: ${resolved.error} ${fileName}`); } if (!fs.existsSync(resolved.fsPath)) { - return `
    orderfile: file not found: ${escapeHtml(fileName)}
    `; + return warn(`orderfile: file not found: ${fileName} -> ${resolved.fsPath}`, `orderfile: file not found: ${fileName}`); } const content = fs.readFileSync(resolved.fsPath, 'utf8'); const rawLines = content.split(/\r?\n/); @@ -918,7 +931,9 @@ module.exports = function (eleventyConfig) { const path = require('path'); let opts = {}; if (typeof optionsJson === 'string' && optionsJson.trim() !== '') { - try { opts = JSON.parse(optionsJson); } catch (e) { return `
    readnr: invalid options JSON: ${escapeHtml(e.message)}
    `; } + try { opts = JSON.parse(optionsJson); } catch (e) { + return warn(`readnr: invalid options JSON: ${e.message}`); + } } const requestedNrid = opts && typeof opts.nrid === 'string' && opts.nrid !== '' ? opts.nrid : undefined; const pageState = _getPageNrState(this); @@ -926,15 +941,23 @@ module.exports = function (eleventyConfig) { let nrid; if (requestedNrid) { const v = validateCrid(requestedNrid); - if (!v.ok) return `
    ${escapeHtml(v.message)}
    `; - if (pageState.nrids.has(requestedNrid)) return `
    readnr: duplicate nrid '${escapeHtml(requestedNrid)}' on this page
    `; + if (!v.ok) { + return warn(`readnr: ${v.message}`); + } + if (pageState.nrids.has(requestedNrid)) { + return warn(`readnr: duplicate id '${requestedNrid}' on this page`); + } nrid = requestedNrid; } else { nrid = (++pageState.counter).toString(); } const resolved = resolveUserPath(file, this); - if (resolved.error) return `
    readnr: path error: ${escapeHtml(resolved.error)} (${escapeHtml(file)})
    `; - if (!fs.existsSync(resolved.fsPath)) return `
    readnr: file not found: ${escapeHtml(file)}
    `; + if (resolved.error) { + return warn(`readnr: path error: ${resolved.error} ${file}`); + } + if (!fs.existsSync(resolved.fsPath)) { + return warn(`readnr: File not found: ${resolved.fsPath}`); + } const content = fs.readFileSync(resolved.fsPath, 'utf8'); const rawLines = content.split(/\r?\n/); const bookmarks = {}; @@ -1175,19 +1198,24 @@ module.exports = function (eleventyConfig) { } if (typeof arg2 === 'undefined') { if (typeof arg1 === 'string' && arg1.trim().startsWith('{')) { - try { opts = JSON.parse(arg1); } catch (e) { return `
    shownr: invalid JSON: ${escapeHtml(e.message)}
    `; } + try { opts = JSON.parse(arg1); } catch (e) { + return warn(`shownr: invalid options JSON: ${e.message}`); + } } else if (typeof arg1 === 'string' && parseRangeString(arg1)) { opts.range = parseRangeString(arg1); } else if (typeof arg1 === 'string') { opts.bookmark = arg1; } else { + warn(`shownr: Invalid arguments: ${arg1}, ${arg2}`); return `
    shownr: invalid arguments
    `; } } else { if (typeof arg1 === 'string' && validateCrid(arg1).ok) { opts.nrid = arg1; if (typeof arg2 === 'string' && arg2.trim().startsWith('{')) { - try { Object.assign(opts, JSON.parse(arg2)); } catch (e) { return `
    shownr: invalid JSON: ${escapeHtml(e.message)}
    `; } + try { Object.assign(opts, JSON.parse(arg2)); } catch (e) { + warn(`shownr: invalid options JSON: ${e.message}`); + } } else if (parseRangeString(arg2)) { opts.range = parseRangeString(arg2); } else { opts.bookmark = arg2; } @@ -1196,7 +1224,9 @@ module.exports = function (eleventyConfig) { if (parseRangeString(arg1)) opts.range = parseRangeString(arg1); else opts.bookmark = arg1; } else { if (typeof arg2 === 'string' && arg2.trim().startsWith('{')) { - try { Object.assign(opts, JSON.parse(arg2)); } catch (e) { return `
    shownr: invalid JSON: ${escapeHtml(e.message)}
    `; } + try { Object.assign(opts, JSON.parse(arg2)); } catch (e) { + warn(`shownr: invalid options JSON: ${e.message}`); + } if (!opts.nrid && typeof arg1 === 'string') { if (parseRangeString(arg1)) opts.range = parseRangeString(arg1); else opts.bookmark = arg1; } } else { if (typeof arg1 === 'string' && validateCrid(arg1).ok) opts.nrid = arg1; else opts.bookmark = arg1; @@ -1216,8 +1246,12 @@ module.exports = function (eleventyConfig) { let nrid = opts.nrid; if (!nrid) nrid = pageState.lastNrid; - if (!nrid) return `
    shownr: no nrid specified and no previous readnr on this page
    `; - if (!pageState.nrFiles || !pageState.nrFiles[nrid]) return `
    shownr: unknown nrid '${escapeHtml(nrid)}' (did you call readnr first?)
    `; + if (!nrid) { + return warn(`shownr: no nrid specified and no previous readnr on this page`); + } + if (!pageState.nrFiles || !pageState.nrFiles[nrid]) { + return warn(`shownr: unknown nrid '${escapeHtml(nrid)}' (did you call readnr first?)`); + } let lineNumbers = opts.lineNumbers || false; @@ -1227,7 +1261,9 @@ module.exports = function (eleventyConfig) { if (opts.bookmark) { if (opts.bookmark === 'list') { const bookmarks = Object.keys(fileInfo.bookmarks || {}); - if (bookmarks.length === 0) return `
    shownr: no bookmarks available for nrid '${escapeHtml(nrid)}'
    `; + if (bookmarks.length === 0) { + return warn(`shownr: no bookmarks available for nrid '${nrid}'`, `
    shownr: no bookmarks available for nrid '${escapeHtml(nrid)}'
    `); + } const listItems = bookmarks.map(bm => { const b = fileInfo.bookmarks[bm]; @@ -1236,11 +1272,15 @@ module.exports = function (eleventyConfig) { return `
      ${listItems}
    `; } const bm = fileInfo.bookmarks && fileInfo.bookmarks[opts.bookmark]; - if (!bm) return `
    shownr: unknown bookmark '${escapeHtml(opts.bookmark)}' for nrid '${escapeHtml(nrid)}'
    `; + if (!bm) { + return warn(`shownr: unknown bookmark '${opts.bookmark}' for nrid '${nrid}'`); + } start = bm.start; end = bm.end; } else if (opts.range) { start = Math.max(1, opts.range.start); end = Math.min(totalLines, opts.range.end); - if (start > end) return `
    shownr: invalid range ${start}-${end}
    `; + if (start > end) { + return warn(`shownr: invalid range ${start}-${end} for nrid '${nrid}'`); + } } const slice = fileInfo.lines.slice(start - 1, end); const inner = slice.map((ln, idx) => {