M4.11: packaging metadata describes a vector illustration app

Drop the file types and wording carried over from the sibling raster
editor: the macOS exported type now declares .vectorcraft/.drawcraft
(was .pcraft) and the raster imported types (large raster documents, QOI)
are gone; the dev bundle's PDF type is "PDF Document"; Linux categories and
keywords say vector graphics (no trademark keyword), the AppStream
description and screenshot show VectorCraft, and the deb/rpm, MSI and web
embedding descriptions say vector illustration app. File associations stay
as they are. An xtask test rejects raster-editor wording in packaging/.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
bflatasticandClaude Opus 5.5 committed 2026-10-04 11:19:13 +07:00
1 parent 016fcbf34e
commit 0af38a31fd
7 files changed
+77 -65

No files matched your search

@@ -10,5 +10,5 @@ Terminal=false
StartupNotify=true
StartupWMClass=ai.storyteller.vectorcraft
Categories=Graphics;2DGraphics;VectorGraphics;
Keywords=vector;illustration;svg;pdf;drawing;bezier;illustrator;
Keywords=vector;illustration;svg;pdf;drawing;bezier;
MimeType=image/svg+xml;application/pdf;
@@ -12,7 +12,9 @@
</developer>
<description>
<p>
VectorCraft is a vector graphics editor. Draw and edit vector illustrations, SVG and PDF
VectorCraft is an open-source vector illustration app. Draw with pen, shape and brush tools,
style art with fills, strokes, gradients and live effects, lay out artboards and type, and
open and save SVG and PDF.
</p>
</description>
<launchable type="desktop-id">ai.storyteller.vectorcraft.desktop</launchable>
@@ -24,19 +26,21 @@
<url type="contact">https://discord.gg/artcraft</url>
<categories>
<category>Graphics</category>
<category>RasterGraphics</category>
<category>Photography</category>
<category>2DGraphics</category>
<category>VectorGraphics</category>
</categories>
<keywords>
<keyword>photo</keyword>
<keyword>image editor</keyword>
<keyword>psd</keyword>
<keyword>layers</keyword>
<keyword>vector</keyword>
<keyword>illustration</keyword>
<keyword>svg</keyword>
<keyword>pdf</keyword>
<keyword>drawing</keyword>
<keyword>bezier</keyword>
</keywords>
<screenshots>
<screenshot type="default">
<caption>Editing The Great Wave off Kanagawa with type layers and adjustment layers</caption>
<image>https://raw.githubusercontent.com/storytold/vectorcraft/main/docs/images/vectorcraft-demo.jpg</image>
<caption>Editing the Neon Drive poster with a live glow effect in the Appearance panel</caption>
<image>https://raw.githubusercontent.com/storytold/vectorcraft/main/docs/images/shot-1-neon.png</image>
</screenshot>
</screenshots>
<branding>
+3 -3
View File
@@ -17,9 +17,9 @@ vendor: Learning Machines LLC
homepage: https://getartcraft.com/apps/vectorcraft
license: MIT OR Apache-2.0
description: |-
Open-source, native image editor that works the way Photoshop users expect.
Layers, masks, adjustment layers, layer styles, type and brushes; opens and
saves layered PSD/PSB files; 8/16/32-bit documents; GPU compositing (wgpu).
Open-source, native vector illustration app.
Pen, shape and brush tools, artboards, type, gradients, symbols and live
effects; opens and saves SVG and PDF.
Includes vectorcraft-cli, a headless converter and command runner.
# The binaries link only glibc and libgcc_s directly. Windowing (X11/Wayland, xkbcommon) and the
+2 -39
View File
@@ -45,7 +45,7 @@
<key>NSHumanReadableCopyright</key>
<string>Copyright © the VectorCraft authors. MIT OR Apache-2.0.</string>
<!-- Vectorcraft's own format. -->
<!-- VectorCraft's own format (.drawcraft is its name from before the rename). -->
<key>UTExportedTypeDeclarations</key>
<array>
<dict>
@@ -63,48 +63,11 @@
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array><string>pcraft</string></array>
<array><string>vectorcraft</string><string>drawcraft</string></array>
<key>public.mime-type</key>
<array><string>application/x-vectorcraft</string></array>
</dict>
</dict>
</array>
<!-- Types macOS may not know; the system's own declaration wins when it has one. -->
<key>UTImportedTypeDeclarations</key>
<array>
<dict>
<key>UTTypeIdentifier</key>
<string>com.adobe.photoshop-large-image</string>
<key>UTTypeDescription</key>
<string>Photoshop Large Document</string>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
<string>public.image</string>
</array>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array><string>psb</string></array>
</dict>
</dict>
<dict>
<key>UTTypeIdentifier</key>
<string>ai.storyteller.vectorcraft.qoi</string>
<key>UTTypeDescription</key>
<string>QOI Image</string>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
<string>public.image</string>
</array>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array><string>qoi</string></array>
</dict>
</dict>
</array>
</dict>
</plist>
+1 -1
View File
@@ -55,7 +55,7 @@ Local test: `python3 -m http.server 8765` inside the folder, then open http://lo
```html
<iframe
src="https://example.com/vectorcraft/"
title="VectorCraft image editor"
title="VectorCraft vector illustration app"
style="width: 100%; height: 720px; border: 0;"
allow="fullscreen; clipboard-read; clipboard-write"
allowfullscreen>
+4 -5
View File
@@ -4,9 +4,8 @@
wix build vectorcraft.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, `.pcraft` owned by VectorCraft,
and VectorCraft offered under "Open with" for PSD/PSB and the image formats it reads (without
taking over the user's default app for them).
Per-machine install into Program Files, a Start Menu shortcut and an App Paths entry (so
`vectorcraft` starts from the Run dialog), plus vectorcraft-cli.
-->
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
<Package
@@ -17,7 +16,7 @@
Scope="perMachine"
Compressed="yes"
Language="1033">
<SummaryInformation Description="VectorCraft image editor" Manufacturer="Learning Machines LLC" />
<SummaryInformation Description="VectorCraft vector illustration app" 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"
@@ -45,7 +44,7 @@
<Component Id="VectorcraftApp" Guid="0E8C6C5E-DE4A-4E1D-9DB0-44E8E38C2103">
<File Id="VectorcraftExe" Source="$(var.BinDir)\vectorcraft.exe" KeyPath="yes">
<Shortcut Id="StartMenuShortcut" Directory="ProgramMenuFolder" Name="VectorCraft"
Description="VectorCraft image editor" WorkingDirectory="INSTALLFOLDER" Advertise="yes"
Description="VectorCraft vector illustration app" WorkingDirectory="INSTALLFOLDER" Advertise="yes"
Icon="VectorcraftIcon" IconIndex="0" />
</File>
+53 -7
View File
@@ -21,8 +21,14 @@ pub fn run(root: &Path) -> Result<(), String> {
std::fs::copy(target.join("release/vectorcraft"), app.join("MacOS/VectorCraft")).map_err(|e| format!("copy app: {e}"))?;
std::fs::copy(target.join("release/vectorcraft-cli"), app.join("MacOS/vectorcraft-cli")).map_err(|e| format!("copy cli: {e}"))?;
std::fs::copy(root.join("assets/app-icon/vectorcraft.icns"), app.join("Resources/VectorCraft.icns")).map_err(|e| format!("copy icon: {e}"))?;
let version = env!("CARGO_PKG_VERSION");
let plist = format!(
std::fs::write(app.join("Info.plist"), info_plist(env!("CARGO_PKG_VERSION"))).map_err(|e| e.to_string())?;
println!("built {}", root.join("dist/VectorCraft.app").display());
Ok(())
}
/// The development bundle's `Info.plist`.
fn info_plist(version: &str) -> String {
format!(
r#"<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"><dict>
@@ -39,12 +45,52 @@ pub fn run(root: &Path) -> Result<(), String> {
<key>CFBundleDocumentTypes</key><array>
<dict><key>CFBundleTypeName</key><string>VectorCraft Document</string><key>CFBundleTypeExtensions</key><array><string>vectorcraft</string></array><key>CFBundleTypeRole</key><string>Editor</string></dict>
<dict><key>CFBundleTypeName</key><string>SVG</string><key>CFBundleTypeExtensions</key><array><string>svg</string></array><key>CFBundleTypeRole</key><string>Editor</string></dict>
<dict><key>CFBundleTypeName</key><string>PDF / Illustrator</string><key>CFBundleTypeExtensions</key><array><string>pdf</string><string>ai</string></array><key>CFBundleTypeRole</key><string>Viewer</string></dict>
<dict><key>CFBundleTypeName</key><string>PDF Document</string><key>CFBundleTypeExtensions</key><array><string>pdf</string><string>ai</string></array><key>CFBundleTypeRole</key><string>Viewer</string></dict>
</array>
</dict></plist>
"#
);
std::fs::write(app.join("Info.plist"), plist).map_err(|e| e.to_string())?;
println!("built {}", root.join("dist/VectorCraft.app").display());
Ok(())
)
}
#[cfg(test)]
mod tests {
use super::*;
/// File types and wording a raster image editor's packaging carries (lowercase).
const RASTER_EDITOR: &[&str] = &["pcraft", "psd", "psb", "qoi", "photo", "rastergraphics", "image editor"];
fn text_files(dir: &Path, out: &mut Vec<(String, String)>) {
for e in std::fs::read_dir(dir).unwrap().flatten() {
let p = e.path();
if p.is_dir() {
text_files(&p, out);
} else if let Ok(t) = std::fs::read_to_string(&p) {
out.push((p.display().to_string(), t.to_ascii_lowercase()));
}
}
}
#[test]
fn packaging_describes_a_vector_app() {
let mut files = vec![];
text_files(&crate::root().join("packaging"), &mut files);
assert!(files.len() > 5, "packaging files found");
for (path, text) in &files {
for w in RASTER_EDITOR {
assert!(!text.contains(w), "{path} mentions `{w}`");
}
}
let read = |p: &str| std::fs::read_to_string(crate::root().join(p)).unwrap();
let plist = read("packaging/macos/Info.plist.in");
assert!(plist.contains("<array><string>vectorcraft</string><string>drawcraft</string></array>"), "native format extensions");
assert!(read("packaging/linux/ai.storyteller.vectorcraft.desktop").contains("Categories=Graphics;2DGraphics;VectorGraphics;"));
assert!(read("packaging/linux/ai.storyteller.vectorcraft.metainfo.xml.in").contains("<category>VectorGraphics</category>"));
}
#[test]
fn dev_bundle_plist_names_types_neutrally() {
let p = info_plist("1.2.3");
assert!(p.contains("<key>CFBundleShortVersionString</key><string>1.2.3</string>"));
assert!(p.contains("<string>VectorCraft Document</string>") && p.contains("<string>PDF Document</string>"));
}
}