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
.hugo_build.lock .hugo_build.lock
jsconfig.json jsconfig.json
.hugo_cache
# NPM # NPM
node_modules/ node_modules/
-1
View File
@@ -141,5 +141,4 @@ For formula blocks:
$$ $$
\bbox[border: solid .4pt magenta, pink]{x^2=4} \bbox[border: solid .4pt magenta, pink]{x^2=4}
$$ $$
{.auto-dark-mode}
{{< /auto-dark >}} {{< /auto-dark >}}
+16 -11
View File
@@ -19,17 +19,6 @@ This post tests the rendering of task lists in Markdown.
- [x] Checked Task - [x] Checked Task
- Regular list item - 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) ## Extended Task Lists (Custom Icons)
- [-] Cancelled Task - [-] Cancelled Task
@@ -40,6 +29,22 @@ This post tests the rendering of task lists in Markdown.
- [?] Question Task - [?] Question Task
- Regular list item - 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 ## Mixed Content in List Items
- [ ] Task with **bold** and _italic_ text - [ ] Task with **bold** and _italic_ text
+1
View File
@@ -7,6 +7,7 @@
@import 'media'; @import 'media';
@import 'scrollbar-width'; @import 'scrollbar-width';
@import 'sticky-top'; @import 'sticky-top';
@import 'task-list';
@import 'theme-switch'; @import 'theme-switch';
@import 'theme-vars'; @import 'theme-vars';
@import 'z-index'; @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 { body {
.cell-tooltip { .cell-tooltip {
--tooltip-bg: light-dark(#ffffff, #39393c); --tooltip-bg: light-dark(#ffffff, #3d444d);
--tooltip-color: light-dark(#0f172a, #e2e2e6); --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%; left: 5%;
top: 50%; top: 50%;
transform: translateY(-50%); transform: translateY(-50%);
@include z-index(base);
color: fixit-var(hr-active-color); color: fixit-var(hr-active-color);
font-size: 20px; font-size: 20px;
line-height: 1; line-height: 1;
@@ -128,6 +127,7 @@
font-family: var(--fa-family-classic); font-family: var(--fa-family-classic);
font-weight: 600; font-weight: 600;
content: '\f0c4'; content: '\f0c4';
@include z-index(base);
} }
&:hover::before { &:hover::before {
@@ -218,50 +218,52 @@
margin-block: 0.5em; margin-block: 0.5em;
} }
ol ol, :is(ol, ul) :is(ol, ul) {
ol ul,
ul ol,
ul ul {
padding-left: 20px; padding-left: 20px;
} }
li::marker { li::marker {
color: fixit-var(global-font-secondary-color); color: fixit-var(secondary);
} }
li:hover::marker { li:hover::marker {
color: fixit-var(single-link-hover-color); color: fixit-var(single-link-hover-color);
} }
// Task lists // Task lists
li[data-task] { li {
list-style: none; &[data-task] {
color: fixit-var(task-color); list-style: none;
@include task-icon {
.checkbox-icon { margin: 0 0.25em 0 -1.5em;
margin: 0 .25em 0 -1.5em; color: fixit-var(task-icon-color, fixit-var(secondary));
color: fixit-var(checkbox-color); };
@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 { &[data-task='-'] {
opacity: 0.6; @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 { dl {
+2 -2
View File
@@ -19,8 +19,8 @@ libFiles:
# autocomplete-js@0.38.1 https://github.com/algolia/autocomplete # autocomplete-js@0.38.1 https://github.com/algolia/autocomplete
# TODO update autocompleteJS: '@algolia/autocomplete-js@1.7.1/dist/umd/index.production.js' # TODO update autocompleteJS: '@algolia/autocomplete-js@1.7.1/dist/umd/index.production.js'
autocompleteJS: autocomplete.js@0.38.1/dist/autocomplete.min.js autocompleteJS: autocomplete.js@0.38.1/dist/autocomplete.min.js
# cell-tooltip@0.3.0 https://github.com/Lruihao/cell-tooltip # cell-tooltip@0.3.1 https://github.com/Lruihao/cell-tooltip
cellTooltipJS: cell-tooltip@0.3.0/dist/cell-tooltip.umd.js cellTooltipJS: cell-tooltip@0.3.1/dist/cell-tooltip.umd.js
# cell-watermark@1.0.3 https://github.com/Lruihao/watermark # cell-watermark@1.0.3 https://github.com/Lruihao/watermark
cellWatermarkJS: cell-watermark@1.0.3/src/watermark.min.js cellWatermarkJS: cell-watermark@1.0.3/src/watermark.min.js
# cookieconsent@3.1.1 https://github.com/osano/cookieconsent # 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 # autocomplete-js@0.38.1 https://github.com/algolia/autocomplete
# TODO update autocompleteJS: '@algolia/autocomplete-js@1.7.1/dist/umd/index.production.js' # TODO update autocompleteJS: '@algolia/autocomplete-js@1.7.1/dist/umd/index.production.js'
autocompleteJS: autocomplete.js@0.38.1/dist/autocomplete.min.js autocompleteJS: autocomplete.js@0.38.1/dist/autocomplete.min.js
# cell-tooltip@0.3.0 https://github.com/Lruihao/cell-tooltip # cell-tooltip@0.3.1 https://github.com/Lruihao/cell-tooltip
cellTooltipJS: cell-tooltip@0.3.0/dist/cell-tooltip.umd.js cellTooltipJS: cell-tooltip@0.3.1/dist/cell-tooltip.umd.js
# cell-watermark@1.0.3 https://github.com/Lruihao/watermark # cell-watermark@1.0.3 https://github.com/Lruihao/watermark
cellWatermarkJS: cell-watermark@1.0.3/src/watermark.min.js cellWatermarkJS: cell-watermark@1.0.3/src/watermark.min.js
# cookieconsent@3.1.1 https://github.com/osano/cookieconsent # cookieconsent@3.1.1 https://github.com/osano/cookieconsent
+8 -2
View File
@@ -1409,7 +1409,14 @@ class FixIt {
initTooltip() { initTooltip() {
if (!this.config.tooltip) return; 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.initEcharts();
this.initTypeit(target); this.initTypeit(target);
this.initMapbox(); this.initMapbox();
this.initFootnotes();
this.initTooltip(); this.initTooltip();
if (includeToc) { if (includeToc) {
window.setTimeout(() => { window.setTimeout(() => {
File diff suppressed because one or more lines are too long
+6 -6
View File
@@ -18,27 +18,27 @@
{{- end -}} {{- end -}}
{{- if $config.linenostoggler -}} {{- if $config.linenostoggler -}}
{{- $lineNosIcon := dict "Class" "fa-solid fa-list-ol" | partial "plugin/icon.html" -}} {{- $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 -}} {{- end -}}
{{- if $config.linewraptoggler -}} {{- if $config.linewraptoggler -}}
{{- $lineWrapIcon := dict "Class" "fa-solid fa-right-left" | partial "plugin/icon.html" -}} {{- $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 -}} {{- end -}}
{{- if $config.editable -}} {{- if $config.editable -}}
{{- $editIcon := dict "Class" "fa-solid fa-pen-to-square" | partial "plugin/icon.html" -}} {{- $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 -}} {{- end -}}
{{- if $config.copyable -}} {{- if $config.copyable -}}
{{- $copyIcon := dict "Class" "fa-regular fa-clone" | partial "plugin/icon.html" -}} {{- $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 -}} {{- end -}}
{{- if $config.downloadable -}} {{- if $config.downloadable -}}
{{- $downloadIcon := dict "Class" "fa-solid fa-download" | partial "plugin/icon.html" -}} {{- $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 -}} {{- end -}}
{{- if $config.fullscreen -}} {{- if $config.fullscreen -}}
{{- $fullscreenIcon := dict "Class" "fa-solid fa-expand" | partial "plugin/icon.html" -}} {{- $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 -}} {{- end -}}
{{- with $config.name -}} {{- with $config.name -}}
{{- $titleEl = replace $titleEl `<span class="code-title">` (printf `<span class="code-title" data-name="%s">` .) -}} {{- $titleEl = replace $titleEl `<span class="code-title">` (printf `<span class="code-title" data-name="%s">` .) -}}
+6 -6
View File
@@ -26,12 +26,12 @@
- [ ] Unchecked - [ ] Unchecked
- [x] Checked - [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" " ") -}} {{- $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") -}} {{- $label := T (printf "taskList.%v" "x") -}}
{{- $icon := dict "Class" (add "checkbox-icon " (index $iconMap "x")) | partial "plugin/icon.html" -}} {{- $icon := dict "Class" (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 -}} {{- $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. The extended syntax is compatible with Obsidian.
@@ -45,11 +45,11 @@
*/ -}} */ -}}
{{- range $extendedSigns -}} {{- range $extendedSigns -}}
{{- $class := index $iconMap . | default "fa-solid fa-check-square" -}} {{- $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 . -}} {{- $sign := htmlEscape . -}}
{{- $originSign := replace . "\\" "" -}} {{- $originSign := replace . "\\" "" -}}
{{- $label := (T (printf "taskList.%v" $originSign)) | default (T (printf "taskList.%v" " ")) -}} {{- $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 -}} {{- end -}}
{{- return $content -}} {{- return $content -}}