forked from mirrors/kingfisher
v1.73.0
This commit is contained in:
parent
239a200c22
commit
08cccfd6ef
8 changed files with 135 additions and 42 deletions
1
.github/workflows/ci.yml
vendored
1
.github/workflows/ci.yml
vendored
|
|
@ -23,7 +23,6 @@ jobs:
|
|||
toolchain: ${{ env.RUST_TOOLCHAIN }}
|
||||
profile: minimal
|
||||
override: true
|
||||
- uses: swatinem/rust-cache@v2
|
||||
- name: Build (Makefile linux-arm64)
|
||||
run: make ubuntu-arm64
|
||||
- name: Run tests
|
||||
|
|
|
|||
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
|
|
@ -79,8 +79,6 @@ jobs:
|
|||
profile: minimal
|
||||
override: true
|
||||
|
||||
- uses: swatinem/rust-cache@v2
|
||||
|
||||
- name: Install packaging tools
|
||||
run: cargo install cargo-deb cargo-generate-rpm
|
||||
|
||||
|
|
|
|||
|
|
@ -66,7 +66,10 @@ Explore Kingfisher’s built-in report viewer and its `--access-map`, which can
|
|||
kingfisher scan /path/to/scan --access-map --view-report
|
||||
```
|
||||
|
||||

|
||||

|
||||
|
||||
**Click to view video**
|
||||
[](docs/kingfisher-usage-access-map-02.mp4)
|
||||
|
||||
|
||||
# Table of Contents
|
||||
|
|
|
|||
3
docs/demos/.gitignore
vendored
3
docs/demos/.gitignore
vendored
|
|
@ -137,3 +137,6 @@ dist
|
|||
|
||||
# SvelteKit build / generate output
|
||||
.svelte-kit
|
||||
|
||||
|
||||
pw-out/*
|
||||
|
|
|
|||
BIN
docs/demos/findings-thumbnail.png
Normal file
BIN
docs/demos/findings-thumbnail.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 666 KiB |
|
|
@ -1,28 +0,0 @@
|
|||
GIF_IN="../kingfisher-usage-access-map-01.gif"
|
||||
WEBM_IN="pw-out/066d10b5ae5d3603dacd69417a8227c6.webm"
|
||||
OUT_GIF="../kingfisher-usage-access-map-01+accessmap.gif"
|
||||
|
||||
# 1) Normalize GIF -> MP4 (H.264, fixed fps/size)
|
||||
ffmpeg -y -i "$GIF_IN" \
|
||||
-vf "fps=12,scale=960:-2:flags=lanczos" \
|
||||
-an -c:v libx264 -pix_fmt yuv420p -crf 18 -preset veryfast \
|
||||
gif_part.mp4
|
||||
|
||||
# 2) Normalize WEBM -> MP4 (same settings)
|
||||
ffmpeg -y -i "$WEBM_IN" \
|
||||
-vf "fps=12,scale=960:-2:flags=lanczos" \
|
||||
-an -c:v libx264 -pix_fmt yuv420p -crf 18 -preset veryfast \
|
||||
webm_part.mp4
|
||||
|
||||
# 3) Concatenate via filter (video-only; reliable)
|
||||
ffmpeg -y -i gif_part.mp4 -i webm_part.mp4 \
|
||||
-filter_complex "[0:v][1:v]concat=n=2:v=1:a=0[v]" \
|
||||
-map "[v]" -c:v libx264 -pix_fmt yuv420p -crf 18 -preset veryfast \
|
||||
combined.mp4
|
||||
|
||||
# 4) Convert combined MP4 -> GIF (single palette across whole thing)
|
||||
ffmpeg -y -i combined.mp4 \
|
||||
-vf "fps=12,scale=960:-1:flags=lanczos,split[s0][s1];[s0]palettegen=max_colors=256[p];[s1][p]paletteuse=dither=bayer" \
|
||||
"$OUT_GIF"
|
||||
|
||||
echo "Wrote: $OUT_GIF"
|
||||
|
|
@ -6,24 +6,142 @@ fs.mkdirSync(outDir, { recursive: true });
|
|||
|
||||
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
||||
|
||||
const cursorOverlayScript = `
|
||||
(() => {
|
||||
const style = document.createElement('style');
|
||||
style.textContent = \`
|
||||
#__pw_cursor {
|
||||
position: fixed;
|
||||
top: 0; left: 0;
|
||||
width: 18px; height: 18px;
|
||||
transform: translate(-100px, -100px);
|
||||
z-index: 2147483647;
|
||||
pointer-events: none;
|
||||
}
|
||||
#__pw_cursor svg { width: 18px; height: 18px; }
|
||||
#__pw_cursor .dot {
|
||||
fill: rgba(255,255,255,0.9);
|
||||
stroke: rgba(0,0,0,0.85);
|
||||
stroke-width: 2;
|
||||
}
|
||||
#__pw_click {
|
||||
position: fixed;
|
||||
width: 8px; height: 8px;
|
||||
border-radius: 50%;
|
||||
transform: translate(-100px, -100px);
|
||||
z-index: 2147483646;
|
||||
pointer-events: none;
|
||||
opacity: 0;
|
||||
border: 2px solid rgba(0,0,0,0.6);
|
||||
}
|
||||
\`;
|
||||
document.documentElement.appendChild(style);
|
||||
|
||||
const cursor = document.createElement('div');
|
||||
cursor.id = '__pw_cursor';
|
||||
cursor.innerHTML = \`
|
||||
<svg viewBox="0 0 24 24" aria-hidden="true">
|
||||
<circle class="dot" cx="12" cy="12" r="6"></circle>
|
||||
</svg>
|
||||
\`;
|
||||
document.documentElement.appendChild(cursor);
|
||||
|
||||
const click = document.createElement('div');
|
||||
click.id = '__pw_click';
|
||||
document.documentElement.appendChild(click);
|
||||
|
||||
let x = -100, y = -100;
|
||||
const move = (nx, ny) => {
|
||||
x = nx; y = ny;
|
||||
cursor.style.transform = \`translate(\${x}px, \${y}px)\`;
|
||||
click.style.transform = \`translate(\${x}px, \${y}px)\`;
|
||||
};
|
||||
|
||||
window.addEventListener('pointermove', (e) => move(e.clientX, e.clientY), { passive: true });
|
||||
window.addEventListener('mousemove', (e) => move(e.clientX, e.clientY), { passive: true });
|
||||
|
||||
window.addEventListener('pointerdown', () => {
|
||||
click.style.transition = 'none';
|
||||
click.style.opacity = '0.9';
|
||||
click.style.width = '8px';
|
||||
click.style.height = '8px';
|
||||
requestAnimationFrame(() => {
|
||||
click.style.transition = 'all 250ms ease-out';
|
||||
click.style.opacity = '0';
|
||||
click.style.width = '28px';
|
||||
click.style.height = '28px';
|
||||
});
|
||||
}, { passive: true });
|
||||
})();
|
||||
`;
|
||||
|
||||
// Converts native <select> dropdowns into in-page listboxes while focused/clicked,
|
||||
// so the “dropdown” actually appears in the recorded page surface.
|
||||
const selectListboxScript = `
|
||||
(() => {
|
||||
const enhance = (sel) => {
|
||||
if (sel.__pwEnhanced) return;
|
||||
sel.__pwEnhanced = true;
|
||||
|
||||
const originalSize = sel.getAttribute('size');
|
||||
|
||||
const open = () => {
|
||||
// Prevent the native popup and instead expand in-page
|
||||
const n = Math.min(Math.max(sel.options.length, 2), 12);
|
||||
sel.setAttribute('size', String(n));
|
||||
sel.style.background = sel.style.background || 'white';
|
||||
};
|
||||
|
||||
const close = () => {
|
||||
if (originalSize === null) sel.removeAttribute('size');
|
||||
else sel.setAttribute('size', originalSize);
|
||||
};
|
||||
|
||||
sel.addEventListener('mousedown', (e) => {
|
||||
// Stop native dropdown UI
|
||||
e.preventDefault();
|
||||
open();
|
||||
sel.focus();
|
||||
});
|
||||
|
||||
sel.addEventListener('blur', () => close());
|
||||
sel.addEventListener('change', () => close());
|
||||
sel.addEventListener('keydown', (e) => {
|
||||
if (e.key === 'Escape' || e.key === 'Enter') close();
|
||||
});
|
||||
};
|
||||
|
||||
const scan = () => document.querySelectorAll('select').forEach(enhance);
|
||||
|
||||
// initial + dynamic pages
|
||||
scan();
|
||||
new MutationObserver(scan).observe(document.documentElement, { childList: true, subtree: true });
|
||||
})();
|
||||
`;
|
||||
|
||||
(async () => {
|
||||
const browser = await chromium.launch({ headless: false });
|
||||
const browser = await chromium.launch({
|
||||
headless: false,
|
||||
// Optional: keeps it from throttling when not focused
|
||||
args: ["--disable-renderer-backgrounding", "--disable-background-timer-throttling"],
|
||||
});
|
||||
|
||||
const context = await browser.newContext({
|
||||
viewport: { width: 1280, height: 720 },
|
||||
recordVideo: { dir: outDir, size: { width: 1280, height: 720 } },
|
||||
viewport: { width: 1280, height: 1024 },
|
||||
recordVideo: { dir: outDir, size: { width: 1280, height: 1024 } },
|
||||
});
|
||||
|
||||
// Make sure overlays exist before any page scripts run
|
||||
await context.addInitScript(cursorOverlayScript);
|
||||
await context.addInitScript(selectListboxScript);
|
||||
|
||||
const page = await context.newPage();
|
||||
|
||||
await page.goto("http://127.0.0.1:7890", { waitUntil: "networkidle" });
|
||||
await sleep(25000);
|
||||
// networkidle is often a trap for SPAs; use domcontentloaded for recording
|
||||
await page.goto("http://127.0.0.1:7890", { waitUntil: "domcontentloaded" });
|
||||
|
||||
// await page.evaluate(() => window.scrollTo(0, document.body.scrollHeight));
|
||||
// await sleep(800);
|
||||
|
||||
// await page.evaluate(() => window.scrollTo(0, 0));
|
||||
// await sleep(800);
|
||||
// Give yourself time to interact manually
|
||||
await sleep(45000);
|
||||
|
||||
await context.close(); // finalizes video
|
||||
await browser.close();
|
||||
|
|
|
|||
BIN
docs/kingfisher-usage-access-map-02.mp4
Normal file
BIN
docs/kingfisher-usage-access-map-02.mp4
Normal file
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue