Merge PR #1993: macOS bundle: drop Info.plist types LightCraft cannot open (#1951)

This commit is contained in:
aiongg
2026-10-21 14:52:57 +00:00
2 changed files with 43 additions and 60 deletions
+38
View File
@@ -22,3 +22,41 @@ for key in ("runtime", "runtime-version", "sdk", "finish-args"):
assert manifests[0][key] == manifests[1][key], f"Flatpak manifests disagree on {key}"
print("LightCraft package identity ok")
PYEOF
# The macOS bundle must declare only file types LightCraft can open. It used to carry PhotoCraft's
# `.pcraft` document type and imported PSB/QOI declarations, so Launch Services typed PhotoCraft
# documents as LightCraft's and `.pcraft` had three claimant apps (issue #1951). plistlib parses the
# template as a property list too, which is the syntax check package.sh's `plutil -lint` repeats on
# the substituted file.
python3 - <<'PYEOF'
import plistlib
with open("packaging/macos/Info.plist.in", "rb") as source:
plist = plistlib.load(source)
for key, value in {
"CFBundleIdentifier": "ai.storyteller.lightcraft",
"CFBundleExecutable": "LightCraft",
"CFBundleIconFile": "LightCraft",
"LSMinimumSystemVersion": "11.0",
}.items():
assert plist.get(key) == value, f"Info.plist {key}: {plist.get(key)!r}, expected {value!r}"
for key in ("CFBundleShortVersionString", "CFBundleVersion", "LightCraftVersion", "LightCraftBuildCommit"):
assert plist.get(key), f"Info.plist lost {key}"
declared = set()
for section in ("UTExportedTypeDeclarations", "UTImportedTypeDeclarations"):
for entry in plist.get(section, []):
tags = entry.get("UTTypeTagSpecification", {})
declared.update(tags.get("public.filename-extension", []))
declared.update(tags.get("public.mime-type", []))
declared.add(entry.get("UTTypeIdentifier", ""))
unsupported = {name.lower() for name in declared} & {
"pcraft",
"psb",
"qoi",
"application/x-lightcraft",
"ai.storyteller.lightcraft.document",
"ai.storyteller.lightcraft.qoi",
"com.adobe.photoshop-large-image",
}
assert not unsupported, f"Info.plist declares types LightCraft cannot open: {sorted(unsupported)}"
print("LightCraft macOS bundle types ok")
PYEOF
+5 -60
View File
@@ -49,66 +49,11 @@
<key>NSHumanReadableCopyright</key>
<string>Copyright © the LightCraft authors. MIT OR Apache-2.0.</string>
<!-- Lightcraft's own format. -->
<key>UTExportedTypeDeclarations</key>
<array>
<dict>
<key>UTTypeIdentifier</key>
<string>ai.storyteller.lightcraft.document</string>
<key>UTTypeDescription</key>
<string>LightCraft Document</string>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
<string>public.image</string>
</array>
<key>UTTypeIconFile</key>
<string>LightCraft</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array><string>pcraft</string></array>
<key>public.mime-type</key>
<array><string>application/x-lightcraft</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.lightcraft.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>
<!-- No UTI declarations: LightCraft has no document type of its own, and the formats it opens
(JPEG, PNG, TIFF, HEIC, the raw formats) are declared by the system or by another app.
Declaring PhotoCraft's `.pcraft` type here (and importing PSB and QOI) made Launch Services
type PhotoCraft documents as LightCraft's; `.pcraft` ended up with three claimant apps
(issue #1951). -->
</dict>
</plist>