File size: 2,138 Bytes
a383d0e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
import sys, pathlib, difflib, json, bs4

src_html = pathlib.Path(sys.argv[1]).read_text(encoding="utf-8")
out_dir  = pathlib.Path(sys.argv[2])
out_dir.mkdir(parents=True, exist_ok=True)

soup = bs4.BeautifulSoup(src_html, "html.parser")

# 1) select elements to be revealed frame by frame
#    here we use all tags inside .box as an example, you can filter by yourself:
targets = []
for box in soup.select("div.box"):
    for node in box.descendants:
        if isinstance(node, bs4.Tag):
            # you can filter out wrapper / script / style etc. as needed
            if node.name in {"script", "style"}:
                continue
            targets.append(node)

total = len(targets)
print(f"Total nodes to be revealed: {total}")

manifest, prev_lines = [], []

for idx, node in enumerate(targets, 1):
    step_soup = bs4.BeautifulSoup(src_html, "html.parser")

    # second pass: hide elements that are not yet shown
    shown_ids = set()        # use id() to identify same node
    for j, n in enumerate(
        step_soup.select("div.box *")    # * = all descendants
    ):
        if isinstance(n, bs4.Tag) and id(n) in shown_ids:
            # already processed (prevent duplicate)
            continue
        if j + 1 > idx:                   # not yet shown elements
            style = n.get("style", "")
            # ensure no duplicate style
            if "opacity" not in style:
                style = (
                    "opacity:0;transition:opacity .35s ease-out;" + style
                )
            n["style"] = style
        shown_ids.add(id(n))

    # 3) write file
    fname = f"{idx:04d}.html"
    (out_dir / fname).write_text(str(step_soup), encoding="utf-8")

    diff = "" if not prev_lines else "\n".join(
        difflib.unified_diff(prev_lines, str(step_soup).splitlines(), lineterm="")
    )
    manifest.append(
        {"file": fname, "caption": f"Elements: {idx}/{total}", "diff": diff}
    )
    prev_lines = str(step_soup).splitlines()

# 4) write manifest
(out_dir / "manifest.json").write_text(
    json.dumps(manifest, ensure_ascii=False, indent=2)
)
print("Finished", out_dir.resolve())