diff --git a/.gitignore b/.gitignore index 5e32b9d..2360c29 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,7 @@ # testing /coverage +/.tmp/ # next.js /.next/ diff --git a/public/articles/browser/browser-figure-1.awebp b/public/articles/browser/browser-figure-1.awebp index bf88e25..75c450e 100644 Binary files a/public/articles/browser/browser-figure-1.awebp and b/public/articles/browser/browser-figure-1.awebp differ diff --git a/public/articles/browser/browser-figure-10.awebp b/public/articles/browser/browser-figure-10.awebp index 81d7840..1cfea01 100644 Binary files a/public/articles/browser/browser-figure-10.awebp and b/public/articles/browser/browser-figure-10.awebp differ diff --git a/public/articles/browser/browser-figure-11.awebp b/public/articles/browser/browser-figure-11.awebp index 82a5907..38ece42 100644 Binary files a/public/articles/browser/browser-figure-11.awebp and b/public/articles/browser/browser-figure-11.awebp differ diff --git a/public/articles/browser/browser-figure-12.awebp b/public/articles/browser/browser-figure-12.awebp index 02ca570..273591b 100644 Binary files a/public/articles/browser/browser-figure-12.awebp and b/public/articles/browser/browser-figure-12.awebp differ diff --git a/public/articles/browser/browser-figure-13.awebp b/public/articles/browser/browser-figure-13.awebp index 38af2ee..8b1e8fc 100644 Binary files a/public/articles/browser/browser-figure-13.awebp and b/public/articles/browser/browser-figure-13.awebp differ diff --git a/public/articles/browser/browser-figure-2.awebp b/public/articles/browser/browser-figure-2.awebp index c07409d..b2af4c5 100644 Binary files a/public/articles/browser/browser-figure-2.awebp and b/public/articles/browser/browser-figure-2.awebp differ diff --git a/public/articles/browser/browser-figure-3.awebp b/public/articles/browser/browser-figure-3.awebp index 6f51504..d0e5a10 100644 Binary files a/public/articles/browser/browser-figure-3.awebp and b/public/articles/browser/browser-figure-3.awebp differ diff --git a/public/articles/browser/browser-figure-4.awebp b/public/articles/browser/browser-figure-4.awebp index 9326782..acda5e7 100644 Binary files a/public/articles/browser/browser-figure-4.awebp and b/public/articles/browser/browser-figure-4.awebp differ diff --git a/public/articles/browser/browser-figure-5.awebp b/public/articles/browser/browser-figure-5.awebp index 66e8a4b..9add7ff 100644 Binary files a/public/articles/browser/browser-figure-5.awebp and b/public/articles/browser/browser-figure-5.awebp differ diff --git a/public/articles/browser/browser-figure-6.awebp b/public/articles/browser/browser-figure-6.awebp index 573345f..7cce95f 100644 Binary files a/public/articles/browser/browser-figure-6.awebp and b/public/articles/browser/browser-figure-6.awebp differ diff --git a/public/articles/browser/browser-figure-7.awebp b/public/articles/browser/browser-figure-7.awebp index 1688584..a2197cd 100644 Binary files a/public/articles/browser/browser-figure-7.awebp and b/public/articles/browser/browser-figure-7.awebp differ diff --git a/public/articles/browser/browser-figure-8.awebp b/public/articles/browser/browser-figure-8.awebp index 640fbde..3a9403a 100644 Binary files a/public/articles/browser/browser-figure-8.awebp and b/public/articles/browser/browser-figure-8.awebp differ diff --git a/public/articles/browser/browser-figure-9.awebp b/public/articles/browser/browser-figure-9.awebp index 8d2c9a8..630635c 100644 Binary files a/public/articles/browser/browser-figure-9.awebp and b/public/articles/browser/browser-figure-9.awebp differ diff --git a/public/articles/code-output/code-output-figure-1.awebp b/public/articles/code-output/code-output-figure-1.awebp index 508d486..12bb3ca 100644 Binary files a/public/articles/code-output/code-output-figure-1.awebp and b/public/articles/code-output/code-output-figure-1.awebp differ diff --git a/public/articles/css/css-figure-1.awebp b/public/articles/css/css-figure-1.awebp index f1422d8..8ac6cab 100644 Binary files a/public/articles/css/css-figure-1.awebp and b/public/articles/css/css-figure-1.awebp differ diff --git a/public/articles/css/css-figure-10.awebp b/public/articles/css/css-figure-10.awebp index a2c404d..8f2b723 100644 Binary files a/public/articles/css/css-figure-10.awebp and b/public/articles/css/css-figure-10.awebp differ diff --git a/public/articles/css/css-figure-11.awebp b/public/articles/css/css-figure-11.awebp index b80ddc4..eaa7dc7 100644 Binary files a/public/articles/css/css-figure-11.awebp and b/public/articles/css/css-figure-11.awebp differ diff --git a/public/articles/css/css-figure-12.awebp b/public/articles/css/css-figure-12.awebp index 4b1945b..315555f 100644 Binary files a/public/articles/css/css-figure-12.awebp and b/public/articles/css/css-figure-12.awebp differ diff --git a/public/articles/css/css-figure-13.awebp b/public/articles/css/css-figure-13.awebp index 28ce886..b05a6da 100644 Binary files a/public/articles/css/css-figure-13.awebp and b/public/articles/css/css-figure-13.awebp differ diff --git a/public/articles/css/css-figure-14.awebp b/public/articles/css/css-figure-14.awebp index ff61706..60072f8 100644 Binary files a/public/articles/css/css-figure-14.awebp and b/public/articles/css/css-figure-14.awebp differ diff --git a/public/articles/css/css-figure-15.awebp b/public/articles/css/css-figure-15.awebp index 01c56a3..ac98951 100644 Binary files a/public/articles/css/css-figure-15.awebp and b/public/articles/css/css-figure-15.awebp differ diff --git a/public/articles/css/css-figure-16.awebp b/public/articles/css/css-figure-16.awebp index 60cc73d..d03baec 100644 Binary files a/public/articles/css/css-figure-16.awebp and b/public/articles/css/css-figure-16.awebp differ diff --git a/public/articles/css/css-figure-17.awebp b/public/articles/css/css-figure-17.awebp index e33a9da..e353b59 100644 Binary files a/public/articles/css/css-figure-17.awebp and b/public/articles/css/css-figure-17.awebp differ diff --git a/public/articles/css/css-figure-18.awebp b/public/articles/css/css-figure-18.awebp index e1a5576..cfc07a2 100644 Binary files a/public/articles/css/css-figure-18.awebp and b/public/articles/css/css-figure-18.awebp differ diff --git a/public/articles/css/css-figure-19.awebp b/public/articles/css/css-figure-19.awebp index feb8687..439a536 100644 Binary files a/public/articles/css/css-figure-19.awebp and b/public/articles/css/css-figure-19.awebp differ diff --git a/public/articles/css/css-figure-2.awebp b/public/articles/css/css-figure-2.awebp index 6a9029b..c235e22 100644 Binary files a/public/articles/css/css-figure-2.awebp and b/public/articles/css/css-figure-2.awebp differ diff --git a/public/articles/css/css-figure-3.awebp b/public/articles/css/css-figure-3.awebp index a39433f..1c9dc6b 100644 Binary files a/public/articles/css/css-figure-3.awebp and b/public/articles/css/css-figure-3.awebp differ diff --git a/public/articles/css/css-figure-4.awebp b/public/articles/css/css-figure-4.awebp index 9991bac..e768c61 100644 Binary files a/public/articles/css/css-figure-4.awebp and b/public/articles/css/css-figure-4.awebp differ diff --git a/public/articles/css/css-figure-5.awebp b/public/articles/css/css-figure-5.awebp index de8d267..f60247a 100644 Binary files a/public/articles/css/css-figure-5.awebp and b/public/articles/css/css-figure-5.awebp differ diff --git a/public/articles/css/css-figure-6.awebp b/public/articles/css/css-figure-6.awebp index b0fbb02..b6bb863 100644 Binary files a/public/articles/css/css-figure-6.awebp and b/public/articles/css/css-figure-6.awebp differ diff --git a/public/articles/css/css-figure-7.awebp b/public/articles/css/css-figure-7.awebp index b1c5518..22fa636 100644 Binary files a/public/articles/css/css-figure-7.awebp and b/public/articles/css/css-figure-7.awebp differ diff --git a/public/articles/css/css-figure-8.awebp b/public/articles/css/css-figure-8.awebp index 43f96b8..3587bf2 100644 Binary files a/public/articles/css/css-figure-8.awebp and b/public/articles/css/css-figure-8.awebp differ diff --git a/public/articles/css/css-figure-9.awebp b/public/articles/css/css-figure-9.awebp index 5cb1c32..1aaa95f 100644 Binary files a/public/articles/css/css-figure-9.awebp and b/public/articles/css/css-figure-9.awebp differ diff --git a/public/articles/html/script-defer-async-timeline.awebp b/public/articles/html/script-defer-async-timeline.awebp index 6e06440..95377f9 100644 Binary files a/public/articles/html/script-defer-async-timeline.awebp and b/public/articles/html/script-defer-async-timeline.awebp differ diff --git a/public/articles/javascript-part-1/javascript-part-1-figure-1.awebp b/public/articles/javascript-part-1/javascript-part-1-figure-1.awebp index 7499c1d..8cce402 100644 Binary files a/public/articles/javascript-part-1/javascript-part-1-figure-1.awebp and b/public/articles/javascript-part-1/javascript-part-1-figure-1.awebp differ diff --git a/public/articles/javascript-part-1/javascript-part-1-figure-2.awebp b/public/articles/javascript-part-1/javascript-part-1-figure-2.awebp index a638abe..668e7a2 100644 Binary files a/public/articles/javascript-part-1/javascript-part-1-figure-2.awebp and b/public/articles/javascript-part-1/javascript-part-1-figure-2.awebp differ diff --git a/public/articles/javascript-part-1/javascript-part-1-figure-3.awebp b/public/articles/javascript-part-1/javascript-part-1-figure-3.awebp index fdd973f..8611ed2 100644 Binary files a/public/articles/javascript-part-1/javascript-part-1-figure-3.awebp and b/public/articles/javascript-part-1/javascript-part-1-figure-3.awebp differ diff --git a/public/articles/javascript-part-1/javascript-part-1-figure-4.awebp b/public/articles/javascript-part-1/javascript-part-1-figure-4.awebp index 98f402d..288def3 100644 Binary files a/public/articles/javascript-part-1/javascript-part-1-figure-4.awebp and b/public/articles/javascript-part-1/javascript-part-1-figure-4.awebp differ diff --git a/public/articles/javascript-part-1/javascript-part-1-figure-5.awebp b/public/articles/javascript-part-1/javascript-part-1-figure-5.awebp index d2fe6a7..1d98d2a 100644 Binary files a/public/articles/javascript-part-1/javascript-part-1-figure-5.awebp and b/public/articles/javascript-part-1/javascript-part-1-figure-5.awebp differ diff --git a/public/articles/javascript-part-1/javascript-part-1-figure-6.awebp b/public/articles/javascript-part-1/javascript-part-1-figure-6.awebp index a445ab0..3efa1da 100644 Binary files a/public/articles/javascript-part-1/javascript-part-1-figure-6.awebp and b/public/articles/javascript-part-1/javascript-part-1-figure-6.awebp differ diff --git a/public/articles/javascript-part-2/javascript-part-2-figure-1.awebp b/public/articles/javascript-part-2/javascript-part-2-figure-1.awebp index f96de9f..24a52a1 100644 Binary files a/public/articles/javascript-part-2/javascript-part-2-figure-1.awebp and b/public/articles/javascript-part-2/javascript-part-2-figure-1.awebp differ diff --git a/public/articles/javascript-part-2/javascript-part-2-figure-2.awebp b/public/articles/javascript-part-2/javascript-part-2-figure-2.awebp index db54a87..14918f9 100644 Binary files a/public/articles/javascript-part-2/javascript-part-2-figure-2.awebp and b/public/articles/javascript-part-2/javascript-part-2-figure-2.awebp differ diff --git a/public/articles/network/network-figure-1.awebp b/public/articles/network/network-figure-1.awebp index bdebaef..60777fc 100644 Binary files a/public/articles/network/network-figure-1.awebp and b/public/articles/network/network-figure-1.awebp differ diff --git a/public/articles/network/network-figure-10.awebp b/public/articles/network/network-figure-10.awebp index 9e16404..c365d3b 100644 Binary files a/public/articles/network/network-figure-10.awebp and b/public/articles/network/network-figure-10.awebp differ diff --git a/public/articles/network/network-figure-11.awebp b/public/articles/network/network-figure-11.awebp index ecd85bd..b7ce885 100644 Binary files a/public/articles/network/network-figure-11.awebp and b/public/articles/network/network-figure-11.awebp differ diff --git a/public/articles/network/network-figure-12.awebp b/public/articles/network/network-figure-12.awebp index 6f702ea..5b6cea2 100644 Binary files a/public/articles/network/network-figure-12.awebp and b/public/articles/network/network-figure-12.awebp differ diff --git a/public/articles/network/network-figure-13.awebp b/public/articles/network/network-figure-13.awebp index c53a79c..5e2e3d4 100644 Binary files a/public/articles/network/network-figure-13.awebp and b/public/articles/network/network-figure-13.awebp differ diff --git a/public/articles/network/network-figure-14.awebp b/public/articles/network/network-figure-14.awebp index 58a0767..8316797 100644 Binary files a/public/articles/network/network-figure-14.awebp and b/public/articles/network/network-figure-14.awebp differ diff --git a/public/articles/network/network-figure-15.awebp b/public/articles/network/network-figure-15.awebp index 7a5ff9d..19bf319 100644 Binary files a/public/articles/network/network-figure-15.awebp and b/public/articles/network/network-figure-15.awebp differ diff --git a/public/articles/network/network-figure-16.awebp b/public/articles/network/network-figure-16.awebp index bdcc078..b7979c2 100644 Binary files a/public/articles/network/network-figure-16.awebp and b/public/articles/network/network-figure-16.awebp differ diff --git a/public/articles/network/network-figure-17.awebp b/public/articles/network/network-figure-17.awebp index 7317a27..3ed773f 100644 Binary files a/public/articles/network/network-figure-17.awebp and b/public/articles/network/network-figure-17.awebp differ diff --git a/public/articles/network/network-figure-18.awebp b/public/articles/network/network-figure-18.awebp index de57147..ae20be8 100644 Binary files a/public/articles/network/network-figure-18.awebp and b/public/articles/network/network-figure-18.awebp differ diff --git a/public/articles/network/network-figure-19.awebp b/public/articles/network/network-figure-19.awebp index 73172dd..fac0516 100644 Binary files a/public/articles/network/network-figure-19.awebp and b/public/articles/network/network-figure-19.awebp differ diff --git a/public/articles/network/network-figure-2.awebp b/public/articles/network/network-figure-2.awebp index bd305a4..3579d81 100644 Binary files a/public/articles/network/network-figure-2.awebp and b/public/articles/network/network-figure-2.awebp differ diff --git a/public/articles/network/network-figure-20.awebp b/public/articles/network/network-figure-20.awebp index 49ca280..4563bf0 100644 Binary files a/public/articles/network/network-figure-20.awebp and b/public/articles/network/network-figure-20.awebp differ diff --git a/public/articles/network/network-figure-3.awebp b/public/articles/network/network-figure-3.awebp index 0f5739f..61b4eb7 100644 Binary files a/public/articles/network/network-figure-3.awebp and b/public/articles/network/network-figure-3.awebp differ diff --git a/public/articles/network/network-figure-4.awebp b/public/articles/network/network-figure-4.awebp index bec7bce..d62ea72 100644 Binary files a/public/articles/network/network-figure-4.awebp and b/public/articles/network/network-figure-4.awebp differ diff --git a/public/articles/network/network-figure-5.awebp b/public/articles/network/network-figure-5.awebp index 3eb5b76..bca6211 100644 Binary files a/public/articles/network/network-figure-5.awebp and b/public/articles/network/network-figure-5.awebp differ diff --git a/public/articles/network/network-figure-6.awebp b/public/articles/network/network-figure-6.awebp index 4971d23..cce787f 100644 Binary files a/public/articles/network/network-figure-6.awebp and b/public/articles/network/network-figure-6.awebp differ diff --git a/public/articles/network/network-figure-7.awebp b/public/articles/network/network-figure-7.awebp index 6fa20e3..b3c05b2 100644 Binary files a/public/articles/network/network-figure-7.awebp and b/public/articles/network/network-figure-7.awebp differ diff --git a/public/articles/network/network-figure-8.awebp b/public/articles/network/network-figure-8.awebp index 31d58f2..928ac32 100644 Binary files a/public/articles/network/network-figure-8.awebp and b/public/articles/network/network-figure-8.awebp differ diff --git a/public/articles/network/network-figure-9.awebp b/public/articles/network/network-figure-9.awebp index 75da169..75033c0 100644 Binary files a/public/articles/network/network-figure-9.awebp and b/public/articles/network/network-figure-9.awebp differ diff --git a/public/articles/performance/performance-figure-1.awebp b/public/articles/performance/performance-figure-1.awebp index 4d34aff..60710ba 100644 Binary files a/public/articles/performance/performance-figure-1.awebp and b/public/articles/performance/performance-figure-1.awebp differ diff --git a/public/articles/performance/performance-figure-2.awebp b/public/articles/performance/performance-figure-2.awebp index b0fbb02..b6bb863 100644 Binary files a/public/articles/performance/performance-figure-2.awebp and b/public/articles/performance/performance-figure-2.awebp differ diff --git a/public/articles/react-part-1/react-part-1-figure-1.awebp b/public/articles/react-part-1/react-part-1-figure-1.awebp index 844cf97..034175a 100644 Binary files a/public/articles/react-part-1/react-part-1-figure-1.awebp and b/public/articles/react-part-1/react-part-1-figure-1.awebp differ diff --git a/public/articles/react-part-1/react-part-1-figure-2.awebp b/public/articles/react-part-1/react-part-1-figure-2.awebp index e4af633..cd309eb 100644 Binary files a/public/articles/react-part-1/react-part-1-figure-2.awebp and b/public/articles/react-part-1/react-part-1-figure-2.awebp differ diff --git a/public/articles/react-part-1/react-part-1-figure-3.awebp b/public/articles/react-part-1/react-part-1-figure-3.awebp index 316a7b0..89d5fe0 100644 Binary files a/public/articles/react-part-1/react-part-1-figure-3.awebp and b/public/articles/react-part-1/react-part-1-figure-3.awebp differ diff --git a/public/articles/react-part-1/react-part-1-figure-4.awebp b/public/articles/react-part-1/react-part-1-figure-4.awebp index 605a1dc..6d6b1b5 100644 Binary files a/public/articles/react-part-1/react-part-1-figure-4.awebp and b/public/articles/react-part-1/react-part-1-figure-4.awebp differ diff --git a/public/articles/react-part-1/react-part-1-figure-5.awebp b/public/articles/react-part-1/react-part-1-figure-5.awebp index 0d394dd..25c3206 100644 Binary files a/public/articles/react-part-1/react-part-1-figure-5.awebp and b/public/articles/react-part-1/react-part-1-figure-5.awebp differ diff --git a/public/articles/react-part-1/react-part-1-figure-6.awebp b/public/articles/react-part-1/react-part-1-figure-6.awebp index 10c5a73..f590b67 100644 Binary files a/public/articles/react-part-1/react-part-1-figure-6.awebp and b/public/articles/react-part-1/react-part-1-figure-6.awebp differ diff --git a/public/articles/react-part-1/react-part-1-figure-7.awebp b/public/articles/react-part-1/react-part-1-figure-7.awebp index 4c4d24e..f7f26c2 100644 Binary files a/public/articles/react-part-1/react-part-1-figure-7.awebp and b/public/articles/react-part-1/react-part-1-figure-7.awebp differ diff --git a/public/articles/react-part-1/react-part-1-figure-8.awebp b/public/articles/react-part-1/react-part-1-figure-8.awebp index 13fae66..655d6c2 100644 Binary files a/public/articles/react-part-1/react-part-1-figure-8.awebp and b/public/articles/react-part-1/react-part-1-figure-8.awebp differ diff --git a/public/articles/react-part-2/react-part-2-figure-1.awebp b/public/articles/react-part-2/react-part-2-figure-1.awebp index 04ae857..28710c9 100644 Binary files a/public/articles/react-part-2/react-part-2-figure-1.awebp and b/public/articles/react-part-2/react-part-2-figure-1.awebp differ diff --git a/public/articles/react-part-2/react-part-2-figure-2.awebp b/public/articles/react-part-2/react-part-2-figure-2.awebp index 1b1b36a..03e9ba4 100644 Binary files a/public/articles/react-part-2/react-part-2-figure-2.awebp and b/public/articles/react-part-2/react-part-2-figure-2.awebp differ diff --git a/public/articles/react-part-2/react-part-2-figure-3.awebp b/public/articles/react-part-2/react-part-2-figure-3.awebp index 89f997d..841fbe2 100644 Binary files a/public/articles/react-part-2/react-part-2-figure-3.awebp and b/public/articles/react-part-2/react-part-2-figure-3.awebp differ diff --git a/public/articles/react-part-2/react-part-2-figure-4.awebp b/public/articles/react-part-2/react-part-2-figure-4.awebp index d90baa0..8e69b1b 100644 Binary files a/public/articles/react-part-2/react-part-2-figure-4.awebp and b/public/articles/react-part-2/react-part-2-figure-4.awebp differ diff --git a/public/articles/react-part-2/react-part-2-figure-5.awebp b/public/articles/react-part-2/react-part-2-figure-5.awebp index 2666ce5..cff1f9f 100644 Binary files a/public/articles/react-part-2/react-part-2-figure-5.awebp and b/public/articles/react-part-2/react-part-2-figure-5.awebp differ diff --git a/public/articles/react-part-2/react-part-2-figure-6.awebp b/public/articles/react-part-2/react-part-2-figure-6.awebp index 3f91176..7d4b135 100644 Binary files a/public/articles/react-part-2/react-part-2-figure-6.awebp and b/public/articles/react-part-2/react-part-2-figure-6.awebp differ diff --git a/public/articles/react-part-2/react-part-2-figure-7.awebp b/public/articles/react-part-2/react-part-2-figure-7.awebp index ba43bda..95dbad3 100644 Binary files a/public/articles/react-part-2/react-part-2-figure-7.awebp and b/public/articles/react-part-2/react-part-2-figure-7.awebp differ diff --git a/public/articles/vue-part-1/vue-part-1-figure-1.awebp b/public/articles/vue-part-1/vue-part-1-figure-1.awebp index 67bce83..e67472a 100644 Binary files a/public/articles/vue-part-1/vue-part-1-figure-1.awebp and b/public/articles/vue-part-1/vue-part-1-figure-1.awebp differ diff --git a/public/articles/vue-part-1/vue-part-1-figure-2.awebp b/public/articles/vue-part-1/vue-part-1-figure-2.awebp index 2d03403..763b2b6 100644 Binary files a/public/articles/vue-part-1/vue-part-1-figure-2.awebp and b/public/articles/vue-part-1/vue-part-1-figure-2.awebp differ diff --git a/public/articles/vue-part-1/vue-part-1-figure-3.awebp b/public/articles/vue-part-1/vue-part-1-figure-3.awebp index a5e7a11..731c762 100644 Binary files a/public/articles/vue-part-1/vue-part-1-figure-3.awebp and b/public/articles/vue-part-1/vue-part-1-figure-3.awebp differ diff --git a/public/articles/vue-part-1/vue-part-1-figure-4.awebp b/public/articles/vue-part-1/vue-part-1-figure-4.awebp index 46540a3..9582898 100644 Binary files a/public/articles/vue-part-1/vue-part-1-figure-4.awebp and b/public/articles/vue-part-1/vue-part-1-figure-4.awebp differ diff --git a/public/articles/vue-part-1/vue-part-1-figure-5.awebp b/public/articles/vue-part-1/vue-part-1-figure-5.awebp index 7403a4e..885b922 100644 Binary files a/public/articles/vue-part-1/vue-part-1-figure-5.awebp and b/public/articles/vue-part-1/vue-part-1-figure-5.awebp differ diff --git a/public/articles/vue-part-1/vue-part-1-figure-6.awebp b/public/articles/vue-part-1/vue-part-1-figure-6.awebp index b249e99..04f25db 100644 Binary files a/public/articles/vue-part-1/vue-part-1-figure-6.awebp and b/public/articles/vue-part-1/vue-part-1-figure-6.awebp differ diff --git a/public/articles/vue-part-1/vue-part-1-figure-7.awebp b/public/articles/vue-part-1/vue-part-1-figure-7.awebp index a7caa43..2f8d5d7 100644 Binary files a/public/articles/vue-part-1/vue-part-1-figure-7.awebp and b/public/articles/vue-part-1/vue-part-1-figure-7.awebp differ diff --git a/public/articles/vue-part-2/vue-part-2-figure-1.awebp b/public/articles/vue-part-2/vue-part-2-figure-1.awebp index 973bb56..b640dee 100644 Binary files a/public/articles/vue-part-2/vue-part-2-figure-1.awebp and b/public/articles/vue-part-2/vue-part-2-figure-1.awebp differ diff --git a/scripts/remove_article_watermarks.py b/scripts/remove_article_watermarks.py new file mode 100644 index 0000000..02f6a91 --- /dev/null +++ b/scripts/remove_article_watermarks.py @@ -0,0 +1,172 @@ +from __future__ import annotations + +import argparse +import shutil +from pathlib import Path + +import numpy as np +from PIL import Image, ImageFilter + + +def inpaint_pixels(data: np.ndarray, mask: np.ndarray) -> np.ndarray: + result = data.astype(np.float32).copy() + remaining = mask.copy() + + for _ in range(data.shape[0] + data.shape[1]): + known = ~remaining + count = np.zeros(remaining.shape, dtype=np.float32) + total = np.zeros(result.shape, dtype=np.float32) + + neighbor = known[:-1, :] + count[1:, :] += neighbor + total[1:, :] += result[:-1, :] * neighbor[..., None] + + neighbor = known[1:, :] + count[:-1, :] += neighbor + total[:-1, :] += result[1:, :] * neighbor[..., None] + + neighbor = known[:, :-1] + count[:, 1:] += neighbor + total[:, 1:] += result[:, :-1] * neighbor[..., None] + + neighbor = known[:, 1:] + count[:, :-1] += neighbor + total[:, :-1] += result[:, 1:] * neighbor[..., None] + + boundary = remaining & (count > 0) + if not boundary.any(): + break + + result[boundary] = total[boundary] / count[boundary, None] + remaining[boundary] = False + + if not remaining.any(): + break + + if remaining.any(): + known_pixels = result[~remaining] + fill = np.median(known_pixels, axis=0) if len(known_pixels) else np.array([255, 255, 255]) + result[remaining] = fill + + return np.clip(result, 0, 255).astype(np.uint8) + + +def build_watermark_mask(image: Image.Image) -> Image.Image: + rgb = image.convert("RGB") + data = np.asarray(rgb).astype(np.int16) + height, width = data.shape[:2] + + yy, xx = np.mgrid[:height, :width] + light_right_width = min(width, max(140, min(190, int(width * 0.27)))) + dark_right_width = min(width, max(180, min(360, int(width * 0.42)))) + light_bottom_height = min(height, max(28, min(72, int(height * 0.1)))) + dark_bottom_height = min(height, max(28, min(54, int(height * 0.075)))) + light_right_band = xx >= width - light_right_width + dark_right_band = xx >= width - dark_right_width + light_target_corner = light_right_band & (yy >= height - light_bottom_height) + dark_target_corner = dark_right_band & (yy >= height - dark_bottom_height) + + channel_max = data.max(axis=2) + channel_min = data.min(axis=2) + saturation = channel_max - channel_min + brightness = data.mean(axis=2) + blurred = np.asarray(rgb.filter(ImageFilter.GaussianBlur(3))).astype(np.int16) + contrast = np.abs(data - blurred).mean(axis=2) + + corner_brightness = brightness[light_target_corner] + local_background = float(np.median(corner_brightness)) if corner_brightness.size else 255.0 + + light_background_mark = ( + (saturation <= 36) + & (brightness >= 165) + & (brightness <= 254) + & (channel_min >= 160) + ) + + dark_background_mark = ( + (saturation <= 48) + & (brightness >= max(58, local_background + 14)) + & (brightness <= 240) + & (channel_min >= 42) + ) + + if local_background < 155: + contrast_mark = ( + (contrast >= 5) + & (saturation <= 105) + & (brightness >= max(70, local_background + 16)) + & (brightness <= 252) + ) + mask = dark_target_corner & (dark_background_mark | contrast_mark) + else: + contrast_mark = ( + (contrast >= 4) + & (saturation <= 72) + & (brightness <= local_background - 3) + & (brightness >= 145) + ) + mask = light_target_corner & (light_background_mark | contrast_mark) + + mask_img = Image.fromarray((mask.astype(np.uint8)) * 255, mode="L") + mask_img = mask_img.filter(ImageFilter.MaxFilter(3)) + mask_img = mask_img.filter(ImageFilter.GaussianBlur(0.6)) + return mask_img + + +def remove_watermark(source: Path, destination: Path, quality: int) -> bool: + with Image.open(source) as opened: + image = opened.convert("RGBA") + + mask = build_watermark_mask(image) + if not mask.getbbox(): + destination.parent.mkdir(parents=True, exist_ok=True) + shutil.copy2(source, destination) + return False + + base = image.convert("RGB") + data = np.asarray(base).copy() + soft_mask = np.asarray(mask) + mask_array = soft_mask > 12 + + if mask_array.any(): + ys, xs = np.where(mask_array) + pad = 20 + y0 = max(0, int(ys.min()) - pad) + y1 = min(data.shape[0], int(ys.max()) + pad + 1) + x0 = max(0, int(xs.min()) - pad) + x1 = min(data.shape[1], int(xs.max()) + pad + 1) + roi = data[y0:y1, x0:x1] + roi_mask = mask_array[y0:y1, x0:x1] + inpainted = inpaint_pixels(roi, roi_mask) + data[y0:y1, x0:x1][roi_mask] = inpainted[roi_mask] + + filled = Image.fromarray(data, mode="RGB") + cleaned = Image.composite(filled.convert("RGBA"), image, mask) + + destination.parent.mkdir(parents=True, exist_ok=True) + cleaned.save(destination, format="WEBP", quality=quality, method=6) + return True + + +def main() -> None: + parser = argparse.ArgumentParser(description="Remove article platform watermarks from lower-right corners.") + parser.add_argument("--source", default="public/articles") + parser.add_argument("--out", default=".tmp/watermark-cleaned") + parser.add_argument("--quality", type=int, default=96) + args = parser.parse_args() + + source_root = Path(args.source) + out_root = Path(args.out) + files = sorted(source_root.rglob("*.awebp")) + changed = 0 + + for source in files: + destination = out_root / source.relative_to(source_root) + if remove_watermark(source, destination, args.quality): + changed += 1 + + print(f"processed={len(files)} changed={changed} out={out_root}") + + +if __name__ == "__main__": + main()