feat: copy bibtex citations rather than downloading them

Close #3141
This commit is contained in:
George Cushen committed 2025-08-17 22:16:26 +01:00
1 parent 9c48341ee8
commit 0c41b518dc
16 files changed
+1376 -11

No files matched your search

+1
View File
@@ -16,6 +16,7 @@ node_modules/
go.sum
resources/
public/
**/assets/jsconfig.json
# Pagefind search index (generated)
**/pagefind/
@@ -0,0 +1,70 @@
# Hugo Blox Tailwind CSS v4 Structure
## Overview
The CSS architecture is modularized for maintainability and organization. The entry point is `main.css` which orchestrates all imports.
## Directory Structure
```
css/
├── main.css # Main entry point
├── color-utilities.css # HB Theme Engine
├── config/ # Tailwind configuration
│ ├── tailwind.css # Tailwind v4 directives (@source, @custom-variant)
│ ├── theme.css # HB Theme variables (@theme block)
│ └── safelist.css # Dynamic classes safelist
├── framework/ # Hugo Blox framework styles
│ ├── base.css # Base styles and typography
│ └── components.css # Framework components
├── components/ # Hugo Blox module components
│ └── all.css # Imports all component files
├── blox/ # Block-specific styles
│ └── all.css # Imports all block styles
└── views/ # Listing view styles
└── all.css # Imports all listing view styles
```
## Key Files
### main.css
The orchestrator that imports everything in the correct order:
1. Tailwind base
2. Configuration
3. Base styles
4. Hugo Blox theme engine
5. Components
6. Safelist
### config/tailwind.css
Contains Tailwind v4-specific directives:
- `@source` - Where to scan for classes
- `@custom-variant` - Custom variants (dark, hover)
- `@plugin` - Plugin imports
### config/theme.css
Defines the theme using `@theme` block:
- Color palettes (primary, secondary, neutral)
- Font families and sizes
- Custom properties
### color-utilities.css
Hugo Blox theme engine with color utility classes:
- All color shades (50-950)
- All variants (hover, dark, focus)
- Gradient utilities
## Tailwind v4 Notes
- `@source`, `@theme`, `@plugin` are new v4 directives
- Linters may show warnings for these - they can be ignored
- Hugo's `css.TailwindCSS` function processes this automatically
- No PostCSS configuration needed anymore
## Maintenance
When adding new styles:
1. Framework classes → `framework/components.css`
2. Theme variables → `config/theme.css`
3. Component styles → `components/[file].css`
4. Dynamic classes → Add to `config/safelist.css`
@@ -0,0 +1 @@
@import "attachments.css";
@@ -0,0 +1,189 @@
/**
* Citation clipboard handler for Hugo Blox Builder
* Copies BibTeX citation to clipboard when cite button is clicked
*/
import { hugoEnvironment, i18n } from '@params';
import { showNotification } from './hb-notifier.js';
import { copyToClipboardSync, ClipboardCache } from './hb-clipboard.js';
// Debug mode based on environment
const isDebugMode = hugoEnvironment === 'development';
// Cache for citation content
const citationCache = new ClipboardCache();
// Initialize citation handlers when DOM is ready
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initializeCitation);
} else {
initializeCitation();
}
function initializeCitation() {
// Handle citation button clicks using event delegation
document.addEventListener('click', handleCiteClick);
// Prefetch citations on hover/focus for better UX and Safari compatibility
document.addEventListener('mouseover', prefetchOnHover);
document.addEventListener('focusin', prefetchOnHover);
// Prefetch all citations on page load
prefetchAllCitations();
}
/**
* Prefetch all citations on page load
*/
function prefetchAllCitations() {
const citeButtons = document.querySelectorAll('.js-cite-clipboard[data-filename]');
citeButtons.forEach(button => {
const filename = button.getAttribute('data-filename');
if (filename && !citationCache.has(filename)) {
// Fetch in background, don't await
fetchAndCacheCitation(filename);
}
});
}
/**
* Prefetch citation on hover/focus
* @param {Event} e - Hover or focus event
*/
function prefetchOnHover(e) {
const citeButton = e.target.closest('.js-cite-clipboard');
if (!citeButton) return;
const filename = citeButton.getAttribute('data-filename');
if (filename && !citationCache.has(filename)) {
// Fetch in background, don't await
fetchAndCacheCitation(filename);
}
}
/**
* Fetch and cache citation content
* @param {string} filename - Citation file URL
* @returns {Promise<string|null>} - Citation content or null if failed
*/
async function fetchAndCacheCitation(filename) {
try {
const response = await fetch(filename);
if (!response.ok) {
throw new Error(`Failed to fetch citation: ${response.statusText}`);
}
const citation = await response.text();
citationCache.set(filename, citation);
return citation;
} catch (error) {
if (isDebugMode) {
console.error(`Failed to fetch citation ${filename}:`, error);
}
return null;
}
}
/**
* Handle cite button clicks - synchronous clipboard write for Safari compatibility
* @param {Event} e - Click event
*/
function handleCiteClick(e) {
// Check if clicked element or its parent is a cite button
const citeButton = e.target.closest('.js-cite-clipboard');
if (!citeButton) return;
e.preventDefault();
e.stopPropagation();
const filename = citeButton.getAttribute('data-filename');
if (!filename) {
if (isDebugMode) {
console.error('No filename specified for citation');
}
showNotification('Citation file not found', 'error');
return;
}
// Check if citation is cached
const cachedCitation = citationCache.get(filename);
if (cachedCitation) {
// Citation is cached, copy immediately (synchronous for Safari)
copyToClipboardSync(cachedCitation).then(success => {
if (success) {
showNotification(i18n?.copied || 'Citation copied!', 'success');
updateButtonText(citeButton);
} else {
showNotification('Failed to copy citation', 'error');
}
});
} else {
// Not cached, need to fetch first (will fail in Safari with strict mode)
fetchAndCopyWithFallback(filename, citeButton);
}
}
/**
* Fetch and copy with fallback (for browsers that allow async clipboard)
* @param {string} filename - Citation file URL
* @param {HTMLElement} button - Cite button element
*/
async function fetchAndCopyWithFallback(filename, button) {
try {
const citation = await fetchAndCacheCitation(filename);
if (citation) {
// Try to copy (might fail in Safari due to lost user activation)
const success = await copyToClipboardSync(citation);
if (success) {
showNotification(i18n?.copied || 'Citation copied!', 'success');
updateButtonText(button);
} else {
showNotification('Failed to copy citation', 'error');
}
} else {
showNotification('Failed to load citation', 'error');
}
} catch (error) {
if (isDebugMode) {
console.error('Failed to copy citation:', error);
}
// If it's a NotAllowedError, suggest hovering first
if (error.name === 'NotAllowedError') {
showNotification('Please hover over the button first, then click', 'info');
} else {
showNotification('Failed to copy citation', 'error');
}
}
}
/**
* Update button text to show copied state
* @param {HTMLElement} button - The cite button element
*/
function updateButtonText(button) {
const copiedText = i18n?.copied || 'Copied!';
// Find text element to update (skip icon)
const textElement = button.querySelector('span');
if (!textElement) {
if (isDebugMode) {
console.warn('Could not find text element in cite button');
}
return;
}
const originalText = textElement.textContent;
textElement.textContent = copiedText;
// Add visual feedback
button.classList.add('opacity-70');
// Revert after 2 seconds
setTimeout(() => {
textElement.textContent = originalText;
button.classList.remove('opacity-70');
}, 2000);
}
// Export functions for potential reuse
export { handleCiteClick, prefetchAllCitations };
@@ -0,0 +1,186 @@
/**
* Clipboard Utilities for Hugo Blox Builder
* Provides cross-browser clipboard functionality
*/
import { hugoEnvironment } from '@params';
// Debug mode based on environment
const isDebugMode = hugoEnvironment === 'development';
/**
* Copy text to clipboard with multiple fallback methods
* @param {string} text - Text to copy
* @returns {Promise<boolean>} - Whether the copy was successful
*/
export async function copyToClipboard(text) {
// Method 1: Modern Clipboard API
if (navigator.clipboard && window.isSecureContext) {
try {
await navigator.clipboard.writeText(text);
if (isDebugMode) {
console.log('Copied using Clipboard API');
}
return true;
} catch (err) {
if (isDebugMode) {
console.warn('Clipboard API failed:', err);
}
}
}
// Method 2: execCommand fallback
return copyUsingExecCommand(text);
}
/**
* Copy text to clipboard synchronously (Safari-compatible)
* @param {string} text - Text to copy
* @returns {Promise<boolean>} - Whether the copy was successful
*/
export function copyToClipboardSync(text) {
return new Promise((resolve) => {
// Try modern clipboard API first
if (navigator.clipboard && window.isSecureContext) {
navigator.clipboard.writeText(text)
.then(() => {
if (isDebugMode) {
console.log('Copied using Clipboard API (sync)');
}
resolve(true);
})
.catch(err => {
if (isDebugMode) {
console.warn('Clipboard API failed:', err);
}
// Fallback to execCommand
resolve(copyUsingExecCommand(text));
});
} else {
// Use execCommand directly
resolve(copyUsingExecCommand(text));
}
});
}
/**
* Legacy copy method using execCommand
* @param {string} text - Text to copy
* @returns {boolean} - Success status
*/
export function copyUsingExecCommand(text) {
const textarea = document.createElement('textarea');
textarea.value = text;
// Make it invisible but copyable
Object.assign(textarea.style, {
position: 'fixed',
top: '0',
left: '0',
width: '2em',
height: '2em',
padding: '0',
border: 'none',
outline: 'none',
boxShadow: 'none',
background: 'transparent',
fontSize: '16px', // Prevent zoom on iOS
});
document.body.appendChild(textarea);
// Select the text
textarea.focus();
textarea.select();
// For iOS
if (navigator.userAgent.match(/ipad|iphone/i)) {
const range = document.createRange();
range.selectNodeContents(textarea);
const selection = window.getSelection();
selection.removeAllRanges();
selection.addRange(range);
textarea.setSelectionRange(0, 999999);
}
let success = false;
try {
success = document.execCommand('copy');
if (isDebugMode) {
console.log(`execCommand copy ${success ? 'succeeded' : 'failed'}`);
}
} catch (err) {
if (isDebugMode) {
console.error('execCommand failed:', err);
}
}
document.body.removeChild(textarea);
return success;
}
/**
* Test if clipboard API is available and working
* @returns {boolean} - Whether clipboard API is available
*/
export function isClipboardAPIAvailable() {
return !!(navigator.clipboard && window.isSecureContext);
}
/**
* Create a prefetch cache for clipboard content
* Useful for Safari compatibility where content must be copied synchronously
*/
export class ClipboardCache {
constructor() {
this.cache = new Map();
}
/**
* Add content to cache
* @param {string} key - Cache key
* @param {string} content - Content to cache
*/
set(key, content) {
this.cache.set(key, content);
if (isDebugMode) {
console.log(`Cached clipboard content for: ${key}`);
}
}
/**
* Get content from cache
* @param {string} key - Cache key
* @returns {string|null} - Cached content or null
*/
get(key) {
return this.cache.get(key) || null;
}
/**
* Check if content is cached
* @param {string} key - Cache key
* @returns {boolean} - Whether content is cached
*/
has(key) {
return this.cache.has(key);
}
/**
* Clear the cache
*/
clear() {
this.cache.clear();
}
/**
* Get cache size
* @returns {number} - Number of cached items
*/
get size() {
return this.cache.size;
}
}
// Export default clipboard copy function
export default copyToClipboard;
@@ -0,0 +1,194 @@
/**
* Notification/Toast System for Hugo Blox Builder
* Provides reusable notification functionality
*/
import { hugoEnvironment } from '@params';
// Debug mode based on environment
const isDebugMode = hugoEnvironment === 'development';
/**
* Show a notification message using Tailwind styles
* @param {string} message - The message to display
* @param {string} type - The type of notification ('success', 'error', 'info', 'warning')
* @param {number} duration - Duration in milliseconds (default 3000)
* @returns {HTMLElement} - The notification element
*/
export function showNotification(message, type = 'success', duration = 3000) {
// Get or create the notification container
const container = getOrCreateContainer();
// Remove any existing notifications with same message
const existingNotification = container.querySelector('.hb-notification');
if (existingNotification && existingNotification.textContent.includes(message)) {
existingNotification.remove();
}
// Create notification element
const notification = createNotificationElement(message, type);
// Add to container
container.appendChild(notification);
// Handle close button
const closeBtn = notification.querySelector('.hb-notification-close');
if (closeBtn) {
closeBtn.addEventListener('click', () => {
removeNotification(notification);
});
}
// Auto-remove after duration
if (duration > 0) {
setTimeout(() => {
removeNotification(notification);
}, duration);
}
return notification;
}
/**
* Get or create the notification container
* @returns {HTMLElement} - The container element
*/
function getOrCreateContainer() {
let container = document.getElementById('hb-notification-container');
if (!container) {
if (isDebugMode) {
console.warn('Notification container not found, creating fallback');
}
container = document.createElement('div');
container.id = 'hb-notification-container';
container.className = 'fixed top-20 right-4 z-[9999] pointer-events-none';
container.setAttribute('aria-live', 'polite');
container.setAttribute('aria-atomic', 'true');
document.body.appendChild(container);
}
return container;
}
/**
* Create a notification element
* @param {string} message - The message to display
* @param {string} type - The type of notification
* @returns {HTMLElement} - The notification element
*/
function createNotificationElement(message, type) {
const notification = document.createElement('div');
notification.setAttribute('role', 'alert');
// Define colors for different types
const colors = {
success: { bg: '#10b981', bgClass: 'bg-green-500' },
error: { bg: '#ef4444', bgClass: 'bg-red-500' },
info: { bg: '#3b82f6', bgClass: 'bg-blue-500' },
warning: { bg: '#f59e0b', bgClass: 'bg-amber-500' }
};
const color = colors[type] || colors.info;
// Set classes
notification.className = `hb-notification pointer-events-auto flex items-center gap-2 px-4 py-3 text-white rounded-lg shadow-lg ${color.bgClass} animate-slide-in`;
// Add inline styles as fallback
notification.style.cssText = `
background-color: ${color.bg};
color: white;
display: flex;
align-items: center;
gap: 0.5rem;
padding: 0.75rem 1rem;
border-radius: 0.5rem;
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
margin-bottom: 0.5rem;
pointer-events: auto;
`;
// Add icon based on type
const icons = {
success: '<svg class="w-5 h-5 flex-shrink-0" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"></path></svg>',
error: '<svg class="w-5 h-5 flex-shrink-0" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z" clip-rule="evenodd"></path></svg>',
info: '<svg class="w-5 h-5 flex-shrink-0" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z" clip-rule="evenodd"></path></svg>',
warning: '<svg class="w-5 h-5 flex-shrink-0" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z" clip-rule="evenodd"></path></svg>'
};
const icon = icons[type] || icons.info;
notification.innerHTML = `
${icon}
<span class="text-sm font-medium">${message}</span>
<button class="hb-notification-close ml-2 text-white/80 hover:text-white transition-colors" aria-label="Close">
<svg class="w-4 h-4" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd"></path>
</svg>
</button>
`;
// Ensure animation styles exist
ensureAnimationStyles();
return notification;
}
/**
* Remove notification with animation
* @param {HTMLElement} notification - The notification element to remove
*/
export function removeNotification(notification) {
if (!notification || !notification.parentNode) return;
notification.classList.remove('animate-slide-in');
notification.classList.add('animate-slide-out');
setTimeout(() => {
if (notification.parentNode) {
notification.remove();
}
}, 300);
}
/**
* Ensure animation styles are in the document
*/
function ensureAnimationStyles() {
if (!document.querySelector('#hb-notification-styles')) {
const style = document.createElement('style');
style.id = 'hb-notification-styles';
style.textContent = `
@keyframes slide-in {
from {
transform: translateX(100%);
opacity: 0;
}
to {
transform: translateX(0);
opacity: 1;
}
}
@keyframes slide-out {
from {
transform: translateX(0);
opacity: 1;
}
to {
transform: translateX(100%);
opacity: 0;
}
}
.animate-slide-in {
animation: slide-in 0.3s ease-out;
}
.animate-slide-out {
animation: slide-out 0.3s ease-out;
}
`;
document.head.appendChild(style);
}
}
// Export default for convenience
export default showNotification;
@@ -0,0 +1,4 @@
{{/* Notification Container for toasts/alerts */}}
{{/* This container is placed at the page level to ensure proper z-index and visibility */}}
{{/* Used by hb-notifier.js module for showing toast notifications */}}
<div id="hb-notification-container" class="fixed top-20 right-4 z-[9999] pointer-events-none" aria-live="polite" aria-atomic="true"></div>
@@ -32,10 +32,10 @@
{{ end }}
{{ $resource := $page.Resources.GetMatch "cite.bib" }}
{{ with $resource }}
<a class="hb-attachment-link {{ if $is_list }}hb-attachment-link-small{{else}}hb-attachment-link-large{{end}}" href="{{ .RelPermalink }}" target="_blank" data-filename="{{ .RelPermalink }}">
<button class="hb-attachment-link {{ if $is_list }}hb-attachment-link-small{{else}}hb-attachment-link-large{{end}} js-cite-clipboard cursor-pointer" type="button" data-filename="{{ .RelPermalink }}">
{{ partial "functions/get_icon" (dict "name" "document-duplicate" "attributes" "style=\"height: 1em\" class='inline-block'") }}
{{ i18n "btn_cite" }}
</a>
<span>{{ i18n "btn_cite" }}</span>
</button>
{{ end }}
{{ with $page.Params.url_code }}
{{ $resource := $page.Resources.GetMatch . }}
@@ -267,7 +267,10 @@
{{- $js_lang := resources.Get "js/hb-i18n.js" | resources.Minify -}}
{{- $js_nav := resources.Get "js/hb-nav.js" | resources.Minify -}}
{{- $js_sidebar := resources.Get "js/hb-sidebar.js" | resources.Minify -}}
{{ $js_bundle := slice $js_bundle_head $js_academic $js_theme $js_lang $js_nav $js_sidebar | resources.Concat (printf "js/hugo-blox-%s.min.js" .Lang) }}
{{- $js_notifier := resources.Get "js/hb-notifier.js" | js.Build (dict "targetPath" (printf "js/hb-notifier-%s.js" .Lang ) "params" $js_params) | resources.Minify -}}
{{- $js_clipboard := resources.Get "js/hb-clipboard.js" | js.Build (dict "targetPath" (printf "js/hb-clipboard-%s.js" .Lang ) "params" $js_params) | resources.Minify -}}
{{- $js_citation := resources.Get "js/hb-citation.js" | js.Build (dict "targetPath" (printf "js/hb-citation-%s.js" .Lang ) "params" $js_params) | resources.Minify -}}
{{ $js_bundle := slice $js_bundle_head $js_academic $js_theme $js_lang $js_nav $js_sidebar $js_notifier $js_clipboard $js_citation | resources.Concat (printf "js/hugo-blox-%s.min.js" .Lang) }}
{{- if hugo.IsProduction -}}
{{ $js_bundle = $js_bundle | fingerprint "sha256" }}
{{- end -}}
@@ -27,6 +27,9 @@
{{ partial "site_footer" . }}
</div>
{{/* Notification Container for toasts/alerts */}}
{{ partial "notification-container" . }}
{{/* EXTENSIBILITY HOOK: BODY-END */}}
{{ partial "functions/get_hook" (dict "hook" "body-end" "context" .) }}
</body>
+2 -2
View File
@@ -9,13 +9,13 @@ importers:
.:
dependencies:
'@tailwindcss/cli':
specifier: ^4.0.0
specifier: ^4.1.12
version: 4.1.12
'@tailwindcss/typography':
specifier: ^0.5.10
version: 0.5.16(tailwindcss@4.1.12)
tailwindcss:
specifier: ^4.0.0
specifier: ^4.1.12
version: 4.1.12
packages:
+2 -2
View File
@@ -9,13 +9,13 @@ importers:
.:
dependencies:
'@tailwindcss/cli':
specifier: ^4.0.0
specifier: ^4.1.12
version: 4.1.12
'@tailwindcss/typography':
specifier: ^0.5.10
version: 0.5.16(tailwindcss@4.1.12)
tailwindcss:
specifier: ^4.0.0
specifier: ^4.1.12
version: 4.1.12
packages:
-2
View File
@@ -1,2 +0,0 @@
/*! tailwindcss v3.3.5 | MIT License | https://tailwindcss.com*/*,:after,:before{-webkit-box-sizing:border-box;box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:Inter var,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;-webkit-font-feature-settings:normal;font-feature-settings:normal;font-variation-settings:normal}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:initial}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;-webkit-font-feature-settings:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button;background-color:initial;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:initial}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-webkit-input-placeholder,textarea::-webkit-input-placeholder{opacity:1;color:#9ca3af}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input:-ms-input-placeholder,textarea:-ms-input-placeholder{opacity:1;color:#9ca3af}input::-ms-input-placeholder,textarea::-ms-input-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}*,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#3b82f680;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }::-ms-backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#3b82f680;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;Line truncated
/*! Wowchemy Components | https://hugoblox.com */.page-wrapper{min-height:100vh;display:grid;grid-template-rows:auto 1fr auto;grid-template-columns:100%}.page-footer,.page-header{-ms-flex-negative:0;flex-shrink:0}.page-body{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1}.article-header{position:relative;clear:both}.article-banner{width:100%;height:260px;-o-object-fit:cover;object-fit:cover}.featured-image-wrapper{position:relative;padding-left:0;padding-right:0}.featured-image{position:relative;width:100%;display:block;margin:0 auto}.article-header-caption{position:absolute;bottom:0;right:0;margin:0 auto;padding:2px 5px;color:#fff;font-size:.7em;background:#000;text-align:right;z-index:5;opacity:.65;border-radius:5px 0 0}@media (min-width:64em){.article-header-caption{padding:5px 10px}}.article-header-caption a{color:#fff;text-decoration:none}#page-bg{position:fixed;left:0;right:0;height:100%;width:100%;z-index:-1;display:block}ul.task-list{list-style:none}ul.task-list li input[type=checkbox]{margin-right:.5rem}ul.task-list input[type=checkbox]:checked{-webkit-appearance:none;-moz-appearance:none;appearance:none;width:1em;height:1em;border:none;background:initial;position:relative}ul.task-list input[type=checkbox]:not(:checked){width:.9em;height:.9em}ul.task-list input[type=checkbox]:checked:after{content:"✅"}.highlight{position:relative;z-index:0}.highlight:hover>.copy-button{visibility:visible}.copy-button{visibility:hidden;position:absolute;right:0;top:0;z-index:10;width:5rem;cursor:pointer;white-space:nowrap;border-bottom-left-radius:.375rem;border-top-right-radius:.375rem;--tw-bg-opacity:1;background-color:rgba(var(--color-neutral-200),var(--tw-bg-opacity));padding-top:.25rem;padding-bottom:.25rem;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:.875rem;line-height:1.25rem;--tw-text-opacity:1;color:rgba(var(--color-neutral-700),var(--tw-text-opacity));opacity:.9}:is(.dark .copy-button){--tw-bg-opacity:1;background-color:rgba(var(--color-neutral-600),var(--tw-bg-opacity));--tw-text-opacity:1;color:rgba(var(--color-neutral-200),var(--tw-text-opacity))}.copy-button:active,.copy-button:active:hover,.copy-button:focus,.copy-button:hover{--tw-bg-opacity:1;background-color:rgba(var(--color-primary-100),var(--tw-bg-opacity))}:is(.dark .copy-button:active),:is(.dark .copy-button:active:hover),:is(.dark .copy-button:focus),:is(.dark .copy-button:hover){--tw-bg-opacity:1;background-color:rgba(var(--color-primary-600),var(--tw-bg-opacity))}.wg-about-avatar{#profile{text-align:center;padding:30px 10px;position:relative}.avatar{width:auto;height:auto;max-width:225px;max-height:225px;-o-object-fit:cover;object-fit:cover}.portrait-title h2{font-size:1.75em;font-weight:300;margin:20px 0 10px}.portrait-title h3{font-size:1rem;font-weight:300;margin:0 0 10px}.network-icon{display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;list-style:none;padding:0;margin:0}#profile .network-icon{margin-top:.5rem}.network-icon li{margin-right:10px;@media (max-width:640px){margin-right:12px}}.network-icon li:last-of-type{margin-right:0}.network-icon li:hover{-webkit-transform:scale(1.2);transform:scale(1.2)}.big-icon{font-size:2rem}.ul-interests li{font-size:.9rem}.ul-edu{list-style:none}.ul-edu li{position:relative;padding:0 15px 4px 3px}.ul-edu li .description p{margin:0}.ul-edu li .description p.course{font-size:.9rem}.ul-edu li .description p.institution{font-size:.75rem}.network-icon .big-icon{font-size:1.5rem}.dark .portrait-title h3{color:#ffffffe6;font-weight:700}.dark .portrait-title h2{color:#fff;font-weight:700}.bio-text{max-width:680px}}.avatar-wrapper{position:relative;width:150px;height:150px;margin-left:auto;margin-right:auto}.avatar-emoji{position:absolute;width:40px;height:40px;line-height:40px;border-radius:100%;bottom:0;right:0;text-align:center;font-size:20px;background-color:#fff;color:#000;-webkit-box-shadow:0 10px 20px #0000000a,0 2px 6px #0000000a,0 0 1px #0000000a;box-shadow:0 10px 20px #0000000a,0 2px 6px #0000000a,0 0 1px #0000000a}.dark .avatar-emoji{background-color:#000;-webkit-box-shadow:0 10px 20px #0000000a,0 2px 6px #0000000a,0 0 1px #fffffff5;box-shadow:0 10px 20px #0000000a,0 2px 6px #0000000a,0 0 1px #fffffff5}:root{--color-neutral:255,255,255;--color-neutral-50:248,250,252;--color-neutral-100:241,245,249;--color-neutral-200:226,232,240;--color-neutral-300:203,213,225;--color-neutral-400:148,163,184;--color-neutral-500:100,116,139;--color-neutral-600:71,85,105;--color-neutral-700:51,65,85;--color-neutral-800:30,41,59;--color-neutral-900:15,23,42;--color-primary-50:239,246,255;--color-primary-100:219,234,254;--color-primary-200:191,219,254;--color-primary-300:147,197,253;--color-primary-400:96,165,250;--color-primarLine truncated
+3
View File
@@ -1,5 +1,8 @@
title: Hugo Blox Test
baseURL: https://example.com
build:
buildStats:
enable: true
module:
imports:
- path: github.com/HugoBlox/hugo-blox-builder/modules/blox-tailwind
+7 -1
View File
@@ -7,9 +7,15 @@
"author": "George Cushen",
"license": "MIT",
"private": true,
"packageManager": "pnpm@10.14.0",
"dependencies": {
"tailwindcss": "^4.1.12",
"@tailwindcss/cli": "^4.1.12",
"@tailwindcss/typography": "^0.5.15"
},
"scripts": {
"view": "hugo server --port 8080 --bind 0.0.0.0",
"build": "hugo --minify --cleanDestinationDir --gc --templateMetrics --templateMetricsHints",
"cms": "(trap 'kill 0' SIGINT; npx netlify-cms-proxy-server & hugo server --port 8080 --bind 0.0.0.0)"
"cms": "(trap 'kill 0' SIGINT; pnpm dlx netlify-cms-proxy-server & hugo server --port 8080 --bind 0.0.0.0)"
}
}
+707
View File
@@ -0,0 +1,707 @@
lockfileVersion: '9.0'
settings:
autoInstallPeers: true
excludeLinksFromLockfile: false
importers:
.:
dependencies:
'@tailwindcss/cli':
specifier: ^4.1.12
version: 4.1.12
'@tailwindcss/typography':
specifier: ^0.5.15
version: 0.5.16(tailwindcss@4.1.12)
tailwindcss:
specifier: ^4.1.12
version: 4.1.12
packages:
'@isaacs/fs-minipass@4.0.1':
resolution: {integrity: sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==}
engines: {node: '>=18.0.0'}
'@jridgewell/gen-mapping@0.3.13':
resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==}
'@jridgewell/remapping@2.3.5':
resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==}
'@jridgewell/resolve-uri@3.1.2':
resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==}
engines: {node: '>=6.0.0'}
'@jridgewell/sourcemap-codec@1.5.5':
resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==}
'@jridgewell/trace-mapping@0.3.30':
resolution: {integrity: sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q==}
'@parcel/watcher-android-arm64@2.5.1':
resolution: {integrity: sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==}
engines: {node: '>= 10.0.0'}
cpu: [arm64]
os: [android]
'@parcel/watcher-darwin-arm64@2.5.1':
resolution: {integrity: sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw==}
engines: {node: '>= 10.0.0'}
cpu: [arm64]
os: [darwin]
'@parcel/watcher-darwin-x64@2.5.1':
resolution: {integrity: sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg==}
engines: {node: '>= 10.0.0'}
cpu: [x64]
os: [darwin]
'@parcel/watcher-freebsd-x64@2.5.1':
resolution: {integrity: sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ==}
engines: {node: '>= 10.0.0'}
cpu: [x64]
os: [freebsd]
'@parcel/watcher-linux-arm-glibc@2.5.1':
resolution: {integrity: sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA==}
engines: {node: '>= 10.0.0'}
cpu: [arm]
os: [linux]
'@parcel/watcher-linux-arm-musl@2.5.1':
resolution: {integrity: sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==}
engines: {node: '>= 10.0.0'}
cpu: [arm]
os: [linux]
'@parcel/watcher-linux-arm64-glibc@2.5.1':
resolution: {integrity: sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==}
engines: {node: '>= 10.0.0'}
cpu: [arm64]
os: [linux]
'@parcel/watcher-linux-arm64-musl@2.5.1':
resolution: {integrity: sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==}
engines: {node: '>= 10.0.0'}
cpu: [arm64]
os: [linux]
'@parcel/watcher-linux-x64-glibc@2.5.1':
resolution: {integrity: sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==}
engines: {node: '>= 10.0.0'}
cpu: [x64]
os: [linux]
'@parcel/watcher-linux-x64-musl@2.5.1':
resolution: {integrity: sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==}
engines: {node: '>= 10.0.0'}
cpu: [x64]
os: [linux]
'@parcel/watcher-win32-arm64@2.5.1':
resolution: {integrity: sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==}
engines: {node: '>= 10.0.0'}
cpu: [arm64]
os: [win32]
'@parcel/watcher-win32-ia32@2.5.1':
resolution: {integrity: sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ==}
engines: {node: '>= 10.0.0'}
cpu: [ia32]
os: [win32]
'@parcel/watcher-win32-x64@2.5.1':
resolution: {integrity: sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA==}
engines: {node: '>= 10.0.0'}
cpu: [x64]
os: [win32]
'@parcel/watcher@2.5.1':
resolution: {integrity: sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==}
engines: {node: '>= 10.0.0'}
'@tailwindcss/cli@4.1.12':
resolution: {integrity: sha512-2PyJ5MGh/6JPS+cEaAq6MGDx3UemkX/mJt+/phm7/VOpycpecwNnHuFZbbgx6TNK/aIjvFOhhTVlappM7tmqvQ==}
hasBin: true
'@tailwindcss/node@4.1.12':
resolution: {integrity: sha512-3hm9brwvQkZFe++SBt+oLjo4OLDtkvlE8q2WalaD/7QWaeM7KEJbAiY/LJZUaCs7Xa8aUu4xy3uoyX4q54UVdQ==}
'@tailwindcss/oxide-android-arm64@4.1.12':
resolution: {integrity: sha512-oNY5pq+1gc4T6QVTsZKwZaGpBb2N1H1fsc1GD4o7yinFySqIuRZ2E4NvGasWc6PhYJwGK2+5YT1f9Tp80zUQZQ==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [android]
'@tailwindcss/oxide-darwin-arm64@4.1.12':
resolution: {integrity: sha512-cq1qmq2HEtDV9HvZlTtrj671mCdGB93bVY6J29mwCyaMYCP/JaUBXxrQQQm7Qn33AXXASPUb2HFZlWiiHWFytw==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [darwin]
'@tailwindcss/oxide-darwin-x64@4.1.12':
resolution: {integrity: sha512-6UCsIeFUcBfpangqlXay9Ffty9XhFH1QuUFn0WV83W8lGdX8cD5/+2ONLluALJD5+yJ7k8mVtwy3zMZmzEfbLg==}
engines: {node: '>= 10'}
cpu: [x64]
os: [darwin]
'@tailwindcss/oxide-freebsd-x64@4.1.12':
resolution: {integrity: sha512-JOH/f7j6+nYXIrHobRYCtoArJdMJh5zy5lr0FV0Qu47MID/vqJAY3r/OElPzx1C/wdT1uS7cPq+xdYYelny1ww==}
engines: {node: '>= 10'}
cpu: [x64]
os: [freebsd]
'@tailwindcss/oxide-linux-arm-gnueabihf@4.1.12':
resolution: {integrity: sha512-v4Ghvi9AU1SYgGr3/j38PD8PEe6bRfTnNSUE3YCMIRrrNigCFtHZ2TCm8142X8fcSqHBZBceDx+JlFJEfNg5zQ==}
engines: {node: '>= 10'}
cpu: [arm]
os: [linux]
'@tailwindcss/oxide-linux-arm64-gnu@4.1.12':
resolution: {integrity: sha512-YP5s1LmetL9UsvVAKusHSyPlzSRqYyRB0f+Kl/xcYQSPLEw/BvGfxzbH+ihUciePDjiXwHh+p+qbSP3SlJw+6g==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
'@tailwindcss/oxide-linux-arm64-musl@4.1.12':
resolution: {integrity: sha512-V8pAM3s8gsrXcCv6kCHSuwyb/gPsd863iT+v1PGXC4fSL/OJqsKhfK//v8P+w9ThKIoqNbEnsZqNy+WDnwQqCA==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
'@tailwindcss/oxide-linux-x64-gnu@4.1.12':
resolution: {integrity: sha512-xYfqYLjvm2UQ3TZggTGrwxjYaLB62b1Wiysw/YE3Yqbh86sOMoTn0feF98PonP7LtjsWOWcXEbGqDL7zv0uW8Q==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
'@tailwindcss/oxide-linux-x64-musl@4.1.12':
resolution: {integrity: sha512-ha0pHPamN+fWZY7GCzz5rKunlv9L5R8kdh+YNvP5awe3LtuXb5nRi/H27GeL2U+TdhDOptU7T6Is7mdwh5Ar3A==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
'@tailwindcss/oxide-wasm32-wasi@4.1.12':
resolution: {integrity: sha512-4tSyu3dW+ktzdEpuk6g49KdEangu3eCYoqPhWNsZgUhyegEda3M9rG0/j1GV/JjVVsj+lG7jWAyrTlLzd/WEBg==}
engines: {node: '>=14.0.0'}
cpu: [wasm32]
bundledDependencies:
- '@napi-rs/wasm-runtime'
- '@emnapi/core'
- '@emnapi/runtime'
- '@tybys/wasm-util'
- '@emnapi/wasi-threads'
- tslib
'@tailwindcss/oxide-win32-arm64-msvc@4.1.12':
resolution: {integrity: sha512-iGLyD/cVP724+FGtMWslhcFyg4xyYyM+5F4hGvKA7eifPkXHRAUDFaimu53fpNg9X8dfP75pXx/zFt/jlNF+lg==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [win32]
'@tailwindcss/oxide-win32-x64-msvc@4.1.12':
resolution: {integrity: sha512-NKIh5rzw6CpEodv/++r0hGLlfgT/gFN+5WNdZtvh6wpU2BpGNgdjvj6H2oFc8nCM839QM1YOhjpgbAONUb4IxA==}
engines: {node: '>= 10'}
cpu: [x64]
os: [win32]
'@tailwindcss/oxide@4.1.12':
resolution: {integrity: sha512-gM5EoKHW/ukmlEtphNwaGx45fGoEmP10v51t9unv55voWh6WrOL19hfuIdo2FjxIaZzw776/BUQg7Pck++cIVw==}
engines: {node: '>= 10'}
'@tailwindcss/typography@0.5.16':
resolution: {integrity: sha512-0wDLwCVF5V3x3b1SGXPCDcdsbDHMBe+lkFzBRaHeLvNi+nrrnZ1lA18u+OTWO8iSWU2GxUOCvlXtDuqftc1oiA==}
peerDependencies:
tailwindcss: '>=3.0.0 || insiders || >=4.0.0-alpha.20 || >=4.0.0-beta.1'
braces@3.0.3:
resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==}
engines: {node: '>=8'}
chownr@3.0.0:
resolution: {integrity: sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==}
engines: {node: '>=18'}
cssesc@3.0.0:
resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==}
engines: {node: '>=4'}
hasBin: true
detect-libc@1.0.3:
resolution: {integrity: sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==}
engines: {node: '>=0.10'}
hasBin: true
detect-libc@2.0.4:
resolution: {integrity: sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==}
engines: {node: '>=8'}
enhanced-resolve@5.18.3:
resolution: {integrity: sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==}
engines: {node: '>=10.13.0'}
fill-range@7.1.1:
resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
engines: {node: '>=8'}
graceful-fs@4.2.11:
resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
is-extglob@2.1.1:
resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
engines: {node: '>=0.10.0'}
is-glob@4.0.3:
resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
engines: {node: '>=0.10.0'}
is-number@7.0.0:
resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
engines: {node: '>=0.12.0'}
jiti@2.5.1:
resolution: {integrity: sha512-twQoecYPiVA5K/h6SxtORw/Bs3ar+mLUtoPSc7iMXzQzK8d7eJ/R09wmTwAjiamETn1cXYPGfNnu7DMoHgu12w==}
hasBin: true
lightningcss-darwin-arm64@1.30.1:
resolution: {integrity: sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ==}
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [darwin]
lightningcss-darwin-x64@1.30.1:
resolution: {integrity: sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [darwin]
lightningcss-freebsd-x64@1.30.1:
resolution: {integrity: sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [freebsd]
lightningcss-linux-arm-gnueabihf@1.30.1:
resolution: {integrity: sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q==}
engines: {node: '>= 12.0.0'}
cpu: [arm]
os: [linux]
lightningcss-linux-arm64-gnu@1.30.1:
resolution: {integrity: sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw==}
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [linux]
lightningcss-linux-arm64-musl@1.30.1:
resolution: {integrity: sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ==}
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [linux]
lightningcss-linux-x64-gnu@1.30.1:
resolution: {integrity: sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [linux]
lightningcss-linux-x64-musl@1.30.1:
resolution: {integrity: sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [linux]
lightningcss-win32-arm64-msvc@1.30.1:
resolution: {integrity: sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA==}
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [win32]
lightningcss-win32-x64-msvc@1.30.1:
resolution: {integrity: sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [win32]
lightningcss@1.30.1:
resolution: {integrity: sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==}
engines: {node: '>= 12.0.0'}
lodash.castarray@4.4.0:
resolution: {integrity: sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q==}
lodash.isplainobject@4.0.6:
resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==}
lodash.merge@4.6.2:
resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
magic-string@0.30.17:
resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==}
micromatch@4.0.8:
resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==}
engines: {node: '>=8.6'}
minipass@7.1.2:
resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==}
engines: {node: '>=16 || 14 >=14.17'}
minizlib@3.0.2:
resolution: {integrity: sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA==}
engines: {node: '>= 18'}
mkdirp@3.0.1:
resolution: {integrity: sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==}
engines: {node: '>=10'}
hasBin: true
mri@1.2.0:
resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==}
engines: {node: '>=4'}
node-addon-api@7.1.1:
resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==}
picocolors@1.1.1:
resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
picomatch@2.3.1:
resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
engines: {node: '>=8.6'}
postcss-selector-parser@6.0.10:
resolution: {integrity: sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==}
engines: {node: '>=4'}
source-map-js@1.2.1:
resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
engines: {node: '>=0.10.0'}
tailwindcss@4.1.12:
resolution: {integrity: sha512-DzFtxOi+7NsFf7DBtI3BJsynR+0Yp6etH+nRPTbpWnS2pZBaSksv/JGctNwSWzbFjp0vxSqknaUylseZqMDGrA==}
tapable@2.2.2:
resolution: {integrity: sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg==}
engines: {node: '>=6'}
tar@7.4.3:
resolution: {integrity: sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==}
engines: {node: '>=18'}
to-regex-range@5.0.1:
resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
engines: {node: '>=8.0'}
util-deprecate@1.0.2:
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
yallist@5.0.0:
resolution: {integrity: sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==}
engines: {node: '>=18'}
snapshots:
'@isaacs/fs-minipass@4.0.1':
dependencies:
minipass: 7.1.2
'@jridgewell/gen-mapping@0.3.13':
dependencies:
'@jridgewell/sourcemap-codec': 1.5.5
'@jridgewell/trace-mapping': 0.3.30
'@jridgewell/remapping@2.3.5':
dependencies:
'@jridgewell/gen-mapping': 0.3.13
'@jridgewell/trace-mapping': 0.3.30
'@jridgewell/resolve-uri@3.1.2': {}
'@jridgewell/sourcemap-codec@1.5.5': {}
'@jridgewell/trace-mapping@0.3.30':
dependencies:
'@jridgewell/resolve-uri': 3.1.2
'@jridgewell/sourcemap-codec': 1.5.5
'@parcel/watcher-android-arm64@2.5.1':
optional: true
'@parcel/watcher-darwin-arm64@2.5.1':
optional: true
'@parcel/watcher-darwin-x64@2.5.1':
optional: true
'@parcel/watcher-freebsd-x64@2.5.1':
optional: true
'@parcel/watcher-linux-arm-glibc@2.5.1':
optional: true
'@parcel/watcher-linux-arm-musl@2.5.1':
optional: true
'@parcel/watcher-linux-arm64-glibc@2.5.1':
optional: true
'@parcel/watcher-linux-arm64-musl@2.5.1':
optional: true
'@parcel/watcher-linux-x64-glibc@2.5.1':
optional: true
'@parcel/watcher-linux-x64-musl@2.5.1':
optional: true
'@parcel/watcher-win32-arm64@2.5.1':
optional: true
'@parcel/watcher-win32-ia32@2.5.1':
optional: true
'@parcel/watcher-win32-x64@2.5.1':
optional: true
'@parcel/watcher@2.5.1':
dependencies:
detect-libc: 1.0.3
is-glob: 4.0.3
micromatch: 4.0.8
node-addon-api: 7.1.1
optionalDependencies:
'@parcel/watcher-android-arm64': 2.5.1
'@parcel/watcher-darwin-arm64': 2.5.1
'@parcel/watcher-darwin-x64': 2.5.1
'@parcel/watcher-freebsd-x64': 2.5.1
'@parcel/watcher-linux-arm-glibc': 2.5.1
'@parcel/watcher-linux-arm-musl': 2.5.1
'@parcel/watcher-linux-arm64-glibc': 2.5.1
'@parcel/watcher-linux-arm64-musl': 2.5.1
'@parcel/watcher-linux-x64-glibc': 2.5.1
'@parcel/watcher-linux-x64-musl': 2.5.1
'@parcel/watcher-win32-arm64': 2.5.1
'@parcel/watcher-win32-ia32': 2.5.1
'@parcel/watcher-win32-x64': 2.5.1
'@tailwindcss/cli@4.1.12':
dependencies:
'@parcel/watcher': 2.5.1
'@tailwindcss/node': 4.1.12
'@tailwindcss/oxide': 4.1.12
enhanced-resolve: 5.18.3
mri: 1.2.0
picocolors: 1.1.1
tailwindcss: 4.1.12
'@tailwindcss/node@4.1.12':
dependencies:
'@jridgewell/remapping': 2.3.5
enhanced-resolve: 5.18.3
jiti: 2.5.1
lightningcss: 1.30.1
magic-string: 0.30.17
source-map-js: 1.2.1
tailwindcss: 4.1.12
'@tailwindcss/oxide-android-arm64@4.1.12':
optional: true
'@tailwindcss/oxide-darwin-arm64@4.1.12':
optional: true
'@tailwindcss/oxide-darwin-x64@4.1.12':
optional: true
'@tailwindcss/oxide-freebsd-x64@4.1.12':
optional: true
'@tailwindcss/oxide-linux-arm-gnueabihf@4.1.12':
optional: true
'@tailwindcss/oxide-linux-arm64-gnu@4.1.12':
optional: true
'@tailwindcss/oxide-linux-arm64-musl@4.1.12':
optional: true
'@tailwindcss/oxide-linux-x64-gnu@4.1.12':
optional: true
'@tailwindcss/oxide-linux-x64-musl@4.1.12':
optional: true
'@tailwindcss/oxide-wasm32-wasi@4.1.12':
optional: true
'@tailwindcss/oxide-win32-arm64-msvc@4.1.12':
optional: true
'@tailwindcss/oxide-win32-x64-msvc@4.1.12':
optional: true
'@tailwindcss/oxide@4.1.12':
dependencies:
detect-libc: 2.0.4
tar: 7.4.3
optionalDependencies:
'@tailwindcss/oxide-android-arm64': 4.1.12
'@tailwindcss/oxide-darwin-arm64': 4.1.12
'@tailwindcss/oxide-darwin-x64': 4.1.12
'@tailwindcss/oxide-freebsd-x64': 4.1.12
'@tailwindcss/oxide-linux-arm-gnueabihf': 4.1.12
'@tailwindcss/oxide-linux-arm64-gnu': 4.1.12
'@tailwindcss/oxide-linux-arm64-musl': 4.1.12
'@tailwindcss/oxide-linux-x64-gnu': 4.1.12
'@tailwindcss/oxide-linux-x64-musl': 4.1.12
'@tailwindcss/oxide-wasm32-wasi': 4.1.12
'@tailwindcss/oxide-win32-arm64-msvc': 4.1.12
'@tailwindcss/oxide-win32-x64-msvc': 4.1.12
'@tailwindcss/typography@0.5.16(tailwindcss@4.1.12)':
dependencies:
lodash.castarray: 4.4.0
lodash.isplainobject: 4.0.6
lodash.merge: 4.6.2
postcss-selector-parser: 6.0.10
tailwindcss: 4.1.12
braces@3.0.3:
dependencies:
fill-range: 7.1.1
chownr@3.0.0: {}
cssesc@3.0.0: {}
detect-libc@1.0.3: {}
detect-libc@2.0.4: {}
enhanced-resolve@5.18.3:
dependencies:
graceful-fs: 4.2.11
tapable: 2.2.2
fill-range@7.1.1:
dependencies:
to-regex-range: 5.0.1
graceful-fs@4.2.11: {}
is-extglob@2.1.1: {}
is-glob@4.0.3:
dependencies:
is-extglob: 2.1.1
is-number@7.0.0: {}
jiti@2.5.1: {}
lightningcss-darwin-arm64@1.30.1:
optional: true
lightningcss-darwin-x64@1.30.1:
optional: true
lightningcss-freebsd-x64@1.30.1:
optional: true
lightningcss-linux-arm-gnueabihf@1.30.1:
optional: true
lightningcss-linux-arm64-gnu@1.30.1:
optional: true
lightningcss-linux-arm64-musl@1.30.1:
optional: true
lightningcss-linux-x64-gnu@1.30.1:
optional: true
lightningcss-linux-x64-musl@1.30.1:
optional: true
lightningcss-win32-arm64-msvc@1.30.1:
optional: true
lightningcss-win32-x64-msvc@1.30.1:
optional: true
lightningcss@1.30.1:
dependencies:
detect-libc: 2.0.4
optionalDependencies:
lightningcss-darwin-arm64: 1.30.1
lightningcss-darwin-x64: 1.30.1
lightningcss-freebsd-x64: 1.30.1
lightningcss-linux-arm-gnueabihf: 1.30.1
lightningcss-linux-arm64-gnu: 1.30.1
lightningcss-linux-arm64-musl: 1.30.1
lightningcss-linux-x64-gnu: 1.30.1
lightningcss-linux-x64-musl: 1.30.1
lightningcss-win32-arm64-msvc: 1.30.1
lightningcss-win32-x64-msvc: 1.30.1
lodash.castarray@4.4.0: {}
lodash.isplainobject@4.0.6: {}
lodash.merge@4.6.2: {}
magic-string@0.30.17:
dependencies:
'@jridgewell/sourcemap-codec': 1.5.5
micromatch@4.0.8:
dependencies:
braces: 3.0.3
picomatch: 2.3.1
minipass@7.1.2: {}
minizlib@3.0.2:
dependencies:
minipass: 7.1.2
mkdirp@3.0.1: {}
mri@1.2.0: {}
node-addon-api@7.1.1: {}
picocolors@1.1.1: {}
picomatch@2.3.1: {}
postcss-selector-parser@6.0.10:
dependencies:
cssesc: 3.0.0
util-deprecate: 1.0.2
source-map-js@1.2.1: {}
tailwindcss@4.1.12: {}
tapable@2.2.2: {}
tar@7.4.3:
dependencies:
'@isaacs/fs-minipass': 4.0.1
chownr: 3.0.0
minipass: 7.1.2
minizlib: 3.0.2
mkdirp: 3.0.1
yallist: 5.0.0
to-regex-range@5.0.1:
dependencies:
is-number: 7.0.0
util-deprecate@1.0.2: {}
yallist@5.0.0: {}