👁️
5
fork

Configure Feed

Select the types of activity you want to include in your feed.

export route and ui

+1148 -823
+10 -1
src/components/deck/DeckActionsMenu.tsx
··· 1 1 import { useQueryClient } from "@tanstack/react-query"; 2 2 import { Link } from "@tanstack/react-router"; 3 - import { MoreVertical, Play, Trash2 } from "lucide-react"; 3 + import { Download, MoreVertical, Play, Trash2 } from "lucide-react"; 4 4 import { useEffect, useRef, useState } from "react"; 5 5 import { toast } from "sonner"; 6 6 import { DeleteDeckDialog } from "@/components/deck/DeleteDeckDialog"; ··· 121 121 > 122 122 <Play size={14} /> 123 123 Playtest 124 + </Link> 125 + <Link 126 + to="/profile/$did/deck/$rkey/export" 127 + params={{ did, rkey }} 128 + className="w-full text-left px-4 py-3 hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors text-gray-900 dark:text-white text-sm flex items-center gap-2" 129 + onClick={() => setIsOpen(false)} 130 + > 131 + <Download size={14} /> 132 + Export 124 133 </Link> 125 134 {!readOnly && ( 126 135 <>
+740 -763
src/lib/deck-formats/__tests__/__snapshots__/snapshots.test.ts.snap
··· 783 783 `; 784 784 785 785 exports[`export snapshots > archidekt/ashling-by-category.txt > export to deckstats 1`] = ` 786 - "1 Ashling, Rekindled // Ashling, Rimebound (ECL) 290 # !Commander 787 - 788 - //Main 789 - 1 Caldera Pyremaw (TDC) 33 #Burn 790 - 1 Exalted Flamer of Tzeentch (40K) 119 #Burn #Recursion 791 - 1 Flash Photography (FIC) 463 #Copy 792 - 1 Relm's Sketching (FIN) 67 #Copy 793 - 1 Replication Technique (M3C) 192 #Copy 794 - 1 Archmage Emeritus (TDC) 145 #Draw 795 - 1 Archmage of Runes (FDN) 30 #Draw 796 - 1 Ashling's Command (ECL) 205 #Draw 797 - 1 Big Score (TDC) 206 #Draw 798 - 1 Deep Analysis (TDC) 150 #Draw 799 - 1 Dig Through Time (DSC) 115 #Draw 800 - 1 Drawn from Dreams (NCC) 220 #Draw 801 - 1 Flame of Anor (LTR) 203 #Draw 802 - 1 Hypothesizzle (PLST) GRN-178 #Draw #Removal 803 - 1 Lórien Revealed (LTR) 60 #Draw 804 - 1 Memories Returning (FIN) 63 #Draw 805 - 1 Memory Deluge (INR) 75 #Draw 806 - 1 Pirate's Pillage (2X2) 120 #Draw 807 - 1 Scattered Thoughts (VOW) 74 #Draw 808 - 1 Sea Gate Restoration // Sea Gate, Reborn (ZNR) 76 #Draw 809 - 1 Silundi Vision // Silundi Isle (ZNR) 80 #Draw 810 - 1 Tellah, Great Sage (FIN) 244 #Draw 811 - 1 Unexpected Windfall (AFR) 164 #Draw 812 - 1 Valakut Awakening // Valakut Stoneforge (PLST) ZNR-174 #Draw 813 - 1 Arcane Bombardment (OTC) 154 #Greed 814 - 1 Chimil, the Inner Sun (LCI) 249 #Greed 815 - 1 Double Vision (NCC) 267 #Greed 816 - 1 Fury Storm (C18) 22 #Greed 817 - 1 Harmonic Prodigy (MH2) 132 #Greed 818 - 1 Jin-Gitaxias, Progress Tyrant (NEO) 59 #Greed 819 - 1 Mana Geyser (TDC) 223 #Greed 820 - 1 Summon: G.F. Cerberus (FIN) 162 #Greed 821 - 1 Sunbird's Invocation (C21) 180 #Greed 822 - 1 Cascade Bluffs (EOC) 153 #Land 823 - 1 Command Tower (ECC) 59 #Land 824 - 1 Fiery Islet (MH1) 238 #Land 825 - 1 Frostboil Snarl (DRC) 158 #Land 826 - 9 Island (ECL) 270 #Land 827 - 1 Izzet Boilerworks (M3C) 350 #Land 828 - 1 Mistrise Village (TDM) 261 #Land 829 - 9 Mountain (ECL) 272 #Land 830 - 1 Reliquary Tower (TDC) 386 #Land 831 - 1 Riverglide Pathway // Lavaglide Pathway (PLST) ZNR-264 #Land 832 - 1 Riverpyre Verge (DFT) 260 #Land 833 - 1 Scalding Tarn (MH2) 254 #Land 834 - 1 Scavenger Grounds (MKC) 287 #Land 835 - 1 Shivan Reef (EOC) 179 #Land 836 - 1 Steam Vents (ECL) 267 #Land 837 - 1 Stormcarved Coast (INR) 285 #Land 838 - 1 Sulfur Falls (EOC) 184 #Land 839 - 1 Training Center (CMM) 434 #Land 840 - 1 Omniscience (FDN) 161 #Okay Pal 841 - 1 Creative Outburst (STX) 171 #Ramp #Removal #Draw 842 - 1 Elemental Masterpiece (STX) 182 #Ramp #Tokens 843 - 1 Hedron Archive (BLC) 275 #Ramp 844 - 1 Magma Opus (TDC) 296 #Ramp #Draw #Tokens #Removal 845 - 1 Sisay's Ring (CMR) 340 #Ramp 846 - 1 Sol Ring (ECC) 57 #Ramp 847 - 1 Stonespeaker Crystal (CLB) 338 #Ramp #Removal 848 - 1 Thran Dynamo (BLC) 290 #Ramp 849 - 1 Ur-Golem's Eye (C14) 280 #Ramp 850 - 1 Archaeomancer (J25) 285 #Recursion 851 - 1 Ardent Elementalist (MID) 128 #Recursion 852 - 1 Mizzix's Mastery (OTC) 175 #Recursion 853 - 1 Pinnacle Monk // Mystic Peak (MH3) 246 #Recursion 854 - 1 Aether Gale (DSC) 109 #Removal 855 - 1 All Is Dust (M3C) 152 #Removal 856 - 1 Baral's Expertise (TDC) 146 #Removal 857 - 1 Blasphemous Act (DSC) 160 #Removal 858 - 1 Call Forth the Tempest (LTC) 509 #Removal 859 - 1 Chaos Warp (OTC) 160 #Removal 860 - 1 Counterspell (DSC) 114 #Removal 861 - 1 Fiery Confluence (LCC) 226 #Removal 862 - 1 Flood of Tears (VOC) 104 #Removal 863 - 1 Ill-Timed Explosion (MKM) 207 #Removal 864 - 1 Mystic Confluence (CMM) 108 #Removal 865 - 1 Prophetic Bolt (2X2) 265 #Removal #Draw 866 - 1 Ral's Outburst (WAR) 212 #Removal 867 - 1 Reckless Endeavor (AFC) 33 #Removal 868 - 1 Sink into Stupor // Soporific Springs (MH3) 241 #Removal 869 - 1 Volcanic Vision (C21) 182 #Removal #Recursion 870 - 1 Rite of the Dragoncaller (FDN) 92 #Tokens 871 - 1 Shark Typhoon (DSC) 127 #Tokens" 786 + "//Main 787 + 1 Ashling, Rekindled // Ashling, Rimebound (ECL) 290 # !Commander 788 + 1 Caldera Pyremaw (TDC) 33 789 + 1 Exalted Flamer of Tzeentch (40K) 119 790 + 1 Flash Photography (FIC) 463 791 + 1 Relm's Sketching (FIN) 67 792 + 1 Replication Technique (M3C) 192 793 + 1 Archmage Emeritus (TDC) 145 794 + 1 Archmage of Runes (FDN) 30 795 + 1 Ashling's Command (ECL) 205 796 + 1 Big Score (TDC) 206 797 + 1 Deep Analysis (TDC) 150 798 + 1 Dig Through Time (DSC) 115 799 + 1 Drawn from Dreams (NCC) 220 800 + 1 Flame of Anor (LTR) 203 801 + 1 Hypothesizzle (PLST) GRN-178 802 + 1 Lórien Revealed (LTR) 60 803 + 1 Memories Returning (FIN) 63 804 + 1 Memory Deluge (INR) 75 805 + 1 Pirate's Pillage (2X2) 120 806 + 1 Scattered Thoughts (VOW) 74 807 + 1 Sea Gate Restoration // Sea Gate, Reborn (ZNR) 76 808 + 1 Silundi Vision // Silundi Isle (ZNR) 80 809 + 1 Tellah, Great Sage (FIN) 244 810 + 1 Unexpected Windfall (AFR) 164 811 + 1 Valakut Awakening // Valakut Stoneforge (PLST) ZNR-174 812 + 1 Arcane Bombardment (OTC) 154 813 + 1 Chimil, the Inner Sun (LCI) 249 814 + 1 Double Vision (NCC) 267 815 + 1 Fury Storm (C18) 22 816 + 1 Harmonic Prodigy (MH2) 132 817 + 1 Jin-Gitaxias, Progress Tyrant (NEO) 59 818 + 1 Mana Geyser (TDC) 223 819 + 1 Summon: G.F. Cerberus (FIN) 162 820 + 1 Sunbird's Invocation (C21) 180 821 + 1 Cascade Bluffs (EOC) 153 822 + 1 Command Tower (ECC) 59 823 + 1 Fiery Islet (MH1) 238 824 + 1 Frostboil Snarl (DRC) 158 825 + 9 Island (ECL) 270 826 + 1 Izzet Boilerworks (M3C) 350 827 + 1 Mistrise Village (TDM) 261 828 + 9 Mountain (ECL) 272 829 + 1 Reliquary Tower (TDC) 386 830 + 1 Riverglide Pathway // Lavaglide Pathway (PLST) ZNR-264 831 + 1 Riverpyre Verge (DFT) 260 832 + 1 Scalding Tarn (MH2) 254 833 + 1 Scavenger Grounds (MKC) 287 834 + 1 Shivan Reef (EOC) 179 835 + 1 Steam Vents (ECL) 267 836 + 1 Stormcarved Coast (INR) 285 837 + 1 Sulfur Falls (EOC) 184 838 + 1 Training Center (CMM) 434 839 + 1 Omniscience (FDN) 161 840 + 1 Creative Outburst (STX) 171 841 + 1 Elemental Masterpiece (STX) 182 842 + 1 Hedron Archive (BLC) 275 843 + 1 Magma Opus (TDC) 296 844 + 1 Sisay's Ring (CMR) 340 845 + 1 Sol Ring (ECC) 57 846 + 1 Stonespeaker Crystal (CLB) 338 847 + 1 Thran Dynamo (BLC) 290 848 + 1 Ur-Golem's Eye (C14) 280 849 + 1 Archaeomancer (J25) 285 850 + 1 Ardent Elementalist (MID) 128 851 + 1 Mizzix's Mastery (OTC) 175 852 + 1 Pinnacle Monk // Mystic Peak (MH3) 246 853 + 1 Aether Gale (DSC) 109 854 + 1 All Is Dust (M3C) 152 855 + 1 Baral's Expertise (TDC) 146 856 + 1 Blasphemous Act (DSC) 160 857 + 1 Call Forth the Tempest (LTC) 509 858 + 1 Chaos Warp (OTC) 160 859 + 1 Counterspell (DSC) 114 860 + 1 Fiery Confluence (LCC) 226 861 + 1 Flood of Tears (VOC) 104 862 + 1 Ill-Timed Explosion (MKM) 207 863 + 1 Mystic Confluence (CMM) 108 864 + 1 Prophetic Bolt (2X2) 265 865 + 1 Ral's Outburst (WAR) 212 866 + 1 Reckless Endeavor (AFC) 33 867 + 1 Sink into Stupor // Soporific Springs (MH3) 241 868 + 1 Volcanic Vision (C21) 182 869 + 1 Rite of the Dragoncaller (FDN) 92 870 + 1 Shark Typhoon (DSC) 127" 872 871 `; 873 872 874 873 exports[`export snapshots > archidekt/ashling-by-category.txt > export to moxfield 1`] = ` ··· 1393 1392 `; 1394 1393 1395 1394 exports[`export snapshots > archidekt/ashling-flat.txt > export to deckstats 1`] = ` 1396 - "1 Ashling, Rekindled // Ashling, Rimebound (ECL) 290 # !Commander 1397 - 1398 - //Main 1399 - 1 Aether Gale (DSC) 109 #Removal 1400 - 1 All Is Dust (M3C) 152 #Removal 1401 - 1 Arcane Bombardment (OTC) 154 #Greed 1402 - 1 Archaeomancer (J25) 285 #Recursion 1403 - 1 Archmage Emeritus (TDC) 145 #Draw 1404 - 1 Archmage of Runes (FDN) 30 #Draw 1405 - 1 Ardent Elementalist (MID) 128 #Recursion 1406 - 1 Ashling's Command (ECL) 205 #Draw 1407 - 1 Baral's Expertise (TDC) 146 #Removal 1408 - 1 Big Score (TDC) 206 #Draw 1409 - 1 Blasphemous Act (DSC) 160 #Removal 1410 - 1 Caldera Pyremaw (TDC) 33 #Burn 1411 - 1 Call Forth the Tempest (LTC) 509 #Removal 1412 - 1 Cascade Bluffs (EOC) 153 #Land 1413 - 1 Chaos Warp (OTC) 160 #Removal 1414 - 1 Chimil, the Inner Sun (LCI) 249 #Greed 1415 - 1 Command Tower (ECC) 59 #Land 1416 - 1 Counterspell (DSC) 114 #Removal 1417 - 1 Creative Outburst (STX) 171 #Ramp #Removal #Draw 1418 - 1 Deep Analysis (TDC) 150 #Draw 1419 - 1 Dig Through Time (DSC) 115 #Draw 1420 - 1 Double Vision (NCC) 267 #Greed 1421 - 1 Drawn from Dreams (NCC) 220 #Draw 1422 - 1 Elemental Masterpiece (STX) 182 #Ramp #Tokens 1423 - 1 Exalted Flamer of Tzeentch (40K) 119 #Burn #Recursion 1424 - 1 Fiery Confluence (LCC) 226 #Removal 1425 - 1 Fiery Islet (MH1) 238 #Land 1426 - 1 Flame of Anor (LTR) 203 #Draw 1427 - 1 Flash Photography (FIC) 463 #Copy 1428 - 1 Flood of Tears (VOC) 104 #Removal 1429 - 1 Frostboil Snarl (DRC) 158 #Land 1430 - 1 Fury Storm (C18) 22 #Greed 1431 - 1 Harmonic Prodigy (MH2) 132 #Greed 1432 - 1 Hedron Archive (BLC) 275 #Ramp 1433 - 1 Hypothesizzle (PLST) GRN-178 #Draw #Removal 1434 - 1 Ill-Timed Explosion (MKM) 207 #Removal 1435 - 9 Island (ECL) 270 #Land 1436 - 1 Izzet Boilerworks (M3C) 350 #Land 1437 - 1 Jin-Gitaxias, Progress Tyrant (NEO) 59 #Greed 1438 - 1 Lórien Revealed (LTR) 60 #Draw 1439 - 1 Magma Opus (TDC) 296 #Ramp #Draw #Tokens #Removal 1440 - 1 Mana Geyser (TDC) 223 #Greed 1441 - 1 Memories Returning (FIN) 63 #Draw 1442 - 1 Memory Deluge (INR) 75 #Draw 1443 - 1 Mistrise Village (TDM) 261 #Land 1444 - 1 Mizzix's Mastery (OTC) 175 #Recursion 1445 - 9 Mountain (ECL) 272 #Land 1446 - 1 Mystic Confluence (CMM) 108 #Removal 1447 - 1 Omniscience (FDN) 161 #Okay Pal 1448 - 1 Pinnacle Monk // Mystic Peak (MH3) 246 #Recursion 1449 - 1 Pirate's Pillage (2X2) 120 #Draw 1450 - 1 Prophetic Bolt (2X2) 265 #Removal #Draw 1451 - 1 Ral's Outburst (WAR) 212 #Removal 1452 - 1 Reckless Endeavor (AFC) 33 #Removal 1453 - 1 Reliquary Tower (TDC) 386 #Land 1454 - 1 Relm's Sketching (FIN) 67 #Copy 1455 - 1 Replication Technique (M3C) 192 #Copy 1456 - 1 Rite of the Dragoncaller (FDN) 92 #Tokens 1457 - 1 Riverglide Pathway // Lavaglide Pathway (PLST) ZNR-264 #Land 1458 - 1 Riverpyre Verge (DFT) 260 #Land 1459 - 1 Scalding Tarn (MH2) 254 #Land 1460 - 1 Scattered Thoughts (VOW) 74 #Draw 1461 - 1 Scavenger Grounds (MKC) 287 #Land 1462 - 1 Sea Gate Restoration // Sea Gate, Reborn (ZNR) 76 #Draw 1463 - 1 Shark Typhoon (DSC) 127 #Tokens 1464 - 1 Shivan Reef (EOC) 179 #Land 1465 - 1 Silundi Vision // Silundi Isle (ZNR) 80 #Draw 1466 - 1 Sink into Stupor // Soporific Springs (MH3) 241 #Removal 1467 - 1 Sisay's Ring (CMR) 340 #Ramp 1468 - 1 Sol Ring (ECC) 57 #Ramp 1469 - 1 Steam Vents (ECL) 267 #Land 1470 - 1 Stonespeaker Crystal (CLB) 338 #Ramp #Removal 1471 - 1 Stormcarved Coast (INR) 285 #Land 1472 - 1 Sulfur Falls (EOC) 184 #Land 1473 - 1 Summon: G.F. Cerberus (FIN) 162 #Greed 1474 - 1 Sunbird's Invocation (C21) 180 #Greed 1475 - 1 Tellah, Great Sage (FIN) 244 #Draw 1476 - 1 Thran Dynamo (BLC) 290 #Ramp 1477 - 1 Training Center (CMM) 434 #Land 1478 - 1 Unexpected Windfall (AFR) 164 #Draw 1479 - 1 Ur-Golem's Eye (C14) 280 #Ramp 1480 - 1 Valakut Awakening // Valakut Stoneforge (PLST) ZNR-174 #Draw 1481 - 1 Volcanic Vision (C21) 182 #Removal #Recursion" 1395 + "//Main 1396 + 1 Ashling, Rekindled // Ashling, Rimebound (ECL) 290 # !Commander 1397 + 1 Aether Gale (DSC) 109 1398 + 1 All Is Dust (M3C) 152 1399 + 1 Arcane Bombardment (OTC) 154 1400 + 1 Archaeomancer (J25) 285 1401 + 1 Archmage Emeritus (TDC) 145 1402 + 1 Archmage of Runes (FDN) 30 1403 + 1 Ardent Elementalist (MID) 128 1404 + 1 Ashling's Command (ECL) 205 1405 + 1 Baral's Expertise (TDC) 146 1406 + 1 Big Score (TDC) 206 1407 + 1 Blasphemous Act (DSC) 160 1408 + 1 Caldera Pyremaw (TDC) 33 1409 + 1 Call Forth the Tempest (LTC) 509 1410 + 1 Cascade Bluffs (EOC) 153 1411 + 1 Chaos Warp (OTC) 160 1412 + 1 Chimil, the Inner Sun (LCI) 249 1413 + 1 Command Tower (ECC) 59 1414 + 1 Counterspell (DSC) 114 1415 + 1 Creative Outburst (STX) 171 1416 + 1 Deep Analysis (TDC) 150 1417 + 1 Dig Through Time (DSC) 115 1418 + 1 Double Vision (NCC) 267 1419 + 1 Drawn from Dreams (NCC) 220 1420 + 1 Elemental Masterpiece (STX) 182 1421 + 1 Exalted Flamer of Tzeentch (40K) 119 1422 + 1 Fiery Confluence (LCC) 226 1423 + 1 Fiery Islet (MH1) 238 1424 + 1 Flame of Anor (LTR) 203 1425 + 1 Flash Photography (FIC) 463 1426 + 1 Flood of Tears (VOC) 104 1427 + 1 Frostboil Snarl (DRC) 158 1428 + 1 Fury Storm (C18) 22 1429 + 1 Harmonic Prodigy (MH2) 132 1430 + 1 Hedron Archive (BLC) 275 1431 + 1 Hypothesizzle (PLST) GRN-178 1432 + 1 Ill-Timed Explosion (MKM) 207 1433 + 9 Island (ECL) 270 1434 + 1 Izzet Boilerworks (M3C) 350 1435 + 1 Jin-Gitaxias, Progress Tyrant (NEO) 59 1436 + 1 Lórien Revealed (LTR) 60 1437 + 1 Magma Opus (TDC) 296 1438 + 1 Mana Geyser (TDC) 223 1439 + 1 Memories Returning (FIN) 63 1440 + 1 Memory Deluge (INR) 75 1441 + 1 Mistrise Village (TDM) 261 1442 + 1 Mizzix's Mastery (OTC) 175 1443 + 9 Mountain (ECL) 272 1444 + 1 Mystic Confluence (CMM) 108 1445 + 1 Omniscience (FDN) 161 1446 + 1 Pinnacle Monk // Mystic Peak (MH3) 246 1447 + 1 Pirate's Pillage (2X2) 120 1448 + 1 Prophetic Bolt (2X2) 265 1449 + 1 Ral's Outburst (WAR) 212 1450 + 1 Reckless Endeavor (AFC) 33 1451 + 1 Reliquary Tower (TDC) 386 1452 + 1 Relm's Sketching (FIN) 67 1453 + 1 Replication Technique (M3C) 192 1454 + 1 Rite of the Dragoncaller (FDN) 92 1455 + 1 Riverglide Pathway // Lavaglide Pathway (PLST) ZNR-264 1456 + 1 Riverpyre Verge (DFT) 260 1457 + 1 Scalding Tarn (MH2) 254 1458 + 1 Scattered Thoughts (VOW) 74 1459 + 1 Scavenger Grounds (MKC) 287 1460 + 1 Sea Gate Restoration // Sea Gate, Reborn (ZNR) 76 1461 + 1 Shark Typhoon (DSC) 127 1462 + 1 Shivan Reef (EOC) 179 1463 + 1 Silundi Vision // Silundi Isle (ZNR) 80 1464 + 1 Sink into Stupor // Soporific Springs (MH3) 241 1465 + 1 Sisay's Ring (CMR) 340 1466 + 1 Sol Ring (ECC) 57 1467 + 1 Steam Vents (ECL) 267 1468 + 1 Stonespeaker Crystal (CLB) 338 1469 + 1 Stormcarved Coast (INR) 285 1470 + 1 Sulfur Falls (EOC) 184 1471 + 1 Summon: G.F. Cerberus (FIN) 162 1472 + 1 Sunbird's Invocation (C21) 180 1473 + 1 Tellah, Great Sage (FIN) 244 1474 + 1 Thran Dynamo (BLC) 290 1475 + 1 Training Center (CMM) 434 1476 + 1 Unexpected Windfall (AFR) 164 1477 + 1 Ur-Golem's Eye (C14) 280 1478 + 1 Valakut Awakening // Valakut Stoneforge (PLST) ZNR-174 1479 + 1 Volcanic Vision (C21) 182" 1482 1480 `; 1483 1481 1484 1482 exports[`export snapshots > archidekt/ashling-flat.txt > export to moxfield 1`] = ` ··· 2019 2017 `; 2020 2018 2021 2019 exports[`export snapshots > archidekt/ashling-flat-no-maybe.txt > export to deckstats 1`] = ` 2022 - "1 Ashling, Rekindled // Ashling, Rimebound (ECL) 290 # !Commander 2023 - 2024 - //Main 2025 - 1 Aether Gale (DSC) 109 #Removal 2026 - 1 All Is Dust (M3C) 152 #Removal 2027 - 1 Arcane Bombardment (OTC) 154 #Greed 2028 - 1 Archaeomancer (J25) 285 #Recursion 2029 - 1 Archmage Emeritus (TDC) 145 #Draw 2030 - 1 Archmage of Runes (FDN) 30 #Draw 2031 - 1 Ardent Elementalist (MID) 128 #Recursion 2032 - 1 Ashling's Command (ECL) 205 #Draw 2033 - 1 Baral's Expertise (TDC) 146 #Removal 2034 - 1 Big Score (TDC) 206 #Draw 2035 - 1 Blasphemous Act (DSC) 160 #Removal 2036 - 1 Caldera Pyremaw (TDC) 33 #Burn 2037 - 1 Call Forth the Tempest (LTC) 509 #Removal 2038 - 1 Cascade Bluffs (EOC) 153 #Land 2039 - 1 Chaos Warp (OTC) 160 #Removal 2040 - 1 Chimil, the Inner Sun (LCI) 249 #Greed 2041 - 1 Command Tower (ECC) 59 #Land 2042 - 1 Counterspell (DSC) 114 #Removal 2043 - 1 Creative Outburst (STX) 171 #Ramp #Removal #Draw 2044 - 1 Deep Analysis (TDC) 150 #Draw 2045 - 1 Dig Through Time (DSC) 115 #Draw 2046 - 1 Double Vision (NCC) 267 #Greed 2047 - 1 Drawn from Dreams (NCC) 220 #Draw 2048 - 1 Elemental Masterpiece (STX) 182 #Ramp #Tokens 2049 - 1 Exalted Flamer of Tzeentch (40K) 119 #Burn #Recursion 2050 - 1 Fiery Confluence (LCC) 226 #Removal 2051 - 1 Fiery Islet (MH1) 238 #Land 2052 - 1 Flame of Anor (LTR) 203 #Draw 2053 - 1 Flash Photography (FIC) 463 #Copy 2054 - 1 Flood of Tears (VOC) 104 #Removal 2055 - 1 Frostboil Snarl (DRC) 158 #Land 2056 - 1 Fury Storm (C18) 22 #Greed 2057 - 1 Harmonic Prodigy (MH2) 132 #Greed 2058 - 1 Hedron Archive (BLC) 275 #Ramp 2059 - 1 Hypothesizzle (PLST) GRN-178 #Draw #Removal 2060 - 1 Ill-Timed Explosion (MKM) 207 #Removal 2061 - 9 Island (ECL) 270 #Land 2062 - 1 Izzet Boilerworks (M3C) 350 #Land 2063 - 1 Jin-Gitaxias, Progress Tyrant (NEO) 59 #Greed 2064 - 1 Lórien Revealed (LTR) 60 #Draw 2065 - 1 Magma Opus (TDC) 296 #Ramp #Draw #Tokens #Removal 2066 - 1 Mana Geyser (TDC) 223 #Greed 2067 - 1 Memories Returning (FIN) 63 #Draw 2068 - 1 Memory Deluge (INR) 75 #Draw 2069 - 1 Mistrise Village (TDM) 261 #Land 2070 - 1 Mizzix's Mastery (OTC) 175 #Recursion 2071 - 9 Mountain (ECL) 272 #Land 2072 - 1 Mystic Confluence (CMM) 108 #Removal 2073 - 1 Omniscience (FDN) 161 #Okay Pal 2074 - 1 Pinnacle Monk // Mystic Peak (MH3) 246 #Recursion 2075 - 1 Pirate's Pillage (2X2) 120 #Draw 2076 - 1 Prophetic Bolt (2X2) 265 #Removal #Draw 2077 - 1 Ral's Outburst (WAR) 212 #Removal 2078 - 1 Reckless Endeavor (AFC) 33 #Removal 2079 - 1 Reliquary Tower (TDC) 386 #Land 2080 - 1 Relm's Sketching (FIN) 67 #Copy 2081 - 1 Replication Technique (M3C) 192 #Copy 2082 - 1 Rite of the Dragoncaller (FDN) 92 #Tokens 2083 - 1 Riverglide Pathway // Lavaglide Pathway (PLST) ZNR-264 #Land 2084 - 1 Riverpyre Verge (DFT) 260 #Land 2085 - 1 Scalding Tarn (MH2) 254 #Land 2086 - 1 Scattered Thoughts (VOW) 74 #Draw 2087 - 1 Scavenger Grounds (MKC) 287 #Land 2088 - 1 Sea Gate Restoration // Sea Gate, Reborn (ZNR) 76 #Draw 2089 - 1 Shark Typhoon (DSC) 127 #Tokens 2090 - 1 Shivan Reef (EOC) 179 #Land 2091 - 1 Silundi Vision // Silundi Isle (ZNR) 80 #Draw 2092 - 1 Sink into Stupor // Soporific Springs (MH3) 241 #Removal 2093 - 1 Sisay's Ring (CMR) 340 #Ramp 2094 - 1 Sol Ring (ECC) 57 #Ramp 2095 - 1 Steam Vents (ECL) 267 #Land 2096 - 1 Stonespeaker Crystal (CLB) 338 #Ramp #Removal 2097 - 1 Stormcarved Coast (INR) 285 #Land 2098 - 1 Sulfur Falls (EOC) 184 #Land 2099 - 1 Summon: G.F. Cerberus (FIN) 162 #Greed 2100 - 1 Sunbird's Invocation (C21) 180 #Greed 2101 - 1 Tellah, Great Sage (FIN) 244 #Draw 2102 - 1 Thran Dynamo (BLC) 290 #Ramp 2103 - 1 Training Center (CMM) 434 #Land 2104 - 1 Unexpected Windfall (AFR) 164 #Draw 2105 - 1 Ur-Golem's Eye (C14) 280 #Ramp 2106 - 1 Valakut Awakening // Valakut Stoneforge (PLST) ZNR-174 #Draw 2107 - 1 Volcanic Vision (C21) 182 #Removal #Recursion" 2020 + "//Main 2021 + 1 Ashling, Rekindled // Ashling, Rimebound (ECL) 290 # !Commander 2022 + 1 Aether Gale (DSC) 109 2023 + 1 All Is Dust (M3C) 152 2024 + 1 Arcane Bombardment (OTC) 154 2025 + 1 Archaeomancer (J25) 285 2026 + 1 Archmage Emeritus (TDC) 145 2027 + 1 Archmage of Runes (FDN) 30 2028 + 1 Ardent Elementalist (MID) 128 2029 + 1 Ashling's Command (ECL) 205 2030 + 1 Baral's Expertise (TDC) 146 2031 + 1 Big Score (TDC) 206 2032 + 1 Blasphemous Act (DSC) 160 2033 + 1 Caldera Pyremaw (TDC) 33 2034 + 1 Call Forth the Tempest (LTC) 509 2035 + 1 Cascade Bluffs (EOC) 153 2036 + 1 Chaos Warp (OTC) 160 2037 + 1 Chimil, the Inner Sun (LCI) 249 2038 + 1 Command Tower (ECC) 59 2039 + 1 Counterspell (DSC) 114 2040 + 1 Creative Outburst (STX) 171 2041 + 1 Deep Analysis (TDC) 150 2042 + 1 Dig Through Time (DSC) 115 2043 + 1 Double Vision (NCC) 267 2044 + 1 Drawn from Dreams (NCC) 220 2045 + 1 Elemental Masterpiece (STX) 182 2046 + 1 Exalted Flamer of Tzeentch (40K) 119 2047 + 1 Fiery Confluence (LCC) 226 2048 + 1 Fiery Islet (MH1) 238 2049 + 1 Flame of Anor (LTR) 203 2050 + 1 Flash Photography (FIC) 463 2051 + 1 Flood of Tears (VOC) 104 2052 + 1 Frostboil Snarl (DRC) 158 2053 + 1 Fury Storm (C18) 22 2054 + 1 Harmonic Prodigy (MH2) 132 2055 + 1 Hedron Archive (BLC) 275 2056 + 1 Hypothesizzle (PLST) GRN-178 2057 + 1 Ill-Timed Explosion (MKM) 207 2058 + 9 Island (ECL) 270 2059 + 1 Izzet Boilerworks (M3C) 350 2060 + 1 Jin-Gitaxias, Progress Tyrant (NEO) 59 2061 + 1 Lórien Revealed (LTR) 60 2062 + 1 Magma Opus (TDC) 296 2063 + 1 Mana Geyser (TDC) 223 2064 + 1 Memories Returning (FIN) 63 2065 + 1 Memory Deluge (INR) 75 2066 + 1 Mistrise Village (TDM) 261 2067 + 1 Mizzix's Mastery (OTC) 175 2068 + 9 Mountain (ECL) 272 2069 + 1 Mystic Confluence (CMM) 108 2070 + 1 Omniscience (FDN) 161 2071 + 1 Pinnacle Monk // Mystic Peak (MH3) 246 2072 + 1 Pirate's Pillage (2X2) 120 2073 + 1 Prophetic Bolt (2X2) 265 2074 + 1 Ral's Outburst (WAR) 212 2075 + 1 Reckless Endeavor (AFC) 33 2076 + 1 Reliquary Tower (TDC) 386 2077 + 1 Relm's Sketching (FIN) 67 2078 + 1 Replication Technique (M3C) 192 2079 + 1 Rite of the Dragoncaller (FDN) 92 2080 + 1 Riverglide Pathway // Lavaglide Pathway (PLST) ZNR-264 2081 + 1 Riverpyre Verge (DFT) 260 2082 + 1 Scalding Tarn (MH2) 254 2083 + 1 Scattered Thoughts (VOW) 74 2084 + 1 Scavenger Grounds (MKC) 287 2085 + 1 Sea Gate Restoration // Sea Gate, Reborn (ZNR) 76 2086 + 1 Shark Typhoon (DSC) 127 2087 + 1 Shivan Reef (EOC) 179 2088 + 1 Silundi Vision // Silundi Isle (ZNR) 80 2089 + 1 Sink into Stupor // Soporific Springs (MH3) 241 2090 + 1 Sisay's Ring (CMR) 340 2091 + 1 Sol Ring (ECC) 57 2092 + 1 Steam Vents (ECL) 267 2093 + 1 Stonespeaker Crystal (CLB) 338 2094 + 1 Stormcarved Coast (INR) 285 2095 + 1 Sulfur Falls (EOC) 184 2096 + 1 Summon: G.F. Cerberus (FIN) 162 2097 + 1 Sunbird's Invocation (C21) 180 2098 + 1 Tellah, Great Sage (FIN) 244 2099 + 1 Thran Dynamo (BLC) 290 2100 + 1 Training Center (CMM) 434 2101 + 1 Unexpected Windfall (AFR) 164 2102 + 1 Ur-Golem's Eye (C14) 280 2103 + 1 Valakut Awakening // Valakut Stoneforge (PLST) ZNR-174 2104 + 1 Volcanic Vision (C21) 182" 2108 2105 `; 2109 2106 2110 2107 exports[`export snapshots > archidekt/ashling-flat-no-maybe.txt > export to moxfield 1`] = ` ··· 2629 2626 `; 2630 2627 2631 2628 exports[`export snapshots > archidekt/ashling-sections.txt > export to deckstats 1`] = ` 2632 - "1 Ashling, Rekindled // Ashling, Rimebound (ECL) 290 # !Commander 2633 - 2634 - //Main 2635 - 1 Caldera Pyremaw (TDC) 33 #Burn 2636 - 1 Exalted Flamer of Tzeentch (40K) 119 #Burn #Recursion 2637 - 1 Flash Photography (FIC) 463 #Copy 2638 - 1 Relm's Sketching (FIN) 67 #Copy 2639 - 1 Replication Technique (M3C) 192 #Copy 2640 - 1 Archmage Emeritus (TDC) 145 #Draw 2641 - 1 Archmage of Runes (FDN) 30 #Draw 2642 - 1 Ashling's Command (ECL) 205 #Draw 2643 - 1 Big Score (TDC) 206 #Draw 2644 - 1 Deep Analysis (TDC) 150 #Draw 2645 - 1 Dig Through Time (DSC) 115 #Draw 2646 - 1 Drawn from Dreams (NCC) 220 #Draw 2647 - 1 Flame of Anor (LTR) 203 #Draw 2648 - 1 Hypothesizzle (PLST) GRN-178 #Draw #Removal 2649 - 1 Lórien Revealed (LTR) 60 #Draw 2650 - 1 Memories Returning (FIN) 63 #Draw 2651 - 1 Memory Deluge (INR) 75 #Draw 2652 - 1 Pirate's Pillage (2X2) 120 #Draw 2653 - 1 Scattered Thoughts (VOW) 74 #Draw 2654 - 1 Sea Gate Restoration // Sea Gate, Reborn (ZNR) 76 #Draw 2655 - 1 Silundi Vision // Silundi Isle (ZNR) 80 #Draw 2656 - 1 Tellah, Great Sage (FIN) 244 #Draw 2657 - 1 Unexpected Windfall (AFR) 164 #Draw 2658 - 1 Valakut Awakening // Valakut Stoneforge (PLST) ZNR-174 #Draw 2659 - 1 Arcane Bombardment (OTC) 154 #Greed 2660 - 1 Chimil, the Inner Sun (LCI) 249 #Greed 2661 - 1 Double Vision (NCC) 267 #Greed 2662 - 1 Fury Storm (C18) 22 #Greed 2663 - 1 Harmonic Prodigy (MH2) 132 #Greed 2664 - 1 Jin-Gitaxias, Progress Tyrant (NEO) 59 #Greed 2665 - 1 Mana Geyser (TDC) 223 #Greed 2666 - 1 Summon: G.F. Cerberus (FIN) 162 #Greed 2667 - 1 Sunbird's Invocation (C21) 180 #Greed 2668 - 1 Cascade Bluffs (EOC) 153 #Land 2669 - 1 Command Tower (ECC) 59 #Land 2670 - 1 Fiery Islet (MH1) 238 #Land 2671 - 1 Frostboil Snarl (DRC) 158 #Land 2672 - 9 Island (ECL) 270 #Land 2673 - 1 Izzet Boilerworks (M3C) 350 #Land 2674 - 1 Mistrise Village (TDM) 261 #Land 2675 - 9 Mountain (ECL) 272 #Land 2676 - 1 Reliquary Tower (TDC) 386 #Land 2677 - 1 Riverglide Pathway // Lavaglide Pathway (PLST) ZNR-264 #Land 2678 - 1 Riverpyre Verge (DFT) 260 #Land 2679 - 1 Scalding Tarn (MH2) 254 #Land 2680 - 1 Scavenger Grounds (MKC) 287 #Land 2681 - 1 Shivan Reef (EOC) 179 #Land 2682 - 1 Steam Vents (ECL) 267 #Land 2683 - 1 Stormcarved Coast (INR) 285 #Land 2684 - 1 Sulfur Falls (EOC) 184 #Land 2685 - 1 Training Center (CMM) 434 #Land 2686 - 1 Omniscience (FDN) 161 #Okay Pal 2687 - 1 Creative Outburst (STX) 171 #Ramp #Removal #Draw 2688 - 1 Elemental Masterpiece (STX) 182 #Ramp #Tokens 2689 - 1 Hedron Archive (BLC) 275 #Ramp 2690 - 1 Magma Opus (TDC) 296 #Ramp #Draw #Tokens #Removal 2691 - 1 Sisay's Ring (CMR) 340 #Ramp 2692 - 1 Sol Ring (ECC) 57 #Ramp 2693 - 1 Stonespeaker Crystal (CLB) 338 #Ramp #Removal 2694 - 1 Thran Dynamo (BLC) 290 #Ramp 2695 - 1 Ur-Golem's Eye (C14) 280 #Ramp 2696 - 1 Archaeomancer (J25) 285 #Recursion 2697 - 1 Ardent Elementalist (MID) 128 #Recursion 2698 - 1 Mizzix's Mastery (OTC) 175 #Recursion 2699 - 1 Pinnacle Monk // Mystic Peak (MH3) 246 #Recursion 2700 - 1 Aether Gale (DSC) 109 #Removal 2701 - 1 All Is Dust (M3C) 152 #Removal 2702 - 1 Baral's Expertise (TDC) 146 #Removal 2703 - 1 Blasphemous Act (DSC) 160 #Removal 2704 - 1 Call Forth the Tempest (LTC) 509 #Removal 2705 - 1 Chaos Warp (OTC) 160 #Removal 2706 - 1 Counterspell (DSC) 114 #Removal 2707 - 1 Fiery Confluence (LCC) 226 #Removal 2708 - 1 Flood of Tears (VOC) 104 #Removal 2709 - 1 Ill-Timed Explosion (MKM) 207 #Removal 2710 - 1 Mystic Confluence (CMM) 108 #Removal 2711 - 1 Prophetic Bolt (2X2) 265 #Removal #Draw 2712 - 1 Ral's Outburst (WAR) 212 #Removal 2713 - 1 Reckless Endeavor (AFC) 33 #Removal 2714 - 1 Sink into Stupor // Soporific Springs (MH3) 241 #Removal 2715 - 1 Volcanic Vision (C21) 182 #Removal #Recursion 2716 - 1 Rite of the Dragoncaller (FDN) 92 #Tokens 2717 - 1 Shark Typhoon (DSC) 127 #Tokens" 2629 + "//Main 2630 + 1 Ashling, Rekindled // Ashling, Rimebound (ECL) 290 # !Commander 2631 + 1 Caldera Pyremaw (TDC) 33 2632 + 1 Exalted Flamer of Tzeentch (40K) 119 2633 + 1 Flash Photography (FIC) 463 2634 + 1 Relm's Sketching (FIN) 67 2635 + 1 Replication Technique (M3C) 192 2636 + 1 Archmage Emeritus (TDC) 145 2637 + 1 Archmage of Runes (FDN) 30 2638 + 1 Ashling's Command (ECL) 205 2639 + 1 Big Score (TDC) 206 2640 + 1 Deep Analysis (TDC) 150 2641 + 1 Dig Through Time (DSC) 115 2642 + 1 Drawn from Dreams (NCC) 220 2643 + 1 Flame of Anor (LTR) 203 2644 + 1 Hypothesizzle (PLST) GRN-178 2645 + 1 Lórien Revealed (LTR) 60 2646 + 1 Memories Returning (FIN) 63 2647 + 1 Memory Deluge (INR) 75 2648 + 1 Pirate's Pillage (2X2) 120 2649 + 1 Scattered Thoughts (VOW) 74 2650 + 1 Sea Gate Restoration // Sea Gate, Reborn (ZNR) 76 2651 + 1 Silundi Vision // Silundi Isle (ZNR) 80 2652 + 1 Tellah, Great Sage (FIN) 244 2653 + 1 Unexpected Windfall (AFR) 164 2654 + 1 Valakut Awakening // Valakut Stoneforge (PLST) ZNR-174 2655 + 1 Arcane Bombardment (OTC) 154 2656 + 1 Chimil, the Inner Sun (LCI) 249 2657 + 1 Double Vision (NCC) 267 2658 + 1 Fury Storm (C18) 22 2659 + 1 Harmonic Prodigy (MH2) 132 2660 + 1 Jin-Gitaxias, Progress Tyrant (NEO) 59 2661 + 1 Mana Geyser (TDC) 223 2662 + 1 Summon: G.F. Cerberus (FIN) 162 2663 + 1 Sunbird's Invocation (C21) 180 2664 + 1 Cascade Bluffs (EOC) 153 2665 + 1 Command Tower (ECC) 59 2666 + 1 Fiery Islet (MH1) 238 2667 + 1 Frostboil Snarl (DRC) 158 2668 + 9 Island (ECL) 270 2669 + 1 Izzet Boilerworks (M3C) 350 2670 + 1 Mistrise Village (TDM) 261 2671 + 9 Mountain (ECL) 272 2672 + 1 Reliquary Tower (TDC) 386 2673 + 1 Riverglide Pathway // Lavaglide Pathway (PLST) ZNR-264 2674 + 1 Riverpyre Verge (DFT) 260 2675 + 1 Scalding Tarn (MH2) 254 2676 + 1 Scavenger Grounds (MKC) 287 2677 + 1 Shivan Reef (EOC) 179 2678 + 1 Steam Vents (ECL) 267 2679 + 1 Stormcarved Coast (INR) 285 2680 + 1 Sulfur Falls (EOC) 184 2681 + 1 Training Center (CMM) 434 2682 + 1 Omniscience (FDN) 161 2683 + 1 Creative Outburst (STX) 171 2684 + 1 Elemental Masterpiece (STX) 182 2685 + 1 Hedron Archive (BLC) 275 2686 + 1 Magma Opus (TDC) 296 2687 + 1 Sisay's Ring (CMR) 340 2688 + 1 Sol Ring (ECC) 57 2689 + 1 Stonespeaker Crystal (CLB) 338 2690 + 1 Thran Dynamo (BLC) 290 2691 + 1 Ur-Golem's Eye (C14) 280 2692 + 1 Archaeomancer (J25) 285 2693 + 1 Ardent Elementalist (MID) 128 2694 + 1 Mizzix's Mastery (OTC) 175 2695 + 1 Pinnacle Monk // Mystic Peak (MH3) 246 2696 + 1 Aether Gale (DSC) 109 2697 + 1 All Is Dust (M3C) 152 2698 + 1 Baral's Expertise (TDC) 146 2699 + 1 Blasphemous Act (DSC) 160 2700 + 1 Call Forth the Tempest (LTC) 509 2701 + 1 Chaos Warp (OTC) 160 2702 + 1 Counterspell (DSC) 114 2703 + 1 Fiery Confluence (LCC) 226 2704 + 1 Flood of Tears (VOC) 104 2705 + 1 Ill-Timed Explosion (MKM) 207 2706 + 1 Mystic Confluence (CMM) 108 2707 + 1 Prophetic Bolt (2X2) 265 2708 + 1 Ral's Outburst (WAR) 212 2709 + 1 Reckless Endeavor (AFC) 33 2710 + 1 Sink into Stupor // Soporific Springs (MH3) 241 2711 + 1 Volcanic Vision (C21) 182 2712 + 1 Rite of the Dragoncaller (FDN) 92 2713 + 1 Shark Typhoon (DSC) 127" 2718 2714 `; 2719 2715 2720 2716 exports[`export snapshots > archidekt/ashling-sections.txt > export to moxfield 1`] = ` ··· 3255 3251 `; 3256 3252 3257 3253 exports[`export snapshots > archidekt/ashling-sections-no-maybe.txt > export to deckstats 1`] = ` 3258 - "1 Ashling, Rekindled // Ashling, Rimebound (ECL) 290 # !Commander 3259 - 3260 - //Main 3261 - 1 Caldera Pyremaw (TDC) 33 #Burn 3262 - 1 Exalted Flamer of Tzeentch (40K) 119 #Burn #Recursion 3263 - 1 Flash Photography (FIC) 463 #Copy 3264 - 1 Relm's Sketching (FIN) 67 #Copy 3265 - 1 Replication Technique (M3C) 192 #Copy 3266 - 1 Archmage Emeritus (TDC) 145 #Draw 3267 - 1 Archmage of Runes (FDN) 30 #Draw 3268 - 1 Ashling's Command (ECL) 205 #Draw 3269 - 1 Big Score (TDC) 206 #Draw 3270 - 1 Deep Analysis (TDC) 150 #Draw 3271 - 1 Dig Through Time (DSC) 115 #Draw 3272 - 1 Drawn from Dreams (NCC) 220 #Draw 3273 - 1 Flame of Anor (LTR) 203 #Draw 3274 - 1 Hypothesizzle (PLST) GRN-178 #Draw #Removal 3275 - 1 Lórien Revealed (LTR) 60 #Draw 3276 - 1 Memories Returning (FIN) 63 #Draw 3277 - 1 Memory Deluge (INR) 75 #Draw 3278 - 1 Pirate's Pillage (2X2) 120 #Draw 3279 - 1 Scattered Thoughts (VOW) 74 #Draw 3280 - 1 Sea Gate Restoration // Sea Gate, Reborn (ZNR) 76 #Draw 3281 - 1 Silundi Vision // Silundi Isle (ZNR) 80 #Draw 3282 - 1 Tellah, Great Sage (FIN) 244 #Draw 3283 - 1 Unexpected Windfall (AFR) 164 #Draw 3284 - 1 Valakut Awakening // Valakut Stoneforge (PLST) ZNR-174 #Draw 3285 - 1 Arcane Bombardment (OTC) 154 #Greed 3286 - 1 Chimil, the Inner Sun (LCI) 249 #Greed 3287 - 1 Double Vision (NCC) 267 #Greed 3288 - 1 Fury Storm (C18) 22 #Greed 3289 - 1 Harmonic Prodigy (MH2) 132 #Greed 3290 - 1 Jin-Gitaxias, Progress Tyrant (NEO) 59 #Greed 3291 - 1 Mana Geyser (TDC) 223 #Greed 3292 - 1 Summon: G.F. Cerberus (FIN) 162 #Greed 3293 - 1 Sunbird's Invocation (C21) 180 #Greed 3294 - 1 Cascade Bluffs (EOC) 153 #Land 3295 - 1 Command Tower (ECC) 59 #Land 3296 - 1 Fiery Islet (MH1) 238 #Land 3297 - 1 Frostboil Snarl (DRC) 158 #Land 3298 - 9 Island (ECL) 270 #Land 3299 - 1 Izzet Boilerworks (M3C) 350 #Land 3300 - 1 Mistrise Village (TDM) 261 #Land 3301 - 9 Mountain (ECL) 272 #Land 3302 - 1 Reliquary Tower (TDC) 386 #Land 3303 - 1 Riverglide Pathway // Lavaglide Pathway (PLST) ZNR-264 #Land 3304 - 1 Riverpyre Verge (DFT) 260 #Land 3305 - 1 Scalding Tarn (MH2) 254 #Land 3306 - 1 Scavenger Grounds (MKC) 287 #Land 3307 - 1 Shivan Reef (EOC) 179 #Land 3308 - 1 Steam Vents (ECL) 267 #Land 3309 - 1 Stormcarved Coast (INR) 285 #Land 3310 - 1 Sulfur Falls (EOC) 184 #Land 3311 - 1 Training Center (CMM) 434 #Land 3312 - 1 Omniscience (FDN) 161 #Okay Pal 3313 - 1 Creative Outburst (STX) 171 #Ramp #Removal #Draw 3314 - 1 Elemental Masterpiece (STX) 182 #Ramp #Tokens 3315 - 1 Hedron Archive (BLC) 275 #Ramp 3316 - 1 Magma Opus (TDC) 296 #Ramp #Draw #Tokens #Removal 3317 - 1 Sisay's Ring (CMR) 340 #Ramp 3318 - 1 Sol Ring (ECC) 57 #Ramp 3319 - 1 Stonespeaker Crystal (CLB) 338 #Ramp #Removal 3320 - 1 Thran Dynamo (BLC) 290 #Ramp 3321 - 1 Ur-Golem's Eye (C14) 280 #Ramp 3322 - 1 Archaeomancer (J25) 285 #Recursion 3323 - 1 Ardent Elementalist (MID) 128 #Recursion 3324 - 1 Mizzix's Mastery (OTC) 175 #Recursion 3325 - 1 Pinnacle Monk // Mystic Peak (MH3) 246 #Recursion 3326 - 1 Aether Gale (DSC) 109 #Removal 3327 - 1 All Is Dust (M3C) 152 #Removal 3328 - 1 Baral's Expertise (TDC) 146 #Removal 3329 - 1 Blasphemous Act (DSC) 160 #Removal 3330 - 1 Call Forth the Tempest (LTC) 509 #Removal 3331 - 1 Chaos Warp (OTC) 160 #Removal 3332 - 1 Counterspell (DSC) 114 #Removal 3333 - 1 Fiery Confluence (LCC) 226 #Removal 3334 - 1 Flood of Tears (VOC) 104 #Removal 3335 - 1 Ill-Timed Explosion (MKM) 207 #Removal 3336 - 1 Mystic Confluence (CMM) 108 #Removal 3337 - 1 Prophetic Bolt (2X2) 265 #Removal #Draw 3338 - 1 Ral's Outburst (WAR) 212 #Removal 3339 - 1 Reckless Endeavor (AFC) 33 #Removal 3340 - 1 Sink into Stupor // Soporific Springs (MH3) 241 #Removal 3341 - 1 Volcanic Vision (C21) 182 #Removal #Recursion 3342 - 1 Rite of the Dragoncaller (FDN) 92 #Tokens 3343 - 1 Shark Typhoon (DSC) 127 #Tokens" 3254 + "//Main 3255 + 1 Ashling, Rekindled // Ashling, Rimebound (ECL) 290 # !Commander 3256 + 1 Caldera Pyremaw (TDC) 33 3257 + 1 Exalted Flamer of Tzeentch (40K) 119 3258 + 1 Flash Photography (FIC) 463 3259 + 1 Relm's Sketching (FIN) 67 3260 + 1 Replication Technique (M3C) 192 3261 + 1 Archmage Emeritus (TDC) 145 3262 + 1 Archmage of Runes (FDN) 30 3263 + 1 Ashling's Command (ECL) 205 3264 + 1 Big Score (TDC) 206 3265 + 1 Deep Analysis (TDC) 150 3266 + 1 Dig Through Time (DSC) 115 3267 + 1 Drawn from Dreams (NCC) 220 3268 + 1 Flame of Anor (LTR) 203 3269 + 1 Hypothesizzle (PLST) GRN-178 3270 + 1 Lórien Revealed (LTR) 60 3271 + 1 Memories Returning (FIN) 63 3272 + 1 Memory Deluge (INR) 75 3273 + 1 Pirate's Pillage (2X2) 120 3274 + 1 Scattered Thoughts (VOW) 74 3275 + 1 Sea Gate Restoration // Sea Gate, Reborn (ZNR) 76 3276 + 1 Silundi Vision // Silundi Isle (ZNR) 80 3277 + 1 Tellah, Great Sage (FIN) 244 3278 + 1 Unexpected Windfall (AFR) 164 3279 + 1 Valakut Awakening // Valakut Stoneforge (PLST) ZNR-174 3280 + 1 Arcane Bombardment (OTC) 154 3281 + 1 Chimil, the Inner Sun (LCI) 249 3282 + 1 Double Vision (NCC) 267 3283 + 1 Fury Storm (C18) 22 3284 + 1 Harmonic Prodigy (MH2) 132 3285 + 1 Jin-Gitaxias, Progress Tyrant (NEO) 59 3286 + 1 Mana Geyser (TDC) 223 3287 + 1 Summon: G.F. Cerberus (FIN) 162 3288 + 1 Sunbird's Invocation (C21) 180 3289 + 1 Cascade Bluffs (EOC) 153 3290 + 1 Command Tower (ECC) 59 3291 + 1 Fiery Islet (MH1) 238 3292 + 1 Frostboil Snarl (DRC) 158 3293 + 9 Island (ECL) 270 3294 + 1 Izzet Boilerworks (M3C) 350 3295 + 1 Mistrise Village (TDM) 261 3296 + 9 Mountain (ECL) 272 3297 + 1 Reliquary Tower (TDC) 386 3298 + 1 Riverglide Pathway // Lavaglide Pathway (PLST) ZNR-264 3299 + 1 Riverpyre Verge (DFT) 260 3300 + 1 Scalding Tarn (MH2) 254 3301 + 1 Scavenger Grounds (MKC) 287 3302 + 1 Shivan Reef (EOC) 179 3303 + 1 Steam Vents (ECL) 267 3304 + 1 Stormcarved Coast (INR) 285 3305 + 1 Sulfur Falls (EOC) 184 3306 + 1 Training Center (CMM) 434 3307 + 1 Omniscience (FDN) 161 3308 + 1 Creative Outburst (STX) 171 3309 + 1 Elemental Masterpiece (STX) 182 3310 + 1 Hedron Archive (BLC) 275 3311 + 1 Magma Opus (TDC) 296 3312 + 1 Sisay's Ring (CMR) 340 3313 + 1 Sol Ring (ECC) 57 3314 + 1 Stonespeaker Crystal (CLB) 338 3315 + 1 Thran Dynamo (BLC) 290 3316 + 1 Ur-Golem's Eye (C14) 280 3317 + 1 Archaeomancer (J25) 285 3318 + 1 Ardent Elementalist (MID) 128 3319 + 1 Mizzix's Mastery (OTC) 175 3320 + 1 Pinnacle Monk // Mystic Peak (MH3) 246 3321 + 1 Aether Gale (DSC) 109 3322 + 1 All Is Dust (M3C) 152 3323 + 1 Baral's Expertise (TDC) 146 3324 + 1 Blasphemous Act (DSC) 160 3325 + 1 Call Forth the Tempest (LTC) 509 3326 + 1 Chaos Warp (OTC) 160 3327 + 1 Counterspell (DSC) 114 3328 + 1 Fiery Confluence (LCC) 226 3329 + 1 Flood of Tears (VOC) 104 3330 + 1 Ill-Timed Explosion (MKM) 207 3331 + 1 Mystic Confluence (CMM) 108 3332 + 1 Prophetic Bolt (2X2) 265 3333 + 1 Ral's Outburst (WAR) 212 3334 + 1 Reckless Endeavor (AFC) 33 3335 + 1 Sink into Stupor // Soporific Springs (MH3) 241 3336 + 1 Volcanic Vision (C21) 182 3337 + 1 Rite of the Dragoncaller (FDN) 92 3338 + 1 Shark Typhoon (DSC) 127" 3344 3339 `; 3345 3340 3346 3341 exports[`export snapshots > archidekt/ashling-sections-no-maybe.txt > export to moxfield 1`] = ` ··· 3886 3881 `; 3887 3882 3888 3883 exports[`export snapshots > archidekt/txt-with-categories.txt > export to deckstats 1`] = ` 3889 - "1 Tifa Lockhart (FIN) 567 # !Commander 3890 - 3891 - //Main 3892 - 1 Archdruid's Charm (MKM) 151 #Instant 3893 - 1 Bala Ged Recovery // Bala Ged Sanctuary (PLST) ZNR-180 #Land 3894 - 1 Basilisk Collar (CLB) 300 #Artifact 3895 - 1 Berserk (CN2) 175 #Instant 3896 - 1 Biophagus (40K) 87 #Creature 3897 - 1 Birds of Paradise (FIC) 483 #Creature 3898 - 1 Blanchwood Armor (BRO) 171 #Enchantment 3899 - 1 Branching Evolution (MH3) 285 #Enchantment 3900 - 1 Bridgeworks Battle // Tanglespan Bridgeworks (MH3) 249 #Land 3901 - 1 Champion's Helm (CMM) 375 #Artifact 3902 - 1 Chocobo Kick (FIN) 178 #Sorcery 3903 - 1 Command Beacon (CMR) 349 #Land 3904 - 1 Court of Garenbrig (WOC) 25 #Enchantment 3905 - 1 Crop Rotation (DMR) 154 #Instant 3906 - 1 Cultivate (CMM) 889 #Sorcery 3907 - 1 Defiler of Vigor (DMU) 160 #Creature 3908 - 1 Delighted Halfling (LTR) 158 #Creature 3909 - 1 Dryad Arbor (TSR) 277 #Land 3910 - 1 Emerald Medallion (CMM) 379 #Artifact 3911 - 1 Evolution Sage (ECC) 105 #Creature 3912 - 1 Fabled Passage (ELD) 244 #Land 3913 - 1 Field of Ruin (MOC) 400 #Land 3914 - 18 Forest (ONS) 349 #Land 3915 - 1 Forgotten Ancient (FIC) 304 #Creature 3916 - 1 Ghost Quarter (PLST) CM2-253 #Land 3917 - 1 Guardian Augmenter (C21) 62 #Creature 3918 - 1 Hardened Scales (FIC) 307 #Enchantment 3919 - 1 Harmonize (PLST) C20-173 #Sorcery 3920 - 1 Heroic Intervention (SLD) 1872 #Instant 3921 - 1 Hunter's Prowess (SCD) 192 #Sorcery 3922 - 1 Innkeeper's Talent (BLB) 180 #Enchantment 3923 - 1 Inscription of Abundance (DSC) 186 #Instant 3924 - 1 Invigorate (PLST) A25-173 #Instant 3925 - 1 Kami of Whispered Hopes (MOM) 196 #Creature 3926 - 1 Kodama's Reach (CMM) 300 #Sorcery 3927 - 1 Mithril Coat (LTR) 379 #Artifact 3928 - 1 Mosswort Bridge (MOC) 415 #Land 3929 - 1 Nature's Claim (FCA) 47 #Instant 3930 - 1 Ordeal of Nylea (FDN) 641 #Enchantment 3931 - 1 Ouroboroid (EOE) 201 #Creature 3932 - 1 Ozolith, the Shattered Spire (MOM) 198 #Artifact 3933 - 1 Primal Order (HML) 92 #Enchantment 3934 - 1 Quirion Beastcaller (J25) 703 #Creature 3935 - 1 Raised by Giants (CLB) 250 #Enchantment 3936 - 1 Ram Through (CMM) 314 #Instant 3937 - 1 Ramunap Excavator (M3C) 241 #Creature 3938 - 1 Reclamation Sage (FDN) 231 #Creature 3939 - 1 Rishkar, Peema Renegade (J25) 708 #Creature 3940 - 1 Rishkar's Expertise (WOC) 130 #Sorcery 3941 - 1 Rogue's Passage (CMM) 426 #Land 3942 - 1 Shifting Woodland (MH3) 228 #Land 3943 - 1 Snakeskin Veil (CMM) 323 #Instant 3944 - 1 Sol Ring (LTC) 284 #Artifact 3945 - 1 Soul's Majesty (NEC) 131 #Sorcery 3946 - 1 Springbloom Druid (MH1) 181 #Creature 3947 - 1 Staff of Titania (BRC) 50 #Artifact 3948 - 1 Summon: Fenrir (FIN) 372 #Creature 3949 - 1 Sylvan Library (DMR) 179 #Enchantment 3950 - 1 Terramorphic Expanse (ECC) 169 #Land 3951 - 1 Terrasymbiosis (EOE) 210 #Enchantment 3952 - 1 The Earth Crystal (FIN) 184 #Artifact 3953 - 1 The Great Henge (CMM) 294 #Artifact 3954 - 1 The Immortal Sun (CMM) 393 #Artifact 3955 - 1 The Ozolith (IKO) 237 #Artifact 3956 - 1 Thundering Mightmare (VOC) 37 #Creature 3957 - 1 Tireless Tracker (EOC) 110 #Creature 3958 - 1 Torgal, A Fine Hound (FIN) 208 #Creature 3959 - 1 Tyrite Sanctum (CMM) 1049 #Land 3960 - 1 Tyvar's Stand (ONE) 190 #Instant 3961 - 1 Verdant Catacombs (MM3) 249 #Land 3962 - 1 Vibrant Cityscape (SPM) 188 #Land 3963 - 1 Viridian Revel (SOM) 132 #Enchantment 3964 - 1 War Room (MKC) 310 #Land 3965 - 1 Warden of the Grove (TDM) 166 #Creature 3966 - 1 Windswept Heath (MH3) 466 #Land 3967 - 1 Witch's Clinic (C21) 81 #Land 3968 - 1 Wood Elves (LTC) 263 #Creature 3969 - 1 Wooded Foothills (KTK) 249 #Land 3970 - 1 Yavimaya, Cradle of Growth (MH2) 261 #Land 3884 + "//Main 3885 + 1 Tifa Lockhart (FIN) 567 # !Commander 3886 + 1 Archdruid's Charm (MKM) 151 3887 + 1 Bala Ged Recovery // Bala Ged Sanctuary (PLST) ZNR-180 3888 + 1 Basilisk Collar (CLB) 300 3889 + 1 Berserk (CN2) 175 3890 + 1 Biophagus (40K) 87 3891 + 1 Birds of Paradise (FIC) 483 3892 + 1 Blanchwood Armor (BRO) 171 3893 + 1 Branching Evolution (MH3) 285 3894 + 1 Bridgeworks Battle // Tanglespan Bridgeworks (MH3) 249 3895 + 1 Champion's Helm (CMM) 375 3896 + 1 Chocobo Kick (FIN) 178 3897 + 1 Command Beacon (CMR) 349 3898 + 1 Court of Garenbrig (WOC) 25 3899 + 1 Crop Rotation (DMR) 154 3900 + 1 Cultivate (CMM) 889 3901 + 1 Defiler of Vigor (DMU) 160 3902 + 1 Delighted Halfling (LTR) 158 3903 + 1 Dryad Arbor (TSR) 277 3904 + 1 Emerald Medallion (CMM) 379 3905 + 1 Evolution Sage (ECC) 105 3906 + 1 Fabled Passage (ELD) 244 3907 + 1 Field of Ruin (MOC) 400 3908 + 18 Forest (ONS) 349 3909 + 1 Forgotten Ancient (FIC) 304 3910 + 1 Ghost Quarter (PLST) CM2-253 3911 + 1 Guardian Augmenter (C21) 62 3912 + 1 Hardened Scales (FIC) 307 3913 + 1 Harmonize (PLST) C20-173 3914 + 1 Heroic Intervention (SLD) 1872 3915 + 1 Hunter's Prowess (SCD) 192 3916 + 1 Innkeeper's Talent (BLB) 180 3917 + 1 Inscription of Abundance (DSC) 186 3918 + 1 Invigorate (PLST) A25-173 3919 + 1 Kami of Whispered Hopes (MOM) 196 3920 + 1 Kodama's Reach (CMM) 300 3921 + 1 Mithril Coat (LTR) 379 3922 + 1 Mosswort Bridge (MOC) 415 3923 + 1 Nature's Claim (FCA) 47 3924 + 1 Ordeal of Nylea (FDN) 641 3925 + 1 Ouroboroid (EOE) 201 3926 + 1 Ozolith, the Shattered Spire (MOM) 198 3927 + 1 Primal Order (HML) 92 3928 + 1 Quirion Beastcaller (J25) 703 3929 + 1 Raised by Giants (CLB) 250 3930 + 1 Ram Through (CMM) 314 3931 + 1 Ramunap Excavator (M3C) 241 3932 + 1 Reclamation Sage (FDN) 231 3933 + 1 Rishkar, Peema Renegade (J25) 708 3934 + 1 Rishkar's Expertise (WOC) 130 3935 + 1 Rogue's Passage (CMM) 426 3936 + 1 Shifting Woodland (MH3) 228 3937 + 1 Snakeskin Veil (CMM) 323 3938 + 1 Sol Ring (LTC) 284 3939 + 1 Soul's Majesty (NEC) 131 3940 + 1 Springbloom Druid (MH1) 181 3941 + 1 Staff of Titania (BRC) 50 3942 + 1 Summon: Fenrir (FIN) 372 3943 + 1 Sylvan Library (DMR) 179 3944 + 1 Terramorphic Expanse (ECC) 169 3945 + 1 Terrasymbiosis (EOE) 210 3946 + 1 The Earth Crystal (FIN) 184 3947 + 1 The Great Henge (CMM) 294 3948 + 1 The Immortal Sun (CMM) 393 3949 + 1 The Ozolith (IKO) 237 3950 + 1 Thundering Mightmare (VOC) 37 3951 + 1 Tireless Tracker (EOC) 110 3952 + 1 Torgal, A Fine Hound (FIN) 208 3953 + 1 Tyrite Sanctum (CMM) 1049 3954 + 1 Tyvar's Stand (ONE) 190 3955 + 1 Verdant Catacombs (MM3) 249 3956 + 1 Vibrant Cityscape (SPM) 188 3957 + 1 Viridian Revel (SOM) 132 3958 + 1 War Room (MKC) 310 3959 + 1 Warden of the Grove (TDM) 166 3960 + 1 Windswept Heath (MH3) 466 3961 + 1 Witch's Clinic (C21) 81 3962 + 1 Wood Elves (LTC) 263 3963 + 1 Wooded Foothills (KTK) 249 3964 + 1 Yavimaya, Cradle of Growth (MH2) 261 3971 3965 3972 3966 //Sideboard 3973 3967 1 Alhammarret's Archive (C21) 233 3974 - 1 Arcane Signet (LTC) 273 #Artifact 3968 + 1 Arcane Signet (LTC) 273 3975 3969 1 Beast Whisperer (CLU) 158 3976 - 1 Blossoming Defense (SCD) 173 #Instant 3970 + 1 Blossoming Defense (SCD) 173 3977 3971 1 Bristly Bill, Spine Sower (OTJ) 157 3978 - 1 Caged Sun (40K) 231 #Artifact 3979 - 1 Cankerbloom (ONE) 294 #Creature 3980 - 1 Eternal Witness (M3C) 227 #Creature 3981 - 1 Evolution Witness (MH3) 424 #Creature 3972 + 1 Caged Sun (40K) 231 3973 + 1 Cankerbloom (ONE) 294 3974 + 1 Eternal Witness (M3C) 227 3975 + 1 Evolution Witness (MH3) 424 3982 3976 1 Farhaven Elf (LTC) 243 3983 3977 1 Herd Heirloom (TDM) 144 3984 3978 1 Ivy Lane Denizen (J25) 674 3985 - 1 Nature's Lore (EOC) 101 #Sorcery 3986 - 1 Primal Bellow (ZEN) 176 #Instant 3979 + 1 Nature's Lore (EOC) 101 3980 + 1 Primal Bellow (ZEN) 176 3987 3981 1 Purestrain Genestealer (40K) 97 3988 - 1 Rampant Growth (CMM) 908 #Sorcery 3982 + 1 Rampant Growth (CMM) 908 3989 3983 1 Retreat to Kazandu (J25) 707 3990 3984 1 Roaring Earth (NEO) 204 3991 - 1 Ruinous Intrusion (LCC) 255 #Instant 3992 - 1 Sixth Sense (AKH) 187 #Enchantment 3985 + 1 Ruinous Intrusion (LCC) 255 3986 + 1 Sixth Sense (AKH) 187 3993 3987 1 Sylvan Ranger (WOC) 134 3994 - 1 Three Visits (CMM) 913 #Sorcery 3995 - 1 Unnatural Restoration (ONE) 191 #Sorcery" 3988 + 1 Three Visits (CMM) 913 3989 + 1 Unnatural Restoration (ONE) 191" 3996 3990 `; 3997 3991 3998 3992 exports[`export snapshots > archidekt/txt-with-categories.txt > export to moxfield 1`] = ` ··· 4645 4639 4646 4640 exports[`export snapshots > arena/pedh-commander.txt > export to deckstats 1`] = ` 4647 4641 "//NAME: hamza levered etf 4648 - 4649 - 1 Hamza, Guardian of Arashin # !Commander 4650 4642 4651 4643 //Main 4644 + 1 Hamza, Guardian of Arashin # !Commander 4652 4645 1 Alabaster Host Intercessor 4653 4646 1 Ambitious Dragonborn 4654 4647 1 Annoyed Altisaur ··· 5306 5299 exports[`export snapshots > deckstats/commander-with-categories.dec > export to deckstats 1`] = ` 5307 5300 "//NAME: Buuurrrrnnnn from deckstats.net 5308 5301 5302 + //Main 5309 5303 1 Black Waltz No. 3 # !Commander 5310 - 5311 - //Main 5312 - 1 Agate Instigator #burn 5313 - 1 Aria of Flame #burn 5314 - 1 Artist's Talent #burn 5315 - 1 Ashling, Flame Dancer #burn 5316 - 1 Black Mage's Rod #burn 5317 - 1 Blisterspit Gremlin #burn 5318 - 1 Bloodchief Ascension #burn 5319 - 1 Bontu's Monument #burn 5320 - 1 Burning Vengeance #burn 5321 - 1 Cabal Paladin #burn 5322 - 1 Caldera Pyremaw #burn 5323 - 1 Cinder Pyromancer #burn 5324 - 1 Circle of Power #burn 5325 - 1 Cornered by Black Mages #burn 5326 - 1 Coruscation Mage #burn 5327 - 1 Curse of Fool's Wisdom #burn 5328 - 1 Defiler of Instinct #burn 5329 - 1 Devoted Duelist #burn 5330 - 1 Dynavolt Tower #burn 5331 - 1 Electrostatic Field #burn 5332 - 1 Erebor Flamesmith #burn 5333 - 1 Fiery Inscription #burn 5334 - 1 Firebrand Archer #burn 5335 - 1 Firespitter Whelp #burn 5336 - 1 Geistflame Reservoir #burn 5337 - 1 Guttersnipe #burn 5338 - 1 Invasion of Regatha // Disciples of the Inferno #burn 5339 - 1 Kessig Flamebreather #burn 5340 - 1 Kindlespark Duo #burn 5341 - 1 Kuja, Genome Sorcerer // Trance Kuja, Fate Defied #burn 5342 - 1 Lambholt Raconteur // Lambholt Ravager #burn 5343 - 1 Mysidian Elder #burn 5344 - 1 Overlord of the Boilerbilges #burn 5345 - 1 Professor Onyx #burn 5346 - 1 Pyromancer's Assault #burn 5347 - 1 Queen Brahne #burn 5348 - 1 Rockslide Sorcerer #burn 5349 - 1 Rottenmouth Viper #burn 5350 - 1 Sawblade Scamp #burn 5351 - 1 Sheoldred, the Apocalypse #burn 5352 - 1 Shrine of Burning Rage #burn 5353 - 1 Sphinx-Bone Wand #burn 5354 - 1 Star Athlete #burn 5355 - 1 Teapot Slinger #burn 5356 - 1 Thermo-Alchemist #burn 5357 - 1 Tor Wauki the Younger #burn 5358 - 1 Transpose #burn 5359 - 1 Urabrask // The Great Work #burn 5360 - 1 Vial Smasher the Fierce #burn 5361 - 1 Virtue of Courage // Embereth Blaze #burn 5362 - 1 Weaver of Lightning #burn 5363 - 1 Basilisk Collar #Non creature spell 5364 - 1 Burst Lightning #Non creature spell 5365 - 1 Char #Non creature spell 5366 - 1 Eternal Thirst #Non creature spell 5367 - 1 Leech Gauntlet #Non creature spell 5368 - 1 Mask of Griselbrand #Non creature spell 5369 - 1 Poet's Quill #Non creature spell 5370 - 1 Resurrection Orb #Non creature spell 5371 - 1 Shadowspear #Non creature spell 5372 - 1 Bothersome Quasit #whenever you cast non creature spell shit 5373 - 1 Burning Prophet #whenever you cast non creature spell shit 5374 - 1 Dragon's Rage Channeler #whenever you cast non creature spell shit 5375 - 1 Fandaniel, Telophoroi Ascian #whenever you cast non creature spell shit 5376 - 1 Garland, Knight of Cornelia // Chaos, the Endless #whenever you cast non creature spell shit 5377 - 1 Harnesser of Storms #whenever you cast non creature spell shit 5378 - 1 Levitating Statue #whenever you cast non creature spell shit 5379 - 1 Manaform Hellkite #whenever you cast non creature spell shit 5380 - 1 Pyroceratops #whenever you cast non creature spell shit 5381 - 1 Rite of the Dragoncaller #whenever you cast non creature spell shit 5382 - 1 Scroll of the Masters #whenever you cast non creature spell shit 5383 - 1 Shambling Cie'th #whenever you cast non creature spell shit 5384 - 1 Spellgorger Weird #whenever you cast non creature spell shit 5385 - 1 Storm-Kiln Artist #whenever you cast non creature spell shit 5386 - 1 Sunbird's Invocation #whenever you cast non creature spell shit 5387 - 1 Vindictive Flamestoker #whenever you cast non creature spell shit 5388 - 1 Chandra's Incinerator #truc cool 5389 - 1 Harmonic Prodigy #truc cool 5390 - 1 Lindblum, Industrial Regency // Mage Siege #land 5391 - 1 Arcane Bombardment #truc rigolo 5392 - 1 Birgi, God of Storytelling // Harnfel, Horn of Bounty #truc rigolo 5393 - 1 Chandra, Hope's Beacon #truc rigolo 5394 - 1 Double Vision #truc rigolo 5395 - 1 Surge to Victory #truc rigolo 5396 - 1 Terror of the Peaks #truc rigolo 5397 - 1 Primal Amulet // Primal Wellspring #reduce cost 5398 - 1 Ambition's Cost #draw 5399 - 1 Ancient Craving #draw 5400 - 1 Bad Deal #draw 5401 - 1 Big Score #draw 5402 - 1 Bitter Reunion #draw 5403 - 1 Black Market Connections #draw 5404 - 1 Cathartic Reunion #draw 5405 - 1 Cosmos Elixir #draw 5406 - 1 Cruel Truths #draw 5407 - 1 Crushing Disappointment #draw 5408 - 1 Cut of the Profits #draw 5409 - 1 Demand Answers #draw 5410 - 1 Demon's Due #draw 5411 - 1 Diresight #draw 5412 - 1 Electric Revelation #draw 5413 - 1 Faithless Looting #draw 5414 - 1 Font of Mythos #draw 5415 - 1 Funeral Rites #draw 5416 - 1 Grab the Prize #draw 5417 - 1 Greed #draw 5418 - 1 Gruesome Realization #draw 5419 - 1 Hoarder's Greed #draw 5420 - 1 Howling Mine #draw 5421 - 1 Imposing Grandeur #draw 5422 - 1 Infectious Inquiry #draw 5423 - 1 Laughing Mad #draw 5424 - 1 Live Fast #draw 5425 - 1 Magmatic Insight #draw 5426 - 1 Monument to Endurance #draw 5427 - 1 Night's Whisper #draw 5428 - 1 Path of the Pyromancer #draw 5429 - 1 Phyrexian Arena #draw 5430 - 1 Pointed Discussion #draw 5431 - 1 Promise of Power #draw 5432 - 1 Racers' Scoreboard #draw 5433 - 1 Read the Bones #draw 5434 - 1 Risky Shortcut #draw 5435 - 1 Seize the Spoils #draw 5436 - 1 Skeletal Scrying #draw 5437 - 1 Invoke Despair #gestion 5438 - 1 Dictate of the Twin Gods #dmg en plus 5439 - 1 Fiendish Duo #dmg en plus 5440 - 1 Fiery Emancipation #dmg en plus 5441 - 1 Ojer Axonil, Deepest Might // Temple of Power #dmg en plus 5442 - 1 Sawhorn Nemesis #dmg en plus 5443 - 1 Solphim, Mayhem Dominus #dmg en plus 5444 - 1 Torbran, Thane of Red Fell #dmg en plus 5445 - 1 Twinflame Tyrant #dmg en plus 5446 - 1 Boltwave #sort de burn 5447 - 1 Breath of Malfegor #sort de burn 5448 - 1 Chandra's Ignition #sort de burn 5449 - 1 Collective Defiance #sort de burn 5450 - 1 Cut // Ribbons #sort de burn 5451 - 1 Delayed Blast Fireball #sort de burn 5452 - 1 End the Festivities #sort de burn 5453 - 1 Farideh's Fireball #sort de burn 5454 - 1 Fiery Confluence #sort de burn 5455 - 1 Iron Maiden #sort de burn 5456 - 1 Misers' Cage #sort de burn 5457 - 1 Mob Verdict #sort de burn 5458 - 1 Oath of Mages #sort de burn 5459 - 1 Price of Knowledge #sort de burn 5460 - 1 Sizzle #sort de burn 5461 - 1 Skull Rend #sort de burn 5462 - 1 Snort #sort de burn 5463 - 1 Spiteful Repossession #sort de burn 5464 - 1 Tectonic Hazard #sort de burn 5465 - 1 The Elder Dragon War #sort de burn 5466 - 1 Vicious Rumors #sort de burn 5467 - 1 Wheel of Torture #sort de burn" 5304 + 1 Agate Instigator 5305 + 1 Aria of Flame 5306 + 1 Artist's Talent 5307 + 1 Ashling, Flame Dancer 5308 + 1 Black Mage's Rod 5309 + 1 Blisterspit Gremlin 5310 + 1 Bloodchief Ascension 5311 + 1 Bontu's Monument 5312 + 1 Burning Vengeance 5313 + 1 Cabal Paladin 5314 + 1 Caldera Pyremaw 5315 + 1 Cinder Pyromancer 5316 + 1 Circle of Power 5317 + 1 Cornered by Black Mages 5318 + 1 Coruscation Mage 5319 + 1 Curse of Fool's Wisdom 5320 + 1 Defiler of Instinct 5321 + 1 Devoted Duelist 5322 + 1 Dynavolt Tower 5323 + 1 Electrostatic Field 5324 + 1 Erebor Flamesmith 5325 + 1 Fiery Inscription 5326 + 1 Firebrand Archer 5327 + 1 Firespitter Whelp 5328 + 1 Geistflame Reservoir 5329 + 1 Guttersnipe 5330 + 1 Invasion of Regatha // Disciples of the Inferno 5331 + 1 Kessig Flamebreather 5332 + 1 Kindlespark Duo 5333 + 1 Kuja, Genome Sorcerer // Trance Kuja, Fate Defied 5334 + 1 Lambholt Raconteur // Lambholt Ravager 5335 + 1 Mysidian Elder 5336 + 1 Overlord of the Boilerbilges 5337 + 1 Professor Onyx 5338 + 1 Pyromancer's Assault 5339 + 1 Queen Brahne 5340 + 1 Rockslide Sorcerer 5341 + 1 Rottenmouth Viper 5342 + 1 Sawblade Scamp 5343 + 1 Sheoldred, the Apocalypse 5344 + 1 Shrine of Burning Rage 5345 + 1 Sphinx-Bone Wand 5346 + 1 Star Athlete 5347 + 1 Teapot Slinger 5348 + 1 Thermo-Alchemist 5349 + 1 Tor Wauki the Younger 5350 + 1 Transpose 5351 + 1 Urabrask // The Great Work 5352 + 1 Vial Smasher the Fierce 5353 + 1 Virtue of Courage // Embereth Blaze 5354 + 1 Weaver of Lightning 5355 + 1 Basilisk Collar 5356 + 1 Burst Lightning 5357 + 1 Char 5358 + 1 Eternal Thirst 5359 + 1 Leech Gauntlet 5360 + 1 Mask of Griselbrand 5361 + 1 Poet's Quill 5362 + 1 Resurrection Orb 5363 + 1 Shadowspear 5364 + 1 Bothersome Quasit 5365 + 1 Burning Prophet 5366 + 1 Dragon's Rage Channeler 5367 + 1 Fandaniel, Telophoroi Ascian 5368 + 1 Garland, Knight of Cornelia // Chaos, the Endless 5369 + 1 Harnesser of Storms 5370 + 1 Levitating Statue 5371 + 1 Manaform Hellkite 5372 + 1 Pyroceratops 5373 + 1 Rite of the Dragoncaller 5374 + 1 Scroll of the Masters 5375 + 1 Shambling Cie'th 5376 + 1 Spellgorger Weird 5377 + 1 Storm-Kiln Artist 5378 + 1 Sunbird's Invocation 5379 + 1 Vindictive Flamestoker 5380 + 1 Chandra's Incinerator 5381 + 1 Harmonic Prodigy 5382 + 1 Lindblum, Industrial Regency // Mage Siege 5383 + 1 Arcane Bombardment 5384 + 1 Birgi, God of Storytelling // Harnfel, Horn of Bounty 5385 + 1 Chandra, Hope's Beacon 5386 + 1 Double Vision 5387 + 1 Surge to Victory 5388 + 1 Terror of the Peaks 5389 + 1 Primal Amulet // Primal Wellspring 5390 + 1 Ambition's Cost 5391 + 1 Ancient Craving 5392 + 1 Bad Deal 5393 + 1 Big Score 5394 + 1 Bitter Reunion 5395 + 1 Black Market Connections 5396 + 1 Cathartic Reunion 5397 + 1 Cosmos Elixir 5398 + 1 Cruel Truths 5399 + 1 Crushing Disappointment 5400 + 1 Cut of the Profits 5401 + 1 Demand Answers 5402 + 1 Demon's Due 5403 + 1 Diresight 5404 + 1 Electric Revelation 5405 + 1 Faithless Looting 5406 + 1 Font of Mythos 5407 + 1 Funeral Rites 5408 + 1 Grab the Prize 5409 + 1 Greed 5410 + 1 Gruesome Realization 5411 + 1 Hoarder's Greed 5412 + 1 Howling Mine 5413 + 1 Imposing Grandeur 5414 + 1 Infectious Inquiry 5415 + 1 Laughing Mad 5416 + 1 Live Fast 5417 + 1 Magmatic Insight 5418 + 1 Monument to Endurance 5419 + 1 Night's Whisper 5420 + 1 Path of the Pyromancer 5421 + 1 Phyrexian Arena 5422 + 1 Pointed Discussion 5423 + 1 Promise of Power 5424 + 1 Racers' Scoreboard 5425 + 1 Read the Bones 5426 + 1 Risky Shortcut 5427 + 1 Seize the Spoils 5428 + 1 Skeletal Scrying 5429 + 1 Invoke Despair 5430 + 1 Dictate of the Twin Gods 5431 + 1 Fiendish Duo 5432 + 1 Fiery Emancipation 5433 + 1 Ojer Axonil, Deepest Might // Temple of Power 5434 + 1 Sawhorn Nemesis 5435 + 1 Solphim, Mayhem Dominus 5436 + 1 Torbran, Thane of Red Fell 5437 + 1 Twinflame Tyrant 5438 + 1 Boltwave 5439 + 1 Breath of Malfegor 5440 + 1 Chandra's Ignition 5441 + 1 Collective Defiance 5442 + 1 Cut // Ribbons 5443 + 1 Delayed Blast Fireball 5444 + 1 End the Festivities 5445 + 1 Farideh's Fireball 5446 + 1 Fiery Confluence 5447 + 1 Iron Maiden 5448 + 1 Misers' Cage 5449 + 1 Mob Verdict 5450 + 1 Oath of Mages 5451 + 1 Price of Knowledge 5452 + 1 Sizzle 5453 + 1 Skull Rend 5454 + 1 Snort 5455 + 1 Spiteful Repossession 5456 + 1 Tectonic Hazard 5457 + 1 The Elder Dragon War 5458 + 1 Vicious Rumors 5459 + 1 Wheel of Torture" 5468 5460 `; 5469 5461 5470 5462 exports[`export snapshots > deckstats/commander-with-categories.dec > export to moxfield 1`] = ` ··· 6599 6591 `; 6600 6592 6601 6593 exports[`export snapshots > deckstats/generic-txt.txt > export to deckstats 1`] = ` 6602 - "1 Black Waltz No. 3 # !Commander 6603 - 6604 - //Main 6594 + "//Main 6595 + 1 Black Waltz No. 3 # !Commander 6605 6596 1 burn 6606 6597 1 Agate Instigator 6607 6598 1 Aria of Flame ··· 8409 8400 8410 8401 exports[`export snapshots > moxfield/bulk-edit-with-tags.txt > export to deckstats 1`] = ` 8411 8402 "//Main 8412 - 1 Alabaster Host Intercessor (MOM) 3 #removal 8413 - 1 Ambitious Dragonborn (CLB) 213 #payoffs / big creatures 8414 - 1 Annoyed Altisaur (2X2) 134 #payoffs / big creatures 8415 - 1 Aquastrand Spider (MM2) 140 #counter creatures 8416 - 1 Arbor Elf (LTC) 232 #dorks 8417 - 1 Arcane Signet (FIC) 334 #ramp 8418 - 1 Arcbound Mouser (MH2) 3 #counter creatures 8403 + 1 Alabaster Host Intercessor (MOM) 3 8404 + 1 Ambitious Dragonborn (CLB) 213 8405 + 1 Annoyed Altisaur (2X2) 134 8406 + 1 Aquastrand Spider (MM2) 140 8407 + 1 Arbor Elf (LTC) 232 8408 + 1 Arcane Signet (FIC) 334 8409 + 1 Arcbound Mouser (MH2) 3 8419 8410 1 Arctic Treeline (KHM) 249 8420 8411 1 Ash Barrens (PIP) 253 8421 - 1 Avacyn's Pilgrim (ISD) 170 #dorks 8412 + 1 Avacyn's Pilgrim (ISD) 170 8422 8413 1 Basking Broodscale (MH3) 145 8423 - 1 Bloom Hulk (WAR) 154 #counters 8414 + 1 Bloom Hulk (WAR) 154 8424 8415 1 Blossoming Sands (KTK) 231 8425 - 1 Bond Beetle (M13) 161 #counter creatures 8416 + 1 Bond Beetle (M13) 161 8426 8417 1 Botanical Plaza (SNC) 247 8427 8418 1 Captivating Cave (LCI) 268 8428 8419 1 Cave of Temptation (MH1) 237 8429 - 1 Citanul Woodreaders (PLST) DDR-4 #card advantage and friends 8430 - 1 Colossal Badger / Dig Deep (CLB) 223 #counters #payoffs / big creatures 8420 + 1 Citanul Woodreaders (PLST) DDR-4 8421 + 1 Colossal Badger / Dig Deep (CLB) 223 8431 8422 1 Command Tower (CMR) 350 8432 - 1 Contagious Vorrac (ONE) 164 #counters 8433 - 1 Crib Swap (2XM) 12 #removal 8434 - 1 Cytospawn Shambler (DIS) 82 #counter creatures 8435 - 1 Deepwood Denizen (MH2) 155 #card advantage and friends 8436 - 1 Devoted Druid (NCC) 286 #dorks 8437 - 1 Dread Linnorm / Scale Deflection (CLB) 225 #counters #payoffs / big creatures #protection 8438 - 1 Drix Fatemaker (EOE) 178 #counter effects #counters 8439 - 1 Druidic Ritual (CLB) 227 #card advantage and friends 8440 - 1 Duskshell Crawler (J25) 653 #counter creatures #counter effects 8441 - 1 Elvish Mystic (CMM) 284 #dorks 8423 + 1 Contagious Vorrac (ONE) 164 8424 + 1 Crib Swap (2XM) 12 8425 + 1 Cytospawn Shambler (DIS) 82 8426 + 1 Deepwood Denizen (MH2) 155 8427 + 1 Devoted Druid (NCC) 286 8428 + 1 Dread Linnorm / Scale Deflection (CLB) 225 8429 + 1 Drix Fatemaker (EOE) 178 8430 + 1 Druidic Ritual (CLB) 227 8431 + 1 Duskshell Crawler (J25) 653 8432 + 1 Elvish Mystic (CMM) 284 8442 8433 1 Etched Cornfield (DSK) 258 8443 8434 1 Evolution Witness (MH3) 151 8444 - 1 Experiment One (2X2) 146 #counter creatures 8445 - 1 Fertilid (CMR) 226 #counter creatures #ramp 8446 - 1 Fierce Empath (M21) 181 #card advantage and friends 8435 + 1 Experiment One (2X2) 146 8436 + 1 Fertilid (CMR) 226 8437 + 1 Fierce Empath (M21) 181 8447 8438 11 Forest (J25) 93 8448 8439 1 Forge of Heroes (FIC) 395 8449 - 1 Fyndhorn Elves (CMR) 228 #dorks 8450 - 1 Generous Gift (CMM) 624 #removal 8451 - 1 Gnarlid Colony (FDN) 224 #counter effects 8452 - 1 Grapple with the Past (EMN) 160 #card advantage and friends 8453 - 1 Guardian Naga / Banishing Coils (CLB) 23 #payoffs / big creatures #removal 8454 - 1 Heritage Reclamation (TDM) 145 #card advantage and friends #removal 8440 + 1 Fyndhorn Elves (CMR) 228 8441 + 1 Generous Gift (CMM) 624 8442 + 1 Gnarlid Colony (FDN) 224 8443 + 1 Grapple with the Past (EMN) 160 8444 + 1 Guardian Naga / Banishing Coils (CLB) 23 8445 + 1 Heritage Reclamation (TDM) 145 8455 8446 1 Idyllic Grange (ELD) 246 8456 - 1 Ilysian Caryatid (THB) 174 #dorks 8457 - 1 Iron Apprentice (NEO) 248 #counter creatures 8458 - 1 Ivy Elemental (IMA) 170 #payoffs / big creatures 8459 - 1 Journey to Nowhere (OTP) 3 #removal 8447 + 1 Ilysian Caryatid (THB) 174 8448 + 1 Iron Apprentice (NEO) 248 8449 + 1 Ivy Elemental (IMA) 170 8450 + 1 Journey to Nowhere (OTP) 3 8460 8451 1 Khalni Garden (PLST) DDR-28 8461 - 1 Now for Wrath, Now for Ruin! (LTR) 24 #counters 8462 - 1 Nyxborn Hydra (MH3) 164 #payoffs / big creatures 8463 - 1 Oblivion Ring (M13) 22 #removal 8452 + 1 Now for Wrath, Now for Ruin! (LTR) 24 8453 + 1 Nyxborn Hydra (MH3) 164 8454 + 1 Oblivion Ring (M13) 22 8464 8455 1 Opal Palace (CMR) 352 8465 - 1 Owlbear (AFR) 331 #card advantage and friends 8456 + 1 Owlbear (AFR) 331 8466 8457 6 Plains (J25) 82 8467 - 1 Pollenbright Druid (WAR) 173 #counter creatures #counters 8468 - 1 Predatory Hunger (EXO) 117 #counters 8469 - 1 Pridemalkin (M21) 196 #counter creatures #counter effects 8458 + 1 Pollenbright Druid (WAR) 173 8459 + 1 Predatory Hunger (EXO) 117 8460 + 1 Pridemalkin (M21) 196 8470 8461 1 Radiant Grove (DMU) 253 8471 - 1 Ram Through (PLST) IKO-170 #removal 8472 - 1 Rust Goliath (BRO) 204 #payoffs / big creatures 8473 - 1 Salt Road Packbeast (TDM) 23 #card advantage and friends 8474 - 1 Scrounging Bandar (CMR) 252 #counter creatures 8462 + 1 Ram Through (PLST) IKO-170 8463 + 1 Rust Goliath (BRO) 204 8464 + 1 Salt Road Packbeast (TDM) 23 8465 + 1 Scrounging Bandar (CMR) 252 8475 8466 1 Secluded Steppe (CMR) 491 8476 8467 1 Selesnya Sanctuary (ZNC) 140 8477 - 1 Selesnya Signet (TDC) 324 #ramp 8478 - 1 Servant of the Scale (J22) 727 #counter creatures 8479 - 1 Simic Initiate (DIS) 92 #counter creatures 8480 - 1 Smell Fear (MH2) 173 #removal 8481 - 1 Snakeskin Veil (TDM) 159 #counters #protection 8482 - 1 Spectacular Tactics (SPM) 15 #counters #protection #removal 8483 - 1 Spike Drone (TMP) 258 #counter creatures 8484 - 1 Star Pupil (J25) 259 #counter creatures 8468 + 1 Selesnya Signet (TDC) 324 8469 + 1 Servant of the Scale (J22) 727 8470 + 1 Simic Initiate (DIS) 92 8471 + 1 Smell Fear (MH2) 173 8472 + 1 Snakeskin Veil (TDM) 159 8473 + 1 Spectacular Tactics (SPM) 15 8474 + 1 Spike Drone (TMP) 258 8475 + 1 Star Pupil (J25) 259 8485 8476 1 Suburban Sanctuary (SPM) 185 8486 - 1 Sunshower Druid (BLB) 195 #counter creatures 8477 + 1 Sunshower Druid (BLB) 195 8487 8478 1 Thornglint Bridge (MH2) 258 8488 - 1 Thraben Charm (MH3) 45 #removal 8479 + 1 Thraben Charm (MH3) 45 8489 8480 1 Tranquil Expanse (C18) 289 8490 8481 1 Tranquil Thicket (BLC) 350 8491 - 1 Travel Preparations (2X2) 162 #counters 8492 - 1 Tuinvale Treefolk / Oaken Boon (ELD) 180 #counters #payoffs / big creatures 8493 - 1 Tuskguard Captain (CMM) 328 #counter effects 8494 - 1 Weftblade Enhancer (EOE) 44 #counters 8495 - 1 You Meet in a Tavern (CLB) 263 #card advantage and friends" 8482 + 1 Travel Preparations (2X2) 162 8483 + 1 Tuinvale Treefolk / Oaken Boon (ELD) 180 8484 + 1 Tuskguard Captain (CMM) 328 8485 + 1 Weftblade Enhancer (EOE) 44 8486 + 1 You Meet in a Tavern (CLB) 263" 8496 8487 `; 8497 8488 8498 8489 exports[`export snapshots > moxfield/bulk-edit-with-tags.txt > export to moxfield 1`] = ` ··· 13458 13449 { 13459 13450 "detected": "generic", 13460 13451 "expected": "generic", 13461 - } 13462 - `; 13463 - 13464 - exports[`format detection > 'archidekt/ashling-sections.txt' detects as expected format 1`] = ` 13465 - { 13466 - "detected": "archidekt", 13467 - "expected": "archidekt", 13468 - } 13469 - `; 13470 - 13471 - exports[`format detection > 'archidekt/ashling-sections-no-maybe.t…' detects as expected format 1`] = ` 13472 - { 13473 - "detected": "archidekt", 13474 - "expected": "archidekt", 13475 13452 } 13476 13453 `; 13477 13454
+3
src/lib/deck-formats/__tests__/snapshots.test.ts
··· 96 96 97 97 // Fixtures with structural differences that prevent text-identical roundtrip 98 98 // - archidekt flat/by-category: cards alphabetized, category headers become card names 99 + // - archidekt sections: old format uses Commander/Mainboard headers, we use # Sideboard + inline [Commander] 99 100 // - deckstats generic-*: cross-format (deckstats dir but generic expected format) 100 101 // - deckstats commander-with-categories: custom //category comments we don't preserve 101 102 const structurallyDifferentFixtures = new Set([ 102 103 "archidekt/ashling-flat.txt", 103 104 "archidekt/ashling-flat-no-maybe.txt", 104 105 "archidekt/ashling-by-category.txt", 106 + "archidekt/ashling-sections.txt", 107 + "archidekt/ashling-sections-no-maybe.txt", 105 108 "archidekt/txt-with-categories.txt", 106 109 "deckstats/generic-simple.txt", 107 110 "deckstats/generic-txt.txt",
+25 -38
src/lib/deck-formats/export.ts
··· 80 80 case "mtgo": 81 81 return `${quantity} ${name}`; 82 82 83 - case "arena": { 83 + case "moxfield": { 84 + // Moxfield supports #tags 84 85 const parts = [String(quantity), name]; 85 86 if (setCode) { 86 87 parts.push(`(${setCode})`); 87 88 if (collectorNumber) { 88 89 parts.push(collectorNumber); 89 90 } 91 + } 92 + if (tags.length > 0) { 93 + parts.push(...tags.map((t) => `#${t}`)); 90 94 } 91 95 return parts.join(" "); 92 96 } 93 97 94 98 default: { 95 - // moxfield, deckstats, generic, and unknown formats 99 + // arena, deckstats, generic, unknown - no tag support 96 100 const parts = [String(quantity), name]; 97 101 if (setCode) { 98 102 parts.push(`(${setCode})`); 99 103 if (collectorNumber) { 100 104 parts.push(collectorNumber); 101 105 } 102 - } 103 - if (tags.length > 0) { 104 - parts.push(...tags.map((t) => `#${t}`)); 105 106 } 106 107 return parts.join(" "); 107 108 } ··· 185 186 } 186 187 187 188 /** 188 - * Archidekt format with Nx quantity, lowercase set codes, and section headers. 189 - * Uses [Category] markers for tags. We don't preserve {top}/{noDeck}/{noPrice} options. 189 + * Archidekt format with Nx quantity, lowercase set codes. 190 + * Uses [Category] markers for tags. Commander uses [Commander] inline tag. 191 + * Only Sideboard and Maybeboard have section headers (`# Sideboard`, `# Maybeboard`). 190 192 */ 191 193 function formatArchidekt(deck: ParsedDeck): string { 192 194 const sections: string[] = []; 193 195 196 + // Commander uses [Commander] inline tag, no section header 194 197 if (deck.commander.length > 0) { 195 - sections.push("Commander"); 196 198 sections.push( 197 199 ...deck.commander.map((c) => { 198 200 const line = formatCardLine(c, "archidekt"); ··· 200 202 if (!c.tags?.length) { 201 203 return `${line} [Commander]`; 202 204 } 203 - return line; 205 + // Append Commander to existing tags 206 + return `${line.slice(0, -1)},Commander]`; 204 207 }), 205 208 ); 206 209 sections.push(""); 207 210 } 208 211 212 + // Mainboard has no section header 209 213 if (deck.mainboard.length > 0) { 210 - sections.push("Mainboard"); 211 214 sections.push(...deck.mainboard.map((c) => formatCardLine(c, "archidekt"))); 212 215 sections.push(""); 213 216 } 214 217 218 + // Sideboard uses # Sideboard header 215 219 if (deck.sideboard.length > 0) { 216 - sections.push("Sideboard"); 217 - sections.push( 218 - ...deck.sideboard.map((c) => { 219 - const line = formatCardLine(c, "archidekt"); 220 - // Add [Sideboard] marker 221 - if (!c.tags?.length) { 222 - return `${line} [Sideboard]`; 223 - } 224 - // Append Sideboard to existing tags 225 - return `${line.slice(0, -1)},Sideboard]`; 226 - }), 227 - ); 220 + sections.push("# Sideboard"); 221 + sections.push(...deck.sideboard.map((c) => formatCardLine(c, "archidekt"))); 228 222 sections.push(""); 229 223 } 230 224 225 + // Maybeboard uses # Maybeboard header 231 226 if (deck.maybeboard.length > 0) { 232 - sections.push("Maybeboard"); 227 + sections.push("# Maybeboard"); 233 228 sections.push( 234 - ...deck.maybeboard.map((c) => { 235 - const line = formatCardLine(c, "archidekt"); 236 - // Add [Maybeboard] marker (we don't preserve {noDeck}{noPrice} options) 237 - if (!c.tags?.length) { 238 - return `${line} [Maybeboard]`; 239 - } 240 - // Append Maybeboard to existing tags 241 - return `${line.slice(0, -1)},Maybeboard]`; 242 - }), 229 + ...deck.maybeboard.map((c) => formatCardLine(c, "archidekt")), 243 230 ); 244 231 } 245 232 ··· 375 362 376 363 /** 377 364 * Deckstats format with //Section comments and //NAME: metadata. 365 + * Commander goes in mainboard with `# !Commander` marker (no separate section). 378 366 */ 379 367 function formatDeckstats(deck: ParsedDeck): string { 380 368 const sections: string[] = []; ··· 384 372 sections.push(""); 385 373 } 386 374 387 - if (deck.commander.length > 0) { 375 + // Mainboard includes commander cards (with # !Commander marker) 376 + const hasMainContent = deck.commander.length > 0 || deck.mainboard.length > 0; 377 + if (hasMainContent) { 378 + sections.push("//Main"); 379 + // Commander cards first with marker 388 380 sections.push( 389 381 ...deck.commander.map( 390 382 (c) => `${formatCardLine(c, "deckstats")} # !Commander`, 391 383 ), 392 384 ); 393 - sections.push(""); 394 - } 395 - 396 - if (deck.mainboard.length > 0) { 397 - sections.push("//Main"); 398 385 sections.push(...deck.mainboard.map((c) => formatCardLine(c, "deckstats"))); 399 386 sections.push(""); 400 387 }
+2 -1
src/lib/deck-formats/index.ts
··· 31 31 export { parseCardLine, parseDeck } from "./parse"; 32 32 // Section utilities (for advanced use) 33 33 export { extractInlineSection, parseSectionMarker } from "./sections"; 34 - // Types 35 34 export type { 36 35 DeckFormat, 37 36 DeckSection, ··· 40 39 ParsedDeck, 41 40 SectionMarkerResult, 42 41 } from "./types"; 42 + // Types and constants 43 + export { DECK_FORMATS } from "./types";
+61 -20
src/lib/deck-formats/types.ts
··· 3 3 */ 4 4 5 5 /** 6 + * Metadata for each supported deck format 7 + */ 8 + export const DECK_FORMATS = { 9 + arena: { 10 + label: "Arena", 11 + description: "MTG Arena format", 12 + extension: "txt", 13 + options: { tags: false, setcodes: true }, 14 + }, 15 + mtgo: { 16 + label: "MTGO", 17 + description: "Names only", 18 + extension: "txt", 19 + options: { tags: false, setcodes: false }, 20 + }, 21 + moxfield: { 22 + label: "Moxfield", 23 + description: "With tags support", 24 + extension: "txt", 25 + options: { tags: true, setcodes: true }, 26 + }, 27 + archidekt: { 28 + label: "Archidekt", 29 + description: "With [markers]", 30 + extension: "txt", 31 + options: { tags: true, setcodes: true }, 32 + }, 33 + mtggoldfish: { 34 + label: "MTGGoldfish", 35 + description: "Exact versions", 36 + extension: "txt", 37 + options: { tags: false, setcodes: true }, 38 + }, 39 + xmage: { 40 + label: "XMage", 41 + description: "With set codes", 42 + extension: "dck", 43 + options: { tags: false, setcodes: true }, 44 + }, 45 + deckstats: { 46 + label: "Deckstats", 47 + description: "With //sections", 48 + extension: "txt", 49 + options: { tags: false, setcodes: true }, 50 + }, 51 + tappedout: { 52 + label: "TappedOut", 53 + description: "4x quantity style", 54 + extension: "txt", 55 + options: { tags: false, setcodes: true }, 56 + }, 57 + generic: { 58 + label: "Plain Text", 59 + description: "Quantity + name only", 60 + extension: "txt", 61 + options: { tags: false, setcodes: false }, 62 + }, 63 + } as const; 64 + 65 + /** 6 66 * Supported deck formats for import/export 7 - * 8 - * - arena: MTG Arena format (de facto standard) 9 - * - mtgo: MTGO format (names only, Sideboard: section) 10 - * - moxfield: Moxfield format (Arena + foil markers + tags) 11 - * - archidekt: Archidekt text export (inline section markers) 12 - * - mtggoldfish: MTGGoldfish exact versions (square brackets for set) 13 - * - xmage: XMage .dck format (set before name) 14 - * - deckstats: Deckstats.net format (comment sections) 15 - * - tappedout: TappedOut format (quantity with x suffix) 16 - * - generic: Plain card list (quantity + name only) 17 67 */ 18 - export type DeckFormat = 19 - | "arena" 20 - | "mtgo" 21 - | "moxfield" 22 - | "archidekt" 23 - | "mtggoldfish" 24 - | "xmage" 25 - | "deckstats" 26 - | "tappedout" 27 - | "generic"; 68 + export type DeckFormat = keyof typeof DECK_FORMATS; 28 69 29 70 /** 30 71 * Sections in a parsed deck
+22
src/routeTree.gen.ts
··· 27 27 import { Route as ProfileDidListRkeyIndexRouteImport } from './routes/profile/$did/list/$rkey/index' 28 28 import { Route as ProfileDidDeckRkeyIndexRouteImport } from './routes/profile/$did/deck/$rkey/index' 29 29 import { Route as ProfileDidDeckRkeyPlayRouteImport } from './routes/profile/$did/deck/$rkey/play' 30 + import { Route as ProfileDidDeckRkeyExportRouteImport } from './routes/profile/$did/deck/$rkey/export' 30 31 import { Route as ProfileDidDeckRkeyBulkEditRouteImport } from './routes/profile/$did/deck/$rkey/bulk-edit' 31 32 32 33 const SignupRoute = SignupRouteImport.update({ ··· 119 120 path: '/play', 120 121 getParentRoute: () => ProfileDidDeckRkeyRoute, 121 122 } as any) 123 + const ProfileDidDeckRkeyExportRoute = 124 + ProfileDidDeckRkeyExportRouteImport.update({ 125 + id: '/export', 126 + path: '/export', 127 + getParentRoute: () => ProfileDidDeckRkeyRoute, 128 + } as any) 122 129 const ProfileDidDeckRkeyBulkEditRoute = 123 130 ProfileDidDeckRkeyBulkEditRouteImport.update({ 124 131 id: '/bulk-edit', ··· 143 150 '/profile/$did/deck/$rkey': typeof ProfileDidDeckRkeyRouteWithChildren 144 151 '/profile/$did/list/$rkey': typeof ProfileDidListRkeyRouteWithChildren 145 152 '/profile/$did/deck/$rkey/bulk-edit': typeof ProfileDidDeckRkeyBulkEditRoute 153 + '/profile/$did/deck/$rkey/export': typeof ProfileDidDeckRkeyExportRoute 146 154 '/profile/$did/deck/$rkey/play': typeof ProfileDidDeckRkeyPlayRoute 147 155 '/profile/$did/deck/$rkey/': typeof ProfileDidDeckRkeyIndexRoute 148 156 '/profile/$did/list/$rkey/': typeof ProfileDidListRkeyIndexRoute ··· 162 170 '/profile/$did/lists': typeof ProfileDidListsRoute 163 171 '/profile/$did': typeof ProfileDidIndexRoute 164 172 '/profile/$did/deck/$rkey/bulk-edit': typeof ProfileDidDeckRkeyBulkEditRoute 173 + '/profile/$did/deck/$rkey/export': typeof ProfileDidDeckRkeyExportRoute 165 174 '/profile/$did/deck/$rkey/play': typeof ProfileDidDeckRkeyPlayRoute 166 175 '/profile/$did/deck/$rkey': typeof ProfileDidDeckRkeyIndexRoute 167 176 '/profile/$did/list/$rkey': typeof ProfileDidListRkeyIndexRoute ··· 184 193 '/profile/$did/deck/$rkey': typeof ProfileDidDeckRkeyRouteWithChildren 185 194 '/profile/$did/list/$rkey': typeof ProfileDidListRkeyRouteWithChildren 186 195 '/profile/$did/deck/$rkey/bulk-edit': typeof ProfileDidDeckRkeyBulkEditRoute 196 + '/profile/$did/deck/$rkey/export': typeof ProfileDidDeckRkeyExportRoute 187 197 '/profile/$did/deck/$rkey/play': typeof ProfileDidDeckRkeyPlayRoute 188 198 '/profile/$did/deck/$rkey/': typeof ProfileDidDeckRkeyIndexRoute 189 199 '/profile/$did/list/$rkey/': typeof ProfileDidListRkeyIndexRoute ··· 207 217 | '/profile/$did/deck/$rkey' 208 218 | '/profile/$did/list/$rkey' 209 219 | '/profile/$did/deck/$rkey/bulk-edit' 220 + | '/profile/$did/deck/$rkey/export' 210 221 | '/profile/$did/deck/$rkey/play' 211 222 | '/profile/$did/deck/$rkey/' 212 223 | '/profile/$did/list/$rkey/' ··· 226 237 | '/profile/$did/lists' 227 238 | '/profile/$did' 228 239 | '/profile/$did/deck/$rkey/bulk-edit' 240 + | '/profile/$did/deck/$rkey/export' 229 241 | '/profile/$did/deck/$rkey/play' 230 242 | '/profile/$did/deck/$rkey' 231 243 | '/profile/$did/list/$rkey' ··· 247 259 | '/profile/$did/deck/$rkey' 248 260 | '/profile/$did/list/$rkey' 249 261 | '/profile/$did/deck/$rkey/bulk-edit' 262 + | '/profile/$did/deck/$rkey/export' 250 263 | '/profile/$did/deck/$rkey/play' 251 264 | '/profile/$did/deck/$rkey/' 252 265 | '/profile/$did/list/$rkey/' ··· 396 409 preLoaderRoute: typeof ProfileDidDeckRkeyPlayRouteImport 397 410 parentRoute: typeof ProfileDidDeckRkeyRoute 398 411 } 412 + '/profile/$did/deck/$rkey/export': { 413 + id: '/profile/$did/deck/$rkey/export' 414 + path: '/export' 415 + fullPath: '/profile/$did/deck/$rkey/export' 416 + preLoaderRoute: typeof ProfileDidDeckRkeyExportRouteImport 417 + parentRoute: typeof ProfileDidDeckRkeyRoute 418 + } 399 419 '/profile/$did/deck/$rkey/bulk-edit': { 400 420 id: '/profile/$did/deck/$rkey/bulk-edit' 401 421 path: '/bulk-edit' ··· 422 442 423 443 interface ProfileDidDeckRkeyRouteChildren { 424 444 ProfileDidDeckRkeyBulkEditRoute: typeof ProfileDidDeckRkeyBulkEditRoute 445 + ProfileDidDeckRkeyExportRoute: typeof ProfileDidDeckRkeyExportRoute 425 446 ProfileDidDeckRkeyPlayRoute: typeof ProfileDidDeckRkeyPlayRoute 426 447 ProfileDidDeckRkeyIndexRoute: typeof ProfileDidDeckRkeyIndexRoute 427 448 } 428 449 429 450 const ProfileDidDeckRkeyRouteChildren: ProfileDidDeckRkeyRouteChildren = { 430 451 ProfileDidDeckRkeyBulkEditRoute: ProfileDidDeckRkeyBulkEditRoute, 452 + ProfileDidDeckRkeyExportRoute: ProfileDidDeckRkeyExportRoute, 431 453 ProfileDidDeckRkeyPlayRoute: ProfileDidDeckRkeyPlayRoute, 432 454 ProfileDidDeckRkeyIndexRoute: ProfileDidDeckRkeyIndexRoute, 433 455 }
+285
src/routes/profile/$did/deck/$rkey/export.tsx
··· 1 + import type { Did } from "@atcute/lexicons"; 2 + import { useSuspenseQuery } from "@tanstack/react-query"; 3 + import { createFileRoute, Link } from "@tanstack/react-router"; 4 + import { Check, Copy, Download } from "lucide-react"; 5 + import { useCallback, useMemo, useState } from "react"; 6 + import { toast } from "sonner"; 7 + import { asRkey } from "@/lib/atproto-client"; 8 + import { prefetchCards } from "@/lib/card-prefetch"; 9 + import { 10 + DECK_FORMATS, 11 + type DeckFormat, 12 + formatDeck, 13 + type ParsedCardLine, 14 + type ParsedDeck, 15 + } from "@/lib/deck-formats"; 16 + import { getDeckQueryOptions } from "@/lib/deck-queries"; 17 + import type { Deck, DeckCard, Section } from "@/lib/deck-types"; 18 + import { getCardsInSection } from "@/lib/deck-types"; 19 + import { getCardByIdQueryOptions } from "@/lib/queries"; 20 + import type { Card, ScryfallId } from "@/lib/scryfall-types"; 21 + 22 + export const Route = createFileRoute("/profile/$did/deck/$rkey/export")({ 23 + component: ExportPage, 24 + loader: async ({ context, params }) => { 25 + const { deck } = await context.queryClient.ensureQueryData( 26 + getDeckQueryOptions(params.did as Did, asRkey(params.rkey)), 27 + ); 28 + const cardIds = deck.cards.map((card) => card.scryfallId); 29 + await prefetchCards(context.queryClient, cardIds); 30 + return deck; 31 + }, 32 + head: ({ loaderData: deck }) => ({ 33 + meta: [ 34 + { 35 + title: deck 36 + ? `Export: ${deck.name} | DeckBelcher` 37 + : "Export | DeckBelcher", 38 + }, 39 + ], 40 + }), 41 + }); 42 + 43 + const EXPORTABLE_FORMATS = (Object.keys(DECK_FORMATS) as DeckFormat[]).filter( 44 + (f) => f !== "generic", 45 + ); 46 + 47 + function ExportPage() { 48 + const { did, rkey } = Route.useParams(); 49 + const queryClient = Route.useRouteContext().queryClient; 50 + 51 + const { 52 + data: { deck }, 53 + } = useSuspenseQuery(getDeckQueryOptions(did as Did, asRkey(rkey))); 54 + 55 + const [format, setFormat] = useState<DeckFormat>("arena"); 56 + const [includeMaybeboard, setIncludeMaybeboard] = useState(false); 57 + const [includeTags, setIncludeTags] = useState(true); 58 + const [includeSetCodes, setIncludeSetCodes] = useState(true); 59 + const [copied, setCopied] = useState(false); 60 + 61 + const formatOptions = DECK_FORMATS[format].options; 62 + 63 + const getCardData = useCallback( 64 + (id: ScryfallId): Card | undefined => { 65 + return queryClient.getQueryData(getCardByIdQueryOptions(id).queryKey); 66 + }, 67 + [queryClient], 68 + ); 69 + 70 + const convertToParsedDeck = useCallback( 71 + ( 72 + deck: Deck, 73 + opts: { 74 + includeMaybe: boolean; 75 + includeTags: boolean; 76 + includeSetCodes: boolean; 77 + }, 78 + ): ParsedDeck => { 79 + const convertSection = (section: Section): ParsedCardLine[] => { 80 + return getCardsInSection(deck, section) 81 + .map((card: DeckCard): ParsedCardLine | null => { 82 + const cardData = getCardData(card.scryfallId); 83 + if (!cardData) return null; 84 + return { 85 + quantity: card.quantity, 86 + name: cardData.name, 87 + setCode: opts.includeSetCodes 88 + ? cardData.set?.toUpperCase() 89 + : undefined, 90 + collectorNumber: opts.includeSetCodes 91 + ? cardData.collector_number 92 + : undefined, 93 + tags: opts.includeTags ? (card.tags ?? []) : [], 94 + raw: "", 95 + }; 96 + }) 97 + .filter((c): c is ParsedCardLine => c !== null); 98 + }; 99 + 100 + return { 101 + name: deck.name, 102 + commander: convertSection("commander"), 103 + mainboard: convertSection("mainboard"), 104 + sideboard: convertSection("sideboard"), 105 + maybeboard: opts.includeMaybe ? convertSection("maybeboard") : [], 106 + }; 107 + }, 108 + [getCardData], 109 + ); 110 + 111 + const exportText = useMemo(() => { 112 + const parsedDeck = convertToParsedDeck(deck, { 113 + includeMaybe: includeMaybeboard, 114 + includeTags: formatOptions.tags && includeTags, 115 + includeSetCodes: formatOptions.setcodes && includeSetCodes, 116 + }); 117 + return formatDeck(parsedDeck, format); 118 + }, [ 119 + deck, 120 + format, 121 + includeMaybeboard, 122 + includeTags, 123 + includeSetCodes, 124 + formatOptions, 125 + convertToParsedDeck, 126 + ]); 127 + 128 + const handleCopy = async () => { 129 + try { 130 + await navigator.clipboard.writeText(exportText); 131 + setCopied(true); 132 + toast.success("Copied to clipboard"); 133 + setTimeout(() => setCopied(false), 2000); 134 + } catch { 135 + toast.error("Failed to copy to clipboard"); 136 + } 137 + }; 138 + 139 + const handleDownload = () => { 140 + const blob = new Blob([exportText], { type: "text/plain" }); 141 + const url = URL.createObjectURL(blob); 142 + const a = document.createElement("a"); 143 + a.href = url; 144 + const ext = DECK_FORMATS[format].extension; 145 + const safeName = deck.name.replace(/[^a-zA-Z0-9-_ ]/g, "").trim() || "deck"; 146 + a.download = `${safeName}.${ext}`; 147 + a.click(); 148 + URL.revokeObjectURL(url); 149 + toast.success("Downloaded"); 150 + }; 151 + 152 + const lineCount = exportText.split("\n").filter((l) => l.trim()).length; 153 + 154 + return ( 155 + <div className="min-h-screen bg-white dark:bg-slate-900"> 156 + <div className="max-w-4xl mx-auto px-6 py-8"> 157 + <div className="mb-6"> 158 + <Link 159 + to="/profile/$did/deck/$rkey" 160 + params={{ did, rkey }} 161 + className="text-blue-600 dark:text-blue-400 hover:underline text-sm" 162 + > 163 + ← Back to deck 164 + </Link> 165 + <h1 className="text-2xl font-bold text-gray-900 dark:text-white mt-2"> 166 + Export: {deck.name} 167 + </h1> 168 + <p className="text-gray-600 dark:text-gray-400 mt-1"> 169 + Export your deck to various formats for use in other tools. 170 + </p> 171 + </div> 172 + 173 + {/* Format selector */} 174 + <div className="mb-6"> 175 + <span className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2"> 176 + Format 177 + </span> 178 + <div className="grid grid-cols-2 sm:grid-cols-4 gap-2"> 179 + {EXPORTABLE_FORMATS.map((f) => { 180 + const meta = DECK_FORMATS[f]; 181 + return ( 182 + <button 183 + type="button" 184 + key={f} 185 + onClick={() => setFormat(f)} 186 + aria-pressed={format === f} 187 + className={`px-3 py-2 text-sm rounded-lg border transition-colors text-left ${ 188 + format === f 189 + ? "border-blue-500 bg-blue-50 dark:bg-blue-900/30 text-blue-700 dark:text-blue-300" 190 + : "border-gray-300 dark:border-slate-700 hover:border-gray-400 dark:hover:border-slate-600 text-gray-700 dark:text-gray-300" 191 + }`} 192 + > 193 + <div className="font-medium">{meta.label}</div> 194 + <div className="text-xs opacity-70">{meta.description}</div> 195 + </button> 196 + ); 197 + })} 198 + </div> 199 + </div> 200 + 201 + {/* Options */} 202 + <div className="mb-6 space-y-2"> 203 + {getCardsInSection(deck, "maybeboard").length > 0 && ( 204 + <label className="flex items-center gap-2 text-sm text-gray-700 dark:text-gray-300 cursor-pointer"> 205 + <input 206 + type="checkbox" 207 + checked={includeMaybeboard} 208 + onChange={(e) => setIncludeMaybeboard(e.target.checked)} 209 + className="rounded border-gray-300 dark:border-slate-600 text-blue-600 focus:ring-blue-500" 210 + /> 211 + Include maybeboard ( 212 + {getCardsInSection(deck, "maybeboard").reduce( 213 + (s, c) => s + c.quantity, 214 + 0, 215 + )}{" "} 216 + cards) 217 + </label> 218 + )} 219 + <label 220 + className={`flex items-center gap-2 text-sm ${ 221 + formatOptions.tags 222 + ? "text-gray-700 dark:text-gray-300 cursor-pointer" 223 + : "text-gray-400 dark:text-gray-600 cursor-not-allowed" 224 + }`} 225 + > 226 + <input 227 + type="checkbox" 228 + checked={formatOptions.tags && includeTags} 229 + onChange={(e) => setIncludeTags(e.target.checked)} 230 + disabled={!formatOptions.tags} 231 + className="rounded border-gray-300 dark:border-slate-600 text-blue-600 focus:ring-blue-500 disabled:opacity-50" 232 + /> 233 + Include tags 234 + </label> 235 + <label 236 + className={`flex items-center gap-2 text-sm ${ 237 + formatOptions.setcodes 238 + ? "text-gray-700 dark:text-gray-300 cursor-pointer" 239 + : "text-gray-400 dark:text-gray-600 cursor-not-allowed" 240 + }`} 241 + > 242 + <input 243 + type="checkbox" 244 + checked={formatOptions.setcodes && includeSetCodes} 245 + onChange={(e) => setIncludeSetCodes(e.target.checked)} 246 + disabled={!formatOptions.setcodes} 247 + className="rounded border-gray-300 dark:border-slate-600 text-blue-600 focus:ring-blue-500 disabled:opacity-50" 248 + /> 249 + Include set codes 250 + </label> 251 + </div> 252 + 253 + {/* Preview */} 254 + <div className="mb-4"> 255 + <div className="flex items-center justify-between mb-2"> 256 + <span className="text-sm font-medium text-gray-700 dark:text-gray-300"> 257 + Preview ({lineCount} lines) 258 + </span> 259 + <div className="flex gap-2"> 260 + <button 261 + type="button" 262 + onClick={handleCopy} 263 + className="flex items-center gap-1.5 px-3 py-1.5 text-sm bg-blue-600 hover:bg-blue-700 text-white rounded-lg transition-colors" 264 + > 265 + {copied ? <Check size={14} /> : <Copy size={14} />} 266 + {copied ? "Copied" : "Copy"} 267 + </button> 268 + <button 269 + type="button" 270 + onClick={handleDownload} 271 + className="flex items-center gap-1.5 px-3 py-1.5 text-sm bg-gray-200 dark:bg-slate-700 hover:bg-gray-300 dark:hover:bg-slate-600 text-gray-900 dark:text-white rounded-lg transition-colors" 272 + > 273 + <Download size={14} /> 274 + Download 275 + </button> 276 + </div> 277 + </div> 278 + <pre className="p-4 bg-gray-50 dark:bg-slate-800 border border-gray-300 dark:border-slate-700 rounded-lg overflow-x-auto text-sm font-mono text-gray-900 dark:text-gray-100 max-h-[60vh] overflow-y-auto whitespace-pre"> 279 + {exportText} 280 + </pre> 281 + </div> 282 + </div> 283 + </div> 284 + ); 285 + }