fix: 修复外部资源、图标模式与嵌套交互(#30)
Fixes: https://github.com/rbetree/menav/issues/30 - Font Awesome:bootcdn→Cloudflare cdnjs - favicon:gstatic `.com` 失败自动回退 `.cn` - `icons.mode`:修复 `site.yml` 配置未生效(提升到顶层) - 站点级图标覆盖:支持 `faviconUrl` / `forceIconMode`(优先级:`faviconUrl` > `forceIconMode` > `icons.mode`) - 折叠交互:恢复二级分组折叠按钮(桌面端悬停显示) - 新标签页:递归补齐多级 `sites.external` 默认值
This commit is contained in:
@@ -1,42 +1,83 @@
|
||||
{{#if url}}
|
||||
<a href="{{url}}" class="site-card{{#if style}} site-card-{{style}}{{/if}}"
|
||||
{{#if external}}target="_blank" rel="noopener"{{/if}}
|
||||
data-type="{{#if type}}{{type}}{{else}}site{{/if}}"
|
||||
data-name="{{name}}"
|
||||
data-url="{{url}}"
|
||||
data-icon="{{#if icon}}{{icon}}{{else}}fas fa-link{{/if}}"
|
||||
data-description="{{#if description}}{{description}}{{else}}{{extractDomain url}}{{/if}}"
|
||||
{{#if publishedAt}}data-published-at="{{publishedAt}}"{{/if}}
|
||||
{{#if source}}data-source="{{source}}"{{/if}}>
|
||||
<a href="{{url}}" class="site-card{{#if style}} site-card-{{style}}{{/if}}"
|
||||
{{#if external}}target="_blank" rel="noopener"{{/if}}
|
||||
data-type="{{#if type}}{{type}}{{else}}site{{/if}}"
|
||||
data-name="{{name}}"
|
||||
data-url="{{url}}"
|
||||
data-icon="{{#if icon}}{{icon}}{{else}}fas fa-link{{/if}}"
|
||||
{{#if faviconUrl}}data-favicon-url="{{faviconUrl}}"{{/if}}
|
||||
{{#if forceIconMode}}data-force-icon-mode="{{forceIconMode}}"{{/if}}
|
||||
data-description="{{#if description}}{{description}}{{else}}{{extractDomain url}}{{/if}}"
|
||||
{{#if publishedAt}}data-published-at="{{publishedAt}}"{{/if}}
|
||||
{{#if source}}data-source="{{source}}"{{/if}}>
|
||||
{{!-- articles:首行图标+标题;下方“时间/来源 + 简介”全宽对齐,不被图标列缩进 --}}
|
||||
{{#ifEquals type "article"}}
|
||||
<div class="article-card-header">
|
||||
<div class="site-card-icon" aria-hidden="true">
|
||||
{{#ifEquals @root.icons.mode "favicon"}}
|
||||
{{#ifHttpUrl url}}
|
||||
<div class="icon-container">
|
||||
<i class="fas fa-circle-notch fa-spin icon-placeholder" aria-hidden="true"></i>
|
||||
<img
|
||||
class="favicon-icon"
|
||||
src="https://t3.gstatic.com/faviconV2?client=SOCIAL&type=FAVICON&fallback_opts=TYPE,SIZE,URL&url={{encodeURIComponent url}}&size=32"
|
||||
alt="{{name}} favicon"
|
||||
loading="lazy"
|
||||
onload="this.classList.add('loaded'); this.previousElementSibling.classList.add('hidden');"
|
||||
onerror="this.classList.add('error'); this.previousElementSibling.classList.add('hidden'); this.nextElementSibling.classList.add('visible');"
|
||||
/>
|
||||
<i class="{{#if icon}}{{icon}}{{else}}fas fa-link{{/if}} icon-fallback" aria-hidden="true"></i>
|
||||
</div>
|
||||
{{else}}
|
||||
<i class="{{#if icon}}{{icon}}{{else}}fas fa-link{{/if}} site-icon" aria-hidden="true"></i>
|
||||
{{/ifHttpUrl}}
|
||||
{{else}}
|
||||
<i class="{{#if icon}}{{icon}}{{else}}fas fa-link{{/if}} site-icon" aria-hidden="true"></i>
|
||||
{{/ifEquals}}
|
||||
</div>
|
||||
<div class="article-card-title">
|
||||
<h3>{{#if name}}{{name}}{{else}}未命名站点{{/if}}</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div class="article-card-header">
|
||||
<div class="site-card-icon" aria-hidden="true">
|
||||
{{!-- 站点图标优先级:faviconUrl > forceIconMode > 全局 icons.mode --}}
|
||||
{{#if faviconUrl}}
|
||||
<div class="icon-container">
|
||||
<i class="fas fa-circle-notch fa-spin icon-placeholder" aria-hidden="true"></i>
|
||||
<img
|
||||
class="favicon-icon"
|
||||
src="{{faviconUrl}}"
|
||||
alt="{{name}} favicon"
|
||||
loading="lazy"
|
||||
onload="this.classList.add('loaded'); this.previousElementSibling.classList.add('hidden');"
|
||||
onerror="this.classList.add('error'); this.previousElementSibling.classList.add('hidden'); this.nextElementSibling.classList.add('visible');"
|
||||
/>
|
||||
<i class="{{#if icon}}{{icon}}{{else}}fas fa-link{{/if}} icon-fallback" aria-hidden="true"></i>
|
||||
</div>
|
||||
{{else}}
|
||||
{{#ifEquals forceIconMode "manual"}}
|
||||
<i class="{{#if icon}}{{icon}}{{else}}fas fa-link{{/if}} site-icon" aria-hidden="true"></i>
|
||||
{{else}}
|
||||
{{#ifEquals forceIconMode "favicon"}}
|
||||
{{#ifHttpUrl url}}
|
||||
<div class="icon-container">
|
||||
<i class="fas fa-circle-notch fa-spin icon-placeholder" aria-hidden="true"></i>
|
||||
<img
|
||||
class="favicon-icon"
|
||||
src="https://t3.gstatic.com/faviconV2?client=SOCIAL&type=FAVICON&fallback_opts=TYPE,SIZE,URL&url={{encodeURIComponent url}}&size=32"
|
||||
alt="{{name}} favicon"
|
||||
loading="lazy"
|
||||
onload="this.classList.add('loaded'); this.previousElementSibling.classList.add('hidden');"
|
||||
onerror="if (!this.dataset.faviconFallbackTried) { this.dataset.faviconFallbackTried = '1'; var next = this.src.replace('t3.gstatic.com', 't3.gstatic.cn'); if (next !== this.src) { this.src = next; return; } } this.classList.add('error'); this.previousElementSibling.classList.add('hidden'); this.nextElementSibling.classList.add('visible');"
|
||||
/>
|
||||
<i class="{{#if icon}}{{icon}}{{else}}fas fa-link{{/if}} icon-fallback" aria-hidden="true"></i>
|
||||
</div>
|
||||
{{else}}
|
||||
<i class="{{#if icon}}{{icon}}{{else}}fas fa-link{{/if}} site-icon" aria-hidden="true"></i>
|
||||
{{/ifHttpUrl}}
|
||||
{{else}}
|
||||
{{#ifEquals @root.icons.mode "favicon"}}
|
||||
{{#ifHttpUrl url}}
|
||||
<div class="icon-container">
|
||||
<i class="fas fa-circle-notch fa-spin icon-placeholder" aria-hidden="true"></i>
|
||||
<img
|
||||
class="favicon-icon"
|
||||
src="https://t3.gstatic.com/faviconV2?client=SOCIAL&type=FAVICON&fallback_opts=TYPE,SIZE,URL&url={{encodeURIComponent url}}&size=32"
|
||||
alt="{{name}} favicon"
|
||||
loading="lazy"
|
||||
onload="this.classList.add('loaded'); this.previousElementSibling.classList.add('hidden');"
|
||||
onerror="if (!this.dataset.faviconFallbackTried) { this.dataset.faviconFallbackTried = '1'; var next = this.src.replace('t3.gstatic.com', 't3.gstatic.cn'); if (next !== this.src) { this.src = next; return; } } this.classList.add('error'); this.previousElementSibling.classList.add('hidden'); this.nextElementSibling.classList.add('visible');"
|
||||
/>
|
||||
<i class="{{#if icon}}{{icon}}{{else}}fas fa-link{{/if}} icon-fallback" aria-hidden="true"></i>
|
||||
</div>
|
||||
{{else}}
|
||||
<i class="{{#if icon}}{{icon}}{{else}}fas fa-link{{/if}} site-icon" aria-hidden="true"></i>
|
||||
{{/ifHttpUrl}}
|
||||
{{else}}
|
||||
<i class="{{#if icon}}{{icon}}{{else}}fas fa-link{{/if}} site-icon" aria-hidden="true"></i>
|
||||
{{/ifEquals}}
|
||||
{{/ifEquals}}
|
||||
{{/ifEquals}}
|
||||
{{/if}}
|
||||
</div>
|
||||
<div class="article-card-title">
|
||||
<h3>{{#if name}}{{name}}{{else}}未命名站点{{/if}}</h3>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="article-card-body">
|
||||
{{#ifCond publishedAt '||' source}}
|
||||
@@ -89,29 +130,68 @@
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/ifCond}}
|
||||
{{else}}
|
||||
<div class="site-card-icon" aria-hidden="true">
|
||||
{{#ifEquals @root.icons.mode "favicon"}}
|
||||
{{#ifHttpUrl url}}
|
||||
<div class="icon-container">
|
||||
<i class="fas fa-circle-notch fa-spin icon-placeholder" aria-hidden="true"></i>
|
||||
<img
|
||||
class="favicon-icon"
|
||||
src="https://t3.gstatic.com/faviconV2?client=SOCIAL&type=FAVICON&fallback_opts=TYPE,SIZE,URL&url={{encodeURIComponent url}}&size=32"
|
||||
alt="{{name}} favicon"
|
||||
loading="lazy"
|
||||
onload="this.classList.add('loaded'); this.previousElementSibling.classList.add('hidden');"
|
||||
onerror="this.classList.add('error'); this.previousElementSibling.classList.add('hidden'); this.nextElementSibling.classList.add('visible');"
|
||||
/>
|
||||
<i class="{{#if icon}}{{icon}}{{else}}fas fa-link{{/if}} icon-fallback" aria-hidden="true"></i>
|
||||
</div>
|
||||
{{else}}
|
||||
<i class="{{#if icon}}{{icon}}{{else}}fas fa-link{{/if}} site-icon" aria-hidden="true"></i>
|
||||
{{/ifHttpUrl}}
|
||||
{{else}}
|
||||
<i class="{{#if icon}}{{icon}}{{else}}fas fa-link{{/if}} site-icon" aria-hidden="true"></i>
|
||||
{{/ifEquals}}
|
||||
</div>
|
||||
{{else}}
|
||||
<div class="site-card-icon" aria-hidden="true">
|
||||
{{!-- 站点图标优先级:faviconUrl > forceIconMode > 全局 icons.mode --}}
|
||||
{{#if faviconUrl}}
|
||||
<div class="icon-container">
|
||||
<i class="fas fa-circle-notch fa-spin icon-placeholder" aria-hidden="true"></i>
|
||||
<img
|
||||
class="favicon-icon"
|
||||
src="{{faviconUrl}}"
|
||||
alt="{{name}} favicon"
|
||||
loading="lazy"
|
||||
onload="this.classList.add('loaded'); this.previousElementSibling.classList.add('hidden');"
|
||||
onerror="this.classList.add('error'); this.previousElementSibling.classList.add('hidden'); this.nextElementSibling.classList.add('visible');"
|
||||
/>
|
||||
<i class="{{#if icon}}{{icon}}{{else}}fas fa-link{{/if}} icon-fallback" aria-hidden="true"></i>
|
||||
</div>
|
||||
{{else}}
|
||||
{{#ifEquals forceIconMode "manual"}}
|
||||
<i class="{{#if icon}}{{icon}}{{else}}fas fa-link{{/if}} site-icon" aria-hidden="true"></i>
|
||||
{{else}}
|
||||
{{#ifEquals forceIconMode "favicon"}}
|
||||
{{#ifHttpUrl url}}
|
||||
<div class="icon-container">
|
||||
<i class="fas fa-circle-notch fa-spin icon-placeholder" aria-hidden="true"></i>
|
||||
<img
|
||||
class="favicon-icon"
|
||||
src="https://t3.gstatic.com/faviconV2?client=SOCIAL&type=FAVICON&fallback_opts=TYPE,SIZE,URL&url={{encodeURIComponent url}}&size=32"
|
||||
alt="{{name}} favicon"
|
||||
loading="lazy"
|
||||
onload="this.classList.add('loaded'); this.previousElementSibling.classList.add('hidden');"
|
||||
onerror="if (!this.dataset.faviconFallbackTried) { this.dataset.faviconFallbackTried = '1'; var next = this.src.replace('t3.gstatic.com', 't3.gstatic.cn'); if (next !== this.src) { this.src = next; return; } } this.classList.add('error'); this.previousElementSibling.classList.add('hidden'); this.nextElementSibling.classList.add('visible');"
|
||||
/>
|
||||
<i class="{{#if icon}}{{icon}}{{else}}fas fa-link{{/if}} icon-fallback" aria-hidden="true"></i>
|
||||
</div>
|
||||
{{else}}
|
||||
<i class="{{#if icon}}{{icon}}{{else}}fas fa-link{{/if}} site-icon" aria-hidden="true"></i>
|
||||
{{/ifHttpUrl}}
|
||||
{{else}}
|
||||
{{#ifEquals @root.icons.mode "favicon"}}
|
||||
{{#ifHttpUrl url}}
|
||||
<div class="icon-container">
|
||||
<i class="fas fa-circle-notch fa-spin icon-placeholder" aria-hidden="true"></i>
|
||||
<img
|
||||
class="favicon-icon"
|
||||
src="https://t3.gstatic.com/faviconV2?client=SOCIAL&type=FAVICON&fallback_opts=TYPE,SIZE,URL&url={{encodeURIComponent url}}&size=32"
|
||||
alt="{{name}} favicon"
|
||||
loading="lazy"
|
||||
onload="this.classList.add('loaded'); this.previousElementSibling.classList.add('hidden');"
|
||||
onerror="if (!this.dataset.faviconFallbackTried) { this.dataset.faviconFallbackTried = '1'; var next = this.src.replace('t3.gstatic.com', 't3.gstatic.cn'); if (next !== this.src) { this.src = next; return; } } this.classList.add('error'); this.previousElementSibling.classList.add('hidden'); this.nextElementSibling.classList.add('visible');"
|
||||
/>
|
||||
<i class="{{#if icon}}{{icon}}{{else}}fas fa-link{{/if}} icon-fallback" aria-hidden="true"></i>
|
||||
</div>
|
||||
{{else}}
|
||||
<i class="{{#if icon}}{{icon}}{{else}}fas fa-link{{/if}} site-icon" aria-hidden="true"></i>
|
||||
{{/ifHttpUrl}}
|
||||
{{else}}
|
||||
<i class="{{#if icon}}{{icon}}{{else}}fas fa-link{{/if}} site-icon" aria-hidden="true"></i>
|
||||
{{/ifEquals}}
|
||||
{{/ifEquals}}
|
||||
{{/ifEquals}}
|
||||
{{/if}}
|
||||
</div>
|
||||
|
||||
<div class="site-card-content">
|
||||
<h3>{{#if name}}{{name}}{{else}}未命名站点{{/if}}</h3>
|
||||
|
||||
Reference in New Issue
Block a user