diff options
| -rw-r--r-- | _log/bumblebee.md | 46 | ||||
| -rw-r--r-- | _site/feed.xml | 2 | ||||
| -rw-r--r-- | _site/index.html | 2 | ||||
| -rw-r--r-- | _site/log/bumblebee/index.html | 50 | ||||
| -rw-r--r-- | _site/posts.xml | 2 | ||||
| -rw-r--r-- | _site/projects/index.html | 4 | ||||
| -rw-r--r-- | _site/robots.txt | 2 | ||||
| -rw-r--r-- | _site/sitemap.xml | 28 |
8 files changed, 64 insertions, 72 deletions
diff --git a/_log/bumblebee.md b/_log/bumblebee.md index 588ae42..25f08e4 100644 --- a/_log/bumblebee.md +++ b/_log/bumblebee.md @@ -1,45 +1,39 @@ --- -title: "Bumblebee: browser automation" +title: 'Bumblebee: web script synthesizer' date: 2025-04-02 layout: post project: true thumbnail: thumb_sm.png --- -Built with Andy Zhang for an employer. Tool to automate web scraping script -generation. +Work project. Browser session-to-code conversion. <video style="max-width:100%; margin-bottom: 10px" controls="" poster="poster.png"> <source src="bee.mp4" type="video/mp4"> </video> -Manual script authoring took hours. Scripts poorly optimized, CPUs maxed -constantly, cloud costs excessive. +Architecture: C# WinForms host, embedded browser, code editor. Browser +extension rejected due to security policy and shallow event control. -Initially considered browser extension. Desktop app won—extensions don't give -deep event control. Company policy blocked extensions anyway. +Tool evaluation: -First prototype: C# Win Forms + CefSharp. + - CefSharp: Discarded. API lacked elegance. + - WebView2: Selected. Better WinForms integration. Hard dependency on + Microsoft Edge--acceptable for corporate Windows environments. -Second prototype: C# Win Forms + WebView2. Packaging and distribution more -complex, but the API is well-designed; integrates well with Win Forms. +Implementation: -Microsoft Edge required. Portability not a concern, only need to target -controlled Windows environments. Choosing WebView2 over CefSharp. + 1. Interception: Injected JS hooks; internal browser event monitoring + (pop-ups/downloads). + 2. Transformation: Event → Token → Instruction Table → String. + 3. Optimization: Parallel event/text lists processing; rendered + in <a href="https://github.com/desjarlais/Scintilla.NET" class="external" + target="_blank" rel="noopener noreferrer">Scintilla.NET</a> -Embed <a href="https://github.com/desjarlais/Scintilla.NET" class="external" -toarget="_blank" rel="noopener noreferrer">Scintilla.NET</a> editor for -overriding generated script. +Bug: Manual mid-session overrides desync code/event lists, bypassing optimizer. +Linear lists inadequate for state synchronization. Need to rethink data +structures; look to compiler Abstract Syntax Trees (AST) for intermediate +representation. -Code generation sequence: Inject JavaScript to intercept client-side events. -Capture internal browser events (pop-ups, file downloads). Event -raised → parsed into a token → insert to list → interpret event → look up -instruction from a table → form instruction with event args → insert text to a -parallel list → run both lists through optimizer → update Scintilla editor. - -Limitation: manual overriding via Scintilla editor mid-session causes the code -list to go out of sync with the event list. Optimizer can't handle this yet. - -Note to self: need to rethink the event/text list data structures in the -context of the optimizer--look to compilers for inspiration maybe? +Verdict: Serves its purpose. diff --git a/_site/feed.xml b/_site/feed.xml index 5d9d93f..4c3b746 100644 --- a/_site/feed.xml +++ b/_site/feed.xml @@ -1 +1 @@ -<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="http://localhost:4000/feed.xml" rel="self" type="application/atom+xml" /><link href="http://localhost:4000/" rel="alternate" type="text/html" /><updated>2026-01-05T18:48:39+08:00</updated><id>http://localhost:4000/feed.xml</id><title type="html">ASCIIMX | Log</title><author><name>W. D. Sadeep Madurange</name></author><entry><title type="html">Search engine (Perl + FastCGI + SA)</title><link href="http://localhost:4000/log/site-search/" rel="alternate" type="text/html" title="Search engine (Perl + FastCGI + SA)" /><published>2026-01-03T00:00:00+08:00</published><updated>2026-01-03T00:00:00+08:00</updated><id>http://localhost:4000/log/site-search</id><author><name>W. D. Sadeep Madurange</name></author><summary type="html"><![CDATA[Article count on the website is growing. Need a way to search.]]></summary></entry><entry><title type="html">Matrix Rain: 2025 refactor</title><link href="http://localhost:4000/log/matrix-digital-rain/" rel="alternate" type="text/html" title="Matrix Rain: 2025 refactor" /><published>2025-12-21T00:00:00+08:00</published><updated>2025-12-21T00:00:00+08:00</updated><id>http://localhost:4000/log/matrix-digital-rain</id><author><name>W. D. Sadeep Madurange</name></author><summary type="html"><![CDATA[The 2022 version worked but had some loose ends. Unicode support was inflexible–couldn’t mix ASCII with Katakana; Phosphor decay was stored in a separate array when it should’ve been packed with RGB; Code was harder to read than it needed to be.]]></summary></entry><entry><title type="html">Fingerprint door lock (LP)</title><link href="http://localhost:4000/log/fpm-door-lock-lp/" rel="alternate" type="text/html" title="Fingerprint door lock (LP)" /><published>2025-08-18T00:00:00+08:00</published><updated>2025-08-18T00:00:00+08:00</updated><id>http://localhost:4000/log/fpm-door-lock-lp</id><author><name>W. D. Sadeep Madurange</name></author><summary type="html"><![CDATA[Second iteration of the RF door lock. Old version worked but drew too much quiescent current. Sensor and servo pulled 13.8mA and 4.6mA idle. Linear regulators were a disaster. Battery didn’t last 24 hours.]]></summary></entry><entry><title type="html">High-side MOSFET switching</title><link href="http://localhost:4000/log/mosfet-switches/" rel="alternate" type="text/html" title="High-side MOSFET switching" /><published>2025-06-22T00:00:00+08:00</published><updated>2025-06-22T00:00:00+08:00</updated><id>http://localhost:4000/log/mosfet-switches</id><author><name>W. D. Sadeep Madurange</name></author><summary type="html"><![CDATA[Needed low-power switching for the fingerprint door lock. Servo and FPM draw high quiescent current–had to cut power electronically during sleep. MOSFETs can do this.]]></summary></entry><entry><title type="html">ATmega328P at 3.3V and 5V</title><link href="http://localhost:4000/log/arduino-uno/" rel="alternate" type="text/html" title="ATmega328P at 3.3V and 5V" /><published>2025-06-10T00:00:00+08:00</published><updated>2025-06-10T00:00:00+08:00</updated><id>http://localhost:4000/log/arduino-uno</id><author><name>W. D. Sadeep Madurange</name></author><summary type="html"><![CDATA[Quick reference for wiring ATmega328P ICs at 5V and 3.3V. 5V uses 16MHz crystal, 3.3V uses 8MHz.]]></summary></entry><entry><title type="html">Fingerprint door lock (RF)</title><link href="http://localhost:4000/log/fpm-door-lock-rf/" rel="alternate" type="text/html" title="Fingerprint door lock (RF)" /><published>2025-06-05T00:00:00+08:00</published><updated>2025-06-05T00:00:00+08:00</updated><id>http://localhost:4000/log/fpm-door-lock-rf</id><author><name>W. D. Sadeep Madurange</name></author><summary type="html"><![CDATA[Wanted to unlock door with fingerprint, wirelessly to avoid drilling.]]></summary></entry><entry><title type="html">Bumblebee: browser automation</title><link href="http://localhost:4000/log/bumblebee/" rel="alternate" type="text/html" title="Bumblebee: browser automation" /><published>2025-04-02T00:00:00+08:00</published><updated>2025-04-02T00:00:00+08:00</updated><id>http://localhost:4000/log/bumblebee</id><author><name>W. D. Sadeep Madurange</name></author><summary type="html"><![CDATA[Built with Andy Zhang for an employer. Tool to automate web scraping script generation.]]></summary></entry><entry><title type="html">ATSAM3X8E bare-metal notes</title><link href="http://localhost:4000/log/arduino-due/" rel="alternate" type="text/html" title="ATSAM3X8E bare-metal notes" /><published>2024-09-16T00:00:00+08:00</published><updated>2024-09-16T00:00:00+08:00</updated><id>http://localhost:4000/log/arduino-due</id><author><name>W. D. Sadeep Madurange</name></author><summary type="html"><![CDATA[Bypassing ATSAM3X8E (Due) bootloader via Serial Wire Debug (SWD).]]></summary></entry><entry><title type="html">Etlas: e-paper dashboard</title><link href="http://localhost:4000/log/etlas/" rel="alternate" type="text/html" title="Etlas: e-paper dashboard" /><published>2024-09-05T00:00:00+08:00</published><updated>2024-09-05T00:00:00+08:00</updated><id>http://localhost:4000/log/etlas</id><author><name>W. D. Sadeep Madurange</name></author><summary type="html"><![CDATA[Repurposed e-reader prototype into something for regular use. News, stocks, weather dashboard. ESP32 NodeMCU D1 + 7.5” Waveshare e-paper + DHT22 sensor.]]></summary></entry><entry><title type="html">512 KB e-reader</title><link href="http://localhost:4000/log/e-reader/" rel="alternate" type="text/html" title="512 KB e-reader" /><published>2023-10-24T00:00:00+08:00</published><updated>2023-10-24T00:00:00+08:00</updated><id>http://localhost:4000/log/e-reader</id><author><name>W. D. Sadeep Madurange</name></author><summary type="html"><![CDATA[First project with e-paper displays and ESP32.]]></summary></entry></feed>
\ No newline at end of file +<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="/feed.xml" rel="self" type="application/atom+xml" /><link href="/" rel="alternate" type="text/html" /><updated>2026-01-05T22:16:02+08:00</updated><id>/feed.xml</id><title type="html">ASCIIMX | Log</title><author><name>W. D. Sadeep Madurange</name></author><entry><title type="html">Search engine (Perl + FastCGI + SA)</title><link href="/log/site-search/" rel="alternate" type="text/html" title="Search engine (Perl + FastCGI + SA)" /><published>2026-01-03T00:00:00+08:00</published><updated>2026-01-03T00:00:00+08:00</updated><id>/log/site-search</id><author><name>W. D. Sadeep Madurange</name></author><summary type="html"><![CDATA[Article count on the website is growing. Need a way to search.]]></summary></entry><entry><title type="html">Matrix Rain: 2025 refactor</title><link href="/log/matrix-digital-rain/" rel="alternate" type="text/html" title="Matrix Rain: 2025 refactor" /><published>2025-12-21T00:00:00+08:00</published><updated>2025-12-21T00:00:00+08:00</updated><id>/log/matrix-digital-rain</id><author><name>W. D. Sadeep Madurange</name></author><summary type="html"><![CDATA[The 2022 version worked but had some loose ends. Unicode support was inflexible–couldn’t mix ASCII with Katakana; Phosphor decay was stored in a separate array when it should’ve been packed with RGB; Code was harder to read than it needed to be.]]></summary></entry><entry><title type="html">Fingerprint door lock (LP)</title><link href="/log/fpm-door-lock-lp/" rel="alternate" type="text/html" title="Fingerprint door lock (LP)" /><published>2025-08-18T00:00:00+08:00</published><updated>2025-08-18T00:00:00+08:00</updated><id>/log/fpm-door-lock-lp</id><author><name>W. D. Sadeep Madurange</name></author><summary type="html"><![CDATA[Second iteration of the RF door lock. Old version worked but drew too much quiescent current. Sensor and servo pulled 13.8mA and 4.6mA idle. Linear regulators were a disaster. Battery didn’t last 24 hours.]]></summary></entry><entry><title type="html">High-side MOSFET switching</title><link href="/log/mosfet-switches/" rel="alternate" type="text/html" title="High-side MOSFET switching" /><published>2025-06-22T00:00:00+08:00</published><updated>2025-06-22T00:00:00+08:00</updated><id>/log/mosfet-switches</id><author><name>W. D. Sadeep Madurange</name></author><summary type="html"><![CDATA[Needed low-power switching for the fingerprint door lock. Servo and FPM draw high quiescent current–had to cut power electronically during sleep. MOSFETs can do this.]]></summary></entry><entry><title type="html">ATmega328P at 3.3V and 5V</title><link href="/log/arduino-uno/" rel="alternate" type="text/html" title="ATmega328P at 3.3V and 5V" /><published>2025-06-10T00:00:00+08:00</published><updated>2025-06-10T00:00:00+08:00</updated><id>/log/arduino-uno</id><author><name>W. D. Sadeep Madurange</name></author><summary type="html"><![CDATA[Quick reference for wiring ATmega328P ICs at 5V and 3.3V. 5V uses 16MHz crystal, 3.3V uses 8MHz.]]></summary></entry><entry><title type="html">Fingerprint door lock (RF)</title><link href="/log/fpm-door-lock-rf/" rel="alternate" type="text/html" title="Fingerprint door lock (RF)" /><published>2025-06-05T00:00:00+08:00</published><updated>2025-06-05T00:00:00+08:00</updated><id>/log/fpm-door-lock-rf</id><author><name>W. D. Sadeep Madurange</name></author><summary type="html"><![CDATA[Wanted to unlock door with fingerprint, wirelessly to avoid drilling.]]></summary></entry><entry><title type="html">Bumblebee: web script synthesizer</title><link href="/log/bumblebee/" rel="alternate" type="text/html" title="Bumblebee: web script synthesizer" /><published>2025-04-02T00:00:00+08:00</published><updated>2025-04-02T00:00:00+08:00</updated><id>/log/bumblebee</id><author><name>W. D. Sadeep Madurange</name></author><summary type="html"><![CDATA[Work project. Browser session-to-code conversion.]]></summary></entry><entry><title type="html">ATSAM3X8E bare-metal notes</title><link href="/log/arduino-due/" rel="alternate" type="text/html" title="ATSAM3X8E bare-metal notes" /><published>2024-09-16T00:00:00+08:00</published><updated>2024-09-16T00:00:00+08:00</updated><id>/log/arduino-due</id><author><name>W. D. Sadeep Madurange</name></author><summary type="html"><![CDATA[Bypassing ATSAM3X8E (Due) bootloader via Serial Wire Debug (SWD).]]></summary></entry><entry><title type="html">Etlas: e-paper dashboard</title><link href="/log/etlas/" rel="alternate" type="text/html" title="Etlas: e-paper dashboard" /><published>2024-09-05T00:00:00+08:00</published><updated>2024-09-05T00:00:00+08:00</updated><id>/log/etlas</id><author><name>W. D. Sadeep Madurange</name></author><summary type="html"><![CDATA[Repurposed e-reader prototype into something for regular use. News, stocks, weather dashboard. ESP32 NodeMCU D1 + 7.5” Waveshare e-paper + DHT22 sensor.]]></summary></entry><entry><title type="html">512 KB e-reader</title><link href="/log/e-reader/" rel="alternate" type="text/html" title="512 KB e-reader" /><published>2023-10-24T00:00:00+08:00</published><updated>2023-10-24T00:00:00+08:00</updated><id>/log/e-reader</id><author><name>W. D. Sadeep Madurange</name></author><summary type="html"><![CDATA[First project with e-paper displays and ESP32.]]></summary></entry></feed>
\ No newline at end of file diff --git a/_site/index.html b/_site/index.html index 5b62029..62cc0dd 100644 --- a/_site/index.html +++ b/_site/index.html @@ -136,7 +136,7 @@ <tr> <td class="posts-td posts-td-link"> - <a href="/log/bumblebee/" class="link-decor-none">Bumblebee: browser automation</a> + <a href="/log/bumblebee/" class="link-decor-none">Bumblebee: web script synthesizer</a> </td> <td class="posts-td posts-td-time"> <span class="post-meta"> diff --git a/_site/log/bumblebee/index.html b/_site/log/bumblebee/index.html index f1881aa..5f5c3b0 100644 --- a/_site/log/bumblebee/index.html +++ b/_site/log/bumblebee/index.html @@ -3,7 +3,7 @@ <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> - <title>Bumblebee: browser automation</title> + <title>Bumblebee: web script synthesizer</title> <link rel="stylesheet" href="/assets/css/main.css"> <link rel="stylesheet" href="/assets/css/skeleton.css"> </head> @@ -37,44 +37,42 @@ <main> <div class="container"> <div class="container-2"> - <h2 class="center" id="title">BUMBLEBEE: BROWSER AUTOMATION</h2> + <h2 class="center" id="title">BUMBLEBEE: WEB SCRIPT SYNTHESIZER</h2> <h5 class="center">02 APRIL 2025</h5> <br> - <div class="twocol justify"><p>Built with Andy Zhang for an employer. Tool to automate web scraping script -generation.</p> + <div class="twocol justify"><p>Work project. Browser session-to-code conversion.</p> <video style="max-width:100%; margin-bottom: 10px" controls="" poster="poster.png"> <source src="bee.mp4" type="video/mp4" /> </video> -<p>Manual script authoring took hours. Scripts poorly optimized, CPUs maxed -constantly, cloud costs excessive.</p> +<p>Architecture: C# WinForms host, embedded browser, code editor. Browser +extension rejected due to security policy and shallow event control.</p> -<p>Initially considered browser extension. Desktop app won—extensions don’t give -deep event control. Company policy blocked extensions anyway.</p> +<p>Tool evaluation:</p> -<p>First prototype: C# Win Forms + CefSharp.</p> +<ul> + <li>CefSharp: Discarded. API lacked elegance.</li> + <li>WebView2: Selected. Better WinForms integration. Hard dependency on +Microsoft Edge–acceptable for corporate Windows environments.</li> +</ul> -<p>Second prototype: C# Win Forms + WebView2. Packaging and distribution more -complex, but the API is well-designed; integrates well with Win Forms.</p> +<p>Implementation:</p> -<p>Microsoft Edge required. Portability not a concern, only need to target -controlled Windows environments. Choosing WebView2 over CefSharp.</p> +<ol> + <li>Interception: Injected JS hooks; internal browser event monitoring +(pop-ups/downloads).</li> + <li>Transformation: Event → Token → Instruction Table → String.</li> + <li>Optimization: Parallel event/text lists processing; rendered +in <a href="https://github.com/desjarlais/Scintilla.NET" class="external" target="_blank" rel="noopener noreferrer">Scintilla.NET</a></li> +</ol> -<p>Embed <a href="https://github.com/desjarlais/Scintilla.NET" class="external" toarget="_blank" rel="noopener noreferrer">Scintilla.NET</a> editor for -overriding generated script.</p> +<p>Bug: Manual mid-session overrides desync code/event lists, bypassing optimizer. +Linear lists inadequate for state synchronization. Need to rethink data +structures; look to compiler Abstract Syntax Trees (AST) for intermediate +representation.</p> -<p>Code generation sequence: Inject JavaScript to intercept client-side events. -Capture internal browser events (pop-ups, file downloads). Event -raised → parsed into a token → insert to list → interpret event → look up -instruction from a table → form instruction with event args → insert text to a -parallel list → run both lists through optimizer → update Scintilla editor.</p> - -<p>Limitation: manual overriding via Scintilla editor mid-session causes the code -list to go out of sync with the event list. Optimizer can’t handle this yet.</p> - -<p>Note to self: need to rethink the event/text list data structures in the -context of the optimizer–look to compilers for inspiration maybe?</p> +<p>Verdict: Serves its purpose.</p> </div> <p class="post-author right">by W. D. Sadeep Madurange</p> diff --git a/_site/posts.xml b/_site/posts.xml index 2b2377d..d381285 100644 --- a/_site/posts.xml +++ b/_site/posts.xml @@ -1 +1 @@ -<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="http://localhost:4000/posts.xml" rel="self" type="application/atom+xml" /><link href="http://localhost:4000/" rel="alternate" type="text/html" /><updated>2026-01-05T18:48:39+08:00</updated><id>http://localhost:4000/posts.xml</id><title type="html">ASCIIMX</title><author><name>W. D. Sadeep Madurange</name></author></feed>
\ No newline at end of file +<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="/posts.xml" rel="self" type="application/atom+xml" /><link href="/" rel="alternate" type="text/html" /><updated>2026-01-05T22:16:02+08:00</updated><id>/posts.xml</id><title type="html">ASCIIMX</title><author><name>W. D. Sadeep Madurange</name></author></feed>
\ No newline at end of file diff --git a/_site/projects/index.html b/_site/projects/index.html index c87b2d7..90732a1 100644 --- a/_site/projects/index.html +++ b/_site/projects/index.html @@ -82,8 +82,8 @@ <td class="project-item"> <a href="../log/bumblebee" class="link-decor-none"> - <img src="../log/bumblebee/thumb_sm.png" alt="Bumblebee: browser automation"> - <h5>Bumblebee: browser automation</h5> + <img src="../log/bumblebee/thumb_sm.png" alt="Bumblebee: web script synthesizer"> + <h5>Bumblebee: web script synthesizer</h5> </a> </td> diff --git a/_site/robots.txt b/_site/robots.txt index d297064..e087884 100644 --- a/_site/robots.txt +++ b/_site/robots.txt @@ -1 +1 @@ -Sitemap: http://localhost:4000/sitemap.xml +Sitemap: /sitemap.xml diff --git a/_site/sitemap.xml b/_site/sitemap.xml index a722c6a..ad3bdcd 100644 --- a/_site/sitemap.xml +++ b/_site/sitemap.xml @@ -1,56 +1,56 @@ <?xml version="1.0" encoding="UTF-8"?> <urlset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd" xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"> <url> -<loc>http://localhost:4000/log/neo4j-a-star-search/</loc> +<loc>/log/neo4j-a-star-search/</loc> <lastmod>2018-03-06T00:00:00+08:00</lastmod> </url> <url> -<loc>http://localhost:4000/log/e-reader/</loc> +<loc>/log/e-reader/</loc> <lastmod>2023-10-24T00:00:00+08:00</lastmod> </url> <url> -<loc>http://localhost:4000/log/etlas/</loc> +<loc>/log/etlas/</loc> <lastmod>2024-09-05T00:00:00+08:00</lastmod> </url> <url> -<loc>http://localhost:4000/log/arduino-due/</loc> +<loc>/log/arduino-due/</loc> <lastmod>2024-09-16T00:00:00+08:00</lastmod> </url> <url> -<loc>http://localhost:4000/log/bumblebee/</loc> +<loc>/log/bumblebee/</loc> <lastmod>2025-04-02T00:00:00+08:00</lastmod> </url> <url> -<loc>http://localhost:4000/log/fpm-door-lock-rf/</loc> +<loc>/log/fpm-door-lock-rf/</loc> <lastmod>2025-06-05T00:00:00+08:00</lastmod> </url> <url> -<loc>http://localhost:4000/log/arduino-uno/</loc> +<loc>/log/arduino-uno/</loc> <lastmod>2025-06-10T00:00:00+08:00</lastmod> </url> <url> -<loc>http://localhost:4000/log/mosfet-switches/</loc> +<loc>/log/mosfet-switches/</loc> <lastmod>2025-06-22T00:00:00+08:00</lastmod> </url> <url> -<loc>http://localhost:4000/log/fpm-door-lock-lp/</loc> +<loc>/log/fpm-door-lock-lp/</loc> <lastmod>2025-08-18T00:00:00+08:00</lastmod> </url> <url> -<loc>http://localhost:4000/log/matrix-digital-rain/</loc> +<loc>/log/matrix-digital-rain/</loc> <lastmod>2025-12-21T00:00:00+08:00</lastmod> </url> <url> -<loc>http://localhost:4000/log/site-search/</loc> +<loc>/log/site-search/</loc> <lastmod>2026-01-03T00:00:00+08:00</lastmod> </url> <url> -<loc>http://localhost:4000/about/</loc> +<loc>/about/</loc> </url> <url> -<loc>http://localhost:4000/</loc> +<loc>/</loc> </url> <url> -<loc>http://localhost:4000/projects/</loc> +<loc>/projects/</loc> </url> </urlset> |
