feat(code): add fullscreen functionality for code blocks (#707)

This commit is contained in:
Cell
2026-03-03 16:00:11 +08:00
parent 6196cd5edf
commit 69d8e67c24
21 changed files with 122 additions and 6 deletions
+43 -4
View File
@@ -132,6 +132,10 @@ pre {
// code fences blocks wrapped
&.code-block {
&.instant-height .code-wrapper {
transition: height 0s !important;
}
.code-wrapper {
overflow: hidden;
height: auto;
@@ -173,6 +177,7 @@ pre {
position: sticky;
top: fixit-var(breadcrumb-height);
transition: border-radius 0s;
cursor: pointer;
@include z-index(base);
@include border-radius(top);
@@ -184,10 +189,6 @@ pre {
}
}
&:hover {
cursor: pointer;
}
.code-title {
width: 100%;
padding: 0.4rem;
@@ -243,6 +244,12 @@ pre {
color: fixit-var(global-link-hover-color);
}
.fullscreen-btn[data-fullscreen] .fa-expand {
--fa: "\f066";
font-weight: 900;
color: fixit-var(global-link-hover-color);
}
@each $type, $text in $code-type-map {
&.language-#{to-lower-case($type)} {
// e.g., --fi-code-type: "JavaScript";
@@ -258,6 +265,38 @@ pre {
color: fixit-var(global-link-hover-color);
}
&.is-fullscreen {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
margin: 0 !important;
overflow: auto;
@include z-index(fixed, 1);
@include border-radius(0);
.code-header {
top: 0 !important;
cursor: default;
@include border-radius(0);
.arrow {
display: none;
}
}
.code-wrapper {
overflow: auto;
// 1.4em for header height, 0.8rem for padding
height: calc(100dvh - 1.4em - 0.8rem);
}
.code-expand-btn {
display: none;
}
}
.code-expand-btn {
width: 100%;
padding-block: 1rem;
+54
View File
@@ -486,6 +486,58 @@ class FixIt {
}, false);
}
_setCodeFullscreenState(codeBlock, show) {
const fullscreenBtn = codeBlock.querySelector('.code-header .fullscreen-btn');
const hasExpandBtn = !!codeBlock.querySelector('.code-expand-btn');
if (show && hasExpandBtn) {
codeBlock.dataset.fullscreenExpanded = codeBlock.classList.contains('is-expanded') ? 'true' : 'false';
codeBlock.classList.add('is-expanded');
}
if (!show && codeBlock.classList.contains('is-fullscreen')) {
codeBlock.classList.add('instant-height');
if (hasExpandBtn && codeBlock.dataset.fullscreenExpanded === 'false') {
codeBlock.classList.remove('is-expanded');
}
delete codeBlock.dataset.fullscreenExpanded;
window.requestAnimationFrame(() => {
codeBlock.classList.remove('instant-height');
});
}
codeBlock.classList.toggle('is-fullscreen', show);
fullscreenBtn?.toggleAttribute('data-fullscreen', show);
const hasFullscreenCode = !!document.querySelector('.code-block.highlight.is-fullscreen');
document.documentElement.style.overflow = hasFullscreenCode ? 'hidden' : '';
}
closeCodeFullscreen() {
const $activeCodeBlock = document.querySelector('.code-block.highlight.is-fullscreen');
if (!$activeCodeBlock) return;
this._setCodeFullscreenState($activeCodeBlock, false);
}
initFullscreenCode(codeBlock) {
const fullscreenBtn = codeBlock.querySelector('.code-header .fullscreen-btn');
if (!fullscreenBtn) return;
fullscreenBtn.addEventListener('click', () => {
const isFullscreen = codeBlock.classList.contains('is-fullscreen');
if (isFullscreen) {
this._setCodeFullscreenState(codeBlock, false);
return;
}
this.closeCodeFullscreen();
codeBlock.classList.remove('is-collapsed');
this._setCodeFullscreenState(codeBlock, true);
}, false);
if (!this._codeFullscreenOnEsc) {
this._codeFullscreenOnEsc = (event) => {
if (event.key === 'Escape') {
this.closeCodeFullscreen();
}
};
document.addEventListener('keydown', this._codeFullscreenOnEsc, false);
}
}
/**
* init code wrapper
*/
@@ -505,8 +557,10 @@ class FixIt {
const $codeHeader = $codeBlock.querySelector('.code-header');
if (!$codeHeader) return;
this.initDownloadCode($codeBlock, $codePreEl);
this.initFullscreenCode($codeBlock);
// code title
$codeHeader.querySelector('.code-title').addEventListener('click', () => {
if ($codeBlock.classList.contains('is-fullscreen')) return;
$codeBlock.classList.toggle('is-collapsed');
}, false);
// ellipses icon
+2
View File
@@ -1146,6 +1146,8 @@ maxShownLines = 10
copyable = true
# [classic] whether to enable code download button in the code block header
downloadable = false
# [classic] whether to enable code fullscreen button in the code block header
fullscreen = false
# [classic] whether to enable line numbers toggle button in the code block header
lineNosToggler = true
# [classic] whether to enable toggle line wrapping button in the code block header
+1
View File
@@ -103,6 +103,7 @@ toggleLineNumbers = "Zeilennummern umschalten"
toggleLineWrap = "Zeilenumbruch umschalten"
toggleCodeEditable = "Codeblock editierbar umschalten"
downloadCode = "Code herunterladen"
toggleCodeFullscreen = "Codeblock-Vollbild umschalten"
expandCode = "Codeblock erweitern oder reduzieren"
cookieconsentMessage = "Diese Website verwendet Cookies, um Ihre Erfahrung zu verbessern."
cookieconsentDismiss = "Zustimmen"
+1
View File
@@ -103,6 +103,7 @@ toggleLineNumbers = "Toggle line numbers"
toggleLineWrap = "Toggle code wrap"
toggleCodeEditable = "Toggle code block editable"
downloadCode = "Download code"
toggleCodeFullscreen = "Toggle code block fullscreen"
expandCode = "Expand or collapse code block"
cookieconsentMessage = "This website uses Cookies to improve your experience."
cookieconsentDismiss = "Got it!"
+1
View File
@@ -103,6 +103,7 @@ toggleLineNumbers = "Alternar números de línea"
toggleLineWrap = "Alternar ajuste de línea"
toggleCodeEditable = "Alternar bloque de código editable"
downloadCode = "Descargar código"
toggleCodeFullscreen = "Alternar pantalla completa del bloque de código"
expandCode = "Expandir o contraer bloque de código"
cookieconsentMessage = "Este sitio web utiliza Cookies para mejorar su experiencia."
cookieconsentDismiss = "De acuerdo"
+1
View File
@@ -103,6 +103,7 @@ toggleLineNumbers = "Basculer les numéros de ligne"
toggleLineWrap = "Basculer le retour à la ligne"
toggleCodeEditable = "Basculer le bloc de code modifiable"
downloadCode = "Télécharger le code"
toggleCodeFullscreen = "Basculer le plein écran du bloc de code"
expandCode = "Développer ou réduire le bloc de code"
cookieconsentMessage = "Ce site Web utilise des Cookies pour améliorer votre expérience."
cookieconsentDismiss = "J'ai compris !"
+1
View File
@@ -104,6 +104,7 @@ toggleLineNumbers = "लाइन नंबर टॉगल करें"
toggleLineWrap = "लाइन रैप टॉगल करें"
toggleCodeEditable = "कोड ब्लॉक संपादन योग्य टॉगल करें"
downloadCode = "कोड डाउनलोड करें"
toggleCodeFullscreen = "कोड ब्लॉक फ़ुलस्क्रीन टॉगल करें"
expandCode = "कोड ब्लॉक का विस्तार या संकुचित करें"
cookieconsentMessage = "यह वेबसाइट आपके अनुभव को बेहतर बनाने के लिए कुकीज़ का उपयोग करती है।"
cookieconsentDismiss = "समझ गया!"
+1
View File
@@ -103,6 +103,7 @@ toggleLineNumbers = "Attiva/disattiva i numeri di linea"
toggleLineWrap = "Attiva/disattiva il ritorno a capo del codice"
toggleCodeEditable = "Attiva/disattiva la modifica del blocco di codice"
downloadCode = "Scarica codice"
toggleCodeFullscreen = "Attiva/disattiva schermo intero del blocco di codice"
expandCode = "Espandi o riduci il blocco di codice"
cookieconsentMessage = "Questo sito Web utilizza i Cookies per migliorare la tua esperienza."
cookieconsentDismiss = "Essere d'accordo"
+1
View File
@@ -101,6 +101,7 @@ toggleLineNumbers = "行番号の切り替え"
toggleLineWrap = "自動折り返しの切り替え"
toggleCodeEditable = "コードブロックの編集切り替え"
downloadCode = "コードをダウンロード"
toggleCodeFullscreen = "コードブロックの全画面表示を切り替え"
expandCode = "コードブロックの展開/折りたたみ"
cookieconsentMessage = "このウェブサイトはクッキーを使用して体験を向上させます。"
cookieconsentDismiss = "同意する"
+1
View File
@@ -101,6 +101,7 @@ toggleLineNumbers = "줄 번호 전환"
toggleLineWrap = "자동 줄 바꿈 전환"
toggleCodeEditable = "코드 블록 편집 전환"
downloadCode = "코드 다운로드"
toggleCodeFullscreen = "코드 블록 전체 화면 전환"
expandCode = "코드 블록 확장/축소"
cookieconsentMessage = "이 웹사이트는 쿠키를 사용하여 경험을 향상시킵니다."
cookieconsentDismiss = "동의"
+1
View File
@@ -103,6 +103,7 @@ toggleLineNumbers = "Przełącz numery linii"
toggleLineWrap = "Przełącz zawijanie linii"
toggleCodeEditable = "Przełącz edytowalny blok kodu"
downloadCode = "Pobierz kod"
toggleCodeFullscreen = "Przełącz pełny ekran bloku kodu"
expandCode = "Rozwiń lub zwiń blok kodu"
cookieconsentMessage = "Ta strona korzysta z plików Cookies, aby poprawić komfort użytkowania."
cookieconsentDismiss = "Zgodzić się"
+1
View File
@@ -104,6 +104,7 @@ toggleLineNumbers = "Alternar números de linha"
toggleLineWrap = "Alternar quebra de linha"
toggleCodeEditable = "Alternar bloco de código editável"
downloadCode = "Baixar código"
toggleCodeFullscreen = "Alternar tela cheia do bloco de código"
expandCode = "Expandir ou recolher bloco de código"
cookieconsentMessage = "Este site usa Cookies para melhorar sua experiência."
cookieconsentDismiss = "Aceitar"
+1
View File
@@ -103,6 +103,7 @@ toggleLineNumbers = "Comută numerele de linie"
toggleLineWrap = "Comută înfășurarea liniei"
toggleCodeEditable = "Comută blocul de cod editabil"
downloadCode = "Descarcă codul"
toggleCodeFullscreen = "Comută ecran complet pentru blocul de cod"
expandCode = "Extinde sau restrânge blocul de cod"
cookieconsentMessage = "Acest site web utilizează Cookies pentru a vă îmbunătăți experiența."
cookieconsentDismiss = "De acord"
+1
View File
@@ -103,6 +103,7 @@ toggleLineNumbers = "Переключить номера строк"
toggleLineWrap = "Переключить перенос строк"
toggleCodeEditable = "Переключить редактируемый блок кода"
downloadCode = "Скачать код"
toggleCodeFullscreen = "Переключить полноэкранный режим блока кода"
expandCode = "Развернуть или свернуть блок кода"
cookieconsentMessage = "Этот сайт использует Cookies для улучшения вашего опыта."
cookieconsentDismiss = "Согласен"
+1
View File
@@ -103,6 +103,7 @@ toggleLineNumbers = "Прекидач за бројеве линија"
toggleLineWrap = "Прекидач за оматање линија"
toggleCodeEditable = "Пребаци уређивање блока кода"
downloadCode = "Преузми код"
toggleCodeFullscreen = "Пребаци цео екран блока кода"
expandCode = "Прошири или смањи блок кода"
cookieconsentMessage = "Ова веб локација користи Cookies да би побољшала ваше искуство."
cookieconsentDismiss = "Договорити се"
+1
View File
@@ -102,6 +102,7 @@ toggleLineNumbers = "Chuyển đổi số dòng"
toggleLineWrap = "Chuyển đổi xuống dòng"
toggleCodeEditable = "Chuyển đổi khối mã có thể chỉnh sửa"
downloadCode = "Tải mã"
toggleCodeFullscreen = "Chuyển đổi toàn màn hình khối mã"
expandCode = "Mở rộng hoặc thu gọn khối mã"
cookieconsentMessage = "Trang web này sử dụng Cookies để cải thiện trải nghiệm của bạn."
cookieconsentDismiss = "Đã hiểu!"
+1
View File
@@ -101,6 +101,7 @@ toggleLineNumbers = "切换行号"
toggleLineWrap = "切换自动换行"
toggleCodeEditable = "切换可编辑代码块"
downloadCode = "下载代码"
toggleCodeFullscreen = "切换代码块全屏"
expandCode = "展开或折叠代码块"
cookieconsentMessage = "本网站使用 Cookies 来改善您的浏览体验。"
cookieconsentDismiss = "同意"
+1
View File
@@ -101,6 +101,7 @@ toggleLineNumbers = "切換行號"
toggleLineWrap = "切換自動換行"
toggleCodeEditable = "切換可編輯程式碼區塊"
downloadCode = "下載程式碼"
toggleCodeFullscreen = "切換程式碼區塊全螢幕"
expandCode = "展開或摺疊程式碼區塊"
cookieconsentMessage = "本網站使用 Cookies 來改善您的流覽體驗。"
cookieconsentDismiss = "同意"
+6 -1
View File
@@ -8,6 +8,7 @@
{{- $editBtn := "" -}}
{{- $copyBtn := "" -}}
{{- $downloadBtn := "" -}}
{{- $fullscreenBtn := "" -}}
{{- $foldIcon := dict "Class" "arrow fa-solid fa-chevron-down" | partial "plugin/icon.html" -}}
{{- $titleEl := printf `<span class="code-title">%s</span>` $foldIcon -}}
{{- $ellipsisBtn := printf `<span class="ellipses-btn" aria-label="Show more options" role="button">%s</span>` (dict "Class" "fa-solid fa-ellipsis-h" | partial "plugin/icon.html") -}}
@@ -35,10 +36,14 @@
{{- $downloadIcon := dict "Class" "fa-solid fa-download" | partial "plugin/icon.html" -}}
{{- $downloadBtn = printf `<span class="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="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">` .) -}}
{{- end -}}
{{- $codeHeader := printf `<div class="code-header language-%s">%s%s%s%s%s%s%s</div>` $lang $titleEl $ellipsisBtn $lineNosBtn $lineWrapBtn $editBtn $copyBtn $downloadBtn -}}
{{- $codeHeader := printf `<div class="code-header language-%s">%s%s%s%s%s%s%s%s</div>` $lang $titleEl $ellipsisBtn $lineNosBtn $lineWrapBtn $editBtn $copyBtn $downloadBtn $fullscreenBtn -}}
{{- $wrapper = replaceRE `(<div class="code-wrapper">)` (printf "%s$1" $codeHeader) $wrapper -}}
{{- return $wrapper -}}
+1 -1
View File
@@ -1,4 +1,4 @@
{{- hugo.Store.Set "version" "v0.4.3-20260302065610-78a994b9" -}}
{{- hugo.Store.Set "version" "v0.4.3-20260303081459-41fe4197" -}}
{{- .Store.Set "this" dict -}}
{{- partial "init/detection-env.html" . -}}