🚀 Big News:Socket Has Acquired Secure Annex.Learn More
Socket
Book a DemoSign in
Socket

@docmd/ui

Package Overview
Dependencies
Maintainers
1
Versions
37
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@docmd/ui - npm Package Compare versions

Comparing version
0.7.5
to
0.7.6
+9
-17
assets/css/docmd-main.css

@@ -42,3 +42,3 @@ /**

/* Code Colors */
--code-bg: #eaeaea1f;
--code-bg: #9392921f;
--code-text: #27272a;

@@ -529,11 +529,2 @@

.content-area {
padding: var(--space-8) 5%;
max-width: 1216px;
/* 1200 + 16 for some wiggle room */
margin: 0 auto;
width: 100%;
box-sizing: border-box;
}
@media (max-width: 768px) {

@@ -1271,3 +1262,3 @@ .content-area {

.content-area {
padding: 1rem 5%;
padding: 1rem 2.5rem;
max-width: 1200px;

@@ -1763,6 +1754,6 @@ margin: 0 auto;

border: 1px solid var(--border-color);
padding: 4px 12px;
padding: 3px 8px;
border-radius: 20px;
font-size: .85rem;
font-weight: 600;
font-size: .75rem;
font-weight: 500;
font-family: var(--font-family-mono)

@@ -1772,5 +1763,5 @@ }

.changelog-body {
border-left: 2px solid var(--border-color);
padding-left: 2rem;
padding-bottom: 1rem
border-left: 1px solid var(--border-color);
padding-left: 2.5rem;
padding-bottom: .5rem;
}

@@ -2246,2 +2237,3 @@

display: inline-block;
margin-right: 5px;
}

@@ -2248,0 +2240,0 @@

@@ -21,2 +21,4 @@ /**

/* global requestAnimationFrame, cancelAnimationFrame */
(function () {

@@ -98,3 +100,4 @@

const normTargetRoot = targetRoot.endsWith('/') ? targetRoot : targetRoot + '/';
const targetHref = normTargetRoot + suffix + window.location.hash;
let targetHref = normTargetRoot + suffix + window.location.hash;
targetHref = targetHref.replace(/([^:])\/{2,}/g, '$1/'); // Prevent double slashes

@@ -363,6 +366,10 @@ // Smart Switcher: Check if the exact page exists in the target version

prefetchTimer = setTimeout(() => {
pageCache.set(url, fetch(url).then(res => {
// Prefetch using hash-stripped URL — the fragment is never sent to the server
const prefetchUrl = new URL(link.href);
const prefetchFetchUrl = prefetchUrl.origin + prefetchUrl.pathname + prefetchUrl.search;
if (pageCache.has(prefetchFetchUrl)) return;
pageCache.set(prefetchFetchUrl, fetch(prefetchFetchUrl).then(res => {
if (!res.ok) throw new Error('Prefetch failed');
return { html: res.text(), finalUrl: res.url };
}).catch(() => pageCache.delete(url)));
}).catch(() => pageCache.delete(prefetchFetchUrl)));
}, 65);

@@ -384,4 +391,14 @@ });

if (url.origin !== location.origin) return;
if (url.pathname === window.location.pathname && url.hash) return;
// Same-page hash navigation: scroll to the target element smoothly
// without a full SPA fetch. The browser's native behaviour doesn't
// fire reliably after a previous pushState, so we handle it manually.
if (url.pathname === window.location.pathname && url.hash) {
e.preventDefault();
history.pushState({}, '', url.href);
const target = document.querySelector(url.hash) || document.getElementById(url.hash.substring(1));
if (target) target.scrollIntoView({ behavior: 'smooth' });
return;
}
e.preventDefault();

@@ -392,3 +409,11 @@ await navigateTo(url.href);

window.addEventListener('popstate', () => {
if (window.location.pathname === currentPath) return;
// Same-page hash change via browser back/forward
if (window.location.pathname === currentPath) {
const hash = window.location.hash;
if (hash) {
const target = document.querySelector(hash) || document.getElementById(hash.substring(1));
if (target) target.scrollIntoView({ behavior: 'smooth' });
}
return;
}
navigateTo(window.location.href, false);

@@ -403,14 +428,21 @@ });

// Separate hash from the fetch URL — servers don't receive fragments,
// and res.url (finalUrl) will never contain the hash. We preserve it
// manually so pushState and the scroll both use the correct value.
const parsedUrl = new URL(url);
const requestedHash = parsedUrl.hash; // e.g. "#configuration"
const fetchUrl = parsedUrl.origin + parsedUrl.pathname + parsedUrl.search;
let data;
if (pageCache.has(url)) {
data = await pageCache.get(url);
if (pageCache.has(fetchUrl)) {
data = await pageCache.get(fetchUrl);
data.html = await data.html;
} else {
const res = await fetch(url);
const res = await fetch(fetchUrl);
if (!res.ok) throw new Error('Fetch failed');
data = { html: await res.text(), finalUrl: res.url };
pageCache.set(url, Promise.resolve(data));
pageCache.set(fetchUrl, Promise.resolve(data));
}
const finalUrl = data.finalUrl;
const finalUrl = data.finalUrl + requestedHash;
const html = data.html;

@@ -496,12 +528,15 @@

const hash = new URL(finalUrl).hash;
if (hash) {
try {
document.querySelector(hash)?.scrollIntoView();
} catch {
document.getElementById(hash.substring(1))?.scrollIntoView();
// Scroll after the browser has painted the new content.
// requestAnimationFrame ensures the swapped innerHTML is in the layout.
requestAnimationFrame(() => {
if (requestedHash) {
try {
const target = document.querySelector(requestedHash)
|| document.getElementById(requestedHash.substring(1));
if (target) target.scrollIntoView({ behavior: 'smooth' });
} catch { /* invalid selector — ignore */ }
} else {
window.scrollTo(0, 0);
}
} else {
window.scrollTo(0, 0);
}
});

@@ -508,0 +543,0 @@ injectCopyButtons();

{
"name": "@docmd/ui",
"version": "0.7.5",
"version": "0.7.6",
"description": "Base UI templates and assets for docmd.",

@@ -5,0 +5,0 @@ "type": "module",

@@ -90,3 +90,3 @@ <!--

<% } else { %>
<h1><a href="<%= relativePathToRoot %>index.html">
<h1><a href="<%= relativePathToRoot %>">
<%= siteTitle %>

@@ -93,0 +93,0 @@ </a></h1>

@@ -10,5 +10,15 @@ <%# ---------------------------------------------------------------

<ul>
<% function normalizePath(p) { if (!p || p==='#' ) return '#' ; if (p.startsWith('http')) return p; let
path=p.replace(/^(\.\/|\/)+/, '' ); path=path.replace(/(\/index\.html|index\.html|\.html|\.md)$/, '' );
path=path.replace(/\/$/, '' ); return '/' + path; } function isChildActive(item, currentPath) { if
<%
// normalizePath: used ONLY for active-state comparison (not for href generation).
// All href generation goes through buildRelativeUrl() which delegates to the
// centralized URL engine in @docmd/parser.
function normalizePath(p) {
if (!p || p === '#') return '#';
if (p.startsWith('http')) return p;
let path = p.replace(/^(\.\/|\/)+/, '');
path = path.replace(/(\/index\.html|index\.html|\.html|\.md)$/, '');
path = path.replace(/\/$/, '');
return '/' + path;
}
function isChildActive(item, currentPath) { if
(!item.children) return false; const currentNorm=normalizePath(currentPath); return item.children.some(child=> {

@@ -48,14 +58,5 @@ const childNorm = normalizePath(child.path);

let href = item.path || '#';
if (!isExternal && !isDummyLink && !href.startsWith('http')) {
let cleanPath = href.replace(/^(\.\/|\/)+/, '');
// Apply locale + version namespace prefix safely
const prefix = (typeof outputPrefix !== 'undefined') ? outputPrefix : '';
href = relativePathToRoot + prefix + cleanPath;
if (isOfflineMode) {
if (href.endsWith('/')) href += 'index.html';
else if (!href.endsWith('.html')) href += '/index.html';
} else {
if (href.endsWith('/index.html')) href = href.slice(0, -10);
}
}
if (!isExternal && !isDummyLink) {
href = buildRelativeUrl(href);
}
%>

@@ -62,0 +63,0 @@ <li class="<%= liClasses.join(' ') %>" <% if(isInteractive) { %> aria-expanded="<%= isOpen %>" <% } %>>

@@ -162,3 +162,3 @@ <!--

<div class="sidebar-header">
<a href="<%= logo.href || (relativePathToRoot + 'index.html') %>" class="logo-link">
<a href="<%= logo.href || relativePathToRoot %>" class="logo-link">
<img src="<%= relativePathToRoot %><%- logo.light.startsWith('/') ? logo.light.substring(1) : logo.light %>"

@@ -165,0 +165,0 @@ alt="<%= logo.alt || siteTitle %>" class="logo-light" <% if (logo.height) { %>style="height: <%= logo.height %>;"<% } %>>

@@ -31,3 +31,3 @@ <%# ---------------------------------------------------------------

<% col.links.forEach(link => { %>
<li><a href="<%= link.url %>" <%= link.external ? 'target="_blank" rel="noopener"' : '' %>><%= link.text %></a></li>
<li><a href="<%= link.external ? link.url : buildRelativeUrl(link.url) %>" <%= link.external ? 'target="_blank" rel="noopener"' : '' %>><%= link.text %></a></li>
<% }) %>

@@ -34,0 +34,0 @@ </ul>

@@ -55,8 +55,10 @@ <%# ---------------------------------------------------------------

const base = config.base || '/';
const normalizedBase = base.endsWith('/') ? base : base + '/';
// Build locale-aware URL preserving version and page path
// Use centralised URL builder — single source of truth
const locPrefix = isLocDefault ? '' : loc.id + '/';
const absoluteHref = isDisabled ? '#' : (normalizedBase + locPrefix + versionPrefix + pagePath);
const absoluteHref = isDisabled
? '#'
: ((typeof buildAbsoluteUrl === 'function')
? buildAbsoluteUrl(config.base || '/', locPrefix, versionPrefix, pagePath)
: ((config.base || '/').replace(/\/?$/, '/') + locPrefix + versionPrefix + pagePath));
%>

@@ -63,0 +65,0 @@ <li>

@@ -9,12 +9,9 @@ <%# ---------------------------------------------------------------

<%
const menubarBase = (config.base || '/').replace(/\/$/, '') + '/';
const menuLocPrefix = (typeof localePrefix !== 'undefined' && localePrefix) ? localePrefix : '';
function menubarHref(item) {
if (!item.url) return '#' ;
if (item.external || item.url.startsWith('http')) return item.url;
let clean=item.url.replace(/^\//, '' );
return menubarBase + menuLocPrefix + clean;
return item.external ? item.url : buildRelativeUrl(item.url);
}
function menubarTarget(item) {
return (item.external || (item.url && item.url.startsWith('http'))) ? ' target="_blank" rel="noopener noreferrer"' : '' ;
// Only open in new tab if user explicitly adds external: prefix
// Users who want their own docs site to open in new tab should add external: prefix
return item.external ? ' target="_blank" rel="noopener noreferrer"' : '' ;
}

@@ -59,3 +56,3 @@ %>

<%= sub.text %>
<% if (sub.external || (sub.url && sub.url.startsWith('http'))) { %>
<% if (sub.external) { %>
<%- renderIcon('external-link', { class: 'menubar-ext-icon' }) %>

@@ -77,3 +74,3 @@ <% } %>

</span>
<% if (item.external || (item.url && item.url.startsWith('http'))) { %>
<% if (item.external) { %>
<%- renderIcon('external-link', { class: 'menubar-ext-icon' }) %>

@@ -109,3 +106,3 @@ <% } %>

<%= sub.text %>
<% if (sub.external || (sub.url && sub.url.startsWith('http'))) { %>
<% if (sub.external) { %>
<%- renderIcon('external-link', { class: 'menubar-ext-icon' }) %>

@@ -127,3 +124,3 @@ <% } %>

</span>
<% if (item.external || (item.url && item.url.startsWith('http'))) { %>
<% if (item.external) { %>
<%- renderIcon('external-link', { class: 'menubar-ext-icon' }) %>

@@ -130,0 +127,0 @@ <% } %>

@@ -30,9 +30,3 @@ <%# ---------------------------------------------------------------

// We use the 'config' object which is available in all templates
const base = config.base || '/';
const normalizedBase = base.endsWith('/') ? base : base + '/';
// Include locale prefix for non-default locales
// Include locale prefix for non-default locales
const locPrefix = (typeof localePrefix !== 'undefined' && localePrefix) ? localePrefix : '';

@@ -45,4 +39,8 @@

const targetSuffix = isTargetRootVersion ? '' : v.id + '/';
const absoluteHref = normalizedBase + effectiveLocPrefix + targetSuffix;
// Use centralised URL builder — single source of truth
const absoluteHref = (typeof buildAbsoluteUrl === 'function')
? buildAbsoluteUrl(config.base || '/', effectiveLocPrefix, targetSuffix, '')
: ((config.base || '/').replace(/\/?$/, '/') + effectiveLocPrefix + targetSuffix);
// Data Root for JS Sticky Logic

@@ -49,0 +47,0 @@ const dataRoot = absoluteHref;