astro-tips
Version:
🎨 Beautiful, customizable tip and notice blocks for Astro - 16 built-in styles with auto dark mode support and built-in compression
141 lines • 5.58 kB
JavaScript
import remarkDirective from "remark-directive";
import { fileURLToPath } from "url";
import { readFileSync, writeFileSync, readdirSync, statSync } from "fs";
import { join } from "path";
import { defaultConfig } from "./src/config.js";
import { remarkTips } from "./src/remark-plugin.js";
function generateThemeCSS() {
const variants = Object.keys(defaultConfig);
const darkThemeCSS = variants
.map((variant) => {
const config = defaultConfig[variant];
const style = config.style || {};
const darkBg = style.dark?.background || "#333";
const borderColor = style.border || "#000";
return `
@media (prefers-color-scheme: dark) {
[data-type="${variant}"] {
background-color: ${darkBg} !important;
border-color: ${borderColor} !important;
}
[data-type="${variant}"] .astro-tips-icon {
color: ${borderColor} !important;
}
}
html.dark [data-type="${variant}"],
html[class~="dark"] [data-type="${variant}"],
.dark [data-type="${variant}"] {
background-color: ${darkBg} !important;
border-color: ${borderColor} !important;
}
html.dark [data-type="${variant}"] .astro-tips-icon,
html[class~="dark"] [data-type="${variant}"] .astro-tips-icon,
.dark [data-type="${variant}"] .astro-tips-icon {
color: ${borderColor} !important;
}`;
})
.join("\n");
const hoverCSS = `
/* 灵动 hover 效果 */
[data-type] {
cursor: pointer;
}
[data-type]:hover {
transform: translateY(-3px);
box-shadow: 0 6px 16px rgba(0, 0, 0, 0.2);
}
[data-type]:hover .astro-tips-icon {
transform: scale(1.25) rotate(8deg);
filter: brightness(1.2);
}`;
return darkThemeCSS + "\n" + hoverCSS;
}
function astroTips(options = {}) {
return {
name: "astro-tips",
hooks: {
"astro:config:setup": ({ updateConfig }) => {
try {
const { minifyCSS = true, minifyJS = true, ...tipTypes } = options;
const finalTipsConfig = { ...defaultConfig };
Object.keys(tipTypes).forEach((typeName) => {
const config = tipTypes[typeName];
if (config &&
typeof config === "object" &&
!Array.isArray(config)) {
finalTipsConfig[typeName] = config;
}
});
try {
const themeCSS = generateThemeCSS();
const styleInjectionScript = `
if (typeof document !== 'undefined' && !document.querySelector('[data-astro-tips="theme"]')) {
const style = document.createElement('style');
style.setAttribute('data-astro-tips', 'theme');
style.textContent = ${JSON.stringify(themeCSS)};
document.head.appendChild(style);
}`;
updateConfig({
markdown: {
remarkPlugins: [remarkDirective, [remarkTips, finalTipsConfig]],
},
vite: {
build: {
cssMinify: minifyCSS,
minify: minifyJS,
},
},
});
updateConfig({
integrations: [
{
name: "astro-tips-style-injector",
hooks: {
"astro:config:setup": ({ injectScript }) => {
injectScript("page", styleInjectionScript);
},
},
},
],
});
}
catch {
}
}
catch {
}
},
"astro:build:generated": ({ dir }) => {
try {
const themeCSS = generateThemeCSS();
const styleTag = `<style data-astro-tips="theme">${themeCSS}</style>`;
const buildDir = fileURLToPath(dir);
function processDirectory(directory) {
const files = readdirSync(directory);
for (const file of files) {
const filePath = join(directory, file);
const stat = statSync(filePath);
if (stat.isDirectory()) {
processDirectory(filePath);
}
else if (file.endsWith(".html")) {
let content = readFileSync(filePath, "utf-8");
if (!content.includes('data-astro-tips="theme"')) {
const newContent = content.replace("</head>", `${styleTag}</head>`);
if (newContent !== content) {
writeFileSync(filePath, newContent);
}
}
}
}
}
processDirectory(buildDir);
}
catch {
}
},
},
};
}
export default astroTips;
//# sourceMappingURL=index.js.map