@helping-ai-workflow/md2doc 2.4.1 → 2.4.2
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.
- package/lib/md2doc.js +77 -0
- package/package.json +2 -2
package/lib/md2doc.js
CHANGED
|
@@ -1868,6 +1868,83 @@ ${mermaidInitTag}` : ''}
|
|
|
1868
1868
|
setSidebarOpen(false);
|
|
1869
1869
|
}
|
|
1870
1870
|
});
|
|
1871
|
+
|
|
1872
|
+
// ── Zoom / resize scroll anchoring ────────────────────────────────────────
|
|
1873
|
+
// Browser zoom (and any window resize) reflows the column but leaves the
|
|
1874
|
+
// pixel scroll offset untouched, so the passage being read slides out of
|
|
1875
|
+
// view. Remember what sat at the top of the reading column and put it back.
|
|
1876
|
+
var ANCHOR_LINE = 80;
|
|
1877
|
+
var contentEl = document.querySelector('main.content');
|
|
1878
|
+
var anchorNode = null;
|
|
1879
|
+
var anchorTop = 0;
|
|
1880
|
+
var anchorFrame = 0;
|
|
1881
|
+
var suppressAnchorCapture = false;
|
|
1882
|
+
var lastLayoutWidth = document.documentElement.clientWidth;
|
|
1883
|
+
var lastPixelRatio = window.devicePixelRatio;
|
|
1884
|
+
|
|
1885
|
+
function captureScrollAnchor() {
|
|
1886
|
+
if (suppressAnchorCapture || !contentEl) return;
|
|
1887
|
+
var rect = contentEl.getBoundingClientRect();
|
|
1888
|
+
var hit = document.elementFromPoint(rect.left + rect.width / 2, ANCHOR_LINE);
|
|
1889
|
+
var node = (hit && hit.closest) ? hit.closest('main.content > *') : null;
|
|
1890
|
+
if (!node) {
|
|
1891
|
+
// Between blocks, or over a gap: fall back to the last heading above the
|
|
1892
|
+
// anchor line. Heading offsets are monotonic in document order, so this
|
|
1893
|
+
// is a binary search rather than a scan of every heading each frame.
|
|
1894
|
+
var lo = 0;
|
|
1895
|
+
var hi = headingNodes.length - 1;
|
|
1896
|
+
while (lo <= hi) {
|
|
1897
|
+
var mid = (lo + hi) >> 1;
|
|
1898
|
+
if (headingNodes[mid].getBoundingClientRect().top <= ANCHOR_LINE) {
|
|
1899
|
+
node = headingNodes[mid];
|
|
1900
|
+
lo = mid + 1;
|
|
1901
|
+
} else {
|
|
1902
|
+
hi = mid - 1;
|
|
1903
|
+
}
|
|
1904
|
+
}
|
|
1905
|
+
}
|
|
1906
|
+
if (!node) return;
|
|
1907
|
+
anchorNode = node;
|
|
1908
|
+
anchorTop = node.getBoundingClientRect().top;
|
|
1909
|
+
}
|
|
1910
|
+
|
|
1911
|
+
function restoreScrollAnchor() {
|
|
1912
|
+
if (!anchorNode || !anchorNode.isConnected) return;
|
|
1913
|
+
var delta = anchorNode.getBoundingClientRect().top - anchorTop;
|
|
1914
|
+
if (!delta) return;
|
|
1915
|
+
window.scrollTo(window.scrollX, window.scrollY + delta);
|
|
1916
|
+
}
|
|
1917
|
+
|
|
1918
|
+
window.addEventListener('scroll', function () {
|
|
1919
|
+
if (anchorFrame) return;
|
|
1920
|
+
anchorFrame = window.requestAnimationFrame(function () {
|
|
1921
|
+
anchorFrame = 0;
|
|
1922
|
+
captureScrollAnchor();
|
|
1923
|
+
});
|
|
1924
|
+
}, { passive: true });
|
|
1925
|
+
|
|
1926
|
+
window.addEventListener('resize', function () {
|
|
1927
|
+
var width = document.documentElement.clientWidth;
|
|
1928
|
+
var ratio = window.devicePixelRatio;
|
|
1929
|
+
// A height-only change (a mobile browser hiding its toolbar, a devtools
|
|
1930
|
+
// dock) reflows nothing, so correcting the scroll would only jerk the page.
|
|
1931
|
+
if (width === lastLayoutWidth && ratio === lastPixelRatio) return;
|
|
1932
|
+
lastLayoutWidth = width;
|
|
1933
|
+
lastPixelRatio = ratio;
|
|
1934
|
+
// Hold the anchor across the whole reflow: the scrollTo below fires scroll
|
|
1935
|
+
// events that would otherwise re-capture a mid-reflow position.
|
|
1936
|
+
suppressAnchorCapture = true;
|
|
1937
|
+
restoreScrollAnchor();
|
|
1938
|
+
window.requestAnimationFrame(function () {
|
|
1939
|
+
restoreScrollAnchor();
|
|
1940
|
+
window.requestAnimationFrame(function () {
|
|
1941
|
+
suppressAnchorCapture = false;
|
|
1942
|
+
captureScrollAnchor();
|
|
1943
|
+
});
|
|
1944
|
+
});
|
|
1945
|
+
});
|
|
1946
|
+
|
|
1947
|
+
captureScrollAnchor();
|
|
1871
1948
|
})();
|
|
1872
1949
|
</script>
|
|
1873
1950
|
</body>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@helping-ai-workflow/md2doc",
|
|
3
|
-
"version": "2.4.
|
|
3
|
+
"version": "2.4.2",
|
|
4
4
|
"description": "Markdown → HTML / PDF renderer with WaveDrom, Mermaid, and Graphviz support",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"markdown",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
},
|
|
37
37
|
"scripts": {
|
|
38
38
|
"preinstall": "node scripts/preinstall.js",
|
|
39
|
-
"test": "node test/md2doc.test.js && node test/images.test.js && node test/cli.test.js && node test/code-operator.test.js"
|
|
39
|
+
"test": "node test/md2doc.test.js && node test/images.test.js && node test/scroll-anchor.test.js && node test/cli.test.js && node test/code-operator.test.js"
|
|
40
40
|
},
|
|
41
41
|
"repository": {
|
|
42
42
|
"type": "git",
|