refactor(alpine): restructure components and remove unused utilities for better modularity and maintainability
这个提交包含在:
+57
-55
@@ -1,66 +1,68 @@
|
||||
<!DOCTYPE html>
|
||||
<html
|
||||
xmlns:th="https://www.thymeleaf.org"
|
||||
th:replace="~{modules/layout :: html(title = |#{page.archives.title} - ${site.title}|, header = null, content = ~{::content}, footer = null)}"
|
||||
th:replace="~{modules/layout :: html(title = |#{page.archives.title} - ${site.title}|, pageType = 'archive', terminalUserName = ${archives != null and archives.items != null and !#lists.isEmpty(archives.items) and archives.items[0].months != null and !#lists.isEmpty(archives.items[0].months) and archives.items[0].months[0].posts != null and !#lists.isEmpty(archives.items[0].months[0].posts) and archives.items[0].months[0].posts[0].owner != null and !#strings.isEmpty(archives.items[0].months[0].posts[0].owner.name) ? archives.items[0].months[0].posts[0].owner.name : 'admin'}, content = ~{::content})}"
|
||||
>
|
||||
<th:block th:fragment="content">
|
||||
<div class="content">
|
||||
<div class="post">
|
||||
<h1 class="post-title" th:text="文章归档">文章归档</h1>
|
||||
<th:block th:each="archive : ${archives.items}">
|
||||
<ul>
|
||||
<th:block th:each="month : ${archive.months}">
|
||||
<li class="post-list" th:each="post : ${month.posts}">
|
||||
<a th:href="${post.status.permalink}">
|
||||
<span class="post-date" th:text="${#dates.format(post.spec.publishTime,'yyyy-MM-dd')}"
|
||||
>发布时间</span
|
||||
>
|
||||
<span class="post-separator">
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
</span>
|
||||
<span class="post-list-title" th:text="${post.spec.title}">文章标题</span></a>
|
||||
<span class="post-tags-inline">
|
||||
<span class="post-separator">
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
</span>
|
||||
<span th:each="tag : ${post.tags}">
|
||||
<a
|
||||
th:href="${tag.status.permalink}"
|
||||
th:title="${tag.spec.displayName}"
|
||||
th:text="'#'+${tag.spec.displayName}"
|
||||
class="post-tag"
|
||||
>#Tag
|
||||
</a>
|
||||
</span>
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
</th:block>
|
||||
</ul>
|
||||
</th:block>
|
||||
<section class="devcm-terminal-window devcm-archive-hero">
|
||||
<div class="devcm-window-titlebar">
|
||||
<span class="devcm-window-dot"></span>
|
||||
<span class="devcm-window-dot"></span>
|
||||
<span class="devcm-window-dot"></span>
|
||||
</div>
|
||||
<div class="pagination" th:if="${archives.hasPrevious() || archives.hasNext()}">
|
||||
<div class="pagination__buttons">
|
||||
<span class="button previous" th:if="${archives.hasPrevious()}">
|
||||
<a th:href="@{${archives.prevUrl}}">
|
||||
<span class="button__icon">< </span>
|
||||
<span class="button__text">上一页</span>
|
||||
</a>
|
||||
</span>
|
||||
<span class="button next" th:if="${archives.hasNext()}">
|
||||
<a th:href="@{${archives.nextUrl}}">
|
||||
<span class="button__text">下一页</span>
|
||||
<span class="button__icon"> ></span>
|
||||
</a>
|
||||
</span>
|
||||
<div class="devcm-hero">
|
||||
<div class="devcm-hero__copy">
|
||||
<div class="devcm-prompt-line">
|
||||
<span th:text="|${terminalUser}@devcm:~$|">admin@devcm:~$</span>
|
||||
<span th:text="#{devcm.archive.command}">archive --view posts</span>
|
||||
</div>
|
||||
<h1 class="devcm-hero__title" th:text="#{devcm.archive.title}">Archives</h1>
|
||||
<p class="devcm-hero__desc" th:text="#{devcm.archive.description}">Browse content by publish date.</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="devcm-archive-table">
|
||||
<div class="devcm-archive-table__title" th:text="#{devcm.archive.tableTitle}">Archive list</div>
|
||||
<div class="devcm-archive-row devcm-archive-row--header">
|
||||
<span th:text="#{devcm.archive.columnTitle}">Title</span>
|
||||
<span th:text="#{devcm.archive.columnTags}">Tags</span>
|
||||
<span th:text="#{devcm.archive.columnDate}">Date</span>
|
||||
</div>
|
||||
<th:block th:each="archive : ${archives.items}">
|
||||
<th:block th:each="month : ${archive.months}">
|
||||
<div class="devcm-archive-row devcm-archive-row--month">
|
||||
<span>
|
||||
<span th:text="#{devcm.archive.group}">Archive group</span>
|
||||
(<span th:text="${#lists.size(month.posts)}">0</span>)
|
||||
</span>
|
||||
</div>
|
||||
<a class="devcm-archive-row" th:each="post : ${month.posts}" th:href="${post.status.permalink}">
|
||||
<span th:text="${post.spec.title}">文章标题</span>
|
||||
<span>
|
||||
<b th:each="tag : ${post.tags}" th:text="'#' + ${tag.spec.displayName} + ' '">#tag</b>
|
||||
</span>
|
||||
<span th:text="${#dates.format(post.spec.publishTime,'MM-dd')}">01-01</span>
|
||||
</a>
|
||||
</th:block>
|
||||
</th:block>
|
||||
</section>
|
||||
|
||||
<div class="pagination" th:if="${archives.hasPrevious() || archives.hasNext()}">
|
||||
<div class="pagination__buttons">
|
||||
<span class="button previous" th:if="${archives.hasPrevious()}">
|
||||
<a th:href="@{${archives.prevUrl}}">
|
||||
<span class="button__icon">< </span>
|
||||
<span class="button__text" th:text="#{devcm.pagination.previous}">Previous</span>
|
||||
</a>
|
||||
</span>
|
||||
<span class="button next" th:if="${archives.hasNext()}">
|
||||
<a th:href="@{${archives.nextUrl}}">
|
||||
<span class="button__text" th:text="#{devcm.pagination.next}">Next</span>
|
||||
<span class="button__icon"> ></span>
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</th:block>
|
||||
</html>
|
||||
|
||||
+35
-8
@@ -1,16 +1,43 @@
|
||||
<!DOCTYPE html>
|
||||
<html
|
||||
xmlns:th="https://www.thymeleaf.org"
|
||||
th:replace="~{modules/layout :: html(title = |#{page.categories.title} - ${site.title}|, header = null, content = ~{::content}, footer = null)}"
|
||||
th:replace="~{modules/layout :: html(title = |#{page.categories.title} - ${site.title}|, pageType = 'categories', terminalUserName = 'admin', content = ~{::content})}"
|
||||
>
|
||||
<th:block th:fragment="content">
|
||||
<div class="content">
|
||||
<div class="post">
|
||||
<h1 class="post-title">所有分类</h1>
|
||||
<ul>
|
||||
<li th:replace="~{modules/category-tree :: single(categories=${categories})}"></li>
|
||||
</ul>
|
||||
<section class="devcm-terminal-window devcm-archive-hero">
|
||||
<div class="devcm-window-titlebar">
|
||||
<span class="devcm-window-dot"></span>
|
||||
<span class="devcm-window-dot"></span>
|
||||
<span class="devcm-window-dot"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="devcm-hero">
|
||||
<div class="devcm-hero__copy">
|
||||
<div class="devcm-prompt-line">
|
||||
<span th:text="|${terminalUser}@devcm:~$|">admin@devcm:~$</span>
|
||||
<span th:text="#{devcm.categories.command}">archive --view categories</span>
|
||||
</div>
|
||||
<h1 class="devcm-hero__title" th:text="#{devcm.categories.title}">Categories</h1>
|
||||
<p class="devcm-hero__desc" th:text="#{devcm.categories.description}">
|
||||
Browse posts by category and explore the site structure.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="devcm-category-grid">
|
||||
<a class="devcm-category-card" th:each="category : ${categories}" th:href="${category.status.permalink}">
|
||||
<h2>
|
||||
<i class="i-pixelarticons-folder"></i>
|
||||
<span th:text="${category.spec.displayName}">Category</span>
|
||||
</h2>
|
||||
<strong
|
||||
th:text="#{devcm.categories.articleCount(${category.status.visiblePostCount != null ? category.status.visiblePostCount : 0})}"
|
||||
>0 articles</strong
|
||||
>
|
||||
<p th:if="${not #strings.isEmpty(category.spec.description)}" th:text="${category.spec.description}">
|
||||
Category description
|
||||
</p>
|
||||
</a>
|
||||
</section>
|
||||
</th:block>
|
||||
</html>
|
||||
|
||||
+43
-58
@@ -1,68 +1,53 @@
|
||||
<!DOCTYPE html>
|
||||
<html
|
||||
xmlns:th="https://www.thymeleaf.org"
|
||||
th:replace="~{modules/layout :: html(title = |#{page.category.title(${category.spec.displayName})} - ${site.title}|, header = null, content = ~{::content}, footer = null)}"
|
||||
th:replace="~{modules/layout :: html(title = |#{page.category.title(${category.spec.displayName})} - ${site.title}|, pageType = 'category', terminalUserName = ${posts != null and posts.items != null and !#lists.isEmpty(posts.items) and posts.items[0].owner != null and !#strings.isEmpty(posts.items[0].owner.name) ? posts.items[0].owner.name : 'admin'}, content = ~{::content})}"
|
||||
>
|
||||
<th:block th:fragment="content">
|
||||
<div class="content">
|
||||
<div class="post">
|
||||
<h1
|
||||
class="post-title"
|
||||
th:text="'分类:'+${category.spec.displayName}+' ('+${category.status.visiblePostCount?:0}+' 篇文章)'"
|
||||
>
|
||||
分类:分类名 (n 篇文章)
|
||||
</h1>
|
||||
<a href="/categories"> 所有分类 </a>
|
||||
<ul>
|
||||
<li class="post-list" th:each="post : ${posts.items}">
|
||||
<a th:href="${post.status.permalink}">
|
||||
<span class="post-date" th:text="${#dates.format(post.spec.publishTime,'yyyy-MM-dd')}"
|
||||
>发布时间</span
|
||||
>
|
||||
<span class="post-separator">
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
</span>
|
||||
<span class="post-list-title" th:text="${post.spec.title}">文章标题</span></a>
|
||||
<span class="post-tags-inline">
|
||||
<span class="post-separator">
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
</span>
|
||||
<span th:each="tag : ${post.tags}">
|
||||
<a
|
||||
th:href="${tag.status.permalink}"
|
||||
th:title="${tag.spec.displayName}"
|
||||
th:text="'#'+${tag.spec.displayName}"
|
||||
class="post-tag"
|
||||
>#Tag
|
||||
</a>
|
||||
</span>
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="pagination" th:if="${posts.hasPrevious() || posts.hasNext()}">
|
||||
<div class="pagination__buttons">
|
||||
<span class="button previous" th:if="${posts.hasPrevious()}">
|
||||
<a th:href="@{${posts.prevUrl}}">
|
||||
<span class="button__icon"><</span>
|
||||
<span class="button__text">上一页</span>
|
||||
</a>
|
||||
</span>
|
||||
<span class="button next" th:if="${posts.hasNext()}">
|
||||
<a th:href="@{${posts.nextUrl}}">
|
||||
<span class="button__text">下一页</span>
|
||||
<span class="button__icon">></span>
|
||||
</a>
|
||||
</span>
|
||||
<section class="devcm-editor-window">
|
||||
<div class="devcm-editor-tabs">
|
||||
<div class="devcm-editor-tab devcm-editor-tab--active">
|
||||
<span th:text="${category.spec.displayName} + '.md'">category.md</span>
|
||||
<a
|
||||
class="devcm-editor-tab__close"
|
||||
href="/categories"
|
||||
th:aria-label="#{devcm.action.closeCategoryTab}"
|
||||
th:title="#{devcm.action.closeCategoryTab}"
|
||||
>×</a
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="devcm-editor-body">
|
||||
<h1 class="devcm-page-title">
|
||||
<span th:text="#{devcm.taxonomy.categoryTitle(${category.spec.displayName})}">Category</span>
|
||||
<small
|
||||
th:text="#{devcm.taxonomy.postCount(${category.status.visiblePostCount != null ? category.status.visiblePostCount : 0})}"
|
||||
>(0 posts)</small
|
||||
>
|
||||
</h1>
|
||||
<div class="devcm-post-stack">
|
||||
<th:block th:each="post,iterStat : ${posts.items}">
|
||||
<th:block th:replace="~{modules/post-card :: post-card(post=${post}, featured=${iterStat.index == 0})}" />
|
||||
</th:block>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="pagination" th:if="${posts.hasPrevious() || posts.hasNext()}">
|
||||
<div class="pagination__buttons">
|
||||
<span class="button previous" th:if="${posts.hasPrevious()}">
|
||||
<a th:href="@{${posts.prevUrl}}">
|
||||
<span class="button__icon"><</span>
|
||||
<span class="button__text" th:text="#{devcm.pagination.previous}">Previous</span>
|
||||
</a>
|
||||
</span>
|
||||
<span class="button next" th:if="${posts.hasNext()}">
|
||||
<a th:href="@{${posts.nextUrl}}">
|
||||
<span class="button__text" th:text="#{devcm.pagination.next}">Next</span>
|
||||
<span class="button__icon">></span>
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</th:block>
|
||||
</html>
|
||||
|
||||
+81
-47
@@ -1,63 +1,97 @@
|
||||
<!DOCTYPE html>
|
||||
<html
|
||||
xmlns:th="https://www.thymeleaf.org"
|
||||
th:replace="~{modules/layout :: html(title = ${site.title}, header = null, content = ~{::content}, footer = null)}"
|
||||
th:replace="~{modules/layout :: html(title = ${site.title}, pageType = 'home', terminalUserName = ${posts != null and posts.items != null and !#lists.isEmpty(posts.items) and posts.items[0].owner != null and !#strings.isEmpty(posts.items[0].owner.name) ? posts.items[0].owner.name : 'admin'}, content = ~{::content})}"
|
||||
>
|
||||
<th:block th:fragment="content">
|
||||
<div class="content">
|
||||
<div class="index-content framed">
|
||||
<h1 class="typed-text" th:text="${theme.config.index.index_notice_title}"></h1>
|
||||
<div th:utext="${theme.config.index.index_notice_content}"></div>
|
||||
<section class="devcm-terminal-window devcm-home-hero">
|
||||
<div class="devcm-window-titlebar">
|
||||
<span class="devcm-window-dot"></span>
|
||||
<span class="devcm-window-dot"></span>
|
||||
<span class="devcm-window-dot"></span>
|
||||
</div>
|
||||
<div class="posts">
|
||||
<div class="post on-list" th:each="post : ${posts.items}">
|
||||
<h1 class="post-title">
|
||||
<a th:text="'< ' + ${post.spec.title} + ' >'" th:href="${post.status.permalink}">Post Title</a>
|
||||
<div class="devcm-hero">
|
||||
<div class="devcm-hero__copy">
|
||||
<div class="devcm-prompt-line">
|
||||
<span th:text="|${terminalUser}@devcm:~$|">admin@devcm:~$</span> <span>./welcome.sh</span>
|
||||
</div>
|
||||
<h1 class="devcm-hero__title typed-text" th:text="${theme.config.index.index_notice_title}">
|
||||
Welcome to DevCM.
|
||||
</h1>
|
||||
<div class="post-meta">
|
||||
<span class="post-date" th:text="${#dates.format(post.spec.publishTime,'yyyy-MM-dd')}">
|
||||
Post CreateTime
|
||||
</span>
|
||||
<span class="post-separator">
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
</span>
|
||||
<span class="post-author" th:with="contributor = ${post.contributors[0]}" th:text="${contributor.displayName}">
|
||||
Author
|
||||
</span>
|
||||
<span class="post-tags-inline" th:each="tag : ${post.tags}">
|
||||
<a th:href="${tag.status.permalink}"
|
||||
th:title="${tag.spec.displayName}"
|
||||
th:text="'#'+${tag.spec.displayName}"
|
||||
class="post-tag"
|
||||
>#Tag
|
||||
</a>
|
||||
</span>
|
||||
<div class="devcm-hero__subtitle" th:text="#{devcm.home.subtitle}">Development Content Management.</div>
|
||||
<div class="devcm-hero__desc" th:utext="${theme.config.index.index_notice_content}">
|
||||
<span th:text="#{devcm.home.defaultContent}">A Terminal-style Halo theme.</span>
|
||||
</div>
|
||||
<div class="post-content" th:text="${post.status.excerpt}">Post Excerpt...</div>
|
||||
|
||||
<div>
|
||||
<a class="read-more button" th:href="${post.status.permalink}">阅读更多 ></a>
|
||||
<div class="devcm-prompt-line devcm-prompt-line--after-typed">
|
||||
<span th:text="|${terminalUser}@devcm:~$|">admin@devcm:~$</span> <span class="devcm-cursor"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="devcm-ascii-badge" aria-hidden="true">
|
||||
<span class="devcm-ascii-badge__grid"></span>
|
||||
<div class="devcm-ascii-badge__inner">
|
||||
<span class="devcm-ascii-badge__label">DEV.CM</span>
|
||||
<pre>
|
||||
DEV
|
||||
CM</pre
|
||||
>
|
||||
<small>< <span th:text="${#dates.year(#dates.createNow())}">2026</span> /></small>
|
||||
<span class="devcm-ascii-badge__scan"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pagination" th:if="${posts.hasPrevious() || posts.hasNext()}">
|
||||
<div class="pagination__buttons">
|
||||
<span class="button previous" th:if="${posts.hasPrevious()}">
|
||||
<a th:href="@{${posts.prevUrl}}">
|
||||
<span class="button__icon">< </span>
|
||||
<span class="button__text">上一页</span>
|
||||
</section>
|
||||
|
||||
<section class="devcm-editor-window" x-data="{ postsOpen: true }">
|
||||
<div class="devcm-editor-tabs">
|
||||
<div class="devcm-editor-tabs__left">
|
||||
<div class="devcm-editor-tab devcm-editor-tab--active" x-show="postsOpen">
|
||||
<span>posts.md</span>
|
||||
<a
|
||||
href="#"
|
||||
class="devcm-editor-tab__close"
|
||||
role="button"
|
||||
@click.prevent="postsOpen = false"
|
||||
th:aria-label="#{devcm.action.closeTab}"
|
||||
th:title="#{devcm.action.closeTab}"
|
||||
>
|
||||
×
|
||||
</a>
|
||||
</span>
|
||||
<span class="button next" th:if="${posts.hasNext()}">
|
||||
<a th:href="@{${posts.nextUrl}}">
|
||||
<span class="button__text">下一页</span>
|
||||
<span class="button__icon"> ></span>
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<a
|
||||
class="devcm-editor-tab__add"
|
||||
href="/console"
|
||||
th:aria-label="#{devcm.action.newPost}"
|
||||
th:title="#{devcm.action.newPost}"
|
||||
>+</a
|
||||
>
|
||||
</div>
|
||||
<div id="devcm-posts-panel" class="devcm-editor-body devcm-post-list-body" x-show="postsOpen">
|
||||
<div class="devcm-post-stack">
|
||||
<th:block th:each="post,iterStat : ${posts.items}">
|
||||
<th:block th:replace="~{modules/post-card :: post-card(post=${post}, featured=${iterStat.index == 0})}" />
|
||||
</th:block>
|
||||
<div class="devcm-list-footnote" th:if="${posts.items != null}">
|
||||
<span th:text="#{devcm.home.postCount(${#lists.size(posts.items)})}">> Current page has 0 post(s)</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="pagination" th:if="${posts.hasPrevious() || posts.hasNext()}">
|
||||
<div class="pagination__buttons">
|
||||
<span class="button previous" th:if="${posts.hasPrevious()}">
|
||||
<a th:href="@{${posts.prevUrl}}">
|
||||
<span class="button__icon">< </span>
|
||||
<span class="button__text" th:text="#{devcm.pagination.previous}">Previous</span>
|
||||
</a>
|
||||
</span>
|
||||
<span class="button next" th:if="${posts.hasNext()}">
|
||||
<a th:href="@{${posts.nextUrl}}">
|
||||
<span class="button__text" th:text="#{devcm.pagination.next}">Next</span>
|
||||
<span class="button__icon"> ></span>
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</th:block>
|
||||
|
||||
+37
-34
@@ -1,43 +1,46 @@
|
||||
<!DOCTYPE html>
|
||||
<html
|
||||
xmlns:th="https://www.thymeleaf.org"
|
||||
th:replace="~{modules/layout :: html(title = |#{page.links.title} - ${site.title}|, header = null, content = ~{::content}, footer = null)}"
|
||||
th:replace="~{modules/layout :: html(title = |#{page.links.title} - ${site.title}|, pageType = 'links', terminalUserName = 'admin', content = ~{::content})}"
|
||||
>
|
||||
<th:block th:fragment="content">
|
||||
<script th:src="@{/assets/libs/pixelit.js}"></script>
|
||||
<div>
|
||||
<section class="">
|
||||
<div class="">
|
||||
<div class="mb-6" th:each="group : ${groups}">
|
||||
<div class="">
|
||||
<h2
|
||||
class="post-title"
|
||||
th:text="${!#strings.isEmpty(group.spec.displayName) ? group.spec.displayName:'友情链接'}"
|
||||
>
|
||||
链接分组
|
||||
</h2>
|
||||
</div>
|
||||
<div class="">
|
||||
<a th:each="link : ${group.links}" th:href="${link.spec.url}" target="_blank" class="mb-2 block">
|
||||
<div class="flex bg-[#a9c1e2] dark:bg-[#3b5070] p-1">
|
||||
<div class="">
|
||||
<img class="w-16" src="sky.jpg" th:src="${link.spec.logo}" id="pixelitimg" th:alt="${link.spec.displayName}">
|
||||
</div>
|
||||
<div class="ml-4 flex flex-col justify-around">
|
||||
<div class="m-0 text-[#003e8a] dark:text-[#6ca4f8]"><span th:text="${link.spec.displayName}"></span><span th:text="| (${link.spec.url})|"></span></div>
|
||||
<div class="m-0 text-[#3e3e3e] dark:text-[#8b949e]" th:text="${link.spec.description}"></div>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<section class="devcm-editor-window">
|
||||
<div class="devcm-editor-tabs">
|
||||
<div class="devcm-editor-tab devcm-editor-tab--active">
|
||||
<span>links.md</span>
|
||||
<a
|
||||
class="devcm-editor-tab__close"
|
||||
href="/"
|
||||
th:aria-label="#{devcm.action.closeLinksTab}"
|
||||
th:title="#{devcm.action.closeLinksTab}"
|
||||
>×</a
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="devcm-editor-body">
|
||||
<div class="devcm-link-group" th:each="group : ${groups}">
|
||||
<h2
|
||||
class="devcm-page-title"
|
||||
th:text="${!#strings.isEmpty(group.spec.displayName) ? group.spec.displayName : #messages.msg('devcm.links.defaultGroup')}"
|
||||
>
|
||||
Links
|
||||
</h2>
|
||||
<div class="devcm-link-grid">
|
||||
<a class="devcm-link-card" th:each="link : ${group.links}" th:href="${link.spec.url}" target="_blank">
|
||||
<img
|
||||
th:if="${not #strings.isEmpty(link.spec.logo)}"
|
||||
th:src="${link.spec.logo}"
|
||||
th:alt="${link.spec.displayName}"
|
||||
/>
|
||||
<span class="devcm-link-card__body">
|
||||
<strong th:text="${link.spec.displayName}">Link</strong>
|
||||
<small th:text="${link.spec.url}">https://example.com</small>
|
||||
<span th:text="${link.spec.description}">description</span>
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<script>
|
||||
//create object
|
||||
const px = new pixelit();
|
||||
px.draw().pixelate();
|
||||
</script>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</th:block>
|
||||
</html>
|
||||
|
||||
@@ -0,0 +1,213 @@
|
||||
<aside class="devcm-activity" th:fragment="activity-bar (pageType)" th:aria-label="#{devcm.activity.aria}">
|
||||
<span class="devcm-activity__icon-bank" aria-hidden="true">
|
||||
<i class="i-pixelarticons-folder"></i>
|
||||
<i class="i-pixelarticons-search"></i>
|
||||
<i class="i-pixelarticons-archive"></i>
|
||||
<i class="i-pixelarticons-script-text"></i>
|
||||
<i class="i-pixelarticons-label"></i>
|
||||
<i class="i-pixelarticons-user"></i>
|
||||
<i class="i-radix-icons-gear"></i>
|
||||
<i class="i-pixelarticons-git-branch"></i>
|
||||
<i class="i-pixelarticons-git-commit"></i>
|
||||
<i class="i-pixelarticons-git-merge"></i>
|
||||
<i class="i-pixelarticons-git-pull-request"></i>
|
||||
<i class="i-pixelarticons-github"></i>
|
||||
</span>
|
||||
|
||||
<th:block th:with="items=${theme.config.activity.activity_items}">
|
||||
<div class="devcm-activity__group devcm-activity__group--up">
|
||||
<th:block th:if="${items != null and !#lists.isEmpty(items)}">
|
||||
<th:block
|
||||
th:each="item : ${items}"
|
||||
th:with="placement=${#strings.isEmpty(item.position) ? 'up' : item.position},
|
||||
itemType=${!#strings.isEmpty(item.type) ? item.type : (!#strings.isEmpty(item.key) ? item.key : 'custom')},
|
||||
entryAction=${itemType == 'search' or item.action == 'search' ? 'search' : 'link'},
|
||||
entryHref=${entryAction == 'search' ? '#' : (!#strings.isEmpty(item.url) ? item.url : (!#strings.isEmpty(item.href) ? item.href : '#'))},
|
||||
entryLabel=${!#strings.isEmpty(item.label) ? item.label : (!#strings.isEmpty(item.labelKey) ? #messages.msg(item.labelKey) : #messages.msg('devcm.activity.link'))}"
|
||||
>
|
||||
<a
|
||||
class="devcm-activity__button"
|
||||
th:if="${placement != 'down' and itemType != 'login' and itemType != 'git' and (item.enabled == null or item.enabled == true or item.enabled == 'true') and (entryAction != 'search' or pluginFinder.available('PluginSearchWidget'))}"
|
||||
th:classappend="${(!#strings.isEmpty(item.activeTypes) and #strings.contains(',' + item.activeTypes + ',', ',' + pageType + ',')) or (itemType == 'home' and pageType == 'home') or (itemType == 'archive' and (pageType == 'archive' or pageType == 'post')) or (itemType == 'categories' and (pageType == 'categories' or pageType == 'category')) or (itemType == 'tags' and (pageType == 'tags' or pageType == 'tag'))} ? ' devcm-activity__button--active' : ''"
|
||||
th:href="${entryHref}"
|
||||
th:target="${item.external == true or item.external == 'true'} ? '_blank' : null"
|
||||
th:rel="${item.external == true or item.external == 'true'} ? 'noopener noreferrer' : null"
|
||||
th:title="${entryLabel}"
|
||||
th:attr="data-label=${entryLabel},aria-label=${entryLabel},data-devcm-action=${entryAction}"
|
||||
>
|
||||
<i th:class="|i-pixelarticons-${!#strings.isEmpty(item.icon) ? item.icon : 'file'}|"></i>
|
||||
</a>
|
||||
<a
|
||||
class="devcm-activity__button"
|
||||
sec:authorize="isAnonymous()"
|
||||
th:if="${placement != 'down' and itemType == 'login' and (item.enabled == null or item.enabled == true or item.enabled == 'true')}"
|
||||
th:href="${entryHref}"
|
||||
th:target="${item.external == true or item.external == 'true'} ? '_blank' : null"
|
||||
th:rel="${item.external == true or item.external == 'true'} ? 'noopener noreferrer' : null"
|
||||
th:title="${entryLabel}"
|
||||
th:attr="data-label=${entryLabel},aria-label=${entryLabel},data-devcm-action=${entryAction}"
|
||||
>
|
||||
<i class="i-pixelarticons-user"></i>
|
||||
</a>
|
||||
<a
|
||||
class="devcm-activity__button"
|
||||
sec:authorize="isAuthenticated()"
|
||||
th:if="${placement != 'down' and itemType == 'login' and (item.enabled == null or item.enabled == true or item.enabled == 'true')}"
|
||||
href="/console"
|
||||
th:title="#{devcm.activity.console}"
|
||||
th:attr="data-label=#{devcm.activity.console},aria-label=#{devcm.activity.console},data-devcm-action='link'"
|
||||
>
|
||||
<i class="i-radix-icons-gear"></i>
|
||||
</a>
|
||||
<a
|
||||
class="devcm-activity__button"
|
||||
sec:authorize="isAuthenticated()"
|
||||
th:if="${placement != 'down' and itemType == 'login' and (item.enabled == null or item.enabled == true or item.enabled == 'true')}"
|
||||
href="/logout"
|
||||
th:title="#{devcm.activity.logout}"
|
||||
th:attr="data-label=#{devcm.activity.logout},aria-label=#{devcm.activity.logout},data-devcm-action='link'"
|
||||
>
|
||||
<i class="i-pixelarticons-user"></i>
|
||||
</a>
|
||||
</th:block>
|
||||
</th:block>
|
||||
|
||||
<th:block th:if="${items == null or #lists.isEmpty(items)}">
|
||||
<a
|
||||
class="devcm-activity__button"
|
||||
th:classappend="${pageType == 'home'} ? ' devcm-activity__button--active' : ''"
|
||||
href="/"
|
||||
th:title="#{devcm.activity.explorer}"
|
||||
th:attr="data-label=#{devcm.activity.explorer},aria-label=#{devcm.activity.explorer}"
|
||||
>
|
||||
<i class="i-pixelarticons-folder"></i>
|
||||
</a>
|
||||
<a
|
||||
class="devcm-activity__button"
|
||||
th:if="${pluginFinder.available('PluginSearchWidget')}"
|
||||
href="#"
|
||||
data-devcm-action="search"
|
||||
th:title="#{devcm.activity.search}"
|
||||
th:attr="data-label=#{devcm.activity.search},aria-label=#{devcm.activity.search}"
|
||||
>
|
||||
<i class="i-pixelarticons-search"></i>
|
||||
</a>
|
||||
<a
|
||||
class="devcm-activity__button"
|
||||
th:classappend="${pageType == 'archive' or pageType == 'post'} ? ' devcm-activity__button--active' : ''"
|
||||
href="/archives"
|
||||
th:title="#{devcm.activity.archive}"
|
||||
th:attr="data-label=#{devcm.activity.archive},aria-label=#{devcm.activity.archive}"
|
||||
>
|
||||
<i class="i-pixelarticons-archive"></i>
|
||||
</a>
|
||||
<a
|
||||
class="devcm-activity__button"
|
||||
th:classappend="${pageType == 'categories' or pageType == 'category'} ? ' devcm-activity__button--active' : ''"
|
||||
href="/categories"
|
||||
th:title="#{devcm.activity.categories}"
|
||||
th:attr="data-label=#{devcm.activity.categories},aria-label=#{devcm.activity.categories}"
|
||||
>
|
||||
<i class="i-pixelarticons-script-text"></i>
|
||||
</a>
|
||||
<a
|
||||
class="devcm-activity__button"
|
||||
th:classappend="${pageType == 'tags' or pageType == 'tag'} ? ' devcm-activity__button--active' : ''"
|
||||
href="/tags"
|
||||
th:title="#{devcm.activity.tags}"
|
||||
th:attr="data-label=#{devcm.activity.tags},aria-label=#{devcm.activity.tags}"
|
||||
>
|
||||
<i class="i-pixelarticons-label"></i>
|
||||
</a>
|
||||
</th:block>
|
||||
</div>
|
||||
|
||||
<div class="devcm-activity__group devcm-activity__group--down">
|
||||
<th:block th:if="${items != null and !#lists.isEmpty(items)}">
|
||||
<th:block
|
||||
th:each="item : ${items}"
|
||||
th:with="placement=${#strings.isEmpty(item.position) ? 'up' : item.position},
|
||||
itemType=${!#strings.isEmpty(item.type) ? item.type : (!#strings.isEmpty(item.key) ? item.key : 'custom')},
|
||||
entryAction=${itemType == 'search' or item.action == 'search' ? 'search' : 'link'},
|
||||
entryHref=${entryAction == 'search' ? '#' : (!#strings.isEmpty(item.url) ? item.url : (!#strings.isEmpty(item.href) ? item.href : '#'))},
|
||||
entryLabel=${!#strings.isEmpty(item.label) ? item.label : (!#strings.isEmpty(item.labelKey) ? #messages.msg(item.labelKey) : #messages.msg('devcm.activity.link'))}"
|
||||
>
|
||||
<a
|
||||
class="devcm-activity__button"
|
||||
th:if="${placement == 'down' and itemType != 'login' and itemType != 'git' and (item.enabled == null or item.enabled == true or item.enabled == 'true') and (entryAction != 'search' or pluginFinder.available('PluginSearchWidget'))}"
|
||||
th:classappend="${(!#strings.isEmpty(item.activeTypes) and #strings.contains(',' + item.activeTypes + ',', ',' + pageType + ',')) or (itemType == 'home' and pageType == 'home') or (itemType == 'archive' and (pageType == 'archive' or pageType == 'post')) or (itemType == 'categories' and (pageType == 'categories' or pageType == 'category')) or (itemType == 'tags' and (pageType == 'tags' or pageType == 'tag'))} ? ' devcm-activity__button--active' : ''"
|
||||
th:href="${entryHref}"
|
||||
th:target="${item.external == true or item.external == 'true'} ? '_blank' : null"
|
||||
th:rel="${item.external == true or item.external == 'true'} ? 'noopener noreferrer' : null"
|
||||
th:title="${entryLabel}"
|
||||
th:attr="data-label=${entryLabel},aria-label=${entryLabel},data-devcm-action=${entryAction}"
|
||||
>
|
||||
<i th:class="|i-pixelarticons-${!#strings.isEmpty(item.icon) ? item.icon : 'file'}|"></i>
|
||||
</a>
|
||||
<a
|
||||
class="devcm-activity__button"
|
||||
sec:authorize="isAnonymous()"
|
||||
th:if="${placement == 'down' and itemType == 'login' and (item.enabled == null or item.enabled == true or item.enabled == 'true')}"
|
||||
th:href="${entryHref}"
|
||||
th:target="${item.external == true or item.external == 'true'} ? '_blank' : null"
|
||||
th:rel="${item.external == true or item.external == 'true'} ? 'noopener noreferrer' : null"
|
||||
th:title="${entryLabel}"
|
||||
th:attr="data-label=${entryLabel},aria-label=${entryLabel},data-devcm-action=${entryAction}"
|
||||
>
|
||||
<i class="i-pixelarticons-user"></i>
|
||||
</a>
|
||||
<a
|
||||
class="devcm-activity__button"
|
||||
sec:authorize="isAuthenticated()"
|
||||
th:if="${placement == 'down' and itemType == 'login' and (item.enabled == null or item.enabled == true or item.enabled == 'true')}"
|
||||
href="/console"
|
||||
th:title="#{devcm.activity.console}"
|
||||
th:attr="data-label=#{devcm.activity.console},aria-label=#{devcm.activity.console},data-devcm-action='link'"
|
||||
>
|
||||
<i class="i-radix-icons-gear"></i>
|
||||
</a>
|
||||
<a
|
||||
class="devcm-activity__button"
|
||||
sec:authorize="isAuthenticated()"
|
||||
th:if="${placement == 'down' and itemType == 'login' and (item.enabled == null or item.enabled == true or item.enabled == 'true')}"
|
||||
href="/logout"
|
||||
th:title="#{devcm.activity.logout}"
|
||||
th:attr="data-label=#{devcm.activity.logout},aria-label=#{devcm.activity.logout},data-devcm-action='link'"
|
||||
>
|
||||
<i class="i-pixelarticons-user"></i>
|
||||
</a>
|
||||
</th:block>
|
||||
</th:block>
|
||||
|
||||
<th:block th:if="${items == null or #lists.isEmpty(items)}">
|
||||
<a
|
||||
class="devcm-activity__button"
|
||||
sec:authorize="isAnonymous()"
|
||||
href="/console"
|
||||
th:title="#{devcm.activity.login}"
|
||||
th:attr="data-label=#{devcm.activity.login},aria-label=#{devcm.activity.login}"
|
||||
>
|
||||
<i class="i-pixelarticons-user"></i>
|
||||
</a>
|
||||
<a
|
||||
class="devcm-activity__button"
|
||||
sec:authorize="isAuthenticated()"
|
||||
href="/console"
|
||||
th:title="#{devcm.activity.console}"
|
||||
th:attr="data-label=#{devcm.activity.console},aria-label=#{devcm.activity.console}"
|
||||
>
|
||||
<i class="i-radix-icons-gear"></i>
|
||||
</a>
|
||||
<a
|
||||
class="devcm-activity__button"
|
||||
sec:authorize="isAuthenticated()"
|
||||
href="/logout"
|
||||
th:title="#{devcm.activity.logout}"
|
||||
th:attr="data-label=#{devcm.activity.logout},aria-label=#{devcm.activity.logout}"
|
||||
>
|
||||
<i class="i-pixelarticons-user"></i>
|
||||
</a>
|
||||
</th:block>
|
||||
</div>
|
||||
</th:block>
|
||||
</aside>
|
||||
@@ -1,10 +1,33 @@
|
||||
<ul th:fragment="next (categories)">
|
||||
<li th:fragment="single (categories)" th:each="category : ${categories}">
|
||||
<a th:href="@{${category.status.permalink}}">
|
||||
<span th:text="${category.spec.displayName}+' ('+${category.status.visiblePostCount?:0}+' 篇文章)'"> </span>
|
||||
</a>
|
||||
<th:block th:if="${not #lists.isEmpty(category.children)}">
|
||||
<ul th:fragment="next (categories)" class="devcm-tree__nested">
|
||||
<li th:fragment="single (categories)" th:each="category : ${categories}" class="devcm-tree__node">
|
||||
<details class="devcm-tree-folder" open th:if="${not #lists.isEmpty(category.children)}">
|
||||
<summary class="devcm-tree__item devcm-tree__item--folder">
|
||||
<span class="devcm-tree__chev" aria-hidden="true"></span>
|
||||
<i class="devcm-tree__icon i-pixelarticons-folder"></i>
|
||||
<span th:text="${category.spec.displayName}">Category</span>
|
||||
<a
|
||||
class="devcm-tree__open"
|
||||
th:href="@{${category.status.permalink}}"
|
||||
th:title="#{devcm.action.open}"
|
||||
th:aria-label="#{devcm.action.openCategory}"
|
||||
>↗</a
|
||||
>
|
||||
</summary>
|
||||
<th:block th:replace="~{modules/category-tree :: next (categories=${category.children})}"></th:block>
|
||||
</th:block>
|
||||
</details>
|
||||
<a
|
||||
class="devcm-tree__item"
|
||||
th:unless="${not #lists.isEmpty(category.children)}"
|
||||
th:href="@{${category.status.permalink}}"
|
||||
>
|
||||
<span class="devcm-tree__chev" aria-hidden="true"></span>
|
||||
<i class="devcm-tree__icon i-pixelarticons-folder"></i>
|
||||
<span th:text="${category.spec.displayName}">Category</span>
|
||||
<span
|
||||
class="devcm-tree__count"
|
||||
th:text="${category.status.visiblePostCount != null ? category.status.visiblePostCount : 0}"
|
||||
>0</span
|
||||
>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
<th:block xmlns:th="https://www.thymeleaf.org">
|
||||
<div class="devcm-terminal-window" th:fragment="terminal-window (content)">
|
||||
<div class="devcm-window-titlebar">
|
||||
<span class="devcm-window-dot"></span>
|
||||
<span class="devcm-window-dot"></span>
|
||||
<span class="devcm-window-dot"></span>
|
||||
</div>
|
||||
<th:block th:replace="${content}" />
|
||||
</div>
|
||||
|
||||
<div class="devcm-editor-window" th:fragment="editor-window (tabTitle, content)">
|
||||
<div class="devcm-editor-tabs">
|
||||
<div class="devcm-editor-tab devcm-editor-tab--active">
|
||||
<span th:text="${tabTitle}">_posts.md</span>
|
||||
<a
|
||||
class="devcm-editor-tab__close"
|
||||
href="/"
|
||||
th:aria-label="#{devcm.action.closeTab}"
|
||||
th:title="#{devcm.action.closeTab}"
|
||||
>×</a
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<th:block th:replace="${content}" />
|
||||
</div>
|
||||
</th:block>
|
||||
@@ -0,0 +1,47 @@
|
||||
<aside class="devcm-sidebar" th:fragment="explorer (pageType)" th:aria-label="#{devcm.explorer.title}">
|
||||
<section class="devcm-side-section">
|
||||
<div class="devcm-section-title">
|
||||
<span th:text="#{devcm.explorer.title}">EXPLORER</span>
|
||||
<span aria-hidden="true">...</span>
|
||||
</div>
|
||||
<div class="devcm-tree" th:with="menu = ${menuFinder.getPrimary()}">
|
||||
<details class="devcm-tree-folder" open>
|
||||
<summary class="devcm-tree__item devcm-tree__item--folder">
|
||||
<span class="devcm-tree__chev" aria-hidden="true"></span>
|
||||
<i class="devcm-tree__icon i-pixelarticons-folder"></i>
|
||||
<span th:text="#{devcm.explorer.pages}">pages</span>
|
||||
</summary>
|
||||
<div class="devcm-tree__nested">
|
||||
<th:block th:if="${menu != null}" th:replace="~{modules/menu-tree :: items(items=${menu.menuItems})}" />
|
||||
</div>
|
||||
</details>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="devcm-side-section" th:if="${categories != null}">
|
||||
<div class="devcm-section-title">
|
||||
<span th:text="#{devcm.explorer.categories}">CATEGORIES</span>
|
||||
<span aria-hidden="true">...</span>
|
||||
</div>
|
||||
<ul class="devcm-tree devcm-tree--list">
|
||||
<li th:replace="~{modules/category-tree :: single(categories=${categories})}"></li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section class="devcm-side-section" th:if="${tags != null}">
|
||||
<div class="devcm-section-title">
|
||||
<span th:text="#{devcm.explorer.tags}">TAGS CLOUD</span>
|
||||
<span aria-hidden="true">...</span>
|
||||
</div>
|
||||
<div class="devcm-tag-cloud">
|
||||
<a
|
||||
class="devcm-tag"
|
||||
th:each="tag : ${tags}"
|
||||
th:href="${tag.status.permalink}"
|
||||
th:text="'#' + ${tag.spec.displayName}"
|
||||
>
|
||||
#tag
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
</aside>
|
||||
@@ -3,7 +3,10 @@
|
||||
<div class="copyright">
|
||||
<span>
|
||||
© <span th:text="${#dates.year(#dates.createNow())}">2024</span> Powered by
|
||||
<a th:href="${theme.config.footer.footer_powered_link}" th:text="${theme.config.footer.footer_powered_text}"></a>
|
||||
<a
|
||||
th:href="${theme.config.footer.footer_powered_link}"
|
||||
th:text="${theme.config.footer.footer_powered_text}"
|
||||
></a>
|
||||
</span>
|
||||
</div>
|
||||
<div class="beian">
|
||||
@@ -16,7 +19,7 @@
|
||||
></a
|
||||
></span>
|
||||
<span th:if="${not #strings.isEmpty(theme.config.beian.gongan_text)}">
|
||||
<img th:src="@{/assets/image/gongan.png}" style="display:inline-block; height: 1.2em;">
|
||||
<img class="beian__icon" th:src="@{/assets/image/gongan.png}" alt="" />
|
||||
<a
|
||||
href="https://www.beian.gov.cn/"
|
||||
target="_blank"
|
||||
|
||||
+25
-70
@@ -1,77 +1,32 @@
|
||||
<header class="header" xmlns:th="http://www.w3.org/1999/xhtml">
|
||||
<div th:fragment="header" th:with="menu = ${menuFinder.getPrimary()}">
|
||||
<div class="header__inner">
|
||||
<a class="logo" href="/" style="text-decoration: none">
|
||||
<img class="icon" th:if="${not #strings.isEmpty(theme.config.basic.logo)}" th:src="${theme.config.basic.logo}" alt="Logo" />
|
||||
<div class="text" th:if="${not #strings.isEmpty(theme.config.basic.title)}" th:text="${theme.config.basic.title}"></div>
|
||||
</a>
|
||||
<div class="header__center" x-data="headerDividing()">
|
||||
<div class="dividing" :class="{ 'sticky': isSticky }"></div>
|
||||
</div>
|
||||
<header class="devcm-topbar header" th:fragment="header (pageType)" th:with="menu = ${menuFinder.getPrimary()}">
|
||||
<div class="devcm-topbar__main header__inner">
|
||||
<a class="devcm-brand logo" href="/" th:aria-label="#{devcm.explorer.home}">
|
||||
<img
|
||||
class="devcm-brand__image icon"
|
||||
th:if="${not #strings.isEmpty(theme.config.basic.logo)}"
|
||||
th:src="${theme.config.basic.logo}"
|
||||
alt="Logo"
|
||||
/>
|
||||
<span class="devcm-brand__mark" th:unless="${not #strings.isEmpty(theme.config.basic.logo)}">DEV<br />CM</span>
|
||||
<span class="devcm-brand__name">DevCM</span>
|
||||
</a>
|
||||
|
||||
<div class="devcm-prompt-stream header__center">
|
||||
<span class="devcm-prompt-stream__name" th:text="|${terminalUser}@devcm:~$|">admin@devcm:~$</span>
|
||||
<span class="devcm-prompt-stream__line dividing" aria-hidden="true"></span>
|
||||
</div>
|
||||
|
||||
<div class="devcm-topbar__actions">
|
||||
<button
|
||||
type="button"
|
||||
class="button"
|
||||
th:if="${pluginFinder.available('PluginSearchWidget')}"
|
||||
onclick="SearchWidget.open()"
|
||||
class="devcm-icon-button button"
|
||||
x-data="themeMode()"
|
||||
@click="handleToggleThemeMode()"
|
||||
th:aria-label="#{devcm.action.toggleTheme}"
|
||||
th:title="#{devcm.action.toggleTheme}"
|
||||
>
|
||||
<th:block th:unless="${theme.config.basic.pixel_style}">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1.5rem" height="1.5rem" viewBox="0 0 24 24">
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="m19.6 21l-6.3-6.3q-.75.6-1.725.95T9.5 16q-2.725 0-4.612-1.888T3 9.5q0-2.725 1.888-4.612T9.5 3q2.725 0 4.612 1.888T16 9.5q0 1.1-.35 2.075T14.7 13.3l6.3 6.3l-1.4 1.4ZM9.5 14q1.875 0 3.188-1.313T14 9.5q0-1.875-1.313-3.188T9.5 5Q7.625 5 6.312 6.313T5 9.5q0 1.875 1.313 3.188T9.5 14Z"
|
||||
/>
|
||||
</svg>
|
||||
</th:block>
|
||||
<th:block th:if="${theme.config.basic.pixel_style}">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1.5rem" height="1.5rem" viewBox="0 0 24 24"><path fill="currentColor" d="M6 2h8v2H6zM4 6V4h2v2zm0 8H2V6h2zm2 2H4v-2h2zm8 0v2H6v-2zm2-2h-2v2h2v2h2v2h2v2h2v-2h-2v-2h-2v-2h-2zm0-8h2v8h-2zm0 0V4h-2v2z"/></svg>
|
||||
</th:block>
|
||||
</button>
|
||||
<button type="button" class="button" x-data="themeMode()" @click="handleToggleThemeMode()">
|
||||
<th:block th:unless="${theme.config.basic.pixel_style}">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
style="vertical-align: -0.125em"
|
||||
width="1.5rem"
|
||||
height="1.5rem"
|
||||
preserveAspectRatio="xMidYMid meet"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M7.5 2c-1.79 1.15-3 3.18-3 5.5s1.21 4.35 3.03 5.5C4.46 13 2 10.54 2 7.5A5.5 5.5 0 0 1 7.5 2m11.57 1.5l1.43 1.43L4.93 20.5L3.5 19.07L19.07 3.5m-6.18 2.43L11.41 5L9.97 6l.42-1.7L9 3.24l1.75-.12l.58-1.65L12 3.1l1.73.03l-1.35 1.13l.51 1.67m-3.3 3.61l-1.16-.73l-1.12.78l.34-1.32l-1.09-.83l1.36-.09l.45-1.29l.51 1.27l1.36.03l-1.05.87l.4 1.31M19 13.5a5.5 5.5 0 0 1-5.5 5.5c-1.22 0-2.35-.4-3.26-1.07l7.69-7.69c.67.91 1.07 2.04 1.07 3.26m-4.4 6.58l2.77-1.15l-.24 3.35l-2.53-2.2m4.33-2.7l1.15-2.77l2.2 2.54l-3.35.23m1.15-4.96l-1.14-2.78l3.34.24l-2.2 2.54M9.63 18.93l2.77 1.15l-2.53 2.19l-.24-3.34Z"
|
||||
/>
|
||||
</svg>
|
||||
</th:block>
|
||||
<th:block th:if="${theme.config.basic.pixel_style}">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1.5rem" height="1.5rem" viewBox="0 0 24 24"><path fill="currentColor" d="M11 0h2v4h-2zm1 12H8v2H4v2H2v4h2v2h10v-2h2v-4h-2v-2h-2zm0 2v2h2v4H4v-4h4v2h2v-2H8v-2zM8 6h6v2H8zm0 2v2H6V8zm8 2h-2V8h2zm0 0h2v2h-2zm4-8h2v2h-2zm0 2v2h-2V4zM2 2h2v2H2zm2 2h2v2H4zm20 7h-4v2h4z"/></svg>
|
||||
</th:block>
|
||||
<i class="i-pixelarticons-sun-alt"></i>
|
||||
</button>
|
||||
</div>
|
||||
<nav class="menu">
|
||||
<ul th:if="${menu != null} and ${not #lists.isEmpty(menu.menuItems)}" class="menu__inner">
|
||||
<li th:each="menuItem : ${menu.menuItems}" x-data="headerMenu()" @mouseenter="handleToggleMenu()" @mouseleave="handleToggleMenu()">
|
||||
<a
|
||||
class="text-gray-600 hover:text-blue-600"
|
||||
th:href="${menuItem.status.href}"
|
||||
th:target="${menuItem.spec.target?.value}"
|
||||
th:text="${menuItem.status.displayName + (not #lists.isEmpty(menuItem.children) ? '▾' : '')}"
|
||||
></a>
|
||||
<ul
|
||||
th:if="${not #lists.isEmpty(menuItem.children)}"
|
||||
class="menu__sub-inner"
|
||||
:class="{'open': isOpen}"
|
||||
>
|
||||
<li th:each="childMenuItem : ${menuItem.children}">
|
||||
<a
|
||||
class="text-gray-600 hover:text-blue-600"
|
||||
th:href="${childMenuItem.status.href}"
|
||||
th:target="${childMenuItem.spec.target?.value}"
|
||||
th:text="${childMenuItem.status.displayName}"
|
||||
></a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
+33
-21
@@ -1,36 +1,48 @@
|
||||
<!DOCTYPE html>
|
||||
<html
|
||||
xmlns:th="https://www.thymeleaf.org"
|
||||
th:lang="${#locale.toLanguageTag}"
|
||||
th:fragment="html (header, content, footer)">
|
||||
th:lang="${#locale.toLanguageTag}"
|
||||
th:fragment="html (title, pageType, terminalUserName, content)"
|
||||
>
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link rel="icon" type="image/x-icon" th:href="${theme.config.basic.favicon}">
|
||||
<link rel="icon" type="image/x-icon" th:href="${theme.config.basic.favicon}" />
|
||||
<title th:text="${title}"></title>
|
||||
<link rel="manifest" th:href="@{/assets/dist/manifest.json}" />
|
||||
<link rel="stylesheet" th:href="@{/assets/dist/main.css?version={version}(version=${theme.spec.version})}" href="./assets/dist/style.css" />
|
||||
<link
|
||||
rel="stylesheet"
|
||||
th:href="@{/assets/dist/main.css?version={version}&build=devcm-ide-1.2.8-visual9(version=${theme.spec.version})}"
|
||||
href="./assets/dist/style.css"
|
||||
/>
|
||||
</head>
|
||||
<!-- 根据情况判断是否添加开启像素化样式 -->
|
||||
<body class="main" th:classappend="${theme.config.basic.pixel_style} ? 'pixel_style' : '' ">
|
||||
<div class="center headings--one-size container">
|
||||
<th:block th:if="${header != null}">
|
||||
<th:block th:replace="${header}" />
|
||||
</th:block>
|
||||
<th:block th:if="${header == null}">
|
||||
<th:block th:replace="~{modules/header :: header(isHome = true)}" />
|
||||
</th:block>
|
||||
<body
|
||||
class="main devcm-body"
|
||||
th:classappend="${theme.config.basic.pixel_style == true or theme.config.basic.pixel_style == 'true'} ? ' pixel_style' : ''"
|
||||
th:with="currentPageType=${#strings.isEmpty(pageType) ? 'home' : pageType},
|
||||
terminalUser=${#strings.isEmpty(terminalUserName) ? 'admin' : terminalUserName}"
|
||||
>
|
||||
<div class="devcm-shell" th:classappend="| devcm-shell--${currentPageType}|">
|
||||
<div class="devcm-app">
|
||||
<th:block th:replace="~{modules/header :: header(pageType=${currentPageType})}" />
|
||||
|
||||
<th:block th:replace="${content}" />
|
||||
<div class="devcm-workspace">
|
||||
<th:block th:replace="~{modules/activity-bar :: activity-bar(pageType=${currentPageType})}" />
|
||||
<th:block th:replace="~{modules/explorer :: explorer(pageType=${currentPageType})}" />
|
||||
|
||||
<th:block th:if="${footer == null}">
|
||||
<th:block th:replace="~{modules/footer}" />
|
||||
</th:block>
|
||||
<th:block th:if="${footer != null}">
|
||||
<th:block th:replace="${footer}" />
|
||||
</th:block>
|
||||
<main class="devcm-editor" id="main-content">
|
||||
<th:block th:replace="${content}" />
|
||||
</main>
|
||||
|
||||
<th:block th:replace="~{modules/right-panel :: right-panel(pageType=${currentPageType})}" />
|
||||
</div>
|
||||
|
||||
<th:block th:replace="~{modules/statusbar :: statusbar(pageType=${currentPageType})}" />
|
||||
</div>
|
||||
</div>
|
||||
<script th:src="@{/assets/dist/main.js?version={version}(version=${theme.spec.version})}"></script>
|
||||
<script
|
||||
th:src="@{/assets/dist/main.js?version={version}&build=devcm-ide-1.2.8-visual9(version=${theme.spec.version})}"
|
||||
></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
<th:block th:fragment="items (items)">
|
||||
<th:block
|
||||
th:each="menuItem : ${items}"
|
||||
th:with="menuHref=${menuItem.status.href},
|
||||
menuTarget=${menuItem.spec.target?.value},
|
||||
menuExternal=${!#strings.isEmpty(menuHref) and (#strings.startsWith(menuHref, 'http://') or #strings.startsWith(menuHref, 'https://') or menuTarget == '_blank')}"
|
||||
>
|
||||
<details class="devcm-tree-folder" open th:if="${not #lists.isEmpty(menuItem.children)}">
|
||||
<summary class="devcm-tree__item devcm-tree__item--folder">
|
||||
<span class="devcm-tree__chev" aria-hidden="true"></span>
|
||||
<i class="devcm-tree__icon i-pixelarticons-folder"></i>
|
||||
<span th:text="${menuItem.status.displayName}">Folder</span>
|
||||
<a
|
||||
class="devcm-tree__open devcm-tree__open--external"
|
||||
th:if="${menuExternal}"
|
||||
th:href="${menuHref}"
|
||||
th:target="${menuTarget}"
|
||||
rel="noopener noreferrer"
|
||||
th:title="#{devcm.action.open}"
|
||||
th:aria-label="#{devcm.action.openPage}"
|
||||
>
|
||||
<i class="i-pixelarticons-external-link"></i>
|
||||
</a>
|
||||
<a
|
||||
class="devcm-tree__open"
|
||||
th:unless="${menuExternal}"
|
||||
th:href="${menuHref}"
|
||||
th:target="${menuTarget}"
|
||||
th:title="#{devcm.action.open}"
|
||||
th:aria-label="#{devcm.action.openPage}"
|
||||
>
|
||||
<i class="i-pixelarticons-open"></i>
|
||||
</a>
|
||||
</summary>
|
||||
<div class="devcm-tree__nested">
|
||||
<th:block th:replace="~{modules/menu-tree :: items(items=${menuItem.children})}" />
|
||||
</div>
|
||||
</details>
|
||||
|
||||
<a
|
||||
class="devcm-tree__item devcm-tree__item--external"
|
||||
th:if="${#lists.isEmpty(menuItem.children) and menuExternal}"
|
||||
th:href="${menuHref}"
|
||||
th:target="${menuTarget}"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<span class="devcm-tree__chev" aria-hidden="true"></span>
|
||||
<i class="devcm-tree__icon i-pixelarticons-external-link"></i>
|
||||
<span th:text="${menuItem.status.displayName}">Page</span>
|
||||
</a>
|
||||
|
||||
<a
|
||||
class="devcm-tree__item"
|
||||
th:if="${#lists.isEmpty(menuItem.children) and !menuExternal}"
|
||||
th:href="${menuHref}"
|
||||
th:target="${menuTarget}"
|
||||
>
|
||||
<span class="devcm-tree__chev" aria-hidden="true"></span>
|
||||
<i class="devcm-tree__icon i-pixelarticons-file"></i>
|
||||
<span th:text="${menuItem.status.displayName}">Page</span>
|
||||
</a>
|
||||
</th:block>
|
||||
</th:block>
|
||||
@@ -0,0 +1,33 @@
|
||||
<article
|
||||
class="devcm-post-card"
|
||||
th:fragment="post-card (post, featured)"
|
||||
th:classappend="${featured} ? ' devcm-post-card--featured' : ''"
|
||||
>
|
||||
<h2 class="devcm-post-card__title">
|
||||
<a th:href="${post.status.permalink}" th:text="${post.spec.title}">Post Title</a>
|
||||
<span class="devcm-badge" th:if="${featured}" th:text="#{devcm.post.featured}">FEATURED</span>
|
||||
</h2>
|
||||
<div class="devcm-post-card__meta">
|
||||
<span th:text="${#dates.format(post.spec.publishTime,'yyyy-MM-dd')}">2026-01-01</span>
|
||||
<span
|
||||
th:if="${post.contributors != null and !#lists.isEmpty(post.contributors)}"
|
||||
th:with="contributor = ${post.contributors[0]}"
|
||||
th:text="${contributor.displayName}"
|
||||
>
|
||||
Author
|
||||
</span>
|
||||
<a
|
||||
class="devcm-post-card__tag"
|
||||
th:each="tag : ${post.tags}"
|
||||
th:href="${tag.status.permalink}"
|
||||
th:title="${tag.spec.displayName}"
|
||||
th:text="'#' + ${tag.spec.displayName}"
|
||||
>
|
||||
#tag
|
||||
</a>
|
||||
</div>
|
||||
<p class="devcm-post-card__excerpt" th:text="${post.status.excerpt}">Post excerpt...</p>
|
||||
<a class="devcm-read-more" th:href="${post.status.permalink}"
|
||||
><span th:text="#{devcm.post.readMore}">Read more</span> <span aria-hidden="true">→</span></a
|
||||
>
|
||||
</article>
|
||||
@@ -0,0 +1,150 @@
|
||||
<aside
|
||||
class="devcm-rightbar"
|
||||
th:fragment="right-panel (pageType)"
|
||||
th:classappend="${pageType == 'page' or pageType == 'links' or pageType == 'moments'} ? ' devcm-rightbar--hidden' : ''"
|
||||
th:aria-label="#{devcm.right.context}"
|
||||
>
|
||||
<th:block th:if="${pageType == 'post'}">
|
||||
<section class="devcm-widget" th:if="${post != null}">
|
||||
<div class="devcm-widget__title">
|
||||
<span th:text="#{devcm.right.articleInfo}">ARTICLE INFO</span>
|
||||
<span aria-hidden="true">...</span>
|
||||
</div>
|
||||
<div class="devcm-info-list">
|
||||
<div class="devcm-info-list__row">
|
||||
<span th:text="#{devcm.right.author}">Author</span>
|
||||
<strong th:text="${post.owner.displayName}">Author</strong>
|
||||
</div>
|
||||
<div class="devcm-info-list__row">
|
||||
<span th:text="#{devcm.right.publishedAt}">Published at</span>
|
||||
<strong th:text="${#dates.format(post.spec.publishTime,'yyyy-MM-dd HH:mm')}">Date</strong>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="devcm-widget" th:if="${post.categories != null and !#lists.isEmpty(post.categories)}">
|
||||
<div class="devcm-widget__title">
|
||||
<span th:text="#{devcm.explorer.categories}">CATEGORIES</span>
|
||||
<span aria-hidden="true">...</span>
|
||||
</div>
|
||||
<div class="devcm-panel-list">
|
||||
<a class="devcm-panel-link" th:each="category : ${post.categories}" th:href="${category.status.permalink}">
|
||||
<strong th:text="${category.spec.displayName}">Category</strong>
|
||||
<span>
|
||||
<span th:text="${category.status.visiblePostCount != null ? category.status.visiblePostCount : 0}">0</span>
|
||||
<span th:text="#{devcm.right.posts}">posts</span>
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="devcm-widget" th:if="${post.tags != null and !#lists.isEmpty(post.tags)}">
|
||||
<div class="devcm-widget__title">
|
||||
<span th:text="#{devcm.right.tags}">TAGS</span>
|
||||
<span aria-hidden="true">...</span>
|
||||
</div>
|
||||
<div class="devcm-tag-cloud">
|
||||
<a
|
||||
class="devcm-tag"
|
||||
th:each="tag : ${post.tags}"
|
||||
th:href="${tag.status.permalink}"
|
||||
th:text="'#' + ${tag.spec.displayName}"
|
||||
>
|
||||
#tag
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="devcm-widget" x-data="postToc" x-init="init()" x-show="items.length > 0">
|
||||
<div class="devcm-widget__title">
|
||||
<span th:text="#{devcm.right.toc}">TABLE OF CONTENTS</span>
|
||||
<span aria-hidden="true">...</span>
|
||||
</div>
|
||||
<div class="post-toc">
|
||||
<ul class="toc-tree">
|
||||
<template x-for="(item, index) in items" :key="index">
|
||||
<li
|
||||
class="toc-item"
|
||||
:class="{ 'toc-item--active': activeId === item.id }"
|
||||
:style="`padding-left: ${getIndent(item.level)}`"
|
||||
@click="scrollTo(item.id)"
|
||||
>
|
||||
<span class="toc-item__toggle toc-item__toggle--empty">▼</span>
|
||||
<span class="toc-item__tag" x-text="item.tagName"></span>
|
||||
<span class="toc-item__title" x-text="item.title"></span>
|
||||
</li>
|
||||
</template>
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<th:block th:with="postCursor=${postFinder.cursor(post.metadata?.name)}">
|
||||
<section class="devcm-widget" th:if="${postCursor.hasPrevious() or postCursor.hasNext()}">
|
||||
<div class="devcm-widget__title">
|
||||
<span th:text="#{devcm.right.nearbyPosts}">NEARBY POSTS</span>
|
||||
<span aria-hidden="true">...</span>
|
||||
</div>
|
||||
<div class="devcm-panel-list">
|
||||
<a
|
||||
class="devcm-panel-link"
|
||||
th:if="${postCursor.hasPrevious()}"
|
||||
th:href="${postCursor.previous?.status?.permalink}"
|
||||
>
|
||||
<span th:text="#{devcm.right.previousPost}">Previous</span>
|
||||
<strong th:text="${postCursor.previous?.spec?.title}">Previous</strong>
|
||||
</a>
|
||||
<a class="devcm-panel-link" th:if="${postCursor.hasNext()}" th:href="${postCursor.next?.status?.permalink}">
|
||||
<span th:text="#{devcm.right.nextPost}">Next</span>
|
||||
<strong th:text="${postCursor.next?.spec?.title}">Next</strong>
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
</th:block>
|
||||
</th:block>
|
||||
|
||||
<th:block th:unless="${pageType == 'post'}">
|
||||
<section class="devcm-widget" th:if="${posts != null and posts.items != null and !#lists.isEmpty(posts.items)}">
|
||||
<div class="devcm-widget__title">
|
||||
<span th:text="#{devcm.right.latestPosts}">LATEST POSTS</span>
|
||||
<span aria-hidden="true">...</span>
|
||||
</div>
|
||||
<div class="devcm-panel-list">
|
||||
<a class="devcm-panel-link" th:each="post : ${posts.items}" th:href="${post.status.permalink}">
|
||||
<strong th:text="${post.spec.title}">Post title</strong>
|
||||
<span th:text="${#dates.format(post.spec.publishTime,'yyyy-MM-dd')}">2026-01-01</span>
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
<section class="devcm-widget" th:if="${categories != null and !#lists.isEmpty(categories)}">
|
||||
<div class="devcm-widget__title">
|
||||
<span th:text="#{devcm.explorer.categories}">CATEGORIES</span>
|
||||
<span aria-hidden="true">...</span>
|
||||
</div>
|
||||
<div class="devcm-panel-list">
|
||||
<a class="devcm-panel-link" th:each="category : ${categories}" th:href="${category.status.permalink}">
|
||||
<strong th:text="${category.spec.displayName}">Category</strong>
|
||||
<span
|
||||
><span th:text="${category.status.visiblePostCount != null ? category.status.visiblePostCount : 0}">0</span>
|
||||
<span th:text="#{devcm.right.posts}">posts</span></span
|
||||
>
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
<section class="devcm-widget" th:if="${tags != null and !#lists.isEmpty(tags)}">
|
||||
<div class="devcm-widget__title">
|
||||
<span th:text="#{devcm.right.tags}">TAGS</span>
|
||||
<span aria-hidden="true">...</span>
|
||||
</div>
|
||||
<div class="devcm-tag-cloud">
|
||||
<a
|
||||
class="devcm-tag"
|
||||
th:each="tag : ${tags}"
|
||||
th:href="${tag.status.permalink}"
|
||||
th:text="'#' + ${tag.spec.displayName}"
|
||||
>
|
||||
#tag
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
</th:block>
|
||||
</aside>
|
||||
@@ -0,0 +1,39 @@
|
||||
<footer class="devcm-statusbar" th:fragment="statusbar (pageType)">
|
||||
<div class="devcm-statusbar__left">
|
||||
<span th:text="${#strings.isEmpty(theme.config.basic.title) ? site.title : theme.config.basic.title}">DevCM</span>
|
||||
<span th:text="${pageType}">home</span>
|
||||
</div>
|
||||
<div class="devcm-statusbar__center">
|
||||
<span>© <span th:text="${#dates.year(#dates.createNow())}">2026</span></span>
|
||||
<span th:text="#{devcm.status.poweredBy}">Powered by</span>
|
||||
<a th:href="${theme.config.footer.footer_powered_link}" th:text="${theme.config.footer.footer_powered_text}"
|
||||
>FillCode</a
|
||||
>
|
||||
<div class="devcm-statusbar__beian">
|
||||
<span th:if="${not #strings.isEmpty(theme.config.footer.footer_icp_text)}">
|
||||
<a
|
||||
href="https://beian.miit.gov.cn/"
|
||||
target="_blank"
|
||||
th:href="${theme.config.footer.footer_icp_link}"
|
||||
th:text="${theme.config.footer.footer_icp_text}"
|
||||
></a>
|
||||
</span>
|
||||
<span th:if="${not #strings.isEmpty(theme.config.footer.footer_gongan_text)}">
|
||||
<img th:src="@{/assets/image/gongan.png}" alt="" />
|
||||
<a
|
||||
href="https://www.beian.gov.cn/"
|
||||
target="_blank"
|
||||
th:href="${theme.config.footer.footer_gongan_link}"
|
||||
th:text="${theme.config.footer.footer_gongan_text}"
|
||||
></a>
|
||||
</span>
|
||||
<halo:footer />
|
||||
</div>
|
||||
</div>
|
||||
<div class="devcm-statusbar__right">
|
||||
<span th:text="${#locale.toLanguageTag()}">en-US</span>
|
||||
<span>UTF-8</span>
|
||||
<span>HTML</span>
|
||||
<i class="devcm-statusbar__dot" aria-hidden="true"></i>
|
||||
</div>
|
||||
</footer>
|
||||
+87
-88
@@ -1,105 +1,104 @@
|
||||
<!DOCTYPE html>
|
||||
<html
|
||||
xmlns:th="https://www.thymeleaf.org"
|
||||
th:replace="~{modules/layout :: html(title = |#{page.moments.title} - ${site.title}|, header = null, content = ~{::content}, footer = null)}"
|
||||
th:replace="~{modules/layout :: html(title = |#{page.moments.title} - ${site.title}|, pageType = 'moments', terminalUserName = ${moments != null and moments.items != null and !#lists.isEmpty(moments.items) and moments.items[0].owner != null and !#strings.isEmpty(moments.items[0].owner.name) ? moments.items[0].owner.name : 'admin'}, content = ~{::content})}"
|
||||
>
|
||||
<th:block th:fragment="content">
|
||||
<link rel="stylesheet" href="https://gcore.jsdelivr.net/npm/glightbox/dist/css/glightbox.min.css" />
|
||||
<script src="https://gcore.jsdelivr.net/gh/mcstudios/glightbox/dist/js/glightbox.min.js"></script>
|
||||
<div class="content">
|
||||
<div class="moments" x-data="upvote('moment','moment.halo.run','moments')">
|
||||
<div
|
||||
class="moment on-list post"
|
||||
th:each="moment,iterStat : ${moments.items}"
|
||||
th:with="content=${moment.spec.content}"
|
||||
th:attr="x-data=|{name:'${moment.metadata.name}',showComment:false}|"
|
||||
>
|
||||
<div class="post-meta">
|
||||
<span class="post-date" th:text="${#dates.format(moment.spec.releaseTime,'yyyy-MM-dd')}">
|
||||
Moment CreateTime
|
||||
</span>
|
||||
<span class="post-separator">
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
</span>
|
||||
<span class="post-author" th:with="owner = ${moment.owner}" th:text="${owner.displayName}">
|
||||
Author
|
||||
</span>
|
||||
</div>
|
||||
<div class="post-content" th:utext="${content.html}">Moment Content...</div>
|
||||
<th:block th:with="medium=${moment.spec.content.medium}">
|
||||
<div
|
||||
th:unless="${#lists.isEmpty(moments)}"
|
||||
class="moment-media mt-4 grid w-4/5 gap-2 sm:w-4/5"
|
||||
th:classappend="${(#lists.size(medium) > 4 ? 'grid-cols-3' : '') + (#lists.size(medium) == 1 ? 'grid-cols-1' :'') + ((#lists.size(medium) > 1 && #lists.size(medium) < 5) ? 'grid-cols-2' :'')}"
|
||||
>
|
||||
<div class="" th:each="media : ${medium}">
|
||||
<a th:class="|glightbox|" th:data-gallery="|gallery${iterStat.count}|" th:href="${media.url}">
|
||||
<img
|
||||
th:if="${#strings.equals(media.type,'PHOTO')}"
|
||||
class="transform-gpu rounded-lg object-cover"
|
||||
th:src="${media.url}"
|
||||
/>
|
||||
</a>
|
||||
<div th:if="${#strings.equals(media.type,'VIDEO')}" class="w-full">
|
||||
<video controls th:src="${media.url}" class="rounded-lg object-cover"></video>
|
||||
|
||||
<section class="devcm-editor-window">
|
||||
<div class="devcm-editor-tabs">
|
||||
<div class="devcm-editor-tab devcm-editor-tab--active">
|
||||
<span>moments.md</span>
|
||||
<a
|
||||
class="devcm-editor-tab__close"
|
||||
href="/"
|
||||
th:aria-label="#{devcm.action.closeMomentsTab}"
|
||||
th:title="#{devcm.action.closeMomentsTab}"
|
||||
>×</a
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="devcm-editor-body">
|
||||
<div class="devcm-moments" x-data="upvote('moment','moment.halo.run','moments')">
|
||||
<article
|
||||
class="devcm-post-card devcm-moment-card"
|
||||
th:each="moment,iterStat : ${moments.items}"
|
||||
th:with="content=${moment.spec.content}"
|
||||
th:attr="x-data=|{name:'${moment.metadata.name}',showComment:false}|"
|
||||
>
|
||||
<div class="devcm-post-card__meta">
|
||||
<span th:text="${#dates.format(moment.spec.releaseTime,'yyyy-MM-dd')}">Moment CreateTime</span>
|
||||
<span th:with="owner = ${moment.owner}" th:text="${owner.displayName}">Author</span>
|
||||
</div>
|
||||
<div class="devcm-post-card__excerpt" th:utext="${content.html}">Moment Content...</div>
|
||||
|
||||
<th:block th:with="medium=${moment.spec.content.medium}">
|
||||
<div
|
||||
th:unless="${#lists.isEmpty(medium)}"
|
||||
class="devcm-moment-media"
|
||||
th:classappend="${(#lists.size(medium) > 4 ? ' devcm-moment-media--three' : '') + (#lists.size(medium) == 1 ? ' devcm-moment-media--one' :'') + ((#lists.size(medium) > 1 && #lists.size(medium) < 5) ? ' devcm-moment-media--two' :'')}"
|
||||
>
|
||||
<div th:each="media : ${medium}">
|
||||
<a th:class="|glightbox|" th:data-gallery="|gallery${iterStat.count}|" th:href="${media.url}">
|
||||
<img
|
||||
th:if="${#strings.equals(media.type,'PHOTO')}"
|
||||
th:src="${media.url}"
|
||||
th:alt="${moment.owner.displayName}"
|
||||
/>
|
||||
</a>
|
||||
<video th:if="${#strings.equals(media.type,'VIDEO')}" controls th:src="${media.url}"></video>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</th:block>
|
||||
<div class="mt-3 flex items-center gap-4">
|
||||
<div
|
||||
class="journal-likes inline-flex cursor-pointer items-center text-sm text-gray-400 transition-all hover:text-red-700"
|
||||
:class="{'text-red-700': getIsUpvoted(name)}"
|
||||
@click="handleUpvote(name)"
|
||||
>
|
||||
<i class="!h-4 !w-4 i-pixelarticons-heart"></i>
|
||||
<span
|
||||
class="ml-1"
|
||||
th:attr="data-upvote-moment-name=${moment.metadata.name}"
|
||||
th:text="${moment.stats.upvote}"
|
||||
>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="inline-flex cursor-pointer items-center text-sm text-gray-400 transition-all hover:text-black dark:hover:text-white"
|
||||
:class="{'!text-black':showComment && storedTheme == 'light','!text-white':showComment && storedTheme == 'dark' }"
|
||||
@click="showComment = !showComment"
|
||||
>
|
||||
<i class="!h-4 !w-4 i-pixelarticons-comment"></i>
|
||||
<span class="ml-1" th:text="${moment.stats.approvedComment}"> </span>
|
||||
</div>
|
||||
</div>
|
||||
</th:block>
|
||||
|
||||
<div class="mt-2" x-show="showComment">
|
||||
<halo:comment
|
||||
group="moment.halo.run"
|
||||
kind="Moment"
|
||||
th:attr="name=${moment.metadata.name}"
|
||||
colorScheme="storedTheme"
|
||||
/>
|
||||
</div>
|
||||
<div class="devcm-moment-actions">
|
||||
<button
|
||||
type="button"
|
||||
class="devcm-action-link"
|
||||
:class="{ 'devcm-action-link--active': getIsUpvoted(name) }"
|
||||
@click="handleUpvote(name)"
|
||||
>
|
||||
<i class="i-pixelarticons-heart"></i>
|
||||
<span th:attr="data-upvote-moment-name=${moment.metadata.name}" th:text="${moment.stats.upvote}"
|
||||
>0</span
|
||||
>
|
||||
</button>
|
||||
<button type="button" class="devcm-action-link" @click="showComment = !showComment">
|
||||
<i class="i-pixelarticons-comment"></i>
|
||||
<span th:text="${moment.stats.approvedComment}">0</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="devcm-moment-comments" x-data="themeComment()" x-init="init()" x-show="showComment">
|
||||
<halo:comment
|
||||
group="moment.halo.run"
|
||||
kind="Moment"
|
||||
th:attr="name=${moment.metadata.name}"
|
||||
colorScheme="localStorage.getItem('theme-mode')"
|
||||
/>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pagination" th:if="${moments.hasPrevious()} or ${moments.hasNext()}">
|
||||
<div class="pagination__buttons">
|
||||
<span class="button previous" th:if="${moments.hasPrevious()}">
|
||||
<a th:href="@{${moments.prevUrl}}">
|
||||
<div class="button__icon i-pixelarticons-chevron-left !h-6 !w-6"></div>
|
||||
<span class="button__text">上一页</span>
|
||||
</a>
|
||||
</span>
|
||||
<span class="button next" th:if="${moments.hasNext()}">
|
||||
<a th:href="@{${moments.nextUrl}}" class="items-center">
|
||||
<span class="button__text">下一页</span>
|
||||
<div class="button__icon i-pixelarticons-chevron-right !h-6 !w-6"></div>
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="pagination" th:if="${moments.hasPrevious()} or ${moments.hasNext()}">
|
||||
<div class="pagination__buttons">
|
||||
<span class="button previous" th:if="${moments.hasPrevious()}">
|
||||
<a th:href="@{${moments.prevUrl}}">
|
||||
<span class="button__text" th:text="#{devcm.pagination.previous}">Previous</span>
|
||||
</a>
|
||||
</span>
|
||||
<span class="button next" th:if="${moments.hasNext()}">
|
||||
<a th:href="@{${moments.nextUrl}}">
|
||||
<span class="button__text" th:text="#{devcm.pagination.next}">Next</span>
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
const lightbox = GLightbox({
|
||||
loop: false,
|
||||
|
||||
+39
-26
@@ -1,35 +1,48 @@
|
||||
<!DOCTYPE html>
|
||||
<html
|
||||
xmlns:th="https://www.thymeleaf.org"
|
||||
th:replace="~{modules/layout :: html(title = |${singlePage.spec.title} - ${site.title}|, header = null, content = ~{::content}, footer = null)}"
|
||||
th:replace="~{modules/layout :: html(title = |${singlePage.spec.title} - ${site.title}|, pageType = 'page', terminalUserName = ${singlePage != null and singlePage.owner != null and !#strings.isEmpty(singlePage.owner.name) ? singlePage.owner.name : 'admin'}, content = ~{::content})}"
|
||||
>
|
||||
<th:block th:fragment="content">
|
||||
<div class="post">
|
||||
<h1 class="post-title" th:text="${singlePage.spec.title}">Post Title</h1>
|
||||
<div class="post-meta">
|
||||
<span class="post-date" th:text="${#dates.format(singlePage.spec.publishTime,'yyyy-MM-dd')}">
|
||||
publishTime
|
||||
</span>
|
||||
<span class="post-separator">
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
</span>
|
||||
<span class="post-author" th:text="${singlePage.owner.displayName}">Author</span>
|
||||
<article class="devcm-editor-window devcm-article">
|
||||
<div class="devcm-editor-tabs">
|
||||
<div class="devcm-editor-tab devcm-editor-tab--active">
|
||||
<span th:text="${singlePage.spec.title} + '.md'">page.md</span>
|
||||
<a
|
||||
class="devcm-editor-tab__close"
|
||||
href="/"
|
||||
th:aria-label="#{devcm.action.closePageTab}"
|
||||
th:title="#{devcm.action.closePageTab}"
|
||||
>×</a
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="post-content">
|
||||
<div th:utext="${singlePage.content.content}">Post Content</div>
|
||||
<div class="devcm-editor-body devcm-article-content">
|
||||
<h1 class="devcm-article-title" th:text="${singlePage.spec.title}">Page Title</h1>
|
||||
<div class="devcm-article-meta">
|
||||
<span th:text="${#dates.format(singlePage.spec.publishTime,'yyyy-MM-dd')}">publishTime</span>
|
||||
<span th:text="${singlePage.owner.displayName}">Author</span>
|
||||
</div>
|
||||
<div th:utext="${singlePage.content.content}">Page Content</div>
|
||||
</div>
|
||||
</div>
|
||||
<div th:if="${haloCommentEnabled}">
|
||||
<h2>评论</h2>
|
||||
<halo:comment
|
||||
group="content.halo.run"
|
||||
kind="SinglePage"
|
||||
th:attr="name=${singlePage.metadata.name}"
|
||||
colorScheme="localStorage.getItem('theme')"
|
||||
/>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<section class="comment-wrap devcm-comments" x-data="themeComment()" x-init="init()" th:if="${haloCommentEnabled}">
|
||||
<div class="devcm-comment-titlebar">
|
||||
<span class="devcm-window-dot"></span>
|
||||
<span class="devcm-window-dot"></span>
|
||||
<span class="devcm-window-dot"></span>
|
||||
<strong th:text="#{devcm.comments.file}">comments.log</strong>
|
||||
</div>
|
||||
<div class="devcm-comment-body">
|
||||
<h2 th:text="#{devcm.comments.title}">## Comments</h2>
|
||||
<halo:comment
|
||||
group="content.halo.run"
|
||||
kind="SinglePage"
|
||||
th:attr="name=${singlePage.metadata.name}"
|
||||
colorScheme="localStorage.getItem('theme')"
|
||||
/>
|
||||
</div>
|
||||
</section>
|
||||
</th:block>
|
||||
</html>
|
||||
|
||||
+53
-62
@@ -1,86 +1,77 @@
|
||||
<!DOCTYPE html>
|
||||
<html
|
||||
xmlns:th="https://www.thymeleaf.org"
|
||||
th:replace="~{modules/layout :: html(title = |${post.spec.title} - ${site.title}|, header = null, content = ~{::content}, footer = null)}"
|
||||
th:replace="~{modules/layout :: html(title = |${post.spec.title} - ${site.title}|, pageType = 'post', terminalUserName = ${post != null and post.owner != null and !#strings.isEmpty(post.owner.name) ? post.owner.name : 'admin'}, content = ~{::content})}"
|
||||
>
|
||||
<th:block th:fragment="content">
|
||||
<!-- 目录组件 -->
|
||||
<div class="post-toc-sticky">
|
||||
<div class="post-toc" x-data="postToc" x-init="init()">
|
||||
<div class="toc-header">
|
||||
<span class="toc-header__icon"><></span>
|
||||
<span class="toc-header__title">Outline</span>
|
||||
<article class="devcm-editor-window devcm-article" x-data="postLineNum" x-init="init()">
|
||||
<div class="devcm-editor-tabs">
|
||||
<div
|
||||
class="devcm-editor-tab devcm-editor-tab--active"
|
||||
th:with="postTabName=${!#strings.isEmpty(post.spec.slug) ? post.spec.slug : post.metadata.name}"
|
||||
>
|
||||
<span th:text="${postTabName}">post</span>
|
||||
<a
|
||||
class="devcm-editor-tab__close"
|
||||
href="/archives"
|
||||
th:aria-label="#{devcm.action.closePostTab}"
|
||||
th:title="#{devcm.action.closePostTab}"
|
||||
>×</a
|
||||
>
|
||||
</div>
|
||||
<ul class="toc-tree">
|
||||
<template x-for="(item, index) in items" :key="index">
|
||||
<li class="toc-item"
|
||||
:class="{'toc-item--active': activeId === item.id}"
|
||||
:style="`padding-left: ${getIndent(item.level)}`"
|
||||
@click="scrollTo(item.id)">
|
||||
<span class="toc-item__toggle toc-item__toggle--empty">▼</span>
|
||||
<span class="toc-item__icon"><></span>
|
||||
<span class="toc-item__tag" x-text="item.tagName"></span>
|
||||
<span class="toc-item__title" x-text="item.title"></span>
|
||||
</li>
|
||||
</template>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="post" x-data="postLineNum" x-init="init()">
|
||||
<h1 class="post-title" th:text="'< ' + ${post.spec.title} + ' >'">Post Title</h1>
|
||||
<div class="post-meta">
|
||||
<span class="post-date" th:text="${#dates.format(post.spec.publishTime,'yyyy-MM-dd')}"> publishTime </span>
|
||||
<span class="post-separator">
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
</span>
|
||||
<span class="post-author" th:text="${post.owner.displayName}">Author</span>
|
||||
<span class="post-tags-inline" th:each="tag : ${post.tags}">
|
||||
<a th:href="${tag.status.permalink}"
|
||||
th:title="${tag.spec.displayName}"
|
||||
th:text="'#'+${tag.spec.displayName}"
|
||||
class="post-tag"
|
||||
>#Tag
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
<div class="post-body">
|
||||
<!-- 行数组件 -->
|
||||
|
||||
<div class="post-body devcm-article-body">
|
||||
<div class="post-line-gutter"></div>
|
||||
<div class="post-content">
|
||||
<div th:utext="${post.content.content}">Post Content</div>
|
||||
<div class="post-content devcm-article-content">
|
||||
<div>
|
||||
<h1 class="devcm-article-title" th:text="'< ' + ${post.spec.title} + ' >'">Post Title</h1>
|
||||
<div class="devcm-article-meta">
|
||||
<span th:text="${#dates.format(post.spec.publishTime,'yyyy-MM-dd')}">publishTime</span>
|
||||
<span th:text="${post.owner.displayName}">Author</span>
|
||||
<a
|
||||
th:each="tag : ${post.tags}"
|
||||
th:href="${tag.status.permalink}"
|
||||
th:title="${tag.spec.displayName}"
|
||||
th:text="'#' + ${tag.spec.displayName}"
|
||||
>
|
||||
#Tag
|
||||
</a>
|
||||
</div>
|
||||
<div th:utext="${post.content.content}">Post Content</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="comment-wrap" th:if="${haloCommentEnabled}">
|
||||
<h2>评论</h2>
|
||||
<halo:comment
|
||||
group="content.halo.run"
|
||||
kind="Post"
|
||||
th:attr="name=${post.metadata.name}"
|
||||
/>
|
||||
</div>
|
||||
<div class="pagination">
|
||||
<div class="pagination__title">
|
||||
<span class="pagination__title-h">其他文章</span>
|
||||
<hr />
|
||||
</article>
|
||||
|
||||
<section class="comment-wrap devcm-comments" x-data="themeComment()" x-init="init()" th:if="${haloCommentEnabled}">
|
||||
<div class="devcm-comment-titlebar">
|
||||
<span class="devcm-window-dot"></span>
|
||||
<span class="devcm-window-dot"></span>
|
||||
<span class="devcm-window-dot"></span>
|
||||
<strong th:text="#{devcm.comments.file}">comments.log</strong>
|
||||
</div>
|
||||
<div class="pagination__buttons" th:with="postCursor=${postFinder.cursor(post.metadata?.name)}">
|
||||
<div class="devcm-comment-body">
|
||||
<h2 th:text="#{devcm.comments.title}">## Comments</h2>
|
||||
<halo:comment group="content.halo.run" kind="Post" th:attr="name=${post.metadata.name}" />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<nav class="pagination devcm-prev-next" th:with="postCursor=${postFinder.cursor(post.metadata?.name)}">
|
||||
<div class="pagination__buttons">
|
||||
<span th:if="${postCursor.hasPrevious()}" class="button previous">
|
||||
<a th:href="${postCursor.previous?.status?.permalink}">
|
||||
<span class="button__icon">< </span>
|
||||
<span class="button__text" th:text="${postCursor.previous?.spec?.title}">prevPost</span>
|
||||
<span class="button__text" th:text="${postCursor.previous?.spec?.title}">Previous</span>
|
||||
</a>
|
||||
</span>
|
||||
<span th:if="${postCursor.hasNext()}" class="button next">
|
||||
<a th:href="${postCursor.next?.status?.permalink}">
|
||||
<span class="button__text" th:text="${postCursor.next?.spec?.title}">nextPost</span>
|
||||
<span class="button__text" th:text="${postCursor.next?.spec?.title}">Next</span>
|
||||
<span class="button__icon"> ></span>
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</th:block>
|
||||
</html>
|
||||
|
||||
+43
-60
@@ -1,70 +1,53 @@
|
||||
<!DOCTYPE html>
|
||||
<html
|
||||
xmlns:th="https://www.thymeleaf.org"
|
||||
th:replace="~{modules/layout :: html(title = |#{page.tag.title(${tag.spec.displayName})} - ${site.title}|, header = null, content = ~{::content}, footer = null)}"
|
||||
th:replace="~{modules/layout :: html(title = |#{page.tag.title(${tag.spec.displayName})} - ${site.title}|, pageType = 'tag', terminalUserName = ${posts != null and posts.items != null and !#lists.isEmpty(posts.items) and posts.items[0].owner != null and !#strings.isEmpty(posts.items[0].owner.name) ? posts.items[0].owner.name : 'admin'}, content = ~{::content})}"
|
||||
>
|
||||
<th:block th:fragment="content">
|
||||
<div class="content">
|
||||
<div class="post">
|
||||
<h1
|
||||
class="post-title"
|
||||
th:text="'标签:'+${tag.spec.displayName}+' ('+${tag.status.visiblePostCount?:0}+' 篇文章)'"
|
||||
>
|
||||
标签:标签名 (n 篇文章)
|
||||
</h1>
|
||||
|
||||
<a href="/tags"> 所有标签 </a>
|
||||
|
||||
<ul>
|
||||
<li class="post-list" th:each="post : ${posts.items}">
|
||||
<a th:href="${post.status.permalink}">
|
||||
<span class="post-date" th:text="${#dates.format(post.spec.publishTime,'yyyy-MM-dd')}"
|
||||
>发布时间</span
|
||||
>
|
||||
<span class="post-separator">
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
</span>
|
||||
<span class="post-list-title" th:text="${post.spec.title}">文章标题</span></a>
|
||||
<span class="post-tags-inline">
|
||||
<span class="post-separator">
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
</span>
|
||||
<span th:each="tag : ${post.tags}">
|
||||
<a
|
||||
th:href="@{${post.status.permalink}}"
|
||||
th:title="${tag.spec.displayName}"
|
||||
th:text="'#'+${tag.spec.displayName}"
|
||||
class="post-tag"
|
||||
>#Tag
|
||||
</a>
|
||||
</span>
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="pagination" th:if="${posts.hasPrevious() || posts.hasNext()}">
|
||||
<div class="pagination__buttons">
|
||||
<span class="button previous" th:if="${posts.hasPrevious()}">
|
||||
<a th:href="@{${posts.prevUrl}}">
|
||||
<span class="button__icon"><</span>
|
||||
<span class="button__text">上一页</span>
|
||||
</a>
|
||||
</span>
|
||||
<span class="button next" th:if="${posts.hasNext()}">
|
||||
<a th:href="@{${posts.nextUrl}}">
|
||||
<span class="button__text">下一页</span>
|
||||
<span class="button__icon">></span>
|
||||
</a>
|
||||
</span>
|
||||
<section class="devcm-editor-window">
|
||||
<div class="devcm-editor-tabs">
|
||||
<div class="devcm-editor-tab devcm-editor-tab--active">
|
||||
<span th:text="'#' + ${tag.spec.displayName} + '.md'">tag.md</span>
|
||||
<a
|
||||
class="devcm-editor-tab__close"
|
||||
href="/tags"
|
||||
th:aria-label="#{devcm.action.closeTagTab}"
|
||||
th:title="#{devcm.action.closeTagTab}"
|
||||
>×</a
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="devcm-editor-body">
|
||||
<h1 class="devcm-page-title">
|
||||
<span th:text="#{devcm.taxonomy.tagTitle(${tag.spec.displayName})}">Tag</span>
|
||||
<small
|
||||
th:text="#{devcm.taxonomy.postCount(${tag.status.visiblePostCount != null ? tag.status.visiblePostCount : 0})}"
|
||||
>(0 posts)</small
|
||||
>
|
||||
</h1>
|
||||
<div class="devcm-post-stack">
|
||||
<th:block th:each="post,iterStat : ${posts.items}">
|
||||
<th:block th:replace="~{modules/post-card :: post-card(post=${post}, featured=${iterStat.index == 0})}" />
|
||||
</th:block>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="pagination" th:if="${posts.hasPrevious() || posts.hasNext()}">
|
||||
<div class="pagination__buttons">
|
||||
<span class="button previous" th:if="${posts.hasPrevious()}">
|
||||
<a th:href="@{${posts.prevUrl}}">
|
||||
<span class="button__icon"><</span>
|
||||
<span class="button__text" th:text="#{devcm.pagination.previous}">Previous</span>
|
||||
</a>
|
||||
</span>
|
||||
<span class="button next" th:if="${posts.hasNext()}">
|
||||
<a th:href="@{${posts.nextUrl}}">
|
||||
<span class="button__text" th:text="#{devcm.pagination.next}">Next</span>
|
||||
<span class="button__icon">></span>
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</th:block>
|
||||
</html>
|
||||
|
||||
+27
-15
@@ -1,23 +1,35 @@
|
||||
<!DOCTYPE html>
|
||||
<html
|
||||
xmlns:th="https://www.thymeleaf.org"
|
||||
th:replace="~{modules/layout :: html(title = |#{page.tags.title} - ${site.title}|, header = null, content = ~{::content}, footer = null)}"
|
||||
th:replace="~{modules/layout :: html(title = |#{page.tags.title} - ${site.title}|, pageType = 'tags', terminalUserName = 'admin', content = ~{::content})}"
|
||||
>
|
||||
<th:block th:fragment="content">
|
||||
<div class="content">
|
||||
<div class="post">
|
||||
<h1 class="post-title">所有标签</h1>
|
||||
<ul>
|
||||
<li th:each="tag: ${tags}" class="tag-list">
|
||||
<a
|
||||
th:href="${tag.status.permalink}"
|
||||
th:text="${tag.spec.displayName}+' ('+${tag.status.visiblePostCount?:0}+' 篇文章)'"
|
||||
>
|
||||
标签名 (n 篇文章)
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<section class="devcm-editor-window">
|
||||
<div class="devcm-editor-tabs">
|
||||
<div class="devcm-editor-tab devcm-editor-tab--active">
|
||||
<span>tags.md</span>
|
||||
<a
|
||||
class="devcm-editor-tab__close"
|
||||
href="/"
|
||||
th:aria-label="#{devcm.action.closeTagsTab}"
|
||||
th:title="#{devcm.action.closeTagsTab}"
|
||||
>×</a
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="devcm-editor-body">
|
||||
<h1 class="devcm-page-title" th:text="#{devcm.tags.title}">All tags</h1>
|
||||
<div class="devcm-tag-cloud devcm-tag-cloud--page">
|
||||
<a
|
||||
class="devcm-tag"
|
||||
th:each="tag : ${tags}"
|
||||
th:href="${tag.status.permalink}"
|
||||
th:text="'#' + ${tag.spec.displayName} + ' (' + ${tag.status.visiblePostCount != null ? tag.status.visiblePostCount : 0} + ')'"
|
||||
>
|
||||
#tag
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</th:block>
|
||||
</html>
|
||||
|
||||
在新议题中引用
屏蔽一个用户