+
@@ -79,22 +88,4 @@ switch (props.icon) {
.tilt {
transform: rotate(-2deg);
}
-
-.box {
- > p {
- margin-bottom: 0;
- }
-
- margin-bottom: 1rem;
- border-bottom: 1px ridge;
- border-right: 1px ridge;
- border-color: v-bind(color);
-}
-
-.icon {
- &-image {
- width: 48px;
- height: 48px;
- }
-}
diff --git a/components/content/CodeControls.vue b/components/content/CodeControls.vue
index 6729da7..cb9a84a 100644
--- a/components/content/CodeControls.vue
+++ b/components/content/CodeControls.vue
@@ -1,32 +1,35 @@
-
+
-
-
diff --git a/content/blog/the-windows-context-menu.md b/content/blog/the-windows-context-menu.md
index f96ebb8..6e71b26 100644
--- a/content/blog/the-windows-context-menu.md
+++ b/content/blog/the-windows-context-menu.md
@@ -48,7 +48,7 @@ and you are as much of a perfectionist as I am, buckle up and prepare for severa
::card
---
-icon: warning
+type: warning
title: Before we begin
---
Invoking `sfc /scannow` or `dism /restorehealth` will likely interfere with your context menu,
@@ -141,7 +141,7 @@ Children of the `Shell` subkey are the «shell entries» — locally provided cu
::card
---
-icon: info
+type: info
title: Clearing up the confusion
---
The terminology may be a little confusing, since Microsoft hasn't ever offered a standard nomenclature for the
@@ -195,7 +195,7 @@ with an exception to the following two macros:
::card
---
-icon: error
+type: error
title: Inconsistency
---
Keep in mind that the `%1` macro is the Batch version of `argv[1]` — the first item in the C argument vector.
@@ -316,7 +316,7 @@ shell entry **do not seem to correspond**.
::card
---
-icon: idea
+type: idea
title: Tip
---
You can use the Explorer folder icon picker to acquire the icon DLL and visually calculate the offset
@@ -669,7 +669,7 @@ The following are fairly common areas Winaero Tweaker doesn't cover.
::card
---
-icon: idea
+type: idea
title: Tip
---
As a rule of thumb, whenever you're dealing with existing shell entries, I _really_ suggest
diff --git a/layouts/Card.vue b/layouts/Card.vue
index 5adf46a..d79590b 100644
--- a/layouts/Card.vue
+++ b/layouts/Card.vue
@@ -53,17 +53,18 @@ onMounted(() => {
class="dimensions accent-background transition-ease overflow-auto flex flex-col gap-4 lm:gap-0 sm:gap-2 py-2 px-6 sm:p-4"
:class="{
'animate__animated-sm animate__delay-1-5s animate__fadeInDown':
- !animationComplete,
+ !reader && !animationComplete,
+ 'animate__animated-sm animate__fadeIn': reader && !animationComplete,
'lm:rounded-none sm:rounded-xl sm:mt-8 lm:mt-0 lt:mt-0': !reader,
'!max-h-full h-full': reader,
}"
>
-
+
-
+
diff --git a/middleware/reader.global.ts b/middleware/reader.global.ts
index 439d8bc..4f2eddb 100644
--- a/middleware/reader.global.ts
+++ b/middleware/reader.global.ts
@@ -1,4 +1,4 @@
-export default defineNuxtRouteMiddleware((to, _from) => {
+export default defineNuxtRouteMiddleware((to, from) => {
const { reader } = storeToRefs(usePageStore())
reader.value = /\/blog\/(.*)/.test(to.path)
diff --git a/nuxt.config.ts b/nuxt.config.ts
index 37085ff..112aa3f 100644
--- a/nuxt.config.ts
+++ b/nuxt.config.ts
@@ -1,35 +1,35 @@
-import config from "./config";
+import config from './config'
// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
app: {
head: {
htmlAttrs: {
- lang: config.locale || "en",
+ lang: config.locale || 'en',
},
link: [
{
- rel: "icon",
- type: "image/x-icon",
- href: "/favicon.ico",
+ rel: 'icon',
+ type: 'image/x-icon',
+ href: '/favicon.ico',
},
],
meta: [
{
- charset: "utf-8",
+ charset: 'utf-8',
},
{
- name: "viewport",
- content: "width=device-width, initial-scale=1",
+ name: 'viewport',
+ content: 'width=device-width, initial-scale=1',
},
{
- "http-equiv": "X-UA-Compatible",
- content: "ie=edge",
+ 'http-equiv': 'X-UA-Compatible',
+ content: 'ie=edge',
},
],
},
- pageTransition: { name: "page", mode: "out-in" },
- rootId: "ender-app",
+ pageTransition: { name: 'page', mode: 'out-in' },
+ rootId: 'ender-app',
},
devtools: {
enabled: true,
@@ -43,64 +43,68 @@ export default defineNuxtConfig({
components: {
dirs: [
{
- path: "~/components",
+ path: '~/components',
pathPrefix: false,
- extensions: [".vue"],
+ extensions: ['.vue'],
},
],
},
- css: ["~/assets/styles/main.scss"],
+ css: ['~/assets/styles/main.scss'],
plugins: [],
modules: [
- "@pinia/nuxt",
- "@nuxt/content",
- "@nuxtjs/seo",
- "@nuxtjs/google-fonts",
- "@nuxtjs/tailwindcss",
- "@nuxtjs/color-mode",
- "@nuxt/eslint",
- ["@nuxtjs/stylelint-module", { failOnError: true, lintOnStart: false }],
+ '@pinia/nuxt',
+ '@nuxt/content',
+ '@nuxtjs/seo',
+ '@nuxtjs/google-fonts',
+ '@nuxtjs/tailwindcss',
+ '@nuxtjs/color-mode',
+ '@nuxt/eslint',
+ ['@nuxtjs/stylelint-module', { failOnError: true, lintOnStart: false }],
],
colorMode: {
- preference: "system",
- fallback: "dark",
- classPrefix: "",
- classSuffix: "",
- componentName: "NuxtTheme",
- storageKey: "ecmatheme",
+ preference: 'system',
+ fallback: 'dark',
+ classPrefix: '',
+ classSuffix: '',
+ componentName: 'NuxtTheme',
+ storageKey: 'ecmatheme',
},
content: {
markdown: {
- remarkPlugins: ["remark-reading-time"],
+ remarkPlugins: ['remark-reading-time'],
},
highlight: {
- theme: "github-dark",
+ theme: {
+ default: 'github-dark',
+ light: 'github-light',
+ sepia: 'monokai',
+ },
langs: [
- "shell",
- "batch",
- "vb",
- "ini",
- "asm",
- "c",
- "cpp",
- "java",
- "python",
- "csv",
- "xml",
- "json",
- "yaml",
- "html",
- "css",
- "sass",
- "php",
- "js",
- "ts",
- "vue",
- "md",
- "mdc",
- "pascal",
- "lisp",
- "sql",
+ 'shell',
+ 'batch',
+ 'vb',
+ 'ini',
+ 'asm',
+ 'c',
+ 'cpp',
+ 'java',
+ 'python',
+ 'csv',
+ 'xml',
+ 'json',
+ 'yaml',
+ 'html',
+ 'css',
+ 'sass',
+ 'php',
+ 'js',
+ 'ts',
+ 'vue',
+ 'md',
+ 'mdc',
+ 'pascal',
+ 'lisp',
+ 'sql',
],
},
},
@@ -109,7 +113,7 @@ export default defineNuxtConfig({
crawlLinks: true,
autoSubfolderIndex: true,
failOnError: true,
- routes: ["/robots.txt", "/sitemap.xml"],
+ routes: ['/robots.txt', '/sitemap.xml'],
},
},
googleFonts: {
@@ -160,22 +164,22 @@ export default defineNuxtConfig({
// },
// },
sitemap: {
- sources: ["/api/__sitemap__/content"],
+ sources: ['/api/__sitemap__/content'],
cacheMaxAgeSeconds: 360,
exclude: [],
credits: false,
xslColumns: [
- { label: "URL", width: "50%" },
- { label: "Last Modified", select: "sitemap:lastmod", width: "25%" },
- { label: "Priority", select: "sitemap:priority", width: "12.5%" },
+ { label: 'URL', width: '50%' },
+ { label: 'Last Modified', select: 'sitemap:lastmod', width: '25%' },
+ { label: 'Priority', select: 'sitemap:priority', width: '12.5%' },
{
- label: "Change Frequency",
- select: "sitemap:changefreq",
- width: "12.5%",
+ label: 'Change Frequency',
+ select: 'sitemap:changefreq',
+ width: '12.5%',
},
],
defaults: {
- changefreq: "yearly",
+ changefreq: 'yearly',
priority: 0.7,
lastmod: config.build.date,
},
@@ -194,7 +198,7 @@ export default defineNuxtConfig({
},
vue: {
compilerOptions: {
- isCustomElement: (tag) => tag === "iconify-icon",
+ isCustomElement: (tag) => tag === 'iconify-icon',
},
},
-});
+})
diff --git a/pages/blog/[slug].vue b/pages/blog/[slug].vue
index 0a4cf1b..5c2cca9 100644
--- a/pages/blog/[slug].vue
+++ b/pages/blog/[slug].vue
@@ -5,6 +5,7 @@ import { render } from 'vue'
import { CodeControls } from '#components'
const config = useAppConfig()
+const router = useRouter()
const route = useRoute()
let slug = route.params.slug
@@ -40,14 +41,12 @@ useSeoMeta({
const clipboard = (el: HTMLElement) => {
if (el.textContent)
- navigator.clipboard
- .writeText(el.textContent)
- .then(() => {
- alert(`successfully copied ${el.textContent}`)
- })
- .catch(() => {
- alert('something went wrong')
- })
+ navigator.clipboard.writeText(el.textContent).catch(() => {
+ console.error(
+ 'Failed to copy element data to the clipboard! Element data:',
+ el,
+ )
+ })
}
const content = ref
(null)
@@ -73,6 +72,11 @@ defineOgImageComponent(
// Hydrate the rendered items.
onMounted(() => {
+ if (route.hash)
+ content.value
+ ?.querySelector(route.hash.toLowerCase())
+ ?.scrollIntoView({ behavior: 'smooth' })
+
content.value
?.querySelectorAll('code:not(pre *)')
.forEach((code: Element) => {
@@ -80,10 +84,27 @@ onMounted(() => {
code.addEventListener('click', () => clipboard(code))
})
- content.value?.querySelectorAll('pre').forEach((pre: HTMLElement) => {
- const icon = h(CodeControls)
+ content.value?.querySelectorAll('pre').forEach((pre: HTMLPreElement) => {
+ const overlay = h(CodeControls, { onCopy: () => clipboard(pre) })
- render(icon, pre)
+ render(overlay, pre)
+ })
+
+ content.value?.querySelectorAll('a').forEach((a: HTMLAnchorElement) => {
+ if (
+ a.hash &&
+ a.host === window.location.host &&
+ a.pathname.toLowerCase() === route.path.toLowerCase()
+ )
+ a.addEventListener('click', (e: Event) => {
+ e.preventDefault()
+
+ content.value
+ ?.querySelector(a.hash.toLowerCase())
+ ?.scrollIntoView({ behavior: 'smooth' })
+
+ history.replaceState(history.state, '', a.hash)
+ })
})
})
@@ -117,7 +138,7 @@ useHead({