Files
brevyscribe/src/transforms/__fixtures__/datasmith.convert.ros
T
luxick 62d6bd211b
CI / check (push) Has been cancelled
Fork FancyScribe as BrevyScribe with the datasheet transforms built in
Print generic datasheets - every option a unit could take, the way the
official cards read - instead of a record of one particular list.

The three Python scripts that used to rewrite the .ros file before upload
are now transforms in src/transforms/, running in the browser between
DOMParser and the roster parser. Most of each script was machinery for
preserving the file byte for byte on the way back to disk; in the browser
the document is never serialised, so only the domain logic came across.

Because they run on the parsed document rather than the uploaded file,
flipping a transform off rebuilds from the original XML with no
re-upload. Saved rosters therefore hold the raw roster XML rather than
the parsed object, under new localStorage keys.

The scripts' output over four 11th-edition rosters is checked in as test
fixtures, so the port is measured against an independent implementation
that was verified by printing the cards; scripts/update-fixtures.mjs
refuses to overwrite those without --force.

Two parser call sites now use :scope> rather than repeating the scope
element's own name, which means the same thing in a browser and also
works under jsdom, where the old form matched nothing.

Also: served at the root rather than a GitHub Pages subpath, PostHog
analytics removed, and deploy/ carries an nginx site for
scribe.luxick.de plus an rsync deploy script.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-25 15:11:10 +02:00

40 lines
13 KiB
XML
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<roster id="7rmu2zl" name="TEST" battleScribeVersion="2.03" generatedBy="https://newrecruit.eu" gameSystemId="sys-352e-adc2-7639-d610" gameSystemName="Warhammer 40,000 11th Edition" gameSystemRevision="6" xmlns="http://www.battlescribe.net/schema/rosterSchema"><costs><cost name="pts" typeId="51b2-306e-1021-d207" value="25" /></costs><forces><force id="7wfvr6o" name="Army Roster" entryId="bb9d-299a-ed60-2d8a" catalogueId="77b9-2f66-3f9b-5cf3" catalogueRevision="5" catalogueName="Imperium - Adeptus Mechanicus"><selections><selection id="bky5c11" name="Battle Size" entryId="7380-3e40-6ed6-b7cc::564e-fbc6-5266-3ea4" number="1" type="upgrade" from="entry"><categories><category id="4ac9-fd30-1e3d-b249" entryId="4ac9-fd30-1e3d-b249" name="Configuration" primary="true" /></categories></selection><selection id="bg2lcx" name="Detachment" entryId="2874-c86-3152-393::c82f-1b42-946-9c9a" number="1" type="upgrade" from="entry"><categories><category id="4ac9-fd30-1e3d-b249" entryId="4ac9-fd30-1e3d-b249" name="Configuration" primary="true" /></categories></selection><selection id="bdcmhqi" name="Force Disposition" entryId="8bc8-6bfe-78bd-2480::2f69-9148-45b4-86a8" number="1" type="upgrade" from="entry"><categories><category id="4ac9-fd30-1e3d-b249" entryId="4ac9-fd30-1e3d-b249" name="Configuration" primary="true" /></categories></selection><selection id="bnoi9vo" name="Show/Hide Options" entryId="3458-3cff-ef5f-a7c5::e8ef-836a-a9d1-901d" number="1" type="upgrade" from="entry"><categories><category id="4ac9-fd30-1e3d-b249" entryId="4ac9-fd30-1e3d-b249" name="Configuration" primary="true" /></categories></selection><selection id="i4n9e8" name="Cybernetica Datasmith" entryId="ec2e-941e-4c80-ab09::d59d-ef1-9ef8-4f44" number="1" type="model" from="entry"><rules><rule id="3342-2180-9c5d-925f" name="Support" hidden="false"><description/></rule><rule id="7a21-a958-e47d-5c0d" name="Doctrina Imperatives" hidden="false"><description>At the start of the battle round, you can select one of the Doctrina Imperatives below. Until the end of the battle round, that Doctrina Imperative is active for your army, and all units from your army that have the Doctrina Imperatives ability gain the relevant abilities shown below.
PROTECTOR IMPERATIVE
■ Ranged weapons equipped by models in this unit have the [HEAVY] ability.
■ Improve the Ballistic Skill characteristic of ranged weapons equipped by models in this unit by 1.
■ Each time a melee attack targets this unit, if this unit has the ^^**Battleline**^^ keyword and/or it is within 6&quot; of one or more friendly **^^Adeptus Mechanicus Battleline**^^ units, subtract 1 from the Hit roll.
CONQUEROR IMPERATIVE
■ Ranged weapons equipped by models in this unit have the [ASSAULT] ability.
■ Improve the Weapon Skill characteristic of melee weapons equipped by models in this unit by 1.
■ Each time a model in this unit makes an attack, if this unit has the **^^Battleline**^^ keyword and/or it is within 6&quot; of one or more friendly **^^Adeptus Mechanicus Battleline**^^ units, improve the Armour Penetration characteristic of that attack by 1.</description></rule></rules><profiles><profile id="0835-db3f-3b41-ae6a" name="Cybernetica Datasmith" hidden="false" typeId="c547-1836-d8a-ff4f" typeName="Unit" from="entry"><characteristics><characteristic name="M" typeId="e703-ecb6-5ce7-aec1">6&quot;</characteristic><characteristic name="T" typeId="d29d-cf75-fc2d-34a4">4</characteristic><characteristic name="Sv" typeId="450-a17e-9d5e-29da">2+</characteristic><characteristic name="W" typeId="750a-a2ec-90d3-21fe">3</characteristic><characteristic name="LD" typeId="58d2-b879-49c7-43bc">7+</characteristic><characteristic name="OC" typeId="bef7-942a-1a23-59f8">1</characteristic><characteristic name="InSv" typeId="55a7-5b54-c60d-11dc">5+</characteristic></characteristics></profile><profile id="dba5-946a-cd1c-0845" name="Support" hidden="false" typeId="9cc3-6d83-4dd3-9b64" typeName="Abilities" from="entry"><characteristics><characteristic name="Description" typeId="9b8f-694b-e5e-b573">This model must be attached to the following unit:
■ ^^**Kastelan Robots^^**
You must attach this model to a Kastelan Robots unit, even if one or more other Cybernetica Datasmith models havealready been attached to it. In such cases, if that bodyguard unit is destroyed, the Leader units attached to it become separate units with their original Starting Strengths. If you cannot attach this model to a Kastelan Robots unit, this model cannot be deployed and counts as having been destroyed during the first battle round. While attached to a Kastelan Robots unit, this model loses the INFANTRY keyword.</characteristic></characteristics></profile><profile id="4016-04e6-9751-89e3" name="Battle Protocols" hidden="false" typeId="9cc3-6d83-4dd3-9b64" typeName="Abilities" from="entry">
<characteristics>
<characteristic name="Description" typeId="9b8f-694b-e5e-b573">At the start of the battle, if this model is leading a ^^**Kastelan Robots^^** unit, that unit enters Aegis Protocols (see below). In your Command phase, if this model is leading a ^^**Kastelan Robots^^** unit, you can select one protocol from those listed below for that unit to enter. Once a unit enters a protocol, it remains in that protocol until it enters a different one</characteristic>
</characteristics>
</profile>
<profile id="5c44-188c-da1d-9bf6" name="Protector Protocol" hidden="false" typeId="ea1d-b442-57b2-e30b" typeName="BATTLE PROTOCOLS" from="entry">
<characteristics>
<characteristic name="Description" typeId="f3e2-93f7-f14e-2720">Add 2 to the Attacks characteristic of ranged weapons equipped by KASTELAN ROBOT models in that unit.</characteristic>
</characteristics>
</profile>
<profile id="855a-a426-7d6c-fe57" name="Conqueror Protocol" hidden="false" typeId="ea1d-b442-57b2-e30b" typeName="BATTLE PROTOCOLS" from="entry">
<characteristics>
<characteristic name="Description" typeId="f3e2-93f7-f14e-2720">Add 2 to the Attacks characteristic of melee weapons equipped by KASTELAN ROBOT models in that unit.</characteristic>
</characteristics>
</profile>
<profile id="aa93-8e86-9c7f-18a1" name="Aegis Protocol" hidden="false" typeId="ea1d-b442-57b2-e30b" typeName="BATTLE PROTOCOLS" from="entry">
<characteristics>
<characteristic name="Description" typeId="f3e2-93f7-f14e-2720">Add 1 to the Toughness characteristic of KASTELAN ROBOT models in that unit.</characteristic>
</characteristics>
</profile></profiles><selections><selection id="i5m9goo" name="Mechanicus pistol" entryId="ec2e-941e-4c80-ab09::44cd-1441-b29d-85d0::2b1f-798d-9bca-4ad9" entryGroupId="ec2e-941e-4c80-ab09::f1f5-f62e-e47d-9dad" number="1" type="upgrade" from="group" group="Wargear"><rules><rule id="be1e-ac8e-1e2c-3528" name="Devastating Wounds" hidden="false" page="28"><description>Each time an attack made with a **[DEVASTATING WOUNDS]** weapon results in a **critical wound**, the attack sequence for that attack ends and the target unit suffers a number of **mortal wounds** equal to the **D** characteristic of that weapon. These are inflicted after resolving any normal damage inflicted by those attacks. 
**Mortal wounds** inflicted by **[DEVASTATING WOUNDS]** weapons can damage a maximum of one model for each **critical wound**; any remaining **mortal wounds** inflicted by that attack are lost. 
**Example: An attack made with a **[DEVASTATING WOUNDS]** weapon with a **D** characteristic of 3 results in a **critical wound** against an Intercessor Squad, so inflicts 3 **mortal wounds**. The first 2 **mortal wounds** are sufficient to **destroy** 1 Intercessor model, so the remaining **mortal wound** is lost.*</description></rule><rule id="8bf7-8812-923d-29e4" name="Pistol" hidden="false" page="25"><description>**[PISTOL]** and **[CLOSE-QUARTERS]** are identical for all rules purposes. 
Units containing one or more models with a **[CLOSE-QUARTERS]** weapon can shoot using **close-quarters shooting** (10.06). When using another **shooting type**, for each model in that unit (excluding **MONSTER/VEHICLE** models), you can only select one of the following to make attacks with: 
- One or more of its **[CLOSE-QUARTERS]** weapons. 
- One or more of its other ranged weapons.</description></rule></rules><profiles><profile id="43ca-9255-d4f5-3962" name="Mechanicus pistol" hidden="false" typeId="f77d-b953-8fa4-b762" typeName="Ranged Weapons" from="entry"><characteristics><characteristic name="Range" typeId="9896-9419-16a1-92fc">12&quot;</characteristic><characteristic name="A" typeId="3bb-c35f-f54-fb08">1</characteristic><characteristic name="BS" typeId="94d-8a98-cf90-183e">3+</characteristic><characteristic name="S" typeId="2229-f494-25db-c5d3">6</characteristic><characteristic name="AP" typeId="9ead-8a10-520-de15">-1</characteristic><characteristic name="D" typeId="a354-c1c8-a745-f9e3">1</characteristic><characteristic name="Keywords" typeId="7f1b-8591-2fcf-d01c">Devastating Wounds, Pistol</characteristic></characteristics></profile></profiles><categories><category id="eeda-8544-a2f3-3fab" name="Ranged Weapon" entryId="eeda-8544-a2f3-3fab" primary="false" /></categories></selection><selection id="i51ks8" name="Power fist" entryId="ec2e-941e-4c80-ab09::666c-57c1-9f31-fd7d" entryGroupId="ec2e-941e-4c80-ab09::f1f5-f62e-e47d-9dad" number="1" type="upgrade" from="group" group="Wargear"><profiles><profile id="86b1-36b9-ac98-eee4" name="Power fist" hidden="false" typeId="8a40-4aaa-c780-9046" typeName="Melee Weapons" from="entry"><characteristics><characteristic name="Range" typeId="914c-b413-91e3-a132">Melee</characteristic><characteristic name="A" typeId="2337-daa1-6682-b110">2</characteristic><characteristic name="WS" typeId="95d1-95f-45b4-11d6">3+</characteristic><characteristic name="S" typeId="ab33-d393-96ce-ccba">8</characteristic><characteristic name="AP" typeId="41a0-1301-112a-e2f2">-2</characteristic><characteristic name="D" typeId="3254-9fe6-d824-513e">2</characteristic><characteristic name="Keywords" typeId="893f-9000-ccf7-648e">-</characteristic></characteristics></profile></profiles><categories><category id="ccdd-3987-11ed-90cd" name="Melee Weapon" entryId="ccdd-3987-11ed-90cd" primary="false" /></categories></selection></selections><costs><cost name="pts" typeId="51b2-306e-1021-d207" value="25" /></costs><categories><category id="6785-add8-89f-d960" name="Cybernetica Datasmith" entryId="6785-add8-89f-d960" primary="false" /><category id="59a9-b5cc-7c11-aaad" name="Tech-Priest" entryId="59a9-b5cc-7c11-aaad" primary="false" /><category id="cf47-a0d7-7207-29dc" name="Infantry" entryId="cf47-a0d7-7207-29dc" primary="false" /><category id="9cfd-1c32-585f-7d5c" entryId="9cfd-1c32-585f-7d5c" name="Character" primary="true" /><category id="aff3-d6a3-2a95-9dc" name="Imperium" entryId="aff3-d6a3-2a95-9dc" primary="false" /><category id="5418-f86b-6e76-c5a" name="Faction: Adeptus Mechanicus" entryId="5418-f86b-6e76-c5a" primary="false" /><category id="3b4e-5e61-ac14-93de" name="Legio Cybernetica" entryId="3b4e-5e61-ac14-93de" primary="false" /></categories></selection></selections><categories><category name="Uncategorized" id="64hwrt" primary="false" entryId="(No Category)" /><category name="Configuration" id="7z2e0hj" primary="false" entryId="4ac9-fd30-1e3d-b249" /><category name="Epic Hero" id="64nr14i" primary="false" entryId="4f3a-f0f7-6647-348d" /><category name="Character" id="64gkppm" primary="false" entryId="9cfd-1c32-585f-7d5c" /><category name="Battleline" id="o6ay1he" primary="false" entryId="e338-111e-d0c6-b687" /><category name="Infantry" id="64y8ajk" primary="false" entryId="cf47-a0d7-7207-29dc" /><category name="Swarm" id="644ixh" primary="false" entryId="b00b-5bae-444f-964e" /><category name="Mounted" id="64s43u8" primary="false" entryId="14a0-40c9-2748-ae6e" /><category name="Beast" id="659su4l" primary="false" entryId="4c3e-9310-a516-3590" /><category name="Monster" id="65e5ukx" primary="false" entryId="9693-cf84-fe69-37a9" /><category name="Vehicle" id="65txtjf" primary="false" entryId="dbd4-63-af05-998" /><category name="Drone" id="65dod9tb" primary="false" entryId="2471-e2e0-3f55-d6cb" /><category name="Dedicated Transport" id="65609s" primary="false" entryId="ba07-411c-2832-1f79" /><category name="Fortification" id="65xxnj" primary="false" entryId="19d7-9c74-2140-5851" /><category name="Unit" id="650oew" primary="false" entryId="1160-70ae-a862-b1a8" /><category name="Allies: Astra Militarum" id="65at09" primary="false" entryId="8247-35f6-ec2a-7caa" /><category name="Allies: Chaos Knights" id="655bee9" primary="false" entryId="8dd6-af11-abd3-55f1" /><category name="Allies: Heretic Astartes" id="6569by" primary="false" entryId="92e6-f82e-0a48-2276" /><category name="Allies: Imperial Agents" id="657gly" primary="false" entryId="742f-5727-1bc9-6da5" /><category name="Allies: Imperial Knights" id="65i3ava" primary="false" entryId="5e03-9044-273d-e818" /><category name="Allies: Legiones Daemonica" id="66l4a9l" primary="false" entryId="e1ea-71b9-f0ef-d788" /><category name="Allies: Titanicus Traitoris" id="66yh21" primary="false" entryId="24fa-8caf-cd68-31fb" /><category name="Allies: Unaligned Forces" id="663x04l" primary="false" entryId="07d9-ab1c-cf28-0939" /><category name="Reference" id="660qhyr" primary="false" entryId="eef1-be80-500a-edfc" /><category name="Allies: Adeptus Titanicus" id="66ox25t" primary="false" entryId="9988-6b5e-660e-d973" /><category name="Illegal Units" id="66fj9" primary="false" entryId="(Illegal Units)" /></categories></force></forces></roster>