zer0-image-generator 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +42 -0
- data/LICENSE +21 -0
- data/README.md +212 -0
- data/lib/zer0-image-generator.rb +15 -0
- data/lib/zer0_image_generator/command.rb +106 -0
- data/lib/zer0_image_generator/preview_generator.py +2435 -0
- data/lib/zer0_image_generator/rasterize-svg.js +65 -0
- data/lib/zer0_image_generator/version.rb +5 -0
- metadata +84 -0
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
// Feature: ZER0-004
|
|
2
|
+
// SVG → PNG rasterizer for the preview-image engine (scripts/lib/preview_generator.py).
|
|
3
|
+
// Last resort in the rasterizer chain (rsvg-convert → inkscape → magick → THIS):
|
|
4
|
+
// uses the repo's Playwright devDependency (the same Chromium that powers the
|
|
5
|
+
// visual test tiers) so contributors need no native image tooling installed.
|
|
6
|
+
//
|
|
7
|
+
// Usage:
|
|
8
|
+
// node scripts/dev/rasterize-svg.js <in.svg> <out.png> [width] [height]
|
|
9
|
+
//
|
|
10
|
+
// Exit codes:
|
|
11
|
+
// 0 PNG written
|
|
12
|
+
// 1 rasterization failed (Chromium error, unreadable SVG, …)
|
|
13
|
+
// 2 usage error
|
|
14
|
+
// 3 @playwright/test not resolvable (caller should fall through / keep .svg)
|
|
15
|
+
const fs = require('fs');
|
|
16
|
+
const path = require('path');
|
|
17
|
+
|
|
18
|
+
const [svgPath, pngPath, widthArg, heightArg] = process.argv.slice(2);
|
|
19
|
+
if (!svgPath || !pngPath) {
|
|
20
|
+
console.error('Usage: node scripts/dev/rasterize-svg.js <in.svg> <out.png> [width] [height]');
|
|
21
|
+
process.exit(2);
|
|
22
|
+
}
|
|
23
|
+
const width = parseInt(widthArg, 10) || 1536;
|
|
24
|
+
const height = parseInt(heightArg, 10) || 1024;
|
|
25
|
+
|
|
26
|
+
let chromium;
|
|
27
|
+
try {
|
|
28
|
+
({ chromium } = require('@playwright/test'));
|
|
29
|
+
} catch (e) {
|
|
30
|
+
console.error('rasterize-svg: @playwright/test not resolvable from ' + process.cwd());
|
|
31
|
+
process.exit(3);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
(async () => {
|
|
35
|
+
const svg = fs.readFileSync(path.resolve(svgPath), 'utf8');
|
|
36
|
+
const browser = await chromium.launch();
|
|
37
|
+
try {
|
|
38
|
+
const ctx = await browser.newContext({
|
|
39
|
+
viewport: { width, height },
|
|
40
|
+
deviceScaleFactor: 1,
|
|
41
|
+
});
|
|
42
|
+
// Defense-in-depth: banner SVG must be self-contained, so block ALL
|
|
43
|
+
// network fetches — an external reference that slipped past the engine's
|
|
44
|
+
// sanitizer becomes a no-op instead of an SSRF/tracking request.
|
|
45
|
+
await ctx.route('**/*', (route) => route.abort());
|
|
46
|
+
const page = await ctx.newPage();
|
|
47
|
+
// Inline the SVG in a zero-margin shim and stretch it to the viewport so the
|
|
48
|
+
// screenshot is exactly width×height regardless of the SVG's own attributes.
|
|
49
|
+
await page.setContent(
|
|
50
|
+
`<!DOCTYPE html><html><head><style>
|
|
51
|
+
html,body{margin:0;padding:0;width:${width}px;height:${height}px;overflow:hidden;background:#000}
|
|
52
|
+
svg{display:block;width:${width}px;height:${height}px}
|
|
53
|
+
</style></head><body>${svg}</body></html>`,
|
|
54
|
+
{ waitUntil: 'load', timeout: 30000 }
|
|
55
|
+
);
|
|
56
|
+
await page.screenshot({ path: path.resolve(pngPath), fullPage: false });
|
|
57
|
+
await ctx.close();
|
|
58
|
+
console.log('wrote', pngPath);
|
|
59
|
+
} finally {
|
|
60
|
+
await browser.close();
|
|
61
|
+
}
|
|
62
|
+
})().catch((err) => {
|
|
63
|
+
console.error('rasterize-svg: ' + (err && err.message ? err.message : err));
|
|
64
|
+
process.exit(1);
|
|
65
|
+
});
|
metadata
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: zer0-image-generator
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Amr Abdel
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2026-07-14 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: jekyll
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - ">="
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '3.9'
|
|
20
|
+
- - "<"
|
|
21
|
+
- !ruby/object:Gem::Version
|
|
22
|
+
version: '5.0'
|
|
23
|
+
type: :runtime
|
|
24
|
+
prerelease: false
|
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
26
|
+
requirements:
|
|
27
|
+
- - ">="
|
|
28
|
+
- !ruby/object:Gem::Version
|
|
29
|
+
version: '3.9'
|
|
30
|
+
- - "<"
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '5.0'
|
|
33
|
+
description: 'Adds a `jekyll preview-images` command that generates front-matter-wired
|
|
34
|
+
preview banners for posts and collections. Claude analyzes each article into an
|
|
35
|
+
art brief and vision-reviews the render; OpenAI (default), xAI, Stability, Gemini,
|
|
36
|
+
or a free deterministic local template produces the image. The engine is a single
|
|
37
|
+
vendored Python file, so it also runs standalone without Ruby. Extracted from the
|
|
38
|
+
zer0-mistakes theme and generalized: collections_dir, front_matter_key, authors_file,
|
|
39
|
+
and collection auto-discovery make it portable to any Jekyll layout.'
|
|
40
|
+
email:
|
|
41
|
+
- amr.abdel@gmail.com
|
|
42
|
+
executables: []
|
|
43
|
+
extensions: []
|
|
44
|
+
extra_rdoc_files: []
|
|
45
|
+
files:
|
|
46
|
+
- CHANGELOG.md
|
|
47
|
+
- LICENSE
|
|
48
|
+
- README.md
|
|
49
|
+
- lib/zer0-image-generator.rb
|
|
50
|
+
- lib/zer0_image_generator/command.rb
|
|
51
|
+
- lib/zer0_image_generator/preview_generator.py
|
|
52
|
+
- lib/zer0_image_generator/rasterize-svg.js
|
|
53
|
+
- lib/zer0_image_generator/version.rb
|
|
54
|
+
homepage: https://github.com/bamr87/zer0-image-generator
|
|
55
|
+
licenses:
|
|
56
|
+
- MIT
|
|
57
|
+
metadata:
|
|
58
|
+
homepage_uri: https://github.com/bamr87/zer0-image-generator
|
|
59
|
+
source_code_uri: https://github.com/bamr87/zer0-image-generator
|
|
60
|
+
changelog_uri: https://github.com/bamr87/zer0-image-generator/blob/main/CHANGELOG.md
|
|
61
|
+
bug_tracker_uri: https://github.com/bamr87/zer0-image-generator/issues
|
|
62
|
+
rubygems_mfa_required: 'true'
|
|
63
|
+
post_install_message:
|
|
64
|
+
rdoc_options: []
|
|
65
|
+
require_paths:
|
|
66
|
+
- lib
|
|
67
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
68
|
+
requirements:
|
|
69
|
+
- - ">="
|
|
70
|
+
- !ruby/object:Gem::Version
|
|
71
|
+
version: 2.7.0
|
|
72
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
73
|
+
requirements:
|
|
74
|
+
- - ">="
|
|
75
|
+
- !ruby/object:Gem::Version
|
|
76
|
+
version: '0'
|
|
77
|
+
requirements:
|
|
78
|
+
- Python 3.9+ with PyYAML (python3 -m pip install pyyaml)
|
|
79
|
+
rubygems_version: 3.0.3.1
|
|
80
|
+
signing_key:
|
|
81
|
+
specification_version: 4
|
|
82
|
+
summary: AI preview/social images for any Jekyll site — Claude directs and reviews,
|
|
83
|
+
an image model renders.
|
|
84
|
+
test_files: []
|