feat(task-list): add task list utility mixins and enhance rendering logic

This commit is contained in:
Cell
2026-03-30 14:55:55 +08:00
parent 164a699701
commit 741ef191bf
13 changed files with 114 additions and 65 deletions
+1
View File
@@ -5,6 +5,7 @@ resources/
# Hugo
.hugo_build.lock
jsconfig.json
.hugo_cache
# NPM
node_modules/
-1
View File
@@ -141,5 +141,4 @@ For formula blocks:
$$
\bbox[border: solid .4pt magenta, pink]{x^2=4}
$$
{.auto-dark-mode}
{{< /auto-dark >}}
+16 -11
View File
@@ -19,17 +19,6 @@ This post tests the rendering of task lists in Markdown.
- [x] Checked Task
- Regular list item
## Nested Task Lists (Bug Fix Verification)
- [ ] Parent Task 1
- [ ] Child Task 1.1
- [x] Child Task 1.2
- Regular list item
- [x] Parent Task 2
- [ ] Child Task 2.1
- [ ] Grandchild Task 2.1.1
- [x] Grandchild Task 2.1.2
## Extended Task Lists (Custom Icons)
- [-] Cancelled Task
@@ -40,6 +29,22 @@ This post tests the rendering of task lists in Markdown.
- [?] Question Task
- Regular list item
## Nested Task Lists (Bug Fix Verification)
- [ ] Parent Task 1
- [ ] Child Task 1.1
- [x] Child Task 1.2
- Regular list item
- [/] Parent Task 2
- Regular list item
- [ ] Child Task 2.1
- [x] Grandchild Task 2.1.1
- [-] Grandchild Task 2.1.2
- [<] Scheduled Task
- [>] Rescheduled Task
- [!] Important Task
- [?] Question Task
## Mixed Content in List Items
- [ ] Task with **bold** and _italic_ text
+1
View File
@@ -7,6 +7,7 @@
@import 'media';
@import 'scrollbar-width';
@import 'sticky-top';
@import 'task-list';
@import 'theme-switch';
@import 'theme-vars';
@import 'z-index';
+34
View File
@@ -0,0 +1,34 @@
// Task list utility mixins
// ----------------------------------------
/// Set task list icon color and allow custom styles via @content
/// @param {Color | Null} $color - Icon color (optional)
/// Usage:
/// @include task-icon(fixit-var(secondary)) {
/// opacity: 0.8;
/// }
@mixin task-icon($color: null) {
> i {
// Set icon color (optional)
@if $color != null {
@include set-fixit-var(task-icon-color, $color);
}
@content;
}
}
/// Set task list text color and allow custom styles via @content
/// @param {Color | Null} $color - Text color (optional)
/// Usage:
/// @include task-text(fixit-var(secondary)) {
/// text-decoration: line-through fixit-var(secondary);
/// }
@mixin task-text($color: null) {
> span {
// Set text color (optional)
@if $color != null {
@include set-fixit-var(task-text-color, $color);
}
@content;
}
}
+3 -2
View File
@@ -1,6 +1,7 @@
body {
.cell-tooltip {
--tooltip-bg: light-dark(#ffffff, #39393c);
--tooltip-color: light-dark(#0f172a, #e2e2e6);
--tooltip-bg: light-dark(#ffffff, #3d444d);
--tooltip-color: fixit-var(global-font-color);
--tooltip-shadow-color: light-dark(rgba(0, 0, 0, 0.18), rgba(255, 255, 255, 0.18));
}
}
+34 -32
View File
@@ -120,7 +120,6 @@
left: 5%;
top: 50%;
transform: translateY(-50%);
@include z-index(base);
color: fixit-var(hr-active-color);
font-size: 20px;
line-height: 1;
@@ -128,6 +127,7 @@
font-family: var(--fa-family-classic);
font-weight: 600;
content: '\f0c4';
@include z-index(base);
}
&:hover::before {
@@ -218,50 +218,52 @@
margin-block: 0.5em;
}
ol ol,
ol ul,
ul ol,
ul ul {
:is(ol, ul) :is(ol, ul) {
padding-left: 20px;
}
li::marker {
color: fixit-var(global-font-secondary-color);
color: fixit-var(secondary);
}
li:hover::marker {
color: fixit-var(single-link-hover-color);
}
// Task lists
li[data-task] {
list-style: none;
color: fixit-var(task-color);
.checkbox-icon {
margin: 0 .25em 0 -1.5em;
color: fixit-var(checkbox-color);
li {
&[data-task] {
list-style: none;
@include task-icon {
margin: 0 0.25em 0 -1.5em;
color: fixit-var(task-icon-color, fixit-var(secondary));
};
@include task-text {
color: fixit-var(task-text-color);
}
}
}
li[data-task='x'] {
@include set-fixit-var(checkbox-color, fixit-var(global-font-secondary-color));
.checkbox-icon {
opacity: 0.6;
&[data-task='-'] {
@include task-icon {
opacity: 0.7;
};
@include task-text(fixit-var(secondary)) {
opacity: 0.7;
text-decoration: line-through fixit-var(secondary);
}
}
&[data-task='/'] {
@include task-icon(fixit-var(success));
@include task-text(fixit-var(success));
}
&[data-task='!'] {
@include task-icon(fixit-var(danger));
}
&[data-task='?'] {
@include task-icon(fixit-var(warning));
}
}
li[data-task='-'] {
opacity: 0.6;
text-decoration: line-through rgba(145, 145, 145, 0.6);
@include set-fixit-var(task-color, fixit-var(global-font-secondary-color));
}
li[data-task='/'] {
@include set-fixit-var(task-color, fixit-var(success));
}
li[data-task='!'] {
@include set-fixit-var(checkbox-color, fixit-var(danger));
}
li[data-task='?'] {
@include set-fixit-var(checkbox-color, fixit-var(warning));
}
dl {
+2 -2
View File
@@ -19,8 +19,8 @@ libFiles:
# autocomplete-js@0.38.1 https://github.com/algolia/autocomplete
# TODO update autocompleteJS: '@algolia/autocomplete-js@1.7.1/dist/umd/index.production.js'
autocompleteJS: autocomplete.js@0.38.1/dist/autocomplete.min.js
# cell-tooltip@0.3.0 https://github.com/Lruihao/cell-tooltip
cellTooltipJS: cell-tooltip@0.3.0/dist/cell-tooltip.umd.js
# cell-tooltip@0.3.1 https://github.com/Lruihao/cell-tooltip
cellTooltipJS: cell-tooltip@0.3.1/dist/cell-tooltip.umd.js
# cell-watermark@1.0.3 https://github.com/Lruihao/watermark
cellWatermarkJS: cell-watermark@1.0.3/src/watermark.min.js
# cookieconsent@3.1.1 https://github.com/osano/cookieconsent
+2 -2
View File
@@ -19,8 +19,8 @@ libFiles:
# autocomplete-js@0.38.1 https://github.com/algolia/autocomplete
# TODO update autocompleteJS: '@algolia/autocomplete-js@1.7.1/dist/umd/index.production.js'
autocompleteJS: autocomplete.js@0.38.1/dist/autocomplete.min.js
# cell-tooltip@0.3.0 https://github.com/Lruihao/cell-tooltip
cellTooltipJS: cell-tooltip@0.3.0/dist/cell-tooltip.umd.js
# cell-tooltip@0.3.1 https://github.com/Lruihao/cell-tooltip
cellTooltipJS: cell-tooltip@0.3.1/dist/cell-tooltip.umd.js
# cell-watermark@1.0.3 https://github.com/Lruihao/watermark
cellWatermarkJS: cell-watermark@1.0.3/src/watermark.min.js
# cookieconsent@3.1.1 https://github.com/osano/cookieconsent
+8 -2
View File
@@ -1409,7 +1409,14 @@ class FixIt {
initTooltip() {
if (!this.config.tooltip) return;
window.CellTooltip.initAll('[data-ct-tooltip]');
// task list items tooltip
window.CellTooltip.initAll('li[data-task] > span[title]', {
placement: 'right',
});
// code block action buttons tooltip
window.CellTooltip.initAll('.action-btn[title]');
// footnote refs tooltip
this.initFootnotes();
}
/**
@@ -1427,7 +1434,6 @@ class FixIt {
this.initEcharts();
this.initTypeit(target);
this.initMapbox();
this.initFootnotes();
this.initTooltip();
if (includeToc) {
window.setTimeout(() => {
File diff suppressed because one or more lines are too long
+6 -6
View File
@@ -18,27 +18,27 @@
{{- end -}}
{{- if $config.linenostoggler -}}
{{- $lineNosIcon := dict "Class" "fa-solid fa-list-ol" | partial "plugin/icon.html" -}}
{{- $lineNosBtn = printf `<span class="action-btn line-nos-btn" aria-label="%s" role="button" title="%s" data-ct-tooltip>%s</span>` (T "assets.toggleLineNumbers") (T "assets.toggleLineNumbers") $lineNosIcon -}}
{{- $lineNosBtn = printf `<span class="action-btn line-nos-btn" aria-label="%s" role="button" title="%s">%s</span>` (T "assets.toggleLineNumbers") (T "assets.toggleLineNumbers") $lineNosIcon -}}
{{- end -}}
{{- if $config.linewraptoggler -}}
{{- $lineWrapIcon := dict "Class" "fa-solid fa-right-left" | partial "plugin/icon.html" -}}
{{- $lineWrapBtn = printf `<span class="action-btn line-wrap-btn" aria-label="%s" role="button" title="%s" data-ct-tooltip>%s</span>` (T "assets.toggleLineWrap") (T "assets.toggleLineWrap") $lineWrapIcon -}}
{{- $lineWrapBtn = printf `<span class="action-btn line-wrap-btn" aria-label="%s" role="button" title="%s">%s</span>` (T "assets.toggleLineWrap") (T "assets.toggleLineWrap") $lineWrapIcon -}}
{{- end -}}
{{- if $config.editable -}}
{{- $editIcon := dict "Class" "fa-solid fa-pen-to-square" | partial "plugin/icon.html" -}}
{{- $editBtn = printf `<span class="action-btn edit-btn" aria-label="%s" role="button" title="%s" data-ct-tooltip>%s</span>` (T "assets.toggleCodeEditable") (T "assets.toggleCodeEditable") $editIcon -}}
{{- $editBtn = printf `<span class="action-btn edit-btn" aria-label="%s" role="button" title="%s">%s</span>` (T "assets.toggleCodeEditable") (T "assets.toggleCodeEditable") $editIcon -}}
{{- end -}}
{{- if $config.copyable -}}
{{- $copyIcon := dict "Class" "fa-regular fa-clone" | partial "plugin/icon.html" -}}
{{- $copyBtn = printf `<span class="action-btn copy-btn" aria-label="%s" role="button" title="%s" data-copied-text="%s" data-ct-tooltip>%s</span>` (T "assets.copyToClipboard") (T "assets.copyToClipboard") (T "assets.copiedText") $copyIcon -}}
{{- $copyBtn = printf `<span class="action-btn copy-btn" aria-label="%s" role="button" title="%s" data-copied-text="%s">%s</span>` (T "assets.copyToClipboard") (T "assets.copyToClipboard") (T "assets.copiedText") $copyIcon -}}
{{- end -}}
{{- if $config.downloadable -}}
{{- $downloadIcon := dict "Class" "fa-solid fa-download" | partial "plugin/icon.html" -}}
{{- $downloadBtn = printf `<span class="action-btn download-btn" aria-label="%s" role="button" title="%s" data-ct-tooltip>%s</span>` (T "assets.downloadCode") (T "assets.downloadCode") $downloadIcon -}}
{{- $downloadBtn = printf `<span class="action-btn download-btn" aria-label="%s" role="button" title="%s">%s</span>` (T "assets.downloadCode") (T "assets.downloadCode") $downloadIcon -}}
{{- end -}}
{{- if $config.fullscreen -}}
{{- $fullscreenIcon := dict "Class" "fa-solid fa-expand" | partial "plugin/icon.html" -}}
{{- $fullscreenBtn = printf `<span class="action-btn fullscreen-btn" aria-label="%s" role="button" title="%s" data-ct-tooltip>%s</span>` (T "assets.toggleCodeFullscreen") (T "assets.toggleCodeFullscreen") $fullscreenIcon -}}
{{- $fullscreenBtn = printf `<span class="action-btn fullscreen-btn" aria-label="%s" role="button" title="%s">%s</span>` (T "assets.toggleCodeFullscreen") (T "assets.toggleCodeFullscreen") $fullscreenIcon -}}
{{- end -}}
{{- with $config.name -}}
{{- $titleEl = replace $titleEl `<span class="code-title">` (printf `<span class="code-title" data-name="%s">` .) -}}
+6 -6
View File
@@ -26,12 +26,12 @@
- [ ] Unchecked
- [x] Checked
*/ -}}
{{- $icon := dict "Class" (add "checkbox-icon " (index $iconMap " ")) | partial "plugin/icon.html" -}}
{{- $icon := dict "Class" (index $iconMap " ") | partial "plugin/icon.html" -}}
{{- $label := T (printf "taskList.%v" " ") -}}
{{- $content := replaceRE `(?s)<li>((\n<p>)*)<input disabled="" type="checkbox">\s?` (printf `<li data-task=" " title=%q>$1%s` $label $icon) . -}}
{{- $content := replaceRE `(?s)<li>((\n<p>)*)<input disabled="" type="checkbox">\s?([\s\S]*?)(<ul|<ol|</li>)` (printf `<li data-task=" ">$1%s<span title=%q>$3</span>$4` $icon $label) . -}}
{{- $label := T (printf "taskList.%v" "x") -}}
{{- $icon := dict "Class" (add "checkbox-icon " (index $iconMap "x")) | partial "plugin/icon.html" -}}
{{- $content = replaceRE `(?s)<li>((\n<p>)*)<input checked="" disabled="" type="checkbox">\s?` (printf `<li data-task="x" title=%q>$1%s` $label $icon) $content -}}
{{- $icon := dict "Class" (index $iconMap "x") | partial "plugin/icon.html" -}}
{{- $content = replaceRE `(?s)<li>((\n<p>)*)<input checked="" disabled="" type="checkbox">\s?([\s\S]*?)(<ul|<ol|</li>)` (printf `<li data-task="x">$1%s<span title=%q>$3</span>$4` $icon $label) $content -}}
{{- /*
The extended syntax is compatible with Obsidian.
@@ -45,11 +45,11 @@
*/ -}}
{{- range $extendedSigns -}}
{{- $class := index $iconMap . | default "fa-solid fa-check-square" -}}
{{- $icon := dict "Class" (add "checkbox-icon " $class) | partial "plugin/icon.html" -}}
{{- $icon := dict "Class" $class | partial "plugin/icon.html" -}}
{{- $sign := htmlEscape . -}}
{{- $originSign := replace . "\\" "" -}}
{{- $label := (T (printf "taskList.%v" $originSign)) | default (T (printf "taskList.%v" " ")) -}}
{{- $content = replaceRE (printf `(?s)<li>((\n<p>)*)\[%s\]\s?` $sign) (printf `<li data-task=%q title=%q>$1%s` $originSign $label $icon) $content -}}
{{- $content = replaceRE (printf `(?s)<li>((\n<p>)*)\[%s\]\s?([\s\S]*?)(<ul|<ol|</li>)` $sign) (printf `<li data-task=%q>$1%s<span title=%q>$3</span>$4` $originSign $icon $label) $content -}}
{{- end -}}
{{- return $content -}}