Rename SlideCraft to DeckCraft: crates, apps, binaries, app id, file extension (.deckcraft; .slidecraft files still open), packaging, docs; ROADMAP alpha and parity estimates

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Brandon Thomas
2026-10-06 01:46:40 -04:00
co-authored by Claude Opus 5.5
parent 49278565ea
commit ae9d525bce
216 changed files with 2021 additions and 1998 deletions
+80
View File
@@ -0,0 +1,80 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
DeckCraft MSI (WiX Toolset v5: `dotnet tool install -g wix`). Built by package.ps1:
wix build deckcraft.wxs -arch x64 -d Version=1.2.3 -d BinDir=... -d IconPath=... -o out.msi
Per-machine install into Program Files, a Start Menu shortcut, `.deckcraft` owned by
DeckCraft, and DeckCraft offered under "Open with" for .pptx/.potx/.ppsx (without taking over
the user's default app for them).
UpgradeCode is fixed for DeckCraft forever (playbook §6); never change it.
-->
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
<Package
Name="DeckCraft"
Manufacturer="Learning Machines LLC"
Version="$(var.Version)"
UpgradeCode="6F9C69E7-7825-40D2-BF26-C274DA676425"
Scope="perMachine"
Compressed="yes"
Language="1033">
<SummaryInformation Description="DeckCraft presentations and slide shows" Manufacturer="Learning Machines LLC" />
<!-- Same-version upgrades let successive pre-releases of one X.Y.Z replace each other
(MSI versions are numeric, so 1.2.3-rc.1 and 1.2.3-rc.2 are both 1.2.3). -->
<MajorUpgrade AllowSameVersionUpgrades="yes"
DowngradeErrorMessage="A newer version of DeckCraft is already installed." />
<MediaTemplate EmbedCab="yes" CompressionLevel="high" />
<Icon Id="DeckcraftIcon.ico" SourceFile="$(var.IconPath)" />
<Property Id="ARPPRODUCTICON" Value="DeckcraftIcon.ico" />
<Property Id="ARPURLINFOABOUT" Value="https://getartcraft.com/apps/deckcraft" />
<Property Id="ARPURLUPDATEINFO" Value="https://getartcraft.com/apps/deckcraft" />
<Property Id="ARPHELPLINK" Value="https://discord.gg/artcraft" />
<StandardDirectory Id="ProgramFiles6432Folder">
<Directory Id="INSTALLFOLDER" Name="DeckCraft" />
</StandardDirectory>
<StandardDirectory Id="ProgramMenuFolder" />
<Feature Id="Main" Title="DeckCraft" Level="1">
<ComponentGroupRef Id="DeckcraftFiles" />
</Feature>
</Package>
<Fragment>
<ComponentGroup Id="DeckcraftFiles" Directory="INSTALLFOLDER">
<Component Id="DeckcraftApp" Guid="D87EA444-41A4-4C19-922E-66D1A29461FF">
<File Id="DeckcraftExe" Source="$(var.BinDir)\deckcraft.exe" KeyPath="yes">
<Shortcut Id="StartMenuShortcut" Directory="ProgramMenuFolder" Name="DeckCraft"
Description="DeckCraft presentations and slide shows" WorkingDirectory="INSTALLFOLDER" Advertise="yes"
Icon="DeckcraftIcon.ico" IconIndex="0" />
</File>
<!-- .deckcraft: DeckCraft's own format. -->
<ProgId Id="DeckCraft.Presentation" Description="DeckCraft Presentation" Icon="DeckcraftExe" IconIndex="0">
<Extension Id="deckcraft" ContentType="application/x-deckcraft">
<Verb Id="open" Command="Open" TargetFile="DeckcraftExe" Argument="&quot;%1&quot;" />
</Extension>
</ProgId>
<!-- "Open with" for PowerPoint formats, without becoming the default. -->
<RegistryValue Root="HKLM" Key="Software\Classes\Applications\deckcraft.exe" Name="FriendlyAppName" Value="DeckCraft" Type="string" />
<RegistryValue Root="HKLM" Key="Software\Classes\Applications\deckcraft.exe\shell\open\command" Value="&quot;[#DeckcraftExe]&quot; &quot;%1&quot;" Type="string" />
<RegistryValue Root="HKLM" Key="Software\Classes\Applications\deckcraft.exe\SupportedTypes" Name=".deckcraft" Value="" Type="string" />
<RegistryValue Root="HKLM" Key="Software\Classes\Applications\deckcraft.exe\SupportedTypes" Name=".pptx" Value="" Type="string" />
<RegistryValue Root="HKLM" Key="Software\Classes\Applications\deckcraft.exe\SupportedTypes" Name=".potx" Value="" Type="string" />
<RegistryValue Root="HKLM" Key="Software\Classes\Applications\deckcraft.exe\SupportedTypes" Name=".ppsx" Value="" Type="string" />
<RegistryValue Root="HKLM" Key="Software\Classes\.pptx\OpenWithProgids" Name="DeckCraft.Presentation" Value="" Type="string" />
<RegistryValue Root="HKLM" Key="Software\Classes\.potx\OpenWithProgids" Name="DeckCraft.Presentation" Value="" Type="string" />
<RegistryValue Root="HKLM" Key="Software\Classes\.ppsx\OpenWithProgids" Name="DeckCraft.Presentation" Value="" Type="string" />
<RegistryValue Root="HKLM" Key="Software\Microsoft\Windows\CurrentVersion\App Paths\deckcraft.exe" Value="[#DeckcraftExe]" Type="string" />
</Component>
<Component Id="DeckcraftCli">
<File Id="DeckcraftCliExe" Source="$(var.BinDir)\deckcraft-cli.exe" KeyPath="yes" />
</Component>
</ComponentGroup>
</Fragment>
</Wix>
+19 -19
View File
@@ -1,11 +1,11 @@
<#
.SYNOPSIS
Build, sign and package SlideCraft for Windows.
Build, sign and package DeckCraft for Windows.
.DESCRIPTION
Produces, in $env:DIST (default: dist/release):
slidecraft-<version>-windows-<arch>.msi per-machine installer (WiX v5)
slidecraft-<version>-windows-<arch>-portable.zip slidecraft.exe + slidecraft-cli.exe
deckcraft-<version>-windows-<arch>.msi per-machine installer (WiX v5)
deckcraft-<version>-windows-<arch>-portable.zip deckcraft.exe + deckcraft-cli.exe
The binaries link the C runtime statically (+crt-static), so neither the MSI nor the portable
zip needs the Visual C++ redistributable. Signing is delegated to sign.ps1 (skipped with a
@@ -33,7 +33,7 @@ function Invoke-Native([string] $What, [scriptblock] $Block) {
}
# The version lives in one place: [workspace.package] version in the root Cargo.toml.
$Version = $env:SLIDECRAFT_VERSION
$Version = $env:DECKCRAFT_VERSION
if (-not $Version) {
$inPkg = $false
foreach ($line in Get-Content (Join-Path $Root 'Cargo.toml')) {
@@ -50,10 +50,10 @@ $Dist = if ($env:DIST) { $env:DIST } else { Join-Path $Root 'dist\release' }
$TargetDir = if ($env:CARGO_TARGET_DIR) { $env:CARGO_TARGET_DIR } else { Join-Path $Root 'target' }
New-Item -ItemType Directory -Force -Path $Dist | Out-Null
if (-not $env:SLIDECRAFT_BUILD_SHA) { $env:SLIDECRAFT_BUILD_SHA = (git -C $Root rev-parse HEAD 2>$null) }
if (-not $env:SLIDECRAFT_BUILD_DATE) { $env:SLIDECRAFT_BUILD_DATE = (Get-Date).ToUniversalTime().ToString('yyyy-MM-dd') }
if (-not $env:DECKCRAFT_BUILD_SHA) { $env:DECKCRAFT_BUILD_SHA = (git -C $Root rev-parse HEAD 2>$null) }
if (-not $env:DECKCRAFT_BUILD_DATE) { $env:DECKCRAFT_BUILD_DATE = (Get-Date).ToUniversalTime().ToString('yyyy-MM-dd') }
Write-Output "SlideCraft $Version for Windows $Arch ($Target)"
Write-Output "DeckCraft $Version for Windows $Arch ($Target)"
if (-not $SkipBuild) {
# Static CRT: no VC++ redistributable needed. Scoped to the target so host build scripts and
@@ -61,8 +61,8 @@ if (-not $SkipBuild) {
$flagVar = 'CARGO_TARGET_' + ($Target.ToUpper() -replace '-', '_') + '_RUSTFLAGS'
[Environment]::SetEnvironmentVariable($flagVar, '-C target-feature=+crt-static')
# Fail the build (rather than warn) if the icon/VERSIONINFO can't be embedded.
$env:SLIDECRAFT_REQUIRE_WINRES = '1'
Invoke-Native "cargo build ($Target)" { cargo build --release --locked -p slidecraft -p slidecraft-cli --target $Target }
$env:DECKCRAFT_REQUIRE_WINRES = '1'
Invoke-Native "cargo build ($Target)" { cargo build --release --locked -p deckcraft -p deckcraft-cli --target $Target }
}
$Bin = Join-Path $TargetDir "$Target\release"
@@ -77,7 +77,7 @@ function Get-PeHeader([string] $Path) {
return @{ Machine = [BitConverter]::ToUInt16($bytes, $pe + 4); Subsystem = [BitConverter]::ToUInt16($bytes, $pe + 0x5C) }
}
$Machine = switch ($Arch) { 'x64' { 0x8664 } 'x86' { 0x14C } 'arm64' { 0xAA64 } }
foreach ($check in @(@('slidecraft.exe', 2), @('slidecraft-cli.exe', 3))) {
foreach ($check in @(@('deckcraft.exe', 2), @('deckcraft-cli.exe', 3))) {
$h = Get-PeHeader (Join-Path $Bin $check[0])
if ($h.Machine -ne $Machine) { throw "$($check[0]) is for machine 0x$('{0:X}' -f $h.Machine), expected 0x$('{0:X}' -f $Machine) ($Arch)" }
if ($h.Subsystem -ne $check[1]) { throw "$($check[0]) has PE subsystem $($h.Subsystem), expected $($check[1])" }
@@ -86,15 +86,15 @@ foreach ($check in @(@('slidecraft.exe', 2), @('slidecraft-cli.exe', 3))) {
$Stage = Join-Path $TargetDir "windows-package\$Arch"
Remove-Item -Recurse -Force $Stage -ErrorAction SilentlyContinue
New-Item -ItemType Directory -Force -Path $Stage | Out-Null
Copy-Item (Join-Path $Bin 'slidecraft.exe'), (Join-Path $Bin 'slidecraft-cli.exe') $Stage
Copy-Item (Join-Path $Bin 'deckcraft.exe'), (Join-Path $Bin 'deckcraft-cli.exe') $Stage
& (Join-Path $PSScriptRoot 'sign.ps1') (Join-Path $Stage 'slidecraft.exe') (Join-Path $Stage 'slidecraft-cli.exe')
& (Join-Path $PSScriptRoot 'sign.ps1') (Join-Path $Stage 'deckcraft.exe') (Join-Path $Stage 'deckcraft-cli.exe')
# ---- MSI ---------------------------------------------------------------------------------------
$Msi = Join-Path $Dist "slidecraft-$Version-windows-$Arch.msi"
$Msi = Join-Path $Dist "deckcraft-$Version-windows-$Arch.msi"
Invoke-Native 'wix build' {
wix build (Join-Path $PSScriptRoot 'slidecraft.wxs') -arch $Arch `
-d "Version=$MsiVersion" -d "BinDir=$Stage" -d "IconPath=$(Join-Path $Root 'assets\app-icon\slidecraft.ico')" `
wix build (Join-Path $PSScriptRoot 'deckcraft.wxs') -arch $Arch `
-d "Version=$MsiVersion" -d "BinDir=$Stage" -d "IconPath=$(Join-Path $Root 'assets\app-icon\deckcraft.ico')" `
-o $Msi
}
# wix writes its debug symbols (.wixpdb) next to the MSI; keep them out of the release assets.
@@ -102,7 +102,7 @@ Remove-Item -Force -ErrorAction SilentlyContinue ([IO.Path]::ChangeExtension($Ms
& (Join-Path $PSScriptRoot 'sign.ps1') $Msi
# ---- portable zip ------------------------------------------------------------------------------
$Portable = Join-Path $TargetDir "windows-package\slidecraft-$Version-windows-$Arch-portable"
$Portable = Join-Path $TargetDir "windows-package\deckcraft-$Version-windows-$Arch-portable"
Remove-Item -Recurse -Force $Portable -ErrorAction SilentlyContinue
New-Item -ItemType Directory -Force -Path $Portable | Out-Null
Copy-Item (Join-Path $Stage '*.exe') $Portable
@@ -116,7 +116,7 @@ if ($env:CRAFT_FONTS_DIR) {
Copy-Item $ofl.FullName (Join-Path $Portable "OFL-$($ofl.Directory.Name).txt")
}
}
$Zip = Join-Path $Dist "slidecraft-$Version-windows-$Arch-portable.zip"
$Zip = Join-Path $Dist "deckcraft-$Version-windows-$Arch-portable.zip"
Remove-Item -Force $Zip -ErrorAction SilentlyContinue
Compress-Archive -Path $Portable -DestinationPath $Zip
@@ -124,8 +124,8 @@ Compress-Archive -Path $Portable -DestinationPath $Zip
# here.
$HostArch = [System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture.ToString().ToLowerInvariant()
if ($Arch -ne 'arm64' -or $HostArch -eq 'arm64') {
Invoke-Native 'slidecraft-cli --version' { & (Join-Path $Stage 'slidecraft-cli.exe') --version }
Invoke-Native 'deckcraft-cli --version' { & (Join-Path $Stage 'deckcraft-cli.exe') --version }
} else {
Write-Output "skipping slidecraft-cli --version: an $Arch build doesn't run on this $HostArch machine"
Write-Output "skipping deckcraft-cli --version: an $Arch build doesn't run on this $HostArch machine"
}
Get-Item $Msi, $Zip | Format-Table Name, Length
+3 -3
View File
@@ -15,7 +15,7 @@
timestamp server, ...). Optional overrides: WINDOWS_TIMESTAMP_URL, SIGNTOOL (path to signtool.exe).
.EXAMPLE
pwsh packaging/windows/sign.ps1 dist/slidecraft.exe dist/Slidecraft.msi
pwsh packaging/windows/sign.ps1 dist/deckcraft.exe dist/Deckcraft.msi
#>
param(
[Parameter(Mandatory = $true, ValueFromRemainingArguments = $true)]
@@ -55,8 +55,8 @@ if (-not $haveCert -and -not $haveAzure) {
}
$script:SignTool = Find-SignTool
$common = @('sign', '/v', '/fd', 'SHA256', '/td', 'SHA256', '/d', 'SlideCraft', '/du', 'https://github.com/storytold/slidecraft')
$tmp = Join-Path ([IO.Path]::GetTempPath()) "slidecraft-sign-$PID"
$common = @('sign', '/v', '/fd', 'SHA256', '/td', 'SHA256', '/d', 'DeckCraft', '/du', 'https://github.com/storytold/deckcraft')
$tmp = Join-Path ([IO.Path]::GetTempPath()) "deckcraft-sign-$PID"
New-Item -ItemType Directory -Force -Path $tmp | Out-Null
try {
-80
View File
@@ -1,80 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
SlideCraft MSI (WiX Toolset v5: `dotnet tool install -g wix`). Built by package.ps1:
wix build slidecraft.wxs -arch x64 -d Version=1.2.3 -d BinDir=... -d IconPath=... -o out.msi
Per-machine install into Program Files, a Start Menu shortcut, `.slidecraft` owned by
SlideCraft, and SlideCraft offered under "Open with" for .pptx/.potx/.ppsx (without taking over
the user's default app for them).
UpgradeCode is fixed for SlideCraft forever (playbook §6); never change it.
-->
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
<Package
Name="SlideCraft"
Manufacturer="Learning Machines LLC"
Version="$(var.Version)"
UpgradeCode="6F9C69E7-7825-40D2-BF26-C274DA676425"
Scope="perMachine"
Compressed="yes"
Language="1033">
<SummaryInformation Description="SlideCraft presentations and slide shows" Manufacturer="Learning Machines LLC" />
<!-- Same-version upgrades let successive pre-releases of one X.Y.Z replace each other
(MSI versions are numeric, so 1.2.3-rc.1 and 1.2.3-rc.2 are both 1.2.3). -->
<MajorUpgrade AllowSameVersionUpgrades="yes"
DowngradeErrorMessage="A newer version of SlideCraft is already installed." />
<MediaTemplate EmbedCab="yes" CompressionLevel="high" />
<Icon Id="SlidecraftIcon.ico" SourceFile="$(var.IconPath)" />
<Property Id="ARPPRODUCTICON" Value="SlidecraftIcon.ico" />
<Property Id="ARPURLINFOABOUT" Value="https://getartcraft.com/apps/slidecraft" />
<Property Id="ARPURLUPDATEINFO" Value="https://getartcraft.com/apps/slidecraft" />
<Property Id="ARPHELPLINK" Value="https://discord.gg/artcraft" />
<StandardDirectory Id="ProgramFiles6432Folder">
<Directory Id="INSTALLFOLDER" Name="SlideCraft" />
</StandardDirectory>
<StandardDirectory Id="ProgramMenuFolder" />
<Feature Id="Main" Title="SlideCraft" Level="1">
<ComponentGroupRef Id="SlidecraftFiles" />
</Feature>
</Package>
<Fragment>
<ComponentGroup Id="SlidecraftFiles" Directory="INSTALLFOLDER">
<Component Id="SlidecraftApp" Guid="D87EA444-41A4-4C19-922E-66D1A29461FF">
<File Id="SlidecraftExe" Source="$(var.BinDir)\slidecraft.exe" KeyPath="yes">
<Shortcut Id="StartMenuShortcut" Directory="ProgramMenuFolder" Name="SlideCraft"
Description="SlideCraft presentations and slide shows" WorkingDirectory="INSTALLFOLDER" Advertise="yes"
Icon="SlidecraftIcon.ico" IconIndex="0" />
</File>
<!-- .slidecraft: SlideCraft's own format. -->
<ProgId Id="SlideCraft.Presentation" Description="SlideCraft Presentation" Icon="SlidecraftExe" IconIndex="0">
<Extension Id="slidecraft" ContentType="application/x-slidecraft">
<Verb Id="open" Command="Open" TargetFile="SlidecraftExe" Argument="&quot;%1&quot;" />
</Extension>
</ProgId>
<!-- "Open with" for PowerPoint formats, without becoming the default. -->
<RegistryValue Root="HKLM" Key="Software\Classes\Applications\slidecraft.exe" Name="FriendlyAppName" Value="SlideCraft" Type="string" />
<RegistryValue Root="HKLM" Key="Software\Classes\Applications\slidecraft.exe\shell\open\command" Value="&quot;[#SlidecraftExe]&quot; &quot;%1&quot;" Type="string" />
<RegistryValue Root="HKLM" Key="Software\Classes\Applications\slidecraft.exe\SupportedTypes" Name=".slidecraft" Value="" Type="string" />
<RegistryValue Root="HKLM" Key="Software\Classes\Applications\slidecraft.exe\SupportedTypes" Name=".pptx" Value="" Type="string" />
<RegistryValue Root="HKLM" Key="Software\Classes\Applications\slidecraft.exe\SupportedTypes" Name=".potx" Value="" Type="string" />
<RegistryValue Root="HKLM" Key="Software\Classes\Applications\slidecraft.exe\SupportedTypes" Name=".ppsx" Value="" Type="string" />
<RegistryValue Root="HKLM" Key="Software\Classes\.pptx\OpenWithProgids" Name="SlideCraft.Presentation" Value="" Type="string" />
<RegistryValue Root="HKLM" Key="Software\Classes\.potx\OpenWithProgids" Name="SlideCraft.Presentation" Value="" Type="string" />
<RegistryValue Root="HKLM" Key="Software\Classes\.ppsx\OpenWithProgids" Name="SlideCraft.Presentation" Value="" Type="string" />
<RegistryValue Root="HKLM" Key="Software\Microsoft\Windows\CurrentVersion\App Paths\slidecraft.exe" Value="[#SlidecraftExe]" Type="string" />
</Component>
<Component Id="SlidecraftCli">
<File Id="SlidecraftCliExe" Source="$(var.BinDir)\slidecraft-cli.exe" KeyPath="yes" />
</Component>
</ComponentGroup>
</Fragment>
</Wix>