diff --git a/.gitignore b/.gitignore index 595cf718..251109d4 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,10 @@ dist/ .output/ +# satori-og +.fonts/ +**/open-graph/*.png + # dependencies node_modules/ diff --git a/astro.config.mjs b/astro.config.mjs index acccb993..fd429a46 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -18,6 +18,7 @@ import remarkCodeSet from '@lucjosin/remark-code-set'; import remarkImageCaption from '@lucjosin/remark-image-caption'; import remarkPostReference from '@lucjosin/remark-post-reference'; import remarkReadmeStats from '@lucjosin/remark-readme-stats'; +import remarkSlider from '@lucjosin/remark-slider'; import rehypeAutolinkHeadings from 'rehype-autolink-headings'; import rehypeExternalLinks from 'rehype-external-links'; import rehypeSlug from 'rehype-slug'; @@ -25,6 +26,7 @@ import remarkCollapse from 'remark-collapse'; import numberedFootnoteLabels from 'remark-numbered-footnote-labels'; import remarkToc from 'remark-toc'; +import { defaultLocale, explicitLocales, locales } from './src/i18n/config'; import HashRenamer from './src/lib/hash-renamer'; import getRedirects from './src/lib/redirects'; @@ -58,6 +60,18 @@ export default defineConfig({ output: 'static', // Specify a mapping of redirects where the key is the route to match and the value is the path to redirect to. redirects: getRedirects(), + // Configures i18n routing + i18n: { + defaultLocale: defaultLocale, + locales: locales, + }, + // Set the route matching behavior + trailingSlash: 'always', + // Build Options + build: { + // Control the output file format of each page. + format: 'directory', + }, // Astro integrations. // // Ref: https://docs.astro.build/en/guides/integrations-guide/ @@ -78,7 +92,12 @@ export default defineConfig({ except: exceptions, }, }), - sitemap(), + sitemap({ + i18n: { + defaultLocale: defaultLocale, + locales: explicitLocales, + }, + }), robotsTxt({ sitemap: true, }), @@ -153,14 +172,23 @@ export default defineConfig({ numberedFootnoteLabels, remarkAlertBlocks, remarkCodeHighlight, + remarkSlider, remarkImageCaption, responsiveTables, remarkCodeSet, - remarkToc, + [ + remarkToc, + { + heading: 'Summary|Sumário', + }, + ], [ remarkCollapse, { - test: 'Table of contents', + test: 'Summary|Sumário', + summary: (str) => { + return str === 'Summary' ? 'Show contents' : 'Mostrar conteúdos'; + }, }, ], ], @@ -174,7 +202,10 @@ export default defineConfig({ external: ['svgo', '@resvg/resvg-js'], }, // Fix 'resvg' on dev mode - optimizeDeps: { exclude: ['@resvg/resvg-js'] }, + optimizeDeps: { + exclude: ['@resvg/resvg-js'], + esbuildOptions: { target: 'esnext' }, + }, build: { rollupOptions: { external: ['@resvg/resvg-js'] } }, }, // Listen on all addresses, including LAN and public addresses. @@ -183,4 +214,13 @@ export default defineConfig({ server: { host: true, }, + // Astro offers experimental flags to give users early access to new features. + // These flags are not guaranteed to be stable. + experimental: { + // Enables a more reliable strategy to prevent scripts from being + // executed in pages where they are not used. + // + // https://docs.astro.build/en/reference/configuration-reference/#experimentaldirectrenderscript + directRenderScript: true, + }, }); diff --git a/package.json b/package.json index 2b915107..1c379717 100644 --- a/package.json +++ b/package.json @@ -1,14 +1,17 @@ { "name": "@lucjosin/lucasjosino.com", "packageManager": "yarn@3.6.4", - "version": "1.12.0", + "version": "1.13.0", "private": true, "scripts": { "dev": "astro dev", "start": "astro dev", "build": "astro build", "preview": "astro preview", - "astro": "astro" + "astro": "astro", + "sync": "astro sync", + "clean": "rm -rf ./dist", + "og:clean": "rm -rf ./public/static/open-graph/*.png" }, "devDependencies": { "@adapttive/remark-responsive-tables": "^1.0.1", @@ -19,30 +22,30 @@ "@lucjosin/remark-image-caption": "./plugins/remark-image-caption", "@lucjosin/remark-post-reference": "./plugins/remark-post-reference", "@lucjosin/remark-readme-stats": "./plugins/remark-readme-stats", + "@lucjosin/remark-slider": "./plugins/remark-slider", "@typescript-eslint/eslint-plugin": "^6.8.0", "@typescript-eslint/parser": "^6.8.0", - "astro": "^4.10.1", - "astro-compress": "^2.2.27", - "astro-expressive-code": "^0.35.3", - "astro-icon": "^1.1.0", + "astro": "^4.16.8", + "astro-compress": "^2.3.5", + "astro-expressive-code": "^0.38.1", + "astro-icon": "^1.1.1", "astro-rename": "^1.1.2", "astro-robots-txt": "^1.0.0", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-astro": "^0.31.4", - "javascript-time-ago": "^2.5.10", - "prettier": "^3.3.1", - "prettier-plugin-astro": "^0.14.0", + "prettier": "^3.3.3", + "prettier-plugin-astro": "^0.14.1", "rehype-autolink-headings": "^7.1.0", "rehype-external-links": "^3.0.0", "rehype-slug": "^6.0.0", "remark-collapse": "^0.1.2", "remark-numbered-footnote-labels": "^1.1.0", "remark-toc": "^9.0.0", - "satori": "^0.10.13", - "satori-html": "^0.3.2", + "satori": "^0.11.3", + "satori-og": "^1.0.0", "svgo": "2.8.0", - "typescript": "^5.4.5" + "typescript": "^5.6.3" }, "dependencies": { "@astrojs/react": "3.0.10", @@ -51,11 +54,12 @@ "@iconify-json/ic": "^1.1.17", "@iconify-json/mdi": "^1.1.64", "@iconify-json/simple-icons": "^1.1.93", + "@iconify-json/tabler": "^1.1.118", "@resvg/resvg-js": "^2.5.0", "@swup/astro": "^1.3.2", "@types/react": "^18.2.29", "@types/react-dom": "^18.2.14", - "astro-meta-tags": "^0.3.0", + "astro-meta-tags": "^0.3.1", "medium-zoom": "^1.1.0", "react": "^18.3.1", "react-dom": "^18.3.1", diff --git a/plugins/remark-code-highlight/src/index.js b/plugins/remark-code-highlight/src/index.js index ed1a14e7..9db56abd 100644 --- a/plugins/remark-code-highlight/src/index.js +++ b/plugins/remark-code-highlight/src/index.js @@ -1,25 +1,37 @@ import { visit } from 'unist-util-visit'; -const HIGHLIGHT_REGEX = '\\{(.*?)((?:#(.*))(?:-(.*)))?\\}'; +const INLINECODE_REGEX = + /(.+?)\[((?:[a-zA-Z0-9_-]+=["'][^"']*["'](?:\s+[a-zA-Z0-9_-]+=["'][^"']*["'])*)\]$)/; + +const ATTR_REGEX = /([a-zA-Z0-9_-]+)=["']([^"']*)["']/g; export default function remarkCodeHighlight() { return function transformer(tree) { visit(tree, 'inlineCode', (inlineCodeNode) => { - const match = inlineCodeNode.value.match(HIGHLIGHT_REGEX); + const match = inlineCodeNode.value.match(INLINECODE_REGEX); if (match) { - // BUG: Regex returns 5 matches, instead of 4 - const className = match[1]; - const bgColor = match[3]; - const textColor = match[4]; + const modifiers = {}; + const text = match[1]; + const attributes = match[2]; + + let attrMatch; + while ((attrMatch = ATTR_REGEX.exec(attributes)) !== null) { + modifiers[attrMatch[1]] = attrMatch[2]; + } - inlineCodeNode.value = inlineCodeNode.value.replace(match[0], ''); + let className = ''; + if (modifiers.class) { + className = modifiers.class; + delete modifiers.class; + } + inlineCodeNode.value = text; inlineCodeNode.data = { hProperties: { - style: [ - bgColor && `background-color: ${bgColor}; color: ${textColor}`, - ], + style: Object.entries(modifiers).map( + ([key, value]) => `${key}:${value};` + ), className: ['remark-text-highlight', className], }, }; diff --git a/plugins/remark-image-caption/src/index.js b/plugins/remark-image-caption/src/index.js index d2c42159..6aa64f6f 100644 --- a/plugins/remark-image-caption/src/index.js +++ b/plugins/remark-image-caption/src/index.js @@ -5,6 +5,7 @@ export default function remarkImageCaption() { visit(tree, 'image', (imageNode) => { const src = imageNode.url; const alt = imageNode.alt; + const title = imageNode.title || alt || ''; if (!src.match('\\.(jpeg|jpg|gif|png|webp|svg)$')) return; @@ -13,7 +14,7 @@ export default function remarkImageCaption() { newNode = { type: 'html', value: `
- ${alt} + ${alt}
${alt} - { + visit(tree, 'paragraph', (node) => { + if (node.children) { + // Check for a paragraph containing the slider structure + const children = node.children; + const hasSliderStart = children[0]?.value?.includes('[remark_slider'); + const hasSliderEnd = + children[children.length - 1]?.value?.includes('[/remark_slider]'); + + if (hasSliderStart && hasSliderEnd) { + // Extract options from the opening tag [remark_slider] + const optionsText = children[0].value + .match(/\[remark_slider(.*?)\]/)?.[1] + ?.trim(); + const options = parseOptions(optionsText); + + // Extract images and their descriptions from the middle nodes + const images = children + .filter( + (child, index) => + index > 0 && + index < children.length - 1 && + child.type === 'image' + ) + .map((imgNode) => ({ + src: imgNode.url, + alt: imgNode.alt, + title: imgNode.title || imgNode.alt || '', + })); + + // Replace the paragraph node content with a slider component + node.type = 'html'; + node.value = generateSliderComponent(images, options); + } + } + }); + }; +} + +// Helper to parse options from [remark_slider ...] +function parseOptions(optionsText) { + const options = optionsText.split(' '); + const parsedOptions = {}; + options.forEach((option) => { + const [key, value] = option.split('='); + parsedOptions[key] = value === 'true'; + }); + + return parsedOptions; +} + +// Generate HTML or JSX string for the slider component with arrows and index display +function generateSliderComponent(images, options) { + // Convert options into data attributes or props as needed + const optionAttributes = Object.entries(options) + .map(([key, value]) => `${key}="${value}"`) + .join(' '); + + const imageSlides = images + .map( + ( + image, + index + ) => `
+ ${image.alt} +
+ ${image.alt} - + + View image in a new tab + +
+
` + ) + .join(''); + + return ` +
+ +
+ ${imageSlides} +
+ + + ${ + options.showArrows + ? ` + + + ` + : '' + } + + + ${ + options.showImageIndex + ? ` +
+ 1 / ${images.length} +
+ ` + : '' + } +
+ + + + `; +} diff --git a/public/static/projects/hawapi/hawapi-1.png b/public/static/projects/hawapi/hawapi-1.png new file mode 100644 index 00000000..947235e0 Binary files /dev/null and b/public/static/projects/hawapi/hawapi-1.png differ diff --git a/public/static/projects/hawapi/hawapi-2.png b/public/static/projects/hawapi/hawapi-2.png new file mode 100644 index 00000000..556df801 Binary files /dev/null and b/public/static/projects/hawapi/hawapi-2.png differ diff --git a/public/static/projects/hawapi/hawapi-3.png b/public/static/projects/hawapi/hawapi-3.png new file mode 100644 index 00000000..f5c333fe Binary files /dev/null and b/public/static/projects/hawapi/hawapi-3.png differ diff --git a/public/static/projects/hawapi/hawapi-4.png b/public/static/projects/hawapi/hawapi-4.png new file mode 100644 index 00000000..55949b28 Binary files /dev/null and b/public/static/projects/hawapi/hawapi-4.png differ diff --git a/public/static/projects/hawbrary/hawbrary-1.png b/public/static/projects/hawbrary/hawbrary-1.png new file mode 100644 index 00000000..346f5041 Binary files /dev/null and b/public/static/projects/hawbrary/hawbrary-1.png differ diff --git a/public/static/projects/hawbrary/hawbrary-2.png b/public/static/projects/hawbrary/hawbrary-2.png new file mode 100644 index 00000000..100788f4 Binary files /dev/null and b/public/static/projects/hawbrary/hawbrary-2.png differ diff --git a/public/static/projects/hawbrary/hawbrary-3.png b/public/static/projects/hawbrary/hawbrary-3.png new file mode 100644 index 00000000..1ac7bdf6 Binary files /dev/null and b/public/static/projects/hawbrary/hawbrary-3.png differ diff --git a/public/static/projects/hawbrary/hawbrary.png b/public/static/projects/hawbrary/hawbrary.png new file mode 100644 index 00000000..746e049c Binary files /dev/null and b/public/static/projects/hawbrary/hawbrary.png differ diff --git a/src/components/core/Description.astro b/src/components/core/Description.astro index 136b7142..80bf2c98 100644 --- a/src/components/core/Description.astro +++ b/src/components/core/Description.astro @@ -6,6 +6,7 @@ interface Props { fontSize?: string; maxLine?: string; align?: boolean; + title?: string; } const { @@ -15,12 +16,13 @@ const { fontSize = '1em', maxLine, align = true, + title, } = Astro.props as Props; const textAlign = align ? 'center' : 'initial'; --- -

+

{value}

@@ -29,6 +31,7 @@ const textAlign = align ? 'center' : 'initial'; overflow: hidden; width: var(--width); display: -webkit-box; + line-clamp: var(--maxLine); -webkit-line-clamp: var(--maxLine); -webkit-box-orient: vertical; margin: var(--margin); diff --git a/src/components/core/I18nHead.astro b/src/components/core/I18nHead.astro new file mode 100644 index 00000000..2a735502 --- /dev/null +++ b/src/components/core/I18nHead.astro @@ -0,0 +1,31 @@ +--- +import { getAbsoluteLocaleUrl } from 'astro:i18n'; +import { extractLocaleAndSlug, useLocale } from 'i18n'; +import type { LocaleSlug } from 'i18n/types'; + +interface Props { + locales?: LocaleSlug[]; +} + +let { locales = [] } = Astro.props as Props; + +const { slug } = useLocale(Astro.url.pathname); + +// Verify if (normal) page has the same slug in another locale +if (locales === undefined || locales.length === 0) { + const pages = await Astro.glob('pages/**/*.astro'); + locales = pages + .map((page) => extractLocaleAndSlug(page!.url!)) + .filter((item) => slug === item.slug); +} +--- + +{ + locales.map(({ locale, slug }) => ( + + )) +} diff --git a/src/components/core/LanguageIcon.astro b/src/components/core/LanguageIcon.astro new file mode 100644 index 00000000..c5820487 --- /dev/null +++ b/src/components/core/LanguageIcon.astro @@ -0,0 +1,86 @@ +--- +import { useLocale } from 'i18n'; +import Tooltip from './Tooltip.astro'; + +const { locale, t, switchLocale } = useLocale(Astro.url.pathname); + +const nextLocale = locale === 'en' ? 'pt' : 'en'; +--- + + + + 🇺🇸 + 🇧🇷 + + + + + + diff --git a/src/components/core/Link/Link.astro b/src/components/core/Link/Link.astro index 804259b6..0351a811 100644 --- a/src/components/core/Link/Link.astro +++ b/src/components/core/Link/Link.astro @@ -15,6 +15,7 @@ interface Props { animatedIcon?: boolean; reverseAnimation?: boolean; event?: string; + accesskey?: string; } const { @@ -31,6 +32,7 @@ const { animatedIcon = false, reverseAnimation = false, event, + accesskey, } = Astro.props as Props; const attr = { 'data-umami-event': event }; @@ -52,6 +54,7 @@ const iconColor = animatedIcon ? 'var(--constrast-color)' : 'gray'; rel={isLocal ? undefined : 'noopener noreferrer'} target={isLocal ? undefined : '_blank'} class="link-data" + accesskey={accesskey} {...attr} > {icon && iconSide === 'left' && } diff --git a/src/components/core/Post/MiniPostCard.astro b/src/components/core/Post/MiniPostCard.astro deleted file mode 100644 index 8477a605..00000000 --- a/src/components/core/Post/MiniPostCard.astro +++ /dev/null @@ -1,91 +0,0 @@ ---- -import { getFormatedDate } from '@lib/date'; -import { getReadTime } from '@lib/time'; -import Description from '../Description.astro'; -import Title from '../Title.astro'; - -interface Props { - image: string; - href: string; - title: string; - description: string; - publishedAt: string; - body: string; - imageAlign?: string; -} - -const { - image, - href, - title, - description, - publishedAt, - body, - imageAlign = 'center', -} = Astro.props; ---- - - - {`Post -
- - {getFormatedDate(publishedAt)} - • - {getReadTime(body)} - - - <Description - value={description} - margin="0" - fontSize="0.8em" - align={false} - maxLine="3" - /> - </div> -</a> - -<style define:vars={{ imageAlign }}> - .blog-item { - height: 10rem; - width: 100%; - border: var(--border-size) solid var(--border-color); - border-radius: var(--border-radius); - display: flex; - padding: var(--card-padding); - box-sizing: border-box; - gap: 1rem; - transition: all var(--transition-duration); - } - - .blog-item:hover { - background-color: var(--secondary-color); - } - - .blog-item-info { - display: flex; - flex-direction: column; - gap: 0.4rem; - } - - .blog-item-image { - width: 12rem; - border-radius: var(--border-radius); - object-fit: cover; - object-position: var(--imageAlign); - } - - .blog-item-info-publish { - font-size: 0.8em; - } - - @media (max-width: 560px) { - .blog-item { - height: fit-content; - flex-direction: column; - } - - .blog-item-image { - width: 100%; - } - } -</style> diff --git a/src/components/core/Post/PostCard.astro b/src/components/core/Post/PostCard.astro index 3dc9e1fe..f597e364 100644 --- a/src/components/core/Post/PostCard.astro +++ b/src/components/core/Post/PostCard.astro @@ -1,6 +1,7 @@ --- import Tags from '@components/data/Tags.astro'; import { getReadTime } from '@lib/time'; +import { useLocale } from 'i18n'; import Description from '../Description.astro'; import Link from '../Link/Link.astro'; import PostDateTime from './PostDateTime.astro'; @@ -17,6 +18,8 @@ interface Props { maxTags?: number; } +const { locale, t, localizePath } = useLocale(Astro.url.pathname); + const { image, category, @@ -34,7 +37,7 @@ const { <div class="post-card-img-container"> { image && ( - <a href={`/blog/${href}`} title={`Read more about: ${title}`}> + <a href={href} title={t('post.card.read_post')}> <img src={image} alt={`Post - ${title}`} class="post-card-img" /> </a> ) @@ -46,18 +49,14 @@ const { <PostDateTime date={publishedAt} /> • <Link title={category} - alt="See all posts with this category" - href={`/blog/categories/${category}`} + alt={t('post.card.see_more_posts_from_this_category', { category })} + href={localizePath(`/blog/categories/${category}`)} /> • - <span>{getReadTime(body)}</span> + <span>{getReadTime(body, locale)}</span> </span> </div> <div class="post-card-header"> - <Link - href={`/blog/${href}`} - alt={`Read more about: ${title}`} - display="inline" - > + <Link href={href} alt={t('post.card.read_post')} display="inline"> <h3>{title}</h3> </Link> </div> @@ -65,15 +64,15 @@ const { value={description} margin="0" align={false} - fontSize="0.9em" maxLine="3" + title={description} /> <Tags values={tags.slice(0, maxTags)} target="tags" active /> <div class="post-card-read-more"> <Link - href={`/blog/${href}`} - alt="Read more about" - title="Read post" + href={href} + alt={t('post.card.read_post')} + title={t('post.card.read_post')} icon="mdi:arrow-right-thin" iconSide="right" hasBorderBottom={false} @@ -146,13 +145,6 @@ const { gap: 0.4rem; } - .post-card-read-more { - display: flex; - align-items: center; - position: absolute; - bottom: 0rem; - } - @media (max-width: 768px) { .post-card { flex-direction: column; @@ -171,9 +163,5 @@ const { .post-card-info { margin-top: 0; } - - .post-card-read-more { - position: initial; - } } </style> diff --git a/src/components/core/Post/PostDateTime.astro b/src/components/core/Post/PostDateTime.astro index 680bc44a..35908847 100644 --- a/src/components/core/Post/PostDateTime.astro +++ b/src/components/core/Post/PostDateTime.astro @@ -1,64 +1,15 @@ --- -import { getDateAgo, getFormatedDate } from '@lib/date'; +import { getFormatedDate } from '@lib/date'; +import type { Locale } from 'i18n/types'; interface Props { date: string; + locale?: Locale; } -const { date } = Astro.props; +const { date, locale } = Astro.props; --- <span class="post-date"> - {getFormatedDate(date)} + {getFormatedDate(date, false, locale)} </span> -<span class="post-time-ago"> - {getDateAgo(date)} -</span> - -<style> - .post-date, - .post-time-ago { - cursor: pointer; - user-select: none; - } - - .post-date:hover, - .post-time-ago:hover { - border-bottom: var(--border-size) solid var(--border-color); - } - - .post-time-ago { - display: none; - } - - .show { - display: block; - } - - .ride { - display: none; - } -</style> - -<script> - const postDateAgo = document.querySelectorAll( - '.post-time-ago' - ) as NodeListOf<HTMLSpanElement>; - const postDate = document.querySelectorAll( - '.post-date' - ) as NodeListOf<HTMLSpanElement>; - - for (let i = 0; i < postDateAgo.length; i++) { - postDate[i]?.addEventListener('click', () => { - postDateAgo[i].classList.toggle('show'); - postDate[i].classList.toggle('ride'); - }); - } - - for (let i = 0; i < postDateAgo.length; i++) { - postDateAgo[i]?.addEventListener('click', () => { - postDateAgo[i].classList.toggle('show'); - postDate[i].classList.toggle('ride'); - }); - } -</script> diff --git a/src/components/core/Post/PostShareBanner.astro b/src/components/core/Post/PostShareBanner.astro index 92b8c200..38b4561e 100644 --- a/src/components/core/Post/PostShareBanner.astro +++ b/src/components/core/Post/PostShareBanner.astro @@ -2,6 +2,7 @@ import PostShare from '@components/data/Post/PostShare.astro'; import headConfig from '@constants/head'; import { Icon } from 'astro-icon/components'; +import { useLocale } from 'i18n'; interface Props { link: string; @@ -11,44 +12,46 @@ interface Props { bluesky: string; } +const { t } = useLocale(Astro.url.pathname); + const { link, linkedin, twitter, reddit, bluesky } = Astro.props; --- <div class="post-extra-share"> <span class="post-extra-share-left"> <Icon name="mdi:cards-heart" width={18} /> - Enjoy this post? Feel free to share! + {t('post.share.title')} </span> <PostShare items={[ { href: linkedin, icon: 'simple-icons:linkedin', - alt: 'Share to Linkedin', + alt: t('post.share.linkedin_alt'), event: `Post Share (Footer) - Linkedin (${link})`, }, { href: twitter, icon: 'simple-icons:x', - alt: 'Share to X (Twitter)', + alt: t('post.share.twitter_alt'), event: `Post Share (Footer) - X (Twitter) (${link})`, }, { href: reddit, icon: 'simple-icons:reddit', - alt: 'Share to Reddit', + alt: t('post.share.reddit_alt'), event: `Post Share (Footer) - Reddit (${link})`, }, { href: bluesky, icon: 'simple-icons:bluesky', - alt: 'Share to Bluesky', + alt: t('post.share.bluesky_alt'), event: `Post Share (Footer) - Blueksy (${link})`, }, { href: headConfig.shortLink + link, icon: 'mdi:link', - alt: 'Copy link', + alt: t('post.share.copy_link_alt'), id: 'share', messageId: 'share-title', event: `Post Share (Footer) - Copy link (${link})`, diff --git a/src/components/core/Post/PostUpdatedAt.astro b/src/components/core/Post/PostUpdatedAt.astro index b375b31d..45e131a7 100644 --- a/src/components/core/Post/PostUpdatedAt.astro +++ b/src/components/core/Post/PostUpdatedAt.astro @@ -1,5 +1,6 @@ --- import { getFormatedDate } from '@lib/date'; +import { useLocale } from 'i18n'; import Link from '../Link/Link.astro'; interface Props { @@ -7,17 +8,19 @@ interface Props { updatedAt: string; } +const { locale, t } = useLocale(Astro.url.pathname); + const { id, updatedAt } = Astro.props; const GIT_REF = `https://github.com/LucJosin/lucasjosino.com/commits/main/src/content/blog/${id}`; --- <div class="post-updated-at"> <i class="post-updated-at-content"> - Last modified: + {t('post.last_updated')} <Link href={GIT_REF} - alt="See post history" - title={getFormatedDate(updatedAt, true)} + alt={t('post.see_post_history')} + title={getFormatedDate(updatedAt, true, locale)} isLocal={false} /> </i> diff --git a/src/components/core/Project/MiniProjectCard.astro b/src/components/core/Project/MiniProjectCard.astro index 060f3663..ef4edfff 100644 --- a/src/components/core/Project/MiniProjectCard.astro +++ b/src/components/core/Project/MiniProjectCard.astro @@ -1,51 +1,62 @@ --- +import { Icon } from 'astro-icon/components'; import Description from '../Description.astro'; import Divider from '../Divider.astro'; import Link from '../Link/Link.astro'; import Title from '../Title.astro'; interface Props { + slug: string; title: string; - image?: string; description: string; + icon: string; + codeLanguage: string; url?: string; git?: string; } -const { title, image, description, url, git } = Astro.props as Props; +const { slug, title, description, codeLanguage, url, git, icon } = + Astro.props as Props; --- <div class="mini-project-item"> - { - image && ( - <img src={image} alt={`Post - ${title}`} class="mini-project-img" /> - ) - } <div class="mini-item-header"> - <Title title={title} margin="0" /> - <div class="mini-item-links"> - { - git && ( - <Link - href={git} - icon="simple-icons:github" - alt={title + ' - Github'} - isLocal={false} - hasBorderBottom={false} - /> - ) - } - { - url && ( - <Link - href={url} - icon="mdi:external-link" - alt={title + ' - Demo'} - isLocal={false} - hasBorderBottom={false} - /> - ) - } + <div class="mini-item-wrapper"> + <Title title={title} margin="0" /> + <div class="mini-item-links"> + { + git && ( + <Link + href={git} + icon="simple-icons:github" + alt={title + ' - Github'} + isLocal={false} + hasBorderBottom={false} + /> + ) + } + { + url && ( + <Link + href={url} + icon="mdi:external-link" + alt={title + ' - Preview'} + isLocal={false} + hasBorderBottom={false} + /> + ) + } + <Link + href={`/projects/${slug}/`} + icon="mdi:plus" + alt={title + ' - See more'} + hasBorderBottom={false} + /> + </div> + </div> + <div class="mini-item-language"> + {codeLanguage} + <Icon name={icon} /> </div> </div> <Divider width="100%" margin="0 0" /> @@ -60,6 +71,8 @@ const { title, image, description, url, git } = Astro.props as Props; <style> .mini-project-item { + height: fit-content; + width: 100%; border: var(--border-size) solid var(--border-color); border-radius: var(--border-radius); box-sizing: border-box; @@ -70,17 +83,24 @@ const { title, image, description, url, git } = Astro.props as Props; gap: 0.5rem; } - .mini-project-img { - height: 50%; - width: 100%; - object-fit: cover; - border-radius: var(--border-radius); - } - .mini-item-header { display: flex; align-items: center; justify-content: space-between; + gap: 1rem; + } + + .mini-item-wrapper { + display: flex; + gap: 0.5rem; + align-items: center; + } + + .mini-item-language { + display: flex; + align-items: center; + gap: 0.5rem; + font-size: 0.8em; } .mini-item-links { diff --git a/src/components/core/Project/ProjectCard.astro b/src/components/core/Project/ProjectCard.astro index 5f5672a1..746711f6 100644 --- a/src/components/core/Project/ProjectCard.astro +++ b/src/components/core/Project/ProjectCard.astro @@ -1,101 +1,172 @@ --- import Tags from '@components/data/Tags.astro'; -import type { ProjectModel } from '@constants/projects'; import { Icon } from 'astro-icon/components'; +import type { CollectionEntry } from 'astro:content'; +import { getEntry } from 'astro:content'; +import { useLocale } from 'i18n'; import Description from '../Description.astro'; import Divider from '../Divider.astro'; import LinkBox from '../Link/LinkBox.astro'; import Title from '../Title.astro'; +import MiniProjectCard from './MiniProjectCard.astro'; +import ProjectCardSlider from './ProjectCardSlider.astro'; interface Props { - project: ProjectModel; + project: CollectionEntry<'projects'>; titleSize?: string; descSize?: string; } +const { t, localizePath } = useLocale(Astro.url.pathname); + const { project, titleSize, descSize } = Astro.props as Props; --- <div class="project-card"> - <div class="project-card-img-container"> - { - project.image && ( - <img - src={project.image} - class="project-card-img" - title={`${project.title}`} - /> - ) - } - </div> + <div class="project-card-wrapper"> + <div class="project-card-img-container"> + { + project.data.images && project.data.showImagesInSlider ? ( + <ProjectCardSlider + images={[project.data.thumbnail!, ...project.data.images]} + /> + ) : ( + <img + src={project.data.thumbnail} + loading="lazy" + class="project-card-img" + title={`${project.data.title}`} + /> + ) + } + </div> - <div class="project-card-container"> - <div class="project-card-header"> - <Title title={project.title} fontSize={titleSize} margin="0" /> - <div class="project-card-language"> - {project.language} - <Icon name={project.icon} /> + <div class="project-card-container"> + <div class="project-card-header"> + <div class="project-card-title"> + <Title title={project.data.title} fontSize={titleSize} margin="0" /> + <span + class="project-card-status" + title={t( + `project.project_status.${project.data.status}.description` + )}>{t(`project.project_status.${project.data.status}.title`)}</span + > + { + project.data.category === 'Org' && ( + <a + href={project.data.org} + class="project-card-org" + title={t('projects.org_alt')} + rel="noopener noreferrer" + target="_blank" + > + {t('projects.org')} + <Icon name="mdi:external-link" /> + </a> + ) + } + </div> + <div class="project-card-language"> + {project.data.codeLanguage} + <Icon name={project.data.icon} /> + </div> </div> - </div> - <Divider width="100%" margin="0 0" /> - <Description - value={project.description} - fontSize={descSize} - margin="0" - align={false} - maxLine="3" - /> - <div class="project-card-bottom"> - <Tags values={project.tags} target="tags" /> - <div class="project-card-links"> - { - project.git && ( - <LinkBox - href={project.git} - icon="simple-icons:github" - title="Github" - alt={`${project.title} - Github`} - isLocal={false} - padding="0.5rem" - /> - ) - } - { - project.url && ( - <LinkBox - href={project.url} - icon="mdi:open-in-new" - title="Demo" - alt={`${project.title} - Demo`} - isLocal={false} - padding="0.5rem" - /> - ) - } - { - project.article && ( - <LinkBox - href={project.article} - icon="ic:outline-article" - title="Read" - alt={`${project.title} - Blog post`} - isLocal={true} - padding="0.5rem" - /> - ) - } + <Divider width="100%" margin="0 0" /> + <Description + value={project.data.description} + title={project.data.description} + fontSize={descSize} + margin="0" + align={false} + maxLine="3" + /> + <div class="project-card-bottom"> + <Tags values={project.data.tags} target="tags" /> + <div class="project-card-links"> + { + project.data.git && ( + <LinkBox + href={project.data.git} + icon="simple-icons:github" + title="Github" + alt={`${project.data.title} - Github`} + isLocal={false} + padding="0.5rem" + /> + ) + } + { + project.data.url && ( + <LinkBox + href={project.data.url} + icon="mdi:open-in-new" + title="Preview" + alt={`${project.data.title} - Preview`} + isLocal={false} + padding="0.5rem" + /> + ) + } + { + project.data.article && ( + <LinkBox + href={project.data.article} + icon="ic:outline-article" + title="Read" + alt={`${project.data.title} - Blog post`} + isLocal={true} + padding="0.5rem" + /> + ) + } + <LinkBox + href={localizePath(`/projects/${project.data.permSlug}/`)} + icon="mdi:plus" + title={t('project.details')} + alt={`${project.data.title} - ${t('project.see_more_alt')}`} + isLocal={true} + padding="0.5rem" + /> + </div> </div> </div> </div> + + { + project.data.subProjects && ( + <div class="project-card-sub-projects-wrapper"> + <h3>{t('projects.repositories')}</h3> + <div class="project-card-sub-projects"> + {project.data.subProjects.map(async (sub) => { + const subProject = await getEntry(sub); + return ( + <MiniProjectCard + slug={subProject.data.permSlug} + title={subProject.data.title} + description={subProject.data.description} + url={subProject.data.url} + git={subProject.data.git} + codeLanguage={subProject.data.codeLanguage} + icon={subProject.data.icon} + /> + ); + })} + </div> + </div> + ) + } </div> <style> .project-card { + border: var(--border-size) solid var(--border-color); + border-radius: var(--border-radius); + } + + .project-card-wrapper { height: 100%; width: 100%; min-height: 15rem; - border: var(--border-size) solid var(--border-color); - border-radius: var(--border-radius); box-sizing: border-box; padding: var(--card-padding); transition: all var(--transition-duration); @@ -103,6 +174,23 @@ const { project, titleSize, descSize } = Astro.props as Props; gap: 1rem; } + .project-card-sub-projects-wrapper { + display: flex; + flex-direction: column; + padding: 0 var(--card-padding) var(--card-padding) var(--card-padding); + gap: 1rem; + } + + .project-card-sub-projects-wrapper h3 { + margin: 0; + } + + .project-card-sub-projects { + width: 100%; + display: flex; + gap: 1rem; + } + .project-card:hover { background-color: var(--secondary-color); } @@ -111,6 +199,9 @@ const { project, titleSize, descSize } = Astro.props as Props; width: 50%; max-width: 50%; min-width: 50%; + display: flex; + wrap: nowrap; + overflow: hidden; } .project-card-img { @@ -118,6 +209,7 @@ const { project, titleSize, descSize } = Astro.props as Props; width: 100%; object-fit: cover; border-radius: var(--border-radius); + transition: all 2.5s ease; } .project-card-container { @@ -144,6 +236,31 @@ const { project, titleSize, descSize } = Astro.props as Props; bottom: 0; } + .project-card-title { + display: flex; + align-items: center; + } + + .project-card-status, + .project-card-org { + margin: 0 0 0 0.5rem; + font-size: 0.8em; + border: var(--border-size) solid var(--border-color); + padding: 0.4rem; + border-radius: var(--border-radius); + transition: all 0.2s; + display: flex; + gap: 0.2rem; + align-items: center; + } + + .project-card-org:hover { + border: var(--border-size) solid var(--primary-color); + background-color: var(--border-color); + color: var(--primary-color); + cursor: pointer; + } + .project-card-language { display: flex; align-items: center; @@ -173,6 +290,18 @@ const { project, titleSize, descSize } = Astro.props as Props; font-size: 1.3em; } + .project-card-org > [data-icon] { + font-size: 1em; + display: flex; + align-items: center; + justify-content: center; + } + + .project-card-org:hover > [data-icon] { + color: var(--primary-color); + fill: var(--primary-color); + } + @media (max-width: 768px) { .project-card-img-container { width: 100%; @@ -184,12 +313,16 @@ const { project, titleSize, descSize } = Astro.props as Props; width: 100%; } - .project-card { + .project-card-wrapper { flex-direction: column; } .project-card-bottom { position: initial; } + + .project-card-sub-projects { + flex-direction: column; + } } </style> diff --git a/src/components/core/Project/ProjectCardSlider.astro b/src/components/core/Project/ProjectCardSlider.astro new file mode 100644 index 00000000..e61df8c7 --- /dev/null +++ b/src/components/core/Project/ProjectCardSlider.astro @@ -0,0 +1,185 @@ +--- +import { Icon } from 'astro-icon/components'; + +interface Props { + images: string[]; +} + +const { images } = Astro.props; +--- + +<div class="project-card-slider-container"> + <div class="project-card-slides" id="project-card-slides"> + { + images.map((image, index) => ( + <div class="project-card-slide" data-key={index}> + <img src={image} loading="lazy" alt={`Slide ${index + 1}`} /> + </div> + )) + } + </div> + <div class="project-card-slide-index"> + <span class="project-card-slide-index-value">1</span>/{images.length} + </div> + <button class="project-card-prev" id="project-card-prev"> + <Icon name="mdi:navigate-before" /> + </button> + <button class="project-card-next" id="project-card-next"> + <Icon name="mdi:navigate-next" /> + </button> +</div> + +<style> + .project-card-slider-container { + position: relative; + max-width: 100%; + overflow: hidden; + border-radius: var(--border-radius); + } + + .project-card-slider-container:hover .project-card-slide-index, + .project-card-slider-container:hover .project-card-prev, + .project-card-slider-container:hover .project-card-next { + pointer-events: all; + opacity: 1; + } + + .project-card-slides { + display: flex; + transition: transform 0.5s ease-in-out; + } + + .project-card-slide { + position: relative; + min-width: 100%; + transition: transform 0.5s ease-in-out; + } + + .project-card-slide img { + height: 100%; + width: 100%; + display: block; + object-fit: cover; + } + + .project-card-slide-index { + position: absolute; + bottom: 1rem; + left: 50%; + transform: translateX(-50%); + background-color: var(--primary-color); + color: var(--primary-text-color); + padding: 5px 10px; + border-radius: 5px; + font-size: 14px; + border: var(--border-size) solid rgba(var(--contrast-color-rgb), 0.5); + pointer-events: none; + opacity: 0.2; + transition: opacity 0.4s ease; + } + + .project-card-prev, + .project-card-next { + position: absolute; + top: 50%; + transform: translateY(-50%); + background-color: var(--primary-color); + color: var(--primary-text-color); + padding: 0.4rem; + cursor: pointer; + font-size: 18px; + border-radius: var(--border-radius); + display: flex; + align-items: center; + justify-content: center; + border: var(--border-size) solid rgba(var(--contrast-color-rgb), 0.5); + pointer-events: none; + opacity: 0.2; + transition: opacity 0.4s ease; + } + + .project-card-prev { + left: 0.5rem; + } + + .project-card-next { + right: 0.5rem; + } + + @media (max-width: 768px) { + .project-card-slide-index { + pointer-events: all; + opacity: 1; + } + + .project-card-prev, + .project-card-next { + pointer-events: all; + opacity: 1; + } + } +</style> + +<script> + const sliderContainers = document.querySelectorAll( + '.project-card-slider-container' + ) as NodeListOf<HTMLDivElement>; + + sliderContainers.forEach((container) => { + const slides = container.querySelector( + '.project-card-slides' + ) as HTMLDivElement; + const prevButton = container.querySelector( + '.project-card-prev' + ) as HTMLButtonElement; + const nextButton = container.querySelector( + '.project-card-next' + ) as HTMLButtonElement; + const images = container.querySelectorAll( + '.project-card-slide' + ) as NodeListOf<HTMLDivElement>; + const slideIndex = container.querySelector( + '.project-card-slide-index-value' + ) as HTMLSpanElement; + + let currentIndex: number = 0; + let sliderInterval: number | undefined; + + function updateSlide(position: number): void { + if (slides) { + slides.style.transform = `translateX(-${position * 100}%)`; + slideIndex.textContent = `${position + 1}`; + } + } + + prevButton?.addEventListener('click', () => { + currentIndex = currentIndex === 0 ? images.length - 1 : currentIndex - 1; + updateSlide(currentIndex); + }); + + nextButton?.addEventListener('click', () => { + currentIndex = currentIndex === images.length - 1 ? 0 : currentIndex + 1; + updateSlide(currentIndex); + }); + + images.forEach((image) => { + image.addEventListener('mouseenter', () => { + sliderInterval = window.setInterval(() => { + currentIndex = + currentIndex === images.length - 1 ? 0 : currentIndex + 1; + updateSlide(currentIndex); + }, 1800); + }); + + image.addEventListener('mouseleave', () => { + if (sliderInterval) { + clearInterval(sliderInterval); + sliderInterval = undefined; + } + }); + }); + + // Initialize the first slide for this slider + updateSlide(currentIndex); + }); +</script> diff --git a/src/components/core/Tag.astro b/src/components/core/Tag.astro index c606bdef..3ca2cc51 100644 --- a/src/components/core/Tag.astro +++ b/src/components/core/Tag.astro @@ -3,18 +3,15 @@ interface Props { href: string; value: string; active?: boolean; + title?: string; } -const { href, value, active = false } = Astro.props; +const { title, href, value, active = false } = Astro.props; --- { active ? ( - <a - href={href} - class="tag-item" - title={`See more posts with '${value}' tag`} - > + <a href={href} class="tag-item" title={title}> {value} </a> ) : ( diff --git a/src/components/core/ThemeIcon.astro b/src/components/core/ThemeIcon.astro index 36c665cc..c441a955 100644 --- a/src/components/core/ThemeIcon.astro +++ b/src/components/core/ThemeIcon.astro @@ -1,16 +1,23 @@ --- import { Icon } from 'astro-icon/components'; +import Tooltip from './Tooltip.astro'; +import { useLocale } from 'i18n'; interface Props { position?: string; } +const { t } = useLocale(Astro.url.pathname); + const { position = 'initial' } = Astro.props; --- -<button id="theme"> - <Icon name="mdi:white-balance-sunny" /> -</button> +<Tooltip message={t('common.header.change_theme_tooltip')} position="bottom"> + <button id="theme" accesskey="t" title={t('common.header.change_theme')}> + <Icon name="mdi:white-balance-sunny" class="dark-icon" /> + <Icon name="mdi:moon-and-stars" class="light-icon" /> + </button> +</Tooltip> <style define:vars={{ position }}> #theme { @@ -34,6 +41,14 @@ const { position = 'initial' } = Astro.props; background-color: var(--contrast-color); } + :root[data-theme='dark'] .light-icon { + display: none; + } + + :root[data-theme='light'] .dark-icon { + display: none; + } + #theme:hover > [data-icon] { color: var(--primary-color); fill: var(--primary-color); diff --git a/src/components/core/Tooltip.astro b/src/components/core/Tooltip.astro index e2819485..7c5087f8 100644 --- a/src/components/core/Tooltip.astro +++ b/src/components/core/Tooltip.astro @@ -4,42 +4,66 @@ interface Props { href?: string; id?: string; messageId?: string; + position?: 'bottom' | 'top' | 'left' | 'right'; } -const { message, href, id, messageId } = Astro.props; +const { message, href, id, messageId, position = 'top' } = Astro.props; --- -<div class="post-share-item" data-href={href} id={id}> - <span class="post-share-item-tooltip" id={messageId}>{message}</span> +<div class="tooltip" data-href={href} id={id}> + { + message && ( + <span class={`tooltip-message tooltip-position-${position}`} id={messageId}> + <Fragment set:html={message} /> + </span> + ) + } <slot /> </div> <style> - .post-share-item { + .tooltip { position: relative; - display: inline-block; + display: inline; } - .post-share-item-tooltip { - min-width: 120px; - position: absolute; + .tooltip-message { + visibility: hidden; + width: 120px; background-color: var(--contrast-color); color: var(--secondary-text-color); text-align: center; - padding: 5px 5px; border-radius: var(--border-radius); - visibility: hidden; - z-index: 3; + padding: 0.4rem; + position: absolute; font-size: 0.85em; + } - /* Location */ - bottom: 100%; + .tooltip:hover .tooltip-message { + visibility: visible; + } + + .tooltip-message.tooltip-position-top { + bottom: 110%; left: 50%; - margin-bottom: 10px; - margin-left: -60px; + transform: translateX(-50%); } - .post-share-item:hover .post-share-item-tooltip { - visibility: visible; + .tooltip-message.tooltip-position-bottom { + top: 110%; + left: 50%; + transform: translateX(-50%); + } + + .tooltip-message.tooltip-position-left { + top: 50%; + right: 110%; + transform: translateY(-50%); + } + + .tooltip-message.tooltip-position-right { + top: 50%; + left: 110%; + transform: translateY(-50%); } </style> diff --git a/src/components/data/Footer.astro b/src/components/data/Footer.astro index 568156cc..63c667cd 100644 --- a/src/components/data/Footer.astro +++ b/src/components/data/Footer.astro @@ -1,33 +1,56 @@ --- import Link from '@components/core/Link/Link.astro'; import LinkBox from '@components/core/Link/LinkBox.astro'; +import Tooltip from '@components/core/Tooltip.astro'; +import { useLocale } from 'i18n'; + +const { t, localizePath } = useLocale(Astro.url.pathname); --- <div class="footer"> <div class="footer-left"> <div class="footer-links"> - <LinkBox - href="/rss.xml" - isLocal={false} - alt="RSS" - icon="mdi:rss" - padding="0.5rem" - event=`RSS (Footer) - (${Astro.url.pathname})` - /> - <LinkBox href="/blog/tags/" alt="Tags" icon="mdi:tags" padding="0.5rem" /> - <LinkBox - href="https://github.com/LucJosin/lucasjosino.com" - isLocal={false} - alt="Source code" - icon="simple-icons:github" - padding="0.5rem" - /> + <Tooltip message={t('common.footer.links.rss')}> + <LinkBox + href="/rss.xml" + isLocal={false} + alt={t('common.footer.links.rss')} + icon="mdi:rss" + padding="0.5rem" + event=`RSS (Footer) - (${Astro.url.pathname})` + /> + </Tooltip> + <Tooltip message={t('common.footer.links.tags')}> + <LinkBox + href={localizePath('/blog/tags/')} + alt={t('common.footer.links.tags')} + icon="mdi:tags" + padding="0.5rem" + /> + </Tooltip> + <Tooltip message={t('common.footer.links.source_code')}> + <LinkBox + href="https://github.com/LucJosin/lucasjosino.com" + isLocal={false} + alt={t('common.footer.links.source_code')} + icon="simple-icons:github" + padding="0.5rem" + /> + </Tooltip> </div> - © 2023 + © {new Date().getUTCFullYear()} <span class="footer-home"> - <Link href="/" alt="Lucas Josino" title="Lucas Josino" /> + <Link href={localizePath('/')} alt="Lucas Josino" title="Lucas Josino" /> </span> - All Rights Reserved. + <div class="footer-powered"> + {t('common.footer.powered')} + <Link + href="https://astro.build/" + isLocal={false} + alt="Astro" + title="Astro" + /> + </div> </div> </div> @@ -63,4 +86,9 @@ import LinkBox from '@components/core/Link/LinkBox.astro'; gap: 1rem; margin: 0 0 1rem 0; } + + .footer-powered { + display: flex; + gap: 0.2rem; + } </style> diff --git a/src/components/data/Header.astro b/src/components/data/Header.astro index 7a6f01b2..aba918fa 100644 --- a/src/components/data/Header.astro +++ b/src/components/data/Header.astro @@ -1,22 +1,54 @@ --- +import LanguageIcon from '@components/core/LanguageIcon.astro'; import Link from '@components/core/Link/Link.astro'; import ThemeIcon from '@components/core/ThemeIcon.astro'; +import Tooltip from '@components/core/Tooltip.astro'; +import { Icon } from 'astro-icon/components'; +import { useLocale } from 'i18n'; + +const { t, localizePath } = useLocale(Astro.url.pathname); --- <header> <div class="header-container"> <div class="header-left"> - <Link href="/" alt="Homepage" hasBorderBottom={false}> - <h3 class="header-title">LUCAS JOSINO</h3> - </Link> + <Tooltip message={t('common.header.homepage_tooltip')} position="bottom"> + <Link + href={localizePath('/')} + alt={t('common.header.homepage')} + hasBorderBottom={false} + accesskey="h" + > + <h3 class="header-title">LUCAS JOSINO</h3> + </Link> + </Tooltip> </div> <nav class="header-nav"> - <Link title="Blog" href="/blog/" alt="Go to blog page" /> - <Link title="Projects" href="/projects/" alt="Go to projects page" /> + <Link + title={t('common.header.blog')} + href={localizePath('/blog/')} + alt={t('common.header.blog_link_alt')} + /> + <Link + title={t('common.header.projects')} + href={localizePath('/projects/')} + alt={t('common.header.projects_link_alt')} + /> + <Link + title={t('common.header.about')} + href={localizePath('/about/')} + alt={t('common.header.about_link_alt')} + /> + <LanguageIcon /> <ThemeIcon /> </nav> </div> - <div class="header-menu-mobile"></div> + <div class="header-menu-mobile"> + <button class="header-menu-btn"> + <Icon name="mdi:menu" class="header-menu-btn-menu" /> + <Icon name="mdi:close" class="header-menu-btn-close" /> + </button> + </div> </header> <style> @@ -38,6 +70,12 @@ import ThemeIcon from '@components/core/ThemeIcon.astro'; .header-title { margin: 0; + transition: color var(--transition-duration) linear; + } + + .header-title:hover { + color: var(--description-text-color); + margin: 0; } .header-nav, @@ -45,5 +83,109 @@ import ThemeIcon from '@components/core/ThemeIcon.astro'; display: flex; gap: 1rem; align-items: center; + z-index: 99; + /* transition: + visibility 0s linear 0.2s, + opacity 0.2s linear; */ + } + + .header-menu-mobile { + display: none; + } + + .header-menu-btn-close, + .header-menu-btn-menu { + font-size: 2em; + } + + .header-menu-btn-close { + visibility: hidden; + pointer-events: none; + display: none; + } + + .header-menu-btn { + height: 2rem; + width: 2rem; + display: flex; + justify-content: center; + align-items: center; + cursor: pointer; + margin-right: 1rem; + border: var(--border-size) solid var(--border-color); + border-radius: var(--border-radius); + transition: all var(--transition-duration) linear; + background-color: transparent; + } + + @media (max-width: 520px) { + .header-nav { + visibility: hidden; + opacity: 0; + position: absolute; + flex-direction: column; + align-items: center; + justify-items: center; + backdrop-filter: blur(2px); + padding: 1em; + border-radius: var(--border-radius); + right: 1rem; + top: 3rem; + border: var(--border-size) solid var(--border-color); + pointer-events: none; + } + + .header-nav.show { + visibility: visible; + opacity: 1; + transition-delay: 0s; + pointer-events: all; + } + + .header-menu-btn-close.show { + visibility: visible; + opacity: 1; + pointer-events: all; + display: initial; + } + + .header-menu-btn-menu.show { + visibility: hidden; + pointer-events: none; + display: none; + } + + .header-menu-mobile { + display: initial; + flex-direction: initial; + position: relative; + } + + .header-nav-mobile { + position: absolute; + display: flex; + flex-direction: column; + gap: 1rem; + background-color: var(--contrast-color); + color: white; + right: 1rem; + } } </style> + +<script> + const headerNav = document.querySelector('.header-nav') as HTMLElement; + const headerMenuBtn = document.querySelector( + '.header-menu-btn-menu' + ) as HTMLElement; + const headerCloseBtn = document.querySelector( + '.header-menu-btn-close' + ) as HTMLElement; + const headerMenu = document.querySelector('.header-menu-mobile'); + + headerMenu?.addEventListener('click', () => { + headerNav.classList.toggle('show'); + headerMenuBtn.classList.toggle('show'); + headerCloseBtn.classList.toggle('show'); + }); +</script> diff --git a/src/components/data/Post/PostComments.astro b/src/components/data/Post/PostComments.astro index 63c7c0fc..83ddcb79 100644 --- a/src/components/data/Post/PostComments.astro +++ b/src/components/data/Post/PostComments.astro @@ -1,13 +1,19 @@ --- +import { useLocale } from 'i18n'; +const { t } = useLocale(Astro.url.pathname); --- <div class="post-comments"> - <h2 id="comments">Comments</h2> + <h2 id="comments">{t('post.comments')}</h2> <div class="giscus"></div> </div> <style> + .post-comments { + width: 100%; + } + .giscus { margin: 1rem 0 0 0; } @@ -27,7 +33,7 @@ 'data-emit-metadata': '0', 'data-input-position': 'top', 'data-theme': getGiscusTheme(theme), - 'data-lang': 'en', + 'data-lang': document.documentElement.lang, 'data-loading': 'lazy', crossorigin: 'anonymous', async: true, diff --git a/src/components/data/Post/PostRelated.astro b/src/components/data/Post/PostRelated.astro index c3bc4fe6..ea436e1f 100644 --- a/src/components/data/Post/PostRelated.astro +++ b/src/components/data/Post/PostRelated.astro @@ -1,16 +1,19 @@ --- import PostCard from '@components/core/Post/PostCard.astro'; import type { CollectionEntry } from 'astro:content'; +import { useLocale } from 'i18n'; interface Props { posts: CollectionEntry<'blog'>[]; } +const { t } = useLocale(Astro.url.pathname); + const { posts } = Astro.props; --- <div class="post-releated"> - <h2>Related Posts</h2> + <h2>{t('post.related_posts')}</h2> <span class="post-related-items"> { posts.map((item) => { diff --git a/src/components/data/Posts.astro b/src/components/data/Posts.astro index e6dc7455..b53505e6 100644 --- a/src/components/data/Posts.astro +++ b/src/components/data/Posts.astro @@ -1,50 +1,53 @@ --- import Link from '@components/core/Link/Link.astro'; -import MiniPostCard from '@components/core/Post/MiniPostCard.astro'; +import PostCard from '@components/core/Post/PostCard.astro'; import SubTitle from '@components/core/SubTitle.astro'; import { getAllPosts } from '@lib/blog'; +import { useLocale } from 'i18n'; -const posts = await getAllPosts(); +const { t, locale, localizePath } = useLocale(Astro.url.pathname); +const posts = await getAllPosts(true, true, locale); --- -<div class="posts-data"> - <div class="posts-header"> - <SubTitle title="Posts" /> - <Link - href="/blog/" - alt="See more posts" - title="See more" - icon="mdi:arrow-right" - iconSide="right" - hasBorderBottom={false} - animatedIcon - event=`Posts (${Astro.url.pathname})` - /> - </div> +{ + posts.length > 0 && ( + <section class="posts-section"> + <div class="posts-header"> + <SubTitle title="Posts" /> + <Link + href={localizePath('/blog/')} + alt={t('home.posts.see_more_alt')} + title={t('home.see_more')} + icon="mdi:arrow-right" + iconSide="right" + hasBorderBottom={false} + animatedIcon + event={`Posts (${Astro.url.pathname})`} + /> + </div> - <div class="posts-container"> - { - posts - .slice(0, 2) - .map((e) => ( - <MiniPostCard - image={e.data.image.src} - imageAlign={e.data.image.position} - href={`/blog/${e.slug}`} - title={e.data.title} - description={e.data.description} - publishedAt={e.data.publishedAt} - body={e.body} + <div class="posts-container"> + {posts.slice(0, 2).map((post) => ( + <PostCard + image={post.data.image.src} + href={localizePath(`/blog/${post.data.permSlug}`)} + title={post.data.title} + description={post.data.description} + publishedAt={post.data.publishedAt} + body={post.body} + category={post.data.category} + tags={post.data.tags} /> - )) - } - </div> -</div> + ))} + </div> + </section> + ) +} <style> - .posts-data { + .posts-section { height: max-content; - width: 80%; + width: 100%; } .posts-header { diff --git a/src/components/data/Projects.astro b/src/components/data/Projects.astro index dc65c869..25aa206b 100644 --- a/src/components/data/Projects.astro +++ b/src/components/data/Projects.astro @@ -1,17 +1,21 @@ --- import Link from '@components/core/Link/Link.astro'; -import MiniProjectCard from '@components/core/Project/MiniProjectCard.astro'; +import ProjectCard from '@components/core/Project/ProjectCard.astro'; import SubTitle from '@components/core/SubTitle.astro'; -import { projects } from '@constants/projects'; +import { getAllProjects } from '@lib/projects'; +import { useLocale } from 'i18n'; + +const { locale, t, localizePath } = useLocale(Astro.url.pathname); +const projects = await getAllProjects(true, locale); --- -<div class="projects-data"> +<section class="projects-section"> <div class="projects-header"> - <SubTitle title="Projects" /> + <SubTitle title={t('home.projects.title')} /> <Link - href="/projects/" - alt="See more projects" - title="See more" + href={localizePath('/projects/')} + alt={t('home.projects.see_more_alt')} + title={t('home.see_more')} icon="mdi:arrow-right" iconSide="right" hasBorderBottom={false} @@ -24,23 +28,15 @@ import { projects } from '@constants/projects'; { projects .slice(0, 2) - .map((data) => ( - <MiniProjectCard - title={data.title} - description={data.description} - git={data.git} - url={data.url} - image={data.image} - /> - )) + .map((data) => <ProjectCard project={data} titleSize="1.2em" />) } </div> -</div> +</section> <style> - .projects-data { + .projects-section { height: max-content; - width: 80%; + width: 100%; } .projects-header { @@ -51,8 +47,8 @@ import { projects } from '@constants/projects'; .projects-container { width: 100%; - display: grid; + display: flex; + flex-direction: column; gap: 1rem; - grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr)); } </style> diff --git a/src/components/data/Socials.astro b/src/components/data/Socials.astro index f66bb079..df7c6ce4 100644 --- a/src/components/data/Socials.astro +++ b/src/components/data/Socials.astro @@ -1,53 +1,69 @@ --- import LinkBox from '@components/core/Link/LinkBox.astro'; import SubTitle from '@components/core/SubTitle.astro'; +import Tooltip from '@components/core/Tooltip.astro'; import { links } from '@constants/links'; import { socials } from '@constants/socials'; interface Props { hasTitle?: boolean; + showName?: boolean; + showTooltip?: boolean; + justifyContent?: string; } -const { hasTitle = true } = Astro.props; +const { + hasTitle = false, + showName = false, + showTooltip = true, + justifyContent = 'center', +} = Astro.props; --- -<div class="socials"> +<section class="socials-section"> <div class="socials-header"> {hasTitle && <SubTitle title="Socials" />} </div> <div class="socials-container"> { links.map((data) => ( - <LinkBox - href={data.url} - icon={data.icon} - title={data.name} - alt={data.alt} - isLocal={false} - event={data.event + ` (${Astro.url.pathname})`} - gridColumn="auto / span 3" - /> + <Tooltip message={showTooltip ? data.name : ''}> + <LinkBox + href={data.url} + title={showName ? data.name : undefined} + icon={data.icon} + iconSize="1em" + padding="0.6rem" + alt={data.alt} + isLocal={false} + event={data.event + ` (${Astro.url.pathname})`} + /> + </Tooltip> )) } { socials.map((data) => ( - <LinkBox - href={data.url} - icon={data.icon} - alt={data.alt} - isLocal={false} - event={data.event + ` (${Astro.url.pathname})`} - gridColumn="auto / span 2" - /> + <Tooltip message={showTooltip ? data.name : ''}> + <LinkBox + href={data.url} + title={showName ? data.name : undefined} + icon={data.icon} + iconSize="1em" + padding="0.6rem" + alt={data.alt} + isLocal={false} + event={data.event + ` (${Astro.url.pathname})`} + /> + </Tooltip> )) } </div> -</div> +</section> -<style> - .socials { +<style define:vars={{ justifyContent }}> + .socials-section { height: max-content; - width: 80%; + width: 100%; } .socials-header { @@ -58,10 +74,10 @@ const { hasTitle = true } = Astro.props; .socials-container { width: 100%; - display: grid; + display: flex; align-items: center; - justify-content: space-between; - grid-template-columns: repeat(6, minmax(1rem, 1fr)); + justify-content: var(--justifyContent); + flex-wrap: wrap; gap: 1rem; } </style> diff --git a/src/components/data/Tags.astro b/src/components/data/Tags.astro index 05e7289e..7e9eed70 100644 --- a/src/components/data/Tags.astro +++ b/src/components/data/Tags.astro @@ -1,6 +1,7 @@ --- import Tag from '@components/core/Tag.astro'; import { getPostLength } from '@lib/blog'; +import { useLocale } from 'i18n'; interface Props { values: string[]; @@ -10,8 +11,11 @@ interface Props { id?: string; center?: boolean; active?: boolean; + wrapContent?: boolean; } +const { localizePath, t, locale } = useLocale(Astro.url.pathname); + const { title, target, @@ -20,8 +24,10 @@ const { center = false, showLength = false, active = false, + wrapContent = true, } = Astro.props; const justifyContent = center ? 'center' : 'initial'; +const flexWrap = wrapContent ? 'wrap' : 'nowrap'; --- <div id={id}> @@ -30,13 +36,14 @@ const justifyContent = center ? 'center' : 'initial'; { values.map(async (tag) => { const filteredPosts = showLength - ? await getPostLength(tag, target) + ? await getPostLength(locale, tag, target) : null; return ( <Tag value={tag + (filteredPosts ? ` (${filteredPosts})` : '')} - href={`/blog/${target}/${tag}`} + href={localizePath(`/blog/${target}/${tag}`)} active={active} + title={t('post.tags_see_more_alt', { tag })} /> ); }) @@ -44,11 +51,12 @@ const justifyContent = center ? 'center' : 'initial'; </div> </div> -<style define:vars={{ justifyContent }}> +<style define:vars={{ justifyContent, flexWrap }}> .tags-list { display: flex; - flex-wrap: wrap; flex-direction: row; + flex-wrap: var(--flexWrap); + overflow: hidden; justify-content: var(--justifyContent); gap: 0.5rem; font-size: 0.9em; diff --git a/src/constants/head.ts b/src/constants/head.ts index 38fc57bb..beeb59ab 100644 --- a/src/constants/head.ts +++ b/src/constants/head.ts @@ -4,7 +4,7 @@ interface HeadConfig { copyright: string; endDescription: string; tags: string; - banner: string; + image: string; robots: string; shortLink: string; canonical: string; @@ -14,10 +14,9 @@ const headConfig: HeadConfig = { name: 'Lucas Josino', social: '@LucJosin', copyright: '© 2024, Lucas Josino. All Rights Reserved.', - endDescription: - ' • lucasjosino.com | lucjos.in | @lucjosin', - tags: 'java, java developer, kotlin, golang, go, sql, postgresql, hawapi, spring, spring boot, spring mvc, backend, backend developer, portfolio, lucasjosino, lucas josino, lucjosin, lucjos.in, josino, developer, @lucjoin, @lucjos.in, desenvolvedor, desenvolvedor backend, desenvolvedor java', - banner: 'static/default-og.png', + endDescription: ' • lucasjosino.com | lucjos.in | @lucjosin', + tags: 'java, java developer, kotlin, golang, go, sql, postgresql, hawapi, spring, spring boot, spring mvc, software, software developer, backend, backend developer, portfolio, lucasjosino, lucas josino, lucjosin, lucjos.in, josino, developer, @lucjoin, @lucjos.in, desenvolvedor, desenvolvedor backend, desenvolvedor java, sistemas, desenvolvedor de sistemas', + image: 'static/default-og.png', robots: 'index,follow', shortLink: 'https://lucjos.in', canonical: 'https://www.lucasjosino.com', diff --git a/src/constants/languages.ts b/src/constants/languages.ts new file mode 100644 index 00000000..797b1662 --- /dev/null +++ b/src/constants/languages.ts @@ -0,0 +1,63 @@ +export interface Language { + name: string; + icon: string; +} + +export const languages: Language[] = [ + { + name: 'Java (Language)', + icon: 'mdi:language-java', + }, + { + name: 'Golang (Language)', + icon: 'mdi:language-go', + }, + { + name: 'Spring Boot (Backend)', + icon: 'simple-icons:springboot', + }, + { + name: 'Spring Framework (Backend)', + icon: 'simple-icons:spring', + }, + { + name: 'JUnit5 (Backend)', + icon: 'simple-icons:junit5', + }, + { + name: 'PostgreSQL (Database)', + icon: 'simple-icons:postgresql', + }, + { + name: 'MySQL (Database)', + icon: 'simple-icons:mysql', + }, + { + name: 'Docker (Tool)', + icon: 'simple-icons:docker', + }, + { + name: 'SQL (Backend)', + icon: 'tabler:file-type-sql', + }, + { + name: 'Git (Tool)', + icon: 'simple-icons:git', + }, + { + name: 'Maven (Tool)', + icon: 'simple-icons:apachemaven', + }, + { + name: 'Swagger (Tool)', + icon: 'simple-icons:swagger', + }, + { + name: 'Restful API (Architectural Style)', + icon: 'mdi:api', + }, + { + name: 'Linux (OS)', + icon: 'simple-icons:linux', + }, +]; diff --git a/src/constants/projects.ts b/src/constants/projects.ts deleted file mode 100644 index 38da1cb6..00000000 --- a/src/constants/projects.ts +++ /dev/null @@ -1,65 +0,0 @@ -export interface ProjectModel { - image?: string; - title: string; - description: string; - git?: string; - url?: string; - article?: string; - tags: string[]; - language: string; - icon: string; - category: 'Project' | 'Collection'; -} - -export const projects: ProjectModel[] = [ - { - image: - 'https://repository-images.githubusercontent.com/680511363/f5989e03-eb8b-43bb-988a-fe80abe00210', - title: 'Hawbrary', - description: - 'The Hawbrary is a showcase of the HawAPI - A Free and Open Source API for Stranger Things - built with React (NextJs) + Typescript.', - git: 'https://github.com/LucJosin/hawbrary', - url: 'https://hawbrary.theproject.id/', - tags: ['React.js', 'Next.js', 'SDK', 'CSS', ' TypeScript'], - language: 'Typescript', - icon: 'simple-icons:typescript', - category: 'Project', - }, - { - image: - 'https://repository-images.githubusercontent.com/566830817/1ee86716-d27f-4703-a003-977eca9aee8b', - title: 'HawAPI', - description: - 'A Free and Open Source API for Stranger Things built with Java (Spring Boot) and PostgreSQL with support for multiple languages (English and Portuguese).', - git: 'https://github.com/HawAPI/HawAPI', - url: 'https://hawapi.theproject.id/', - tags: ['Java', 'Spring Boot', 'JUnit', 'PostgreSQL', 'SQL'], - language: 'Java', - icon: 'mdi:language-java', - category: 'Collection', - }, - { - image: 'https://www.lucasjosino.com/static/default-og.png', - title: 'lucasjosino.com', - description: - 'Minimalist portfolio website/blog built with Astro & Typescript.', - git: 'https://github.com/LucJosin/lucasjosino.com', - tags: ['Astro', 'TypeScript', 'JavaScript', 'CSS'], - language: 'Astro', - icon: 'simple-icons:astro', - category: 'Project', - }, - { - image: - 'https://pub.dev/static/hash-v7cgjij4/img/pub-dev-icon-cover-image.png', - title: 'on_audio_query', - description: - 'Flutter Plugin used to query audios/songs infos from device storage.', - git: 'https://github.com/LucJosin/on_audio_query', - url: 'https://pub.dev/packages/on_audio_query#gif-examples', - tags: ['Kotlin', 'Swift', 'Flutter', 'Dart'], - language: 'Dart', - icon: 'simple-icons:dart', - category: 'Project', - }, -]; diff --git a/src/constants/socials.ts b/src/constants/socials.ts index 259d50a8..3abdc22c 100644 --- a/src/constants/socials.ts +++ b/src/constants/socials.ts @@ -5,7 +5,7 @@ export const socials = [ icon: 'simple-icons:x', user: 'LucJosin', url: 'https://x.com/LucJosin', - event: 'X (Twitter)' + event: 'X (Twitter)', }, { name: 'Bluesky', @@ -13,14 +13,14 @@ export const socials = [ icon: 'simple-icons:bluesky', user: 'lucjos.in', url: 'https://bsky.app/profile/lucjos.in/', - event: 'Bluesky' + event: 'Bluesky', }, { - name: 'StackOverFlow', - alt: 'StackOverFlow - @lucas-josino', - icon: 'simple-icons:stackoverflow', + name: 'Email', + alt: 'Email - contact@lucasjosino.com', + icon: 'mdi:alternate-email', user: 'lucas-josino', - url: 'https://stackoverflow.com/u/14500144/', - event: 'StackOverFlow' + url: 'mailto:contact@lucasjosino.com', + event: 'Email', }, ]; diff --git a/src/content/_schemas.ts b/src/content/_schemas.ts index a53f2a41..798daf8a 100644 --- a/src/content/_schemas.ts +++ b/src/content/_schemas.ts @@ -1,13 +1,14 @@ import { reference, z } from 'astro:content'; +import { locales } from 'i18n/config'; export const blogSchema = z.object({ - refFile: z.string().optional(), + permSlug: z.string(), image: z.object({ src: z.string().default('/static/default-og.png'), position: z.string().default('center'), showInPost: z.boolean().default(true), }), - color: z.string().default("#111"), + color: z.string().default('#111'), publishedAt: z.string(), updatedAt: z.string().optional(), title: z.string().max(65), @@ -23,3 +24,41 @@ export const blogSchema = z.object({ relatedPosts: z.array(reference('blog')).max(4).optional(), easyShare: z.boolean().default(true), }); + +export const projectSchema = z.object({ + permSlug: z.string(), + thumbnail: z.string().optional(), + images: z.array(z.string()).optional(), + showImagesInSlider: z.boolean().default(true), + title: z.string(), + description: z.string(), + git: z.string().optional(), + url: z.string().optional(), + article: z.string().optional(), + tags: z.array(z.string()), + codeLanguage: z.string(), + language: z.enum(locales), + icon: z.string(), + category: z.enum(['Project', 'Org']), + org: z.string().optional(), + status: z.enum(['active', 'inactive', 'in_progress', 'completed', 'on_hold']), + subProjects: z.array(reference('projects')).optional(), + isVisible: z.boolean().default(true), + isIndexable: z.boolean().default(true), + color: z.string().default('#111'), + target: z + .array( + z.enum([ + 'Web', + 'Mobile', + 'Desktop', + 'CLI', + 'API', + 'SDK', + 'Library', + 'Plugin', + 'Other', + ]) + ) + .optional(), +}); diff --git a/src/content/_templates/project.md b/src/content/_templates/project.md new file mode 100644 index 00000000..739c48c0 --- /dev/null +++ b/src/content/_templates/project.md @@ -0,0 +1,36 @@ +--- +permSlug: '' +thumbnail: '' +images: + - '' +title: '' +description: '' +git: '' +url: '' +article: '' +tags: + - '' +codeLanguage: '' +language: 'en' +icon: '' +category: '' +org: '' +target: + - '' +status: '' +isVisible: true +isIndexable: true +--- + +Lorem Ipsum + +- **Inspiration**: Lorem Ipsum +- **Technologies**: Lorem Ipsum +- **Features**: Lorem Ipsum +- **Challenges**: Lorem Ipsum +- **Deployment & Hosting**: Lorem Ipsum +- **Improvements**: Lorem Ipsum +- **Testing & Debugging**: Lorem Ipsum +- **Documentation**: Lorem Ipsum + +### Tecnologias diff --git a/src/content/blog/astro-class-rename.md b/src/content/blog/astro-class-rename.md index ab1528a4..6a968eb9 100644 --- a/src/content/blog/astro-class-rename.md +++ b/src/content/blog/astro-class-rename.md @@ -1,5 +1,5 @@ --- -slug: 'how-to-hash-class-names-in-astro-using-astro-rename-integration' +permSlug: 'how-to-hash-class-names-in-astro-using-astro-rename-integration' title: 'How to hash class names in Astro using astro-rename integration' description: 'Learn how to use the astro-rename integration to hash all CSS class names from your Astro project.' image: @@ -23,7 +23,7 @@ publishedAt: '2023-10-14 18:00 UTC-3' updatedAt: '2023-10-24 21:08 UTC-3' --- -## Table of Contents +## Summary ## Introduction diff --git a/src/content/blog/go-scs-test.md b/src/content/blog/go-scs-test.md index b0e5078d..f35fd050 100644 --- a/src/content/blog/go-scs-test.md +++ b/src/content/blog/go-scs-test.md @@ -1,5 +1,5 @@ --- -slug: 'go-how-to-mock-scs-session-authentication-in-tests' +permSlug: 'go-how-to-mock-scs-session-authentication-in-tests' title: 'Go: How to mock SCS session authentication in tests' description: "In this article, we'll explore how to mock our session when using SCS and inject data into context for authentication tests." image: @@ -24,7 +24,7 @@ publishedAt: '2024-02-01 20:00 UTC-3' updatedAt: '2024-05-01 12:00 UTC-3' --- -## Table of Contents +## Summary ## Introduction @@ -187,10 +187,10 @@ Now, the testing part. Our test will have four paths: -- Public endpoint that will return `200 (Ok){endpointOk1#green-white}` -- Admin endpoint **without role** that will return `401 (Unauthorized){endpointUnauthorized1#goldenrod-white}` -- Admin endpoint **with wrong role** that will return `401 (Unauthorized){endpointUnauthorized2#goldenrod-white}` -- Admin endpoint **with correct role** that will return `200 (Ok){endpointOk2#green-white}` +- Public endpoint that will return `200 (Ok)[class="endpointOk1" background-color="green" color="white"]` +- Admin endpoint **without role** that will return `401 (Unauthorized)[class="endpointUnauthorized1" background-color="goldenrod" color="white"]` +- Admin endpoint **with wrong role** that will return `401 (Unauthorized)[class="endpointUnauthorized2" background-color="goldenrod" color="white"]` +- Admin endpoint **with correct role** that will return `200 (Ok)[class="endpointOk2" background-color="green" color="white"]` ```go title="main_test.go" func Test_main(t *testing.T) { diff --git a/src/content/blog/hawapi-what-is-pt.md b/src/content/blog/hawapi-what-is-pt.md new file mode 100644 index 00000000..dabd0e84 --- /dev/null +++ b/src/content/blog/hawapi-what-is-pt.md @@ -0,0 +1,248 @@ +--- +permSlug: 'hawapi-explore-the-world-of-stranger-things-using-this-api' +title: 'HawAPI: Explore o mundo de Stranger Things usando essa API' +description: 'Vamos explorar a HawAPI – uma API gratuita e de código aberto para Stranger Things. Aprenda a usá-la para acessar personagens, episódios, locais e muito mais!' +image: + src: 'https://repository-images.githubusercontent.com/566830817/1ee86716-d27f-4703-a003-977eca9aee8b' + position: 'center' + showInPost: true +tags: + - 'api' + - 'java' + - 'what-is' + - 'showcase' + - 'i18n' +category: 'Showcase' +language: 'pt' +shortlink: '/pt/b/zBLtyQby' +isVisible: true +enableComments: true +color: '#691313' +publishedAt: '2024-11-06 17:00 UTC-3' +--- + +## Sumário + +## Introdução + +Enquanto aprendia sobre desenvolvimento Backend com **Java** e **Spring Boot**, decidi criar um projeto simples, mas não tão simples. A ideia principal era desenvolver uma API parecida com [PokeAPI - Uma API de Pokémon](https://pokeapi.co/) e [SWAPI - Uma API de Star Wars](https://swapi.dev/). + +Na época, a quarta temporada de Stranger Things havia sido lançada, e eu não encontrei uma API interessante sobre a série. Defini algumas características essenciais para o projeto: + +1. Ser Open Source +2. Suportar múltiplos idiomas +3. Ter um bom suporte a filtros + +## O que é HawAPI + +HawAPI é uma API **Gratuita** e [Open Source](https://github.com/HawAPI/) projetada para a série [Stranger Things](https://www.netflix.com/title/80057281). Ela oferece várias informações sobre a série, incluindo atores, personagens, episódios, jogos, localizações e temporadas, por meio de uma **API RESTful** que permite acesso a esses dados. + +> Todas essas informações estão disponíveis via uma API RESTful implementada com Java (Spring Boot) + PostgreSQL e servida em JSON, facilitando a criação de aplicativos desktop, web e mobile - [HawAPI/docs](https://hawapi.theproject.id/docs/) + +!!!note O nome **HawAPI** vem de: \ +\ +\- **Haw**: Referindo-se a **Hawkins**, a cidade rural fictícia apresentada em **Stranger Things**. \ +\- **API**: Uma abreviação para **Application Programming Interface** _(Interface de Programação de Aplicações, em português)_. + +### Internacionalização (i18n) + +O suporte a múltiplos idiomas era uma característica fundamental do projeto desde o início. + +A versão atual do projeto suporta apenas Inglês (en-US) e Português (pt-BR). Em breve, com o lançamento da versão **1.3.0**, ela também oferecerá suporte para Francês (fr-FR) e Espanhol (es-ES). + +| Escopo | en-US | pt-BR | fr-FR | es-ES | +| :---------- | :---: | :---: | :-----------: | :-----------: | +| Atores | -- | -- | -- | -- | +| Personagens | -- | -- | -- | -- | +| Episódios | Sim | Sim | **Em breve!** | **Em breve!** | +| Jogos | Sim | Sim | **Em breve!** | **Em breve!** | +| Locais | Sim | Sim | **Em breve!** | **Em breve!** | +| Temporadas | Sim | Sim | **Em breve!** | **Em breve!** | +| Trilhas | -- | -- | -- | -- | + +Exemplos de respostas: + +- [/api/v1/episodes/bce28964-fcfa-4a8c-9df0-413d4648d661?language=en-US](https://hawapi.theproject.id/api/v1/episodes/bce28964-fcfa-4a8c-9df0-413d4648d661?language=en-US) +- [/api/v1/episodes/bce28964-fcfa-4a8c-9df0-413d4648d661?language=pt-BR](https://hawapi.theproject.id/api/v1/episodes/bce28964-fcfa-4a8c-9df0-413d4648d661?language=pt-BR) + +````codeset tabs=json-example +```json label=English ins={8-10} +{ + "uuid": "bce28964-fcfa-4a8c-9df0-413d4648d661", + "href": "/api/v1/episodes/bce28964-fcfa-4a8c-9df0-413d4648d661", + "sources": [ + "https://www.netflix.com/title/80057281" + ], + "thumbnail": "https://s6.imgcdn.dev/xtSpy.jpg", + "title": "The Bathtub", + "description": "Eleven struggles to reach Will, while Lucas warns that \"the bad men are coming.\" Nancy and Jonathan show the police what Jonathan caught on camera.", + "language": "en-US", + "duration": 2580000, + "season": "/api/v1/seasons/3b980ad3-aef8-4663-a7a9-64cb4979500a", + "created_at": "2023-07-23T20:19:29.908", + "updated_at": "2023-07-23T20:19:29.908", + "episode_num": 7, + "next_episode": "/api/v1/episodes/cf90565d-c906-4e2c-a992-b190b5d117f8", + "prev_episode": "/api/v1/episodes/b664d023-2f2e-4d11-8af7-00d21bd565dd" +} +``` +:-: +```json label=Portuguese ins={8-10} +{ + "uuid": "bce28964-fcfa-4a8c-9df0-413d4648d661", + "href": "/api/v1/episodes/bce28964-fcfa-4a8c-9df0-413d4648d661", + "sources": [ + "https://www.netflix.com/title/80057281" + ], + "thumbnail": "https://s6.imgcdn.dev/xtSpy.jpg", + "title": "A banheira", + "description": "Onze tenta chegar a Will, mas Lucas dá o alerta de perigo. Nancy e Jonathan mostram à polícia as imagens capturadas pela câmera.", + "language": "pt-BR", + "duration": 2580000, + "season": "/api/v1/seasons/3b980ad3-aef8-4663-a7a9-64cb4979500a", + "created_at": "2023-07-23T20:19:29.908", + "updated_at": "2023-07-23T20:19:29.908", + "episode_num": 7, + "next_episode": "/api/v1/episodes/cf90565d-c906-4e2c-a992-b190b5d117f8", + "prev_episode": "/api/v1/episodes/b664d023-2f2e-4d11-8af7-00d21bd565dd" +} +``` +```` + +!!!info Por padrão, o idioma inglês (en-US) será usado. + +### Filtros + +A capacidade de realizar buscas e filtros foi essencial, mas eu queria mais do que um endpoint básico de busca. + +Base da busca da HawAPI: + +| Campo | Exemplo | Padrão | Opções | +| :------- | :----------------------- | :----- | :----------------------------------------------------- | +| sort | [..]?sort=first_name,ASC | — | campo, ASC ou DESC | +| page | [..]?page=1 | 1 | 1..X | +| size | [..]?size=12 | 10 | 1..20 | +| language | [..]?language=en-US | en-US | [I18N](https://hawapi.theproject.id/docs/guides/i18n/) | + +Exemplo avançado de busca usando **símbolos de modificação**: + +| Modification | Type(s) | Symbol | +| :------------------- | :----------: | :----: | +| LIKE | \* | \* | +| NOT_LIKE | \* | !\* | +| BETWEEN | Número, Data | :: | +| NOT_IN | \* | !: | +| IN | \* | : | +| GREATER_OR_EQUALS_TO | Número, Data | >= | +| LESS_OR_EQUALS_TO | Número, Data | <= | +| GREATER_THAN | Número, Data | > | +| LESS_THAN | Número, Data | < | +| NOT_EQUALS | \* | ! | +| EQUALS | \* | | + +Com esse poder, podemos criar pesquisas de API robustas e complexas como: + +> Todos os personagens com **sobrenome `parecido com` Wheeler**, **gênero `igual a` 1** e **data de nascimento `maior ou igual a` 1967-01-01** +> +> - [/api/v1/characters?**last_name=\*Wheeler&gender=1&birth_date=>=1967-01-01**](https://hawapi.theproject.id/api/v1/characters?last_name=*Wheeler&gender=1&birth_date=>=1967-01-01) + +## Como usar a API com JavaScript + +Nesta seção, veremos como buscar informações do **HawAPI** usando a API [Fetch](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch) e o pacote [@hawapi/js-sdk](https://npmjs.com/package/@hawapi/js-sdk): + +### Fetch API + +Veja como usar com a API nativa **Fetch**: + +1. Usando **then/catch**: + +```js title="index.js" +fetch('https://hawapi.theproject.id/api/v1/characters/') + .then((response) => response.json()) + .then((data) => { + console.log(data); + }) + .catch((error) => console.error(error)); +``` + +2. Usando **async/await**: + +```js title="index.js" +async function fetchAndLogCharacters() { + try { + const response = await fetch( + 'https://hawapi.theproject.id/api/v1/characters/' + ); + const data = await response.json(); + console.log(data); + } catch (error) { + console.error('Error:', error); + } +} + +fetchAndLogCharacters(); +``` + +### HawAPI SDK + +Podemos usar o **SDK do HawAPI em JavaScript** para melhorar o código: + +1. Instale o SDK: + +````codeset tabs=run-add +```bash label=npm showLineNumbers=false +npm install @hawapi/js-sdk +``` +:-: +```bash label=yarn showLineNumbers=false +yarn add @hawapi/js-sdk +``` +```` + +2. Crie a instância e faça solicitações: + +```ts title="index.ts" +import { EpisodeModel, createClient } from '@hawapi/js-sdk'; +// const { EpisodeModel, createClient } = require('@hawapi/js-sdk'); + +const client = createClient(); + +async function fetchAndLogCharacters() { + const res = await client.getRandom<EpisodeModel>('episodes'); + console.log(res); +} + +fetchAndLogCharacters(); +``` + +!!!note O SDK também pode ser usado no navegador com a tag \<script\>. \ +Veja mais em [HawAPI/js-sdk#examples/web](https://github.com/HawAPI/js-sdk/tree/main/examples/web) + +## Hawbrary + +A **Hawbrary** é uma "biblioteca" que exibe todas as informações fornecidas pela HawAPI. Foi desenvolvida com React (NextJs) + Typescript, hospedada no GitHub Pages e utiliza o SDK oficial [@hawapi/js-sdk](https://npmjs.com/package/@hawapi/js-sdk). + +[remark_slider showArrows=true showImageInde=true] +![Hawbrary - Image 3](/static/projects/hawbrary/hawbrary-3.png) +![Hawbrary - Image 1](/static/projects/hawbrary/hawbrary-1.png) +![Hawbrary - Image 2](/static/projects/hawbrary/hawbrary-2.png) +[/remark_slider] + +Veja a demo [Hawbrary](https://hawbrary.theproject.id/) e o [repositório no GitHub](https://github.com/LucJosin/hawbrary) + +## Conclusão + +Nesta publicação, exploramos o histórico e os recursos do projeto HawAPI, incluindo o projeto Hawbrary. + +Se você achar a API útil, dê uma estrela ao **repositório GitHub** e aproveite o **#StrangerThingsDay** para criar um projeto novo! + +!!!ref:repo HawAPI/HawAPI + +## Recursos e Referências + +- https://github.com/HawAPI/ +- https://hawapi.theproject.id + - https://hawapi.theproject.id/docs/ + - https://hawapi.theproject.id/try-it/ +- https://hawbrary.theproject.id + - https://hawbrary.theproject.id/explorer/ diff --git a/src/content/blog/hawapi-what-is.md b/src/content/blog/hawapi-what-is.md new file mode 100644 index 00000000..1e1865f7 --- /dev/null +++ b/src/content/blog/hawapi-what-is.md @@ -0,0 +1,249 @@ +--- +permSlug: 'hawapi-explore-the-world-of-stranger-things-using-this-api' +title: 'HawAPI: Explore the world of Stranger Things using this API' +description: "Let's explore the HawAPI - a Free and Open Source API for Stranger Things. Learn how to use it to access characters, episodes, locations, and more!" +image: + src: 'https://repository-images.githubusercontent.com/566830817/1ee86716-d27f-4703-a003-977eca9aee8b' + position: 'center' + showInPost: true +tags: + - 'api' + - 'java' + - 'what-is' + - 'showcase' + - 'i18n' +category: 'Showcase' +language: 'en' +shortlink: '/b/zBLtyQby' +isVisible: true +enableComments: true +color: '#691313' +publishedAt: '2024-11-06 17:00 UTC-3' +--- + +## Summary + +## Introduction + +While learning about Backend development with **Java** and **Spring Boot** I've decided to create a simple, but no so simpler, project. +The main idea was to create an API like [PokeAPI - The RESTful Pokémon API](https://pokeapi.co/) and [SWAPI - The Star Wars API](https://swapi.dev/). + +In the time, the fourth season of Stranger Things was released and i couldn't find a good API about the series. I had a few key features to the project: + +1. Be Open Source +2. Support multi languages +3. A Good filter support + +## What is HawAPI + +HawAPI is a **Free** and [Open Source](https://github.com/HawAPI/) API designed for [Stranger Things](https://www.netflix.com/title/80057281) TV show. It provides various information related to the show including actors, characters, episodes, games, locations and seasons through a **RESTful API** that allow users to access data about the series. + +> All this information is available through a RESTful API implemented with Java (Spring Boot) + PostgreSQL and served via JSON and allows developers to create desktop, web and mobile applications using this data very easy - [HawAPI/docs](https://hawapi.theproject.id/docs/) + +!!!note The **HawAPI** name comes from: \ +\ +\- **Haw**: Referring to **Hawkins**, the fictional rural town featured in **Stranger Things**. \ +\- **API**: An abbreviation for **Application Programming Interface**. + +### Internationalization (i18n) + +First of all, the support of multiple languages was the MUST-HAVE feature of the project. + +The current release of HawAPI only supports English (en-US) and Portuguese (pt-BR). Soon, after release of **1.3.0**, it will also support French (fr-BR) and Spanish (es-ES). + +| Scope | en-US | pt-BR | fr-FR | es-ES | +| :---------- | :---: | :---: | :-------: | :-------: | +| Actors | -- | -- | -- | -- | +| Characters | -- | -- | -- | -- | +| Episodes | Yes | Yes | **Soon!** | **Soon!** | +| Games | Yes | Yes | **Soon!** | **Soon!** | +| Locations | Yes | Yes | **Soon!** | **Soon!** | +| Seasons | Yes | Yes | **Soon!** | **Soon!** | +| Soundtracks | -- | -- | -- | -- | + +Response examples + +- [/api/v1/episodes/bce28964-fcfa-4a8c-9df0-413d4648d661?language=en-US](https://hawapi.theproject.id/api/v1/episodes/bce28964-fcfa-4a8c-9df0-413d4648d661?language=en-US) +- [/api/v1/episodes/bce28964-fcfa-4a8c-9df0-413d4648d661?language=pt-BR](https://hawapi.theproject.id/api/v1/episodes/bce28964-fcfa-4a8c-9df0-413d4648d661?language=pt-BR) + +````codeset tabs=json-example +```json label=English ins={8-10} +{ + "uuid": "bce28964-fcfa-4a8c-9df0-413d4648d661", + "href": "/api/v1/episodes/bce28964-fcfa-4a8c-9df0-413d4648d661", + "sources": [ + "https://www.netflix.com/title/80057281" + ], + "thumbnail": "https://s6.imgcdn.dev/xtSpy.jpg", + "title": "The Bathtub", + "description": "Eleven struggles to reach Will, while Lucas warns that \"the bad men are coming.\" Nancy and Jonathan show the police what Jonathan caught on camera.", + "language": "en-US", + "duration": 2580000, + "season": "/api/v1/seasons/3b980ad3-aef8-4663-a7a9-64cb4979500a", + "created_at": "2023-07-23T20:19:29.908", + "updated_at": "2023-07-23T20:19:29.908", + "episode_num": 7, + "next_episode": "/api/v1/episodes/cf90565d-c906-4e2c-a992-b190b5d117f8", + "prev_episode": "/api/v1/episodes/b664d023-2f2e-4d11-8af7-00d21bd565dd" +} +``` +:-: +```json label=Portuguese ins={8-10} +{ + "uuid": "bce28964-fcfa-4a8c-9df0-413d4648d661", + "href": "/api/v1/episodes/bce28964-fcfa-4a8c-9df0-413d4648d661", + "sources": [ + "https://www.netflix.com/title/80057281" + ], + "thumbnail": "https://s6.imgcdn.dev/xtSpy.jpg", + "title": "A banheira", + "description": "Onze tenta chegar a Will, mas Lucas dá o alerta de perigo. Nancy e Jonathan mostram à polícia as imagens capturadas pela câmera.", + "language": "pt-BR", + "duration": 2580000, + "season": "/api/v1/seasons/3b980ad3-aef8-4663-a7a9-64cb4979500a", + "created_at": "2023-07-23T20:19:29.908", + "updated_at": "2023-07-23T20:19:29.908", + "episode_num": 7, + "next_episode": "/api/v1/episodes/cf90565d-c906-4e2c-a992-b190b5d117f8", + "prev_episode": "/api/v1/episodes/b664d023-2f2e-4d11-8af7-00d21bd565dd" +} +``` +```` + +!!!info By default English (en-US) will be used. + +### Filters + +Second, the ability to search/filter the data from API was essential for the project, but i wanted more than a simple search endpoint. + +The base of the HawAPI search: + +| Field | Example | Default | Options | +| :------- | :----------------------- | :------ | :----------------------------------------------------- | +| sort | [..]?sort=first_name,ASC | — | field, ASC or DESC | +| page | [..]?page=1 | 1 | 1..X | +| size | [..]?size=12 | 10 | 1..20 | +| language | [..]?language=en-US | en-US | [I18N](https://hawapi.theproject.id/docs/guides/i18n/) | + +Now, let's see the complex HawAPI search where the request can be modified using the **modificaton symbols**. + +| Modification | Type(s) | Symbol | +| :------------------- | :----------: | :----: | +| LIKE | \* | \* | +| NOT_LIKE | \* | !\* | +| BETWEEN | Number, Date | :: | +| NOT_IN | \* | !: | +| IN | \* | : | +| GREATER_OR_EQUALS_TO | Number, Date | >= | +| LESS_OR_EQUALS_TO | Number, Date | <= | +| GREATER_THAN | Number, Date | > | +| LESS_THAN | Number, Date | < | +| NOT_EQUALS | \* | ! | +| EQUALS | \* | | + +With this power, we can create robust and complex API searches like: + +> All characters with **last name `like` Wheeler**, **gender `equals to` 1** and **birth date `greater or equals to` 1967-01-01** +> +> - [/api/v1/characters?**last_name=\*Wheeler&gender=1&birth_date=>=1967-01-01**](https://hawapi.theproject.id/api/v1/characters?last_name=*Wheeler&gender=1&birth_date=>=1967-01-01) + +## How to use the API with JavaScript + +In this section we'll see how to fetch information from **HawAPI** using both [Fetch](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch) API and the [@hawapi/js-sdk](https://npmjs.com/package/@hawapi/js-sdk) package: + +### Fetch API + +Here's how to use with the native **Fetch API**: + +1. Using **then/catch**: + +```js title="index.js" +fetch('https://hawapi.theproject.id/api/v1/characters/') + .then((response) => response.json()) + .then((data) => { + console.log(data); + }) + .catch((error) => console.error(error)); +``` + +2. Using **async/await**: + +```js title="index.js" +async function fetchAndLogCharacters() { + try { + const response = await fetch( + 'https://hawapi.theproject.id/api/v1/characters/' + ); + const data = await response.json(); + console.log(data); + } catch (error) { + console.error('Error:', error); + } +} + +fetchAndLogCharacters(); +``` + +### HawAPI SDK + +We can use the **HawaPI JavaScript SDK** to make the code better: + +1. Install the SDK: + +````codeset tabs=run-add +```bash label=npm showLineNumbers=false +npm install @hawapi/js-sdk +``` +:-: +```bash label=yarn showLineNumbers=false +yarn add @hawapi/js-sdk +``` +```` + +2. Create the instance and Make Requests: + +```ts title="index.ts" +import { EpisodeModel, createClient } from '@hawapi/js-sdk'; +// const { EpisodeModel, createClient } = require('@hawapi/js-sdk'); + +const client = createClient(); + +async function fetchAndLogCharacters() { + const res = await client.getRandom<EpisodeModel>('episodes'); + console.log(res); +} + +fetchAndLogCharacters(); +``` + +!!!note This SDK can also be used in the browser with the \<script\> tag. \ +See more in [HawAPI/js-sdk#examples/web](https://github.com/HawAPI/js-sdk/tree/main/examples/web) + +## Hawbrary + +The **Hawbrary** is a "library" to showcase all information provided from the HawAPI project, built with React (NextJs) + Typescript, hosted in GitHub Pages and using the official [@hawapi/js-sdk](https://npmjs.com/package/@hawapi/js-sdk). + +[remark_slider showArrows=true showImageInde=true] +![Hawbrary - Image 3](/static/projects/hawbrary/hawbrary-3.png) +![Hawbrary - Image 1](/static/projects/hawbrary/hawbrary-1.png) +![Hawbrary - Image 2](/static/projects/hawbrary/hawbrary-2.png) +[/remark_slider] + +See the live demo of [Hawbrary](https://hawbrary.theproject.id/) and the [GitHub repository](https://github.com/LucJosin/hawbrary) + +## Conclusion + +In this post we explore the history and features of the HawAPI project, including the Hawbrary project. + +If you find the API useful, give the **GitHub repository** a star and take advantage of **#StrangerThingsDay** to create a new project! + +!!!ref:repo HawAPI/HawAPI + +## Resources and References + +- https://github.com/HawAPI/ +- https://hawapi.theproject.id + - https://hawapi.theproject.id/docs/ + - https://hawapi.theproject.id/try-it/ +- https://hawbrary.theproject.id + - https://hawbrary.theproject.id/explorer/ diff --git a/src/content/blog/hello-world.md b/src/content/blog/hello-world.md index 1616d44d..e4624369 100644 --- a/src/content/blog/hello-world.md +++ b/src/content/blog/hello-world.md @@ -1,4 +1,5 @@ --- +permSlug: 'hello-world' title: 'Hello World' description: 'A markdown showcase of all features.' image: @@ -17,12 +18,12 @@ isIndexable: false enableComments: false easyShare: false publishedAt: '2023-10-19 09:08 UTC-3' -updatedAt: '2023-10-19 09:08 UTC-3' +updatedAt: '2024-09-01 18:15 UTC-3' --- -## Table of contents +## Summary -## Tab list +## Tabs Code: @@ -88,7 +89,9 @@ public class Application { --- -## Repository reference +## References + +### Repository Source: [github.com/github-readme-stats](https://github.com/anuraghazra/github-readme-stats) @@ -106,7 +109,7 @@ Preview: --- -## Post reference +### Post Code: @@ -333,77 +336,6 @@ inline. --- -### Headers - -Markdown supports two styles of headers, Setext and atx. - -#### Setext - -HTML Tags: `<h1>`, `<h2>` - -“Underlined” using **equal signs (=)** as `<h1>` and **dashes (-)** as `<h2>` in any number. - -Code: - - This is an H1 - ============= - This is an H2 - ------------- - -Preview: - ---- - -# This is an H1 - -## This is an H2 - ---- - -#### atx - -HTML Tags: `<h1>`, `<h2>`, `<h3>`, `<h4>`, `<h5>`, `<h6>` - -Uses 1-6 **hash characters (#)** at the start of the line, corresponding to `<h1>` - `<h6>`. - -Code: - - # This is an H1 - ## This is an H2 - ###### This is an H6 - -Preview: - ---- - -# This is an H1 - -## This is an H2 - -###### This is an H6 - ---- - -Optionally, you may “close” atx-style headers. The closing hashes **don’t need to match** the number of hashes used to open the header. - -Code: - - # This is an H1 # - ## This is an H2 ## - ### This is an H3 ###### - -Preview: - ---- - -# This is an H1 - -## This is an H2 - -### This is an H3 - ---- - ### Blockquotes HTML Tag: `<blockquote>` @@ -806,18 +738,17 @@ Code: ``` | Left | Center | Right | -|:-----|:------:|------:| -|aaa |bbb |ccc | -|ddd |eee |fff | - - A | B ----|--- -123|456 +| :--- | :----: | ----: | +| aaa | bbb | ccc | +| ddd | eee | fff | +| A | B | +| --- | --- | +| 123 | 456 | -A |B ---|-- -12|45 +| A | B | +| --- | --- | +| 12 | 45 | ``` Preview: @@ -1181,6 +1112,34 @@ Code: . dot ! exclamation mark +Preview: + +--- + +\\ backslash + +\` backtick \* asterisk + +\_ underscore + +\{\} curly braces + +\[\] square brackets + +\(\) parentheses + +\# hash mark + +\+ plus sign + +\- minus sign (hyphen) + +\. dot + +\! exclamation mark + +--- + ## Inline HTML For any markup that is not covered by Markdown’s syntax, you simply use HTML itself. There’s no need to preface it or delimit it to indicate that you’re switching from Markdown to HTML; you just use the tags. @@ -1234,4 +1193,5 @@ Preview: <div> **No Work** </div> -*** + +--- diff --git a/src/content/blog/spring-urlhandler-filter.md b/src/content/blog/spring-urlhandler-filter.md index ee165a31..145ca84a 100644 --- a/src/content/blog/spring-urlhandler-filter.md +++ b/src/content/blog/spring-urlhandler-filter.md @@ -1,5 +1,5 @@ --- -slug: 'spring-boot-using-the-new-filter-for-trailing-slash-handling' +permSlug: 'spring-boot-using-the-new-filter-for-trailing-slash-handling' title: 'Spring Boot: Using the new filter for trailing slash handling' description: 'In this tutorial, we’ll explore how to use the new UrlHandlerFilter to handle trailing slash in Spring Boot 3, including how to forward or redirect requests.' image: @@ -22,7 +22,7 @@ easyShare: true publishedAt: '2024-06-13 18:20 UTC-3' --- -## Table of contents +## Summary ## Introduction @@ -59,7 +59,7 @@ The problem is: this solution will only work effectively if the application has ### Using a custom OncePerRequestFilter To avoid adding a second route mapping to all routes, we can create a custom `OncePerRequestFilter` to redirect -all request urls that contain trailing slash **(/)** to the url without it and using the `301 (Moved Permanently){301-status-code##f0ad4e-white}` status code. +all request urls that contain trailing slash **(/)** to the url without it and using the `301 (Moved Permanently)[class="301-status-code" background-color="#f0ad4e" color="white"]` status code. ```java title="TrailingSlashHandlerFilter.java" ins={10-19} @Component @@ -137,7 +137,7 @@ It's a good option but we'll need to redirect all requests the url without trail In this version we can use the new **UrlHandlerFilter** with a few possible options: -1. Redirect **all** or **only specific** urls with `301 (Moved Permanently){301-status-code##f0ad4e-white}` +1. Redirect **all** or **only specific** urls with `301 (Moved Permanently)[class="301-status-code" background-color="#f0ad4e" color="white"]` 2. Handle **all** or **only specific** urls (Same as before Spring Boot **3.X** (Spring Framework **6.X**)) ```java title="TrailingSlashHandlerFilter.java" ins={10-15} diff --git a/src/content/config.ts b/src/content/config.ts index e67f6399..7b370615 100644 --- a/src/content/config.ts +++ b/src/content/config.ts @@ -1,11 +1,17 @@ import { defineCollection } from 'astro:content'; -import { blogSchema } from './_schemas'; +import { blogSchema, projectSchema } from './_schemas'; const blogCollection = defineCollection({ type: 'content', schema: blogSchema, }); +const projectCollection = defineCollection({ + type: 'content', + schema: projectSchema, +}); + export const collections = { blog: blogCollection, + projects: projectCollection, }; diff --git a/src/content/projects/hawapi-go-sdk.md b/src/content/projects/hawapi-go-sdk.md new file mode 100644 index 00000000..58c33aec --- /dev/null +++ b/src/content/projects/hawapi-go-sdk.md @@ -0,0 +1,74 @@ +--- +permSlug: '@hawapi/go-sdk' +title: '@hawapi/go-sdk' +description: 'HawAPI SDK for Golang designed to simplify the integration with the API.' +git: 'https://github.com/HawAPI/go-sdk' +url: 'https://pkg.go.dev/github.com/HawAPI/go-sdk' +tags: + - 'Golang' + - 'API' + - 'SDK' + - 'HawAPI' +codeLanguage: 'Typescript' +language: 'en' +icon: 'simple-icons:go' +category: 'Project' +target: + - 'Web' + - 'SDK' + - 'Library' +color: '#691313' +status: 'active' +isVisible: false +isIndexable: false +--- + +[HawAPI](/projects/hawapi/) SDK for **Golang** designed to simplify the integration with the **API**. + +## Usage + +### Installation + +```bash showLineNumbers=false +go get github.com/HawAPI/go-sdk/hawapi@latest +``` + +### Importing and Requesting + +```go +package main + +import ( + "fmt" + + "github.com/HawAPI/go-sdk/hawapi" +) + +func main() { + // Create a new client with default options + client := hawapi.NewClient() + + // Override options + client.WithOpts(hawapi.Options{ + Endpoint: "http://localhost:8080/api", + // When using 'WithOpts' or 'NewClientWithOpts' the value of + // 'UseInMemoryCache' will be set to false + UseInMemoryCache: true, + }) + + res, err := client.ListActors() + if err != nil { + panic(err) + } + + fmt.Println(res) + fmt.Println(len(res.Data)) +} +``` + +### Links + +- [Website](https://pkg.go.dev/github.com/HawAPI/go-sdk) +- [Docs](https://pkg.go.dev/github.com/HawAPI/go-sdk) +- [API Docs](https://hawapi.theproject.id/docs/) +- [GitHub](https://github.com/HawAPI/go-sdk/) diff --git a/src/content/projects/hawapi-js-sdk.md b/src/content/projects/hawapi-js-sdk.md new file mode 100644 index 00000000..5e6eeb17 --- /dev/null +++ b/src/content/projects/hawapi-js-sdk.md @@ -0,0 +1,65 @@ +--- +permSlug: '@hawapi/js-sdk' +title: '@hawapi/js-sdk' +description: 'HawAPI SDK for JavaScript/TypeScript designed to simplify the integration with the API.' +git: 'https://github.com/HawAPI/js-sdk' +url: 'https://npmjs.com/package/@hawapi/js-sdk' +tags: + - 'Typescript' + - 'API' + - 'SDK' + - 'HawAPI' +codeLanguage: 'Typescript' +language: 'en' +icon: 'simple-icons:typescript' +category: 'Project' +target: + - 'Web' + - 'SDK' + - 'Library' +color: '#691313' +status: 'active' +isVisible: false +isIndexable: false +--- + +[HawAPI](/projects/hawapi/) SDK for **JavaScript/TypeScript** designed to simplify the integration with the **API**. + +## Usage + +### Installation + +````codeset tabs=create-hawapi-client +```bash label=npm showLineNumbers=false +npm install @hawapi/js-sdk +``` +:-: +```bash label=yarn showLineNumbers=false +yarn add @hawapi/js-sdk +``` +:-: +```html label=cdn showLineNumbers=true +<script src="https://cdn.jsdelivr.net/npm/@hawapi/js-sdk/dist/index.umd.min.js"></script> +``` +```` + +### Importing and Requesting + +```ts +import { createClient } from '@hawapi/js-sdk'; + +const client = createClient(); +const result = client + .getAll('actors') + .then((data) => data) + .catch((err) => console.error(err)); + +console.log('HawAPI actors: ', result); +``` + +### Links + +- [Website](https://npmjs.com/package/@hawapi/js-sdk) +- [Docs (TypeDoc)](https://hawapi.github.io/js-sdk/v1/) +- [API Docs](https://hawapi.theproject.id/docs/) +- [GitHub](https://github.com/HawAPI/js-sdk/) diff --git a/src/content/projects/hawapi-pt.md b/src/content/projects/hawapi-pt.md new file mode 100644 index 00000000..2c4707d1 --- /dev/null +++ b/src/content/projects/hawapi-pt.md @@ -0,0 +1,62 @@ +--- +permSlug: 'hawapi' +thumbnail: 'https://repository-images.githubusercontent.com/566830817/1ee86716-d27f-4703-a003-977eca9aee8b' +images: + - '/static/projects/hawapi/hawapi-1.png' + - '/static/projects/hawapi/hawapi-2.png' + - '/static/projects/hawapi/hawapi-3.png' + - '/static/projects/hawapi/hawapi-4.png' +title: 'HawAPI' +description: 'Uma API de código aberto feita com Java (Spring Boot) e PostgreSQL sobre a série Stranger Things. Suporta múltiplas línguas (Inglês e Português) e um método de busca avançado.' +git: 'https://github.com/HawAPI/HawAPI' +url: 'https://hawapi.theproject.id/' +tags: + - 'Java' + - 'Spring Boot' + - 'JUnit' + - 'PostgreSQL' + - 'SQL' +codeLanguage: 'Java' +language: 'pt' +icon: 'mdi:language-java' +category: 'Org' +org: 'https://github.com/HawAPI/' +target: + - 'API' + - 'Web' +color: '#691313' +status: 'active' +isVisible: true +isIndexable: true +subProjects: + - 'hawapi-js-sdk' + - 'hawapi-go-sdk' +--- + +Uma API **Gratuita e Open Source** para **Stranger Things** construída com **Java (Spring Boot)** e **PostgreSQL**, com suporte para múltiplos idiomas _(Inglês e Português)_. Todas essas informações estão disponíveis através de uma **API RESTful** e servidas via **JSON**. + +### Funcionalidades + +- **Informações**: Dados detalhados sobre **personagens**, **atores**, **episódios**, **temporadas** e **locações** da série. +- **Multilíngue**: Oferece suporte à internacionalização (_i18n_) para **Inglês** e **Português**. +- **Limites**: Desenvolvedores podem fazer um número específico de requisições **por segundo**, _dependendo do nível (role)_. +- **Autenticação**: Suporta tokens de autenticação **JWT** e múltiplos níveis (roles), incluindo **ANONYMOUS**, **BASIC**, **DEV**, and **ADMIN**. +- **Cache**: Utiliza cache para melhorar o desempenho e reduzir a carga no banco de dados, armazenando temporariamente dados acessados com frequência para requisições mais rápida. +- **Busca e Filtros**: A API permite que os usuários **filtrarem** dados com base em vários parâmetros, incluindo suporte a **paginação** e **modificação de url**. +- **Open Source**: Totalmente **Gratuita** e **Open Source**, permitindo que desenvolvedores contribuam para a API ou a utilizem como um recurso de aprendizado. + +### Tecnologias + +- **Java**: API RESTful construída com Spring Boot. +- **PostgreSQL**: Dados armazenados em um banco de dados SQL. +- **Docker**: Contêineres para facilitar a implantação (deployment). +- **Astro**: Front-end para a página inicial. +- **Swagger**: Front-end para a página "Try It". +- **Retype**: Front-end para a documentação. + +### Links + +- [Website](https://hawapi.theproject.id/) +- [Docs](https://hawapi.theproject.id/docs/) +- [API](https://hawapi.theproject.id/api/) +- [GitHub](https://hawapi.theproject.id/api/) diff --git a/src/content/projects/hawapi.md b/src/content/projects/hawapi.md new file mode 100644 index 00000000..77da7d55 --- /dev/null +++ b/src/content/projects/hawapi.md @@ -0,0 +1,62 @@ +--- +permSlug: 'hawapi' +thumbnail: 'https://repository-images.githubusercontent.com/566830817/1ee86716-d27f-4703-a003-977eca9aee8b' +images: + - '/static/projects/hawapi/hawapi-1.png' + - '/static/projects/hawapi/hawapi-2.png' + - '/static/projects/hawapi/hawapi-3.png' + - '/static/projects/hawapi/hawapi-4.png' +title: 'HawAPI' +description: 'A Free and Open Source API for Stranger Things built with Java (Spring Boot) and PostgreSQL with support for multiple languages (English and Portuguese).' +git: 'https://github.com/HawAPI/HawAPI' +url: 'https://hawapi.theproject.id/' +tags: + - 'Java' + - 'Spring Boot' + - 'JUnit' + - 'PostgreSQL' + - 'SQL' +codeLanguage: 'Java' +language: 'en' +icon: 'mdi:language-java' +category: 'Org' +org: 'https://github.com/HawAPI/' +target: + - 'API' + - 'Web' +color: '#691313' +status: 'active' +isVisible: true +isIndexable: true +subProjects: + - 'hawapi-js-sdk' + - 'hawapi-go-sdk' +--- + +A Free and **Open Source** API for **Stranger Things** built with **Java (Spring Boot)** and **PostgreSQL** with support for multiple languages _(English and Portuguese)_. All this information is available through a **RESTful API** and served via **JSON**. + +### Features + +- **Information**: Detailed data about **characters**, **actors**, **episodes**, **seasons**, and **locations** from the show. +- **Multilanguage**: Provides internationalization (_i18n_) support for **English** and **Portuguese**. +- **Rate Limiting**: Developers are allowed a specific number of requests **per second**, _depending on their usage tier_. +- **Authentication**: Supports **JWT** bearer tokens and multiple roles, including **ANONYMOUS**, **BASIC**, **DEV**, and **ADMIN**. +- **Cache**: Utilizes caching to improve performance and reduce database load, storing frequently accessed data temporarily for faster retrieval. +- **Search & Filtering**: The API allows users to **filter** data based on various parameters, including support **pagination** and **query modification**. +- **Open Source**: Completely **Free** and **Open Source**, allowing developers to contribute to the API or use it as a learning resource. + +### Technologies + +- **Java**: RESTful API built with Spring Boot. +- **PostgreSQL**: Data stored in a SQL database. +- **Docker**: Containers for easy deployment. +- **Astro**: Front-end for the home page. +- **Swagger**: Front-end for the "Try It" page. +- **Retype**: Front-end for documentation. + +### Links + +- [Website](https://hawapi.theproject.id/) +- [Docs](https://hawapi.theproject.id/docs/) +- [API](https://hawapi.theproject.id/api/) +- [GitHub](https://hawapi.theproject.id/api/) diff --git a/src/content/projects/hawbrary-pt.md b/src/content/projects/hawbrary-pt.md new file mode 100644 index 00000000..ee77e667 --- /dev/null +++ b/src/content/projects/hawbrary-pt.md @@ -0,0 +1,55 @@ +--- +permSlug: 'hawbrary' +thumbnail: '/static/projects/hawbrary/hawbrary.png' +images: + - '/static/projects/hawbrary/hawbrary-1.png' + - '/static/projects/hawbrary/hawbrary-2.png' + - '/static/projects/hawbrary/hawbrary-3.png' +title: 'Hawbrary' +description: 'O Hawbrary é uma amostra do projeto HawAPI - Uma API gratuita e de código aberto para Stranger Things - construída com React (NextJs) + Typescript.' +git: 'https://github.com/LucJosin/hawbrary' +url: 'https://hawbrary.theproject.id/' +tags: + - 'React.js' + - 'Next.js' + - 'SDK' + - 'CSS' + - 'TypeScript' +codeLanguage: 'Typescript' +language: 'pt' +icon: 'simple-icons:typescript' +category: 'Project' +target: + - 'Web' +color: '#691313' +status: 'active' +isVisible: true +isIndexable: true +--- + +O Hawbrary é uma amostra do [HawAPI - Uma API Gratuita e Open Source para Stranger Things](/pt/projects/hawapi/) - construída com **React (NextJs)** + **TypeScript**. Esta biblioteca inclui **atores**, **personagens**, **episódios**, **locações**, **temporadas** e todas as suas informações. + +- **Informações**: Todos os dados são obtidos através da API RESTful [HawAPI](/projects/hawapi/). +- **Multilíngue**: O site oferece uma opção para alternar o idioma dos dados, aproveitando o suporte multilíngue da API. +- **Implantação e Hospedagem**: Implantado utilizando **CI/CD**, este site estático é hospedado no [GitHub Pages](https://pages.github.com/). + +### Tecnologias + +- **React (Next.Js)**: Utilizado para construir a interface de usuário dinâmica e interativa. +- **CSS**: Para estilização e garantir um layout responsivo. +- **TypeScript**: Melhora a eficiência do desenvolvimento com segurança de tipos. +- **ImgCDN**: Todas as imagens são entregues através de [imgcdn.dev](https://imgcdn.dev) para melhorar o desempenho. +- **SDK**: Utiliza o [SDK JavaScript/TypeScript](https://www.npmjs.com/package/@hawapi/js-sdk) (_Kit de Desenvolvimento de Software_) oficial do HawAPI. + +### Links + +- [Website](https://hawbrary.theproject.id/) +- [Explorador](https://hawbrary.theproject.id/explorer/) + - [Atores](https://hawbrary.theproject.id/explorer/actors/) + - [Personagens](https://hawbrary.theproject.id/explorer/characters/) + - [Episódios](https://hawbrary.theproject.id/explorer/episodes/) + - [Temporadas](https://hawbrary.theproject.id/explorer/seasons/) + - [Localizações](https://hawbrary.theproject.id/explorer/locations/) + - [Jogos](https://hawbrary.theproject.id/explorer/games/) +- [GitHub](https://github.com/LucJosin/hawbrary/) +- [HawAPI JS/TS SDK](https://www.npmjs.com/package/@hawapi/js-sdk) diff --git a/src/content/projects/hawbrary.md b/src/content/projects/hawbrary.md new file mode 100644 index 00000000..969ea852 --- /dev/null +++ b/src/content/projects/hawbrary.md @@ -0,0 +1,55 @@ +--- +permSlug: 'hawbrary' +thumbnail: '/static/projects/hawbrary/hawbrary.png' +images: + - '/static/projects/hawbrary/hawbrary-1.png' + - '/static/projects/hawbrary/hawbrary-2.png' + - '/static/projects/hawbrary/hawbrary-3.png' +title: 'Hawbrary' +description: 'The Hawbrary is a showcase of the HawAPI - A Free and Open Source API for Stranger Things - built with React (NextJs) + Typescript.' +git: 'https://github.com/LucJosin/hawbrary' +url: 'https://hawbrary.theproject.id/' +tags: + - 'React.js' + - 'Next.js' + - 'SDK' + - 'CSS' + - 'TypeScript' +codeLanguage: 'Typescript' +language: 'en' +icon: 'simple-icons:typescript' +category: 'Project' +target: + - 'Web' +color: '#691313' +status: 'active' +isVisible: true +isIndexable: true +--- + +The Hawbrary is a showcase of the [HawAPI - A Free and Open Source API for Stranger Things](/projects/hawapi/) - built with **React (NextJs)** + **Typescript**. This library includes **actors**, **characters**, **episodes**, **locations**, **seasons** and all its information. + +- **Information**: All data is fetched from the [HawAPI](/projects/hawapi/) RESTful API. +- **Multilanguage**: The website provides an option to toggle the data language, taking advantage of the API multilanguage support. +- **Deployment & Hosting**: Deployed using **CI/CD**, this static site is hosted on [GitHub Pages](https://pages.github.com/) + +### Technologies + +- **React (Next.Js)**: Utilized for building the dynamic and interactive user interface. +- **CSS**: Styling and ensuring a responsive layout. +- **TypeScript**: Enhances development efficiency with type safety. +- **ImgCDN**: All images are delivered using [imgcdn.dev](https://imgcdn.dev) for improved performance. +- **SDK**: Uses the official HawAPI [JavaScript/TypeScript SDK](https://www.npmjs.com/package/@hawapi/js-sdk) (_Software Development Kit_). + +### Links + +- [Website](https://hawbrary.theproject.id/) +- [Explorer](https://hawbrary.theproject.id/explorer/) + - [Actors](https://hawbrary.theproject.id/explorer/actors/) + - [Characters](https://hawbrary.theproject.id/explorer/characters/) + - [Episodes](https://hawbrary.theproject.id/explorer/episodes/) + - [Seasons](https://hawbrary.theproject.id/explorer/seasons/) + - [Locations](https://hawbrary.theproject.id/explorer/locations/) + - [Games](https://hawbrary.theproject.id/explorer/games/) +- [GitHub](https://github.com/LucJosin/hawbrary/) +- [HawAPI JS/TS SDK](https://www.npmjs.com/package/@hawapi/js-sdk) diff --git a/src/content/projects/lucasjosino-com-pt.md b/src/content/projects/lucasjosino-com-pt.md new file mode 100644 index 00000000..e441713c --- /dev/null +++ b/src/content/projects/lucasjosino-com-pt.md @@ -0,0 +1,29 @@ +--- +permSlug: 'lucasjosino.com' +thumbnail: 'https://www.lucasjosino.com/static/default-og.png' +title: 'lucasjosino.com' +description: 'Portfólio/blog minimalista construído com Astro, TypeScript e i18n para suporte de múltiplos idiomas.' +git: 'https://github.com/LucJosin/lucasjosino.com' +tags: + - 'Astro' + - 'TypeScript' + - 'JavaScript' + - 'CSS' +codeLanguage: 'Astro' +language: 'pt' +icon: 'simple-icons:astro' +category: 'Project' +target: + - 'Web' +status: 'active' +isVisible: true +isIndexable: true +--- + +**Portfólio/blog** minimalista construído com **Astro**, **TypeScript** e **i18n** para suporte de múltiplos idiomas. + +### Tecnologias + +- **Astro**: Um framework web JavaScript otimizado para a criação de sites rápidos e voltados para conteúdo. +- **CSS**: Para estilização e garantir um layout responsivo. +- **TypeScript**: Melhora a eficiência do desenvolvimento com segurança de tipos. diff --git a/src/content/projects/lucasjosino-com.md b/src/content/projects/lucasjosino-com.md new file mode 100644 index 00000000..6d40fdba --- /dev/null +++ b/src/content/projects/lucasjosino-com.md @@ -0,0 +1,29 @@ +--- +permSlug: 'lucasjosino.com' +thumbnail: 'https://www.lucasjosino.com/static/default-og.png' +title: 'lucasjosino.com' +description: 'Minimalist portfolio website/blog built with Astro, TypeScript, and i18n for multilingual support.' +git: 'https://github.com/LucJosin/lucasjosino.com' +tags: + - 'Astro' + - 'TypeScript' + - 'JavaScript' + - 'CSS' +codeLanguage: 'Astro' +language: 'en' +icon: 'simple-icons:astro' +category: 'Project' +target: + - 'Web' +status: 'active' +isVisible: true +isIndexable: true +--- + +Minimalist portfolio **website/blog** built with **Astro**, **TypeScript**, and **i18n** for multilingual support. + +### Technologies + +- **Astro**: A JavaScript web framework optimized for building fast, content-driven websites. +- **CSS**: Styling and ensuring a responsive layout. +- **TypeScript**: Enhances development efficiency with type safety. diff --git a/src/content/projects/on-audio-query-pt.md b/src/content/projects/on-audio-query-pt.md new file mode 100644 index 00000000..d0210679 --- /dev/null +++ b/src/content/projects/on-audio-query-pt.md @@ -0,0 +1,45 @@ +--- +permSlug: 'on_audio_query' +thumbnail: 'https://pub.dev/static/hash-v7cgjij4/img/pub-dev-icon-cover-image.png' +title: 'on_audio_query' +description: 'Plugin Flutter usado para consultar informações de áudios/músicas do armazenamento do dispositivo.' +git: 'https://github.com/LucJosin/on_audio_query' +url: 'https://pub.dev/packages/on_audio_query#gif-examples' +tags: + - 'Kotlin' + - 'Swift' + - 'Flutter' + - 'Dart' +codeLanguage: 'Dart' +language: 'pt' +icon: 'simple-icons:dart' +category: 'Project' +target: + - 'Mobile' +color: '#555555' +status: 'inactive' +isVisible: true +isIndexable: true +--- + +[Flutter](https://flutter.dev/) **Plugin** usado para consultar informações de **áudios/músicas** _[título, artista, álbum, etc..]_ do armazenamento do dispositivo. + +Este plugin utiliza a interface de plataforma do Flutter para lidar com código nativo de **Android (Kotlin)** e **iOS (Swift)**. Suporta vários formatos como mp3, flac, aac, opus, etc., e oferece um poderoso sistema de filtragem. + +- **Recursos**: + - Permissões de armazenamento **integradas** para **leitura** e **escrita**. + - Acesso a todos os **áudios**, **álbuns**, **artistas**, **playlists** e **gêneros**, com métodos de consulta específicos para **busca e ordenação**. + - Gerencie playlists **criando**, **excluindo**, **renomeando** e **modificando**, incluindo adicionar, remover ou mover áudios. + +### Tecnologias + +- **Flutter**: Um kit de ferramentas UI para criar aplicativos compilados nativamente para dispositivos móveis, web e desktop a partir de uma única base de código. + - **Flutter Plugin**: Estenda as capacidades do Flutter com recursos específicos da plataforma usando integração com código nativo. +- **Kotlin**: Uma linguagem de programação moderna para desenvolvimento Android e JVM, oferecendo sintaxe concisa, segurança e interoperabilidade com Java. +- **Swift**: Uma linguagem de programação poderosa e intuitiva para apps iOS, macOS, watchOS e tvOS, projetada para segurança e desempenho. + +### Links + +- [Website](https://pub.dev/packages/on_audio_query) +- [Docs](https://pub.dev/documentation/on_audio_query/latest/) +- [GitHub](https://github.com/LucJosin/on_audio_query) diff --git a/src/content/projects/on-audio-query.md b/src/content/projects/on-audio-query.md new file mode 100644 index 00000000..9cafbb61 --- /dev/null +++ b/src/content/projects/on-audio-query.md @@ -0,0 +1,51 @@ +--- +permSlug: 'on_audio_query' +thumbnail: 'https://pub.dev/static/hash-v7cgjij4/img/pub-dev-icon-cover-image.png' +images: + - 'https://user-images.githubusercontent.com/76869974/129740857-33f38b27-06a3-4959-bb31-2ae97d6b66ff.gif' + - 'https://user-images.githubusercontent.com/76869974/129741012-1215b292-d700-466f-9c41-552df0ad5e89.gif' + - 'https://user-images.githubusercontent.com/76869974/129741188-e6803432-24d7-4e39-bfde-cc6765e13663.gif' + - 'https://user-images.githubusercontent.com/76869974/129741151-b820edc9-ddbf-4446-b67a-6e254cb5a46d.gif' +showImagesInSlider: false +title: 'on_audio_query' +description: 'Flutter Plugin used to query audios/songs infos from device storage.' +git: 'https://github.com/LucJosin/on_audio_query' +url: 'https://pub.dev/packages/on_audio_query#gif-examples' +tags: + - 'Kotlin' + - 'Swift' + - 'Flutter' + - 'Dart' +codeLanguage: 'Dart' +language: 'en' +icon: 'simple-icons:dart' +category: 'Project' +target: + - 'Mobile' +color: '#555555' +status: 'inactive' +isVisible: true +isIndexable: true +--- + +[Flutter](https://flutter.dev/) **Plugin** used to query **audios/songs** infos _[title, artist, album, etc..]_ from device storage. + +This plugin uses flutter platform interface to handle native code from **Android (Kotlin)** and **iOS (Swift)**. Supports multiple formats mp3, flac, aac, opus, etc.. and a powerful filtering. + +- **Features**: + - **Built-in** storage permissions to **read** and **write**. + - Access all **audios**, **albums**, **artists**, **playlists**, and **genres**, with specific query methods for **search and sorting**. + - Manage playlists by **creating**, **deleting**, **renaming**, and **modifying** them, including adding, removing, or moving audios. + +### Technologies + +- **Flutter**: A UI toolkit for building natively compiled apps for mobile, web, and desktop from a single codebase. + - **Flutter Plugin**: Extend Flutter's capabilities with platform-specific features using native code integration. +- **Kotlin**: A modern programming language for Android and JVM development, offering concise syntax, safety, and interoperability with Java. +- **Swift**: A powerful, intuitive programming language for iOS, macOS, watchOS, and tvOS apps, designed for safety and performance. + +### Links + +- [Website](https://pub.dev/packages/on_audio_query) +- [Docs](https://pub.dev/documentation/on_audio_query/latest/) +- [GitHub](https://github.com/LucJosin/on_audio_query) diff --git a/src/i18n/config.ts b/src/i18n/config.ts new file mode 100644 index 00000000..437a8af2 --- /dev/null +++ b/src/i18n/config.ts @@ -0,0 +1,17 @@ +/** + * Default locale of the site, defined in the Astro config + */ +export const defaultLocale = 'en' as const; + +/** + * List of available locales, defined in the Astro config + */ +export const locales = ['en', 'pt'] as const; + +/** + * List of available locales, with the explicit format + */ +export const explicitLocales = { + en: 'en-US', + pt: 'pt-BR', +} as const; diff --git a/src/i18n/en/404.ts b/src/i18n/en/404.ts new file mode 100644 index 00000000..d97234ed --- /dev/null +++ b/src/i18n/en/404.ts @@ -0,0 +1,12 @@ +export const s404 = { + description: 'Page not found. Maybe something was deleted or moved.', + help_message: 'Need help? Contact using:', + go_back: 'Go Back', + go_back_alt: 'Go back to home page', + links: { + github_alt: 'Repository of lucasjosino.com project', + email_alt: 'Email for contact', + copy_email_tooltip: 'Copy email', + copy_email_success_tooltip: 'Copied!', + }, +}; diff --git a/src/i18n/en/about.ts b/src/i18n/en/about.ts new file mode 100644 index 00000000..25a46cdb --- /dev/null +++ b/src/i18n/en/about.ts @@ -0,0 +1,38 @@ +export const about = { + title: 'About Me', + article: { + topic_1: { + title: 'About Me', + paragraph_1: 'Hi, 👋!', + paragraph_2: + "I'm <strong>Lucas Josino</strong>, a 21 y/o from <strong>Brazil 🇧🇷</strong> and an enthusiastic <strong>Software Developer</strong>. I'm currently pursuing a <strong>Bachelor's degree in Information Systems</strong> (<i>Sistemas da Informação, in Portuguese</i>).", + paragraph_3: + 'I have always enjoyed <strong>technology</strong> and <strong>innovations</strong>, which is why I have been immersed in this world since I was young. Eventually, I decided to fully dedicate myself and pursue a degree in this field.', + paragraph_4: + "I have been studying <strong>Backend & APIs</strong> developement using <strong>Java</strong>, <strong>Golang</strong> and <strong>Spring Boot</strong> through courses/bootcamps and working on some <a href={{link}} class='about-link'>personal projects</a>. I aim to contribute as much as possible, continually developing more knowledge in areas and technologies that I enjoy.", + paragraph_5: + "<strong><i>As I'm always trying to learn new things</i></strong>, I like sharing what I discover during my studies. <a href={{link}} class='about-link'>My blog</a> is where I experiment with new technologies and break down solutions to the challenges I run into. The goal is documenting the process and hopefully helping others figure things out too.", + }, + topic_2: { + title: 'Beyond the Code', + paragraph_1: + 'Alongside my passion for technology, in my free time I enjoy <strong>listening to music</strong>, <strong>reading</strong>, <strong>playing video games</strong>, and <strong>chilling with my cats</strong>.', + paragraph_2: + "I'm also keen on <strong>photography</strong> and <strong>cooking</strong>.", + }, + topic_3: { + title: 'Toolbox', + paragraph_1: + 'A collection of <strong>programming languages</strong>, <strong>frameworks</strong>, and <strong>tools</strong> I use:', + }, + topic_4: { + title: 'Github Stats', + paragraph_1: + 'Check out my GitHub stats to see my <strong>contributions</strong> e <strong>repositories</strong>.', + }, + topic_5: { + title: 'Contact', + paragraph_1: 'Feel free to connect with me through:', + }, + }, +}; diff --git a/src/i18n/en/blog.ts b/src/i18n/en/blog.ts new file mode 100644 index 00000000..72aac0c6 --- /dev/null +++ b/src/i18n/en/blog.ts @@ -0,0 +1,7 @@ +export const blog = { + title: 'Blog', + description: + 'Explore my developer blog with thoughts, ideas and other stuff.', + no_post_found: + "No posts found! 🕵️‍♂️ Looks like they're hiding... <br> How about trying a different language?", +}; diff --git a/src/i18n/en/categories.ts b/src/i18n/en/categories.ts new file mode 100644 index 00000000..2d1a6203 --- /dev/null +++ b/src/i18n/en/categories.ts @@ -0,0 +1,11 @@ +export const categories = { + title: 'Categories', + description: 'Explore all categories of my personal blog', + category: { + title: '{{category}} - Category', + description: 'Explore all posts categorized with: {{category}}', + description_one: 'Explore {{count}} post categorized with "{{category}}"', + description_other: + 'Explore {{count}} posts categorized with "{{category}}"', + }, +}; diff --git a/src/i18n/en/common.ts b/src/i18n/en/common.ts new file mode 100644 index 00000000..36d8e1e1 --- /dev/null +++ b/src/i18n/en/common.ts @@ -0,0 +1,31 @@ +export const common = { + title: 'Software Developer', + description: + "Hi! I'm Lucas Josino, an enthusiastic Software Developer with a focus on Java and Golang, based in Brazil.", + header: { + homepage: 'Home', + homepage_tooltip: + 'Home <br> <kbd aria-label="alt">Alt</kbd> + <kbd aria-label="h">H</kbd>', + blog: 'Blog', + projects: 'Projects', + about: 'About', + blog_link_alt: 'Go to blog page', + projects_link_alt: 'Go to projects page', + about_link_alt: 'Go to about page', + change_language: 'Change language', + change_language_tooltip: + 'Change language <br> <kbd aria-label="alt">Alt</kbd> + <kbd aria-label="l">L</kbd>', + change_language_tooltip_disabled: 'Translation not available', + change_theme: 'Change theme', + change_theme_tooltip: + 'Change theme <br> <kbd aria-label="alt">Alt</kbd> + <kbd aria-label="t">T</kbd>', + }, + footer: { + powered: 'Built with ', + links: { + rss: 'RSS', + tags: 'Tags', + source_code: 'Source Code', + }, + }, +}; diff --git a/src/i18n/en/home.ts b/src/i18n/en/home.ts new file mode 100644 index 00000000..c05c686c --- /dev/null +++ b/src/i18n/en/home.ts @@ -0,0 +1,13 @@ +export const home = { + welcome: + "Hi 👋, I'm <strong>Lucas Josino</strong>, a 21 y/o from <strong>Brazil</strong> 🇧🇷... - About ➞", + see_more: 'See more', + posts: { + title: 'Posts', + see_more_alt: 'See more posts', + }, + projects: { + title: 'Projects', + see_more_alt: 'See more projects', + }, +}; diff --git a/src/i18n/en/index.ts b/src/i18n/en/index.ts new file mode 100644 index 00000000..849ba7d3 --- /dev/null +++ b/src/i18n/en/index.ts @@ -0,0 +1,23 @@ +import { s404 } from './404'; +import { about } from './about'; +import { blog } from './blog'; +import { categories } from './categories'; +import { common } from './common'; +import { home } from './home'; +import { post } from './post'; +import { project } from './project'; +import { projects } from './projects'; +import { tags } from './tags'; + +export const enLocale = { + '404': s404, + about, + blog, + categories, + common, + home, + post, + projects, + project, + tags, +}; diff --git a/src/i18n/en/post.ts b/src/i18n/en/post.ts new file mode 100644 index 00000000..62668ff5 --- /dev/null +++ b/src/i18n/en/post.ts @@ -0,0 +1,22 @@ +export const post = { + card: { + read_post: 'Read post', + see_more_posts_from_this_category: 'See all posts with this category', + }, + tags: 'Tags', + tags_alt: 'See all tags', + tags_see_more_alt: 'See more posts with "{{tag}}" tag', + comments: 'Comments', + comments_go_alt: 'Go to comments', + related_posts: 'Related posts', + see_post_history: 'See post history', + last_updated: 'Last updated: ', + share: { + title: 'Enjoy this post? Feel free to share!', + linkedin_alt: 'Share to LinkedIn', + twitter_alt: 'Share to Twitter', + reddit_alt: 'Share to Reddit', + bluesky_alt: 'Share to Bluesky', + copy_link_alt: 'Copy link', + }, +}; diff --git a/src/i18n/en/project.ts b/src/i18n/en/project.ts new file mode 100644 index 00000000..1fb04f8a --- /dev/null +++ b/src/i18n/en/project.ts @@ -0,0 +1,38 @@ +export const project = { + title: 'Project', + target: 'Target', + type: 'Type', + status: 'Status', + language: 'Language', + article: 'Article', + article_alt: 'View article', + images: 'Images', + images_alt: 'View images', + code_alt: 'View code', + preview_alt: 'View preview', + details: 'Details', + see_more_alt: 'See more', + project_status: { + in_progress: { + title: 'In Progress', + description: 'Work on the project is currently ongoing.', + }, + on_hold: { + title: 'On Hold', + description: 'The project has been temporarily paused.', + }, + completed: { + title: 'Completed', + description: 'The project has been finished.', + }, + inactive: { + title: 'Inactive', + description: + 'The project is not currently active but may be resumed in the future.', + }, + active: { + title: 'Active', + description: 'The project is currently active and work is ongoing.', + }, + }, +}; diff --git a/src/i18n/en/projects.ts b/src/i18n/en/projects.ts new file mode 100644 index 00000000..ac9d5151 --- /dev/null +++ b/src/i18n/en/projects.ts @@ -0,0 +1,8 @@ +export const projects = { + title: 'Projects', + description: + "Discover the projects I've been a part of and those I'm actively involved in.", + repositories: 'Repositories', + org: 'Org', + org_alt: 'The project is a collection of related projects', +}; diff --git a/src/i18n/en/tags.ts b/src/i18n/en/tags.ts new file mode 100644 index 00000000..78813b7d --- /dev/null +++ b/src/i18n/en/tags.ts @@ -0,0 +1,10 @@ +export const tags = { + title: 'Tags', + description: 'Explore all tags of my personal blog', + tag: { + title: '{{tag}} - Tag', + description: 'Explore all posts tagged with: {{tag}}', + description_one: 'Explore {{count}} post tagged with "{{tag}}"', + description_other: 'Explore {{count}} posts tagged with "{{tag}}"', + }, +}; diff --git a/src/i18n/index.ts b/src/i18n/index.ts new file mode 100644 index 00000000..eebc789e --- /dev/null +++ b/src/i18n/index.ts @@ -0,0 +1,235 @@ +import { getRelativeLocaleUrl } from 'astro:i18n'; +import { defaultLocale, locales } from './config'; +import { enLocale } from './en'; +import { ptLocale } from './pt'; +import type { i18nSchema } from './schema'; +import { + type Locale, + type LocaleSlug, + type NestedKeys, + type TranslationKeys, +} from './types'; + +/** + * Get the locale and slug from a path + * @param path path to extract locale and slug + * @returns locale and slug extracted from the path + * @example + * ```ts + * // path = '/pt/about' + * console.log(extractLocaleAndSlug(path)) + * // Output: { locale: 'pt', slug: '/about' } + * ``` + */ +export function extractLocaleAndSlug(path: string): LocaleSlug { + const parts = path.split('/').filter(Boolean); + + let locale = defaultLocale as Locale; + let slug = path; + + if (parts.length > 0 && locales.includes(parts[0] as Locale)) { + locale = parts[0] as Locale; + slug = '/' + parts.slice(1).join('/'); + } + + return { + locale, + slug: normalizeUrl(slug) || '/', + }; +} + +/** + * Normalize a URL by adding a trailing slash at start and end + * @param url URL to normalize + * @returns normalized URL + * @example + * ```ts + * // url = 'about' + * console.log(normalizeUrl(url)) + * // Output: '/about/' + * ``` + */ +export function normalizeUrl(url: string): string { + url = url.trim(); + + if (!url.startsWith('/')) { + url = '/' + url; + } + + if (!url.endsWith('/')) { + url += '/'; + } + + return url; +} + +interface NestedTranslations { + [key: string]: string | NestedTranslations; +} + +const translations: { [key: string]: string | NestedTranslations } = { + ['' || defaultLocale]: enLocale, + pt: ptLocale, +}; + +interface useLocaleReturn { + locale: Locale; + slug: string; + t: ( + key: TranslationKeys, + replacements?: Record<string, string | number> + ) => string; + localizePath: (path: string) => string; + switchLocale: (locale: string) => string; +} + +/** + * Utility function to use i18n in Astro + * @param pathname current page path + * @returns object with locale, slug, t, localizePath and switchLocale + * @example + * ```astro + * --- + * import { useLocale } from 'lib/i18n'; + * + * const { locale, t, localizePath, switchLocale } = useLocale(Astro.url.pathname); + * --- + * + * <div> + * <h1>{t('home.title')}</h1> + * <p>Current locale: {locale}</p> + * <p>{t('home.greeting', { name: 'Alice' })}</p> + * <a href={localizePath('/about')}>{t('home.about')}</a> + * <a href={switchLocale('en')}>English</a> + * <a href={switchLocale('pt')}>Portuguese</a> + * </div> + * ``` + */ +export function useLocale(pathname: string): useLocaleReturn { + const { locale, slug } = extractLocaleAndSlug(pathname); + return { + /** + * Locale of the current page + */ + locale, + /** + * Slug of the current page + */ + slug, + /** + * Translate a key to the current locale + * @param key key reference to the translation + * @param replacements object with values to replace in the translation + * @returns translated string + * @example + * ```ts + * console.log(t('home.title')) + * // Output: 'Welcome to Astro' + * + * console.log(t('home.greeting', { name: 'Alice' })) + * // Output: 'Hello, Alice!' + * + * console.log(t('home.unreadMessages', { count: 5 })) + * // Output: 'You have 5 unread messages' + * ``` + */ + t: (key: TranslationKeys, replacements?: Record<string, string | number>) => + t(locale, key, replacements), + /** + * Get the relative URL for the current locale + * @param path path to be appended to the current locale + * @returns relative URL for the current locale + * @example + * ```ts + * // currentLocale = pt + * console.log(localizePath('/about')) + * // Output: '/pt/about' + * ``` + */ + localizePath: (path: string) => getRelativeLocaleUrl(locale, path), + /** + * Get the relative URL for a specific locale + * @param locale locale to be appended to the path + * @returns relative URL for the specific locale + * @example + * ```ts + * // current Path: '/about' + * console.log(switchLocale('pt')) + * // Output: '/pt/about' + * ``` + */ + switchLocale: (locale: string) => getRelativeLocaleUrl(locale, slug), + }; +} + +function t( + locale: string, + key: TranslationKeys, + replacements?: Record<string, string | number> +): string { + const keys = key.split('.') as Array<string>; + const schema = translations[locale]; + let result: NestedTranslations | string | undefined = getNestedValue( + schema, + keys + ); + + if (!result) { + throw new Error(`Missing translation for key: ${key}`); + } + + // Handle pluralization if 'count' is provided + if ( + replacements && + 'count' in replacements && + typeof replacements.count === 'number' + ) { + const count = replacements.count; + const baseKey = key as string; + + const oneKey = `${baseKey}_one` as NestedKeys<i18nSchema>; + const otherKey = `${baseKey}_other` as NestedKeys<i18nSchema>; + + const one = getNestedValue(schema, oneKey.split('.')); + const other = getNestedValue(schema, otherKey.split('.')); + + if (typeof one === 'string' && typeof other === 'string') { + result = count === 1 ? one : other; + } else { + throw new Error(`Missing pluralization for key: ${key}, count: ${count}`); + } + } + + // If result is a string and replacements are provided, replace placeholders + if (typeof result === 'string' && replacements) { + let translated = result; + for (const [replaceKey, replaceValue] of Object.entries(replacements)) { + translated = translated.replace( + `{{${replaceKey}}}`, + String(replaceValue) + ); + } + return translated; + } + + if (typeof result !== 'string') { + throw new Error(`Translation result is not a string for key: ${key}`); + } + + return result; +} + +function getNestedValue( + obj: NestedTranslations | string, + keys: string[] +): NestedTranslations | string | undefined { + let result: NestedTranslations | string = obj; + for (const key of keys) { + if (result && typeof result === 'object' && key in result) { + result = result[key]; + } else { + return undefined; + } + } + return result; +} diff --git a/src/i18n/pt/404.ts b/src/i18n/pt/404.ts new file mode 100644 index 00000000..0f764b95 --- /dev/null +++ b/src/i18n/pt/404.ts @@ -0,0 +1,12 @@ +export const s404 = { + description: 'Página não encontrada. Talvez tenha sido apagada ou movida.', + help_message: 'Precisa de ajuda? Entre em contato:', + go_back: 'Voltar', + go_back_alt: 'Voltar para o início', + links: { + github_alt: 'Repositório do lucasjosino.com', + email_alt: 'Email para contato', + copy_email_tooltip: 'Copiar email', + copy_email_success_tooltip: 'Copiado!', + }, +}; diff --git a/src/i18n/pt/about.ts b/src/i18n/pt/about.ts new file mode 100644 index 00000000..35cf848b --- /dev/null +++ b/src/i18n/pt/about.ts @@ -0,0 +1,38 @@ +export const about = { + title: 'Sobre Mim', + article: { + topic_1: { + title: 'Sobre Mim', + paragraph_1: 'Olá, 👋!', + paragraph_2: + 'Sou <strong>Lucas Josino</strong>, um <strong>Brasileiro 🇧🇷</strong> de 21 anos e um entusiasta em <strong>Desenvolvimento de Software</strong>. Atualmente, estou cursando um <strong>Bacharelado em Sistemas de Informação</strong>.', + paragraph_3: + 'Eu sempre gostei de <strong>tecnologia</strong> e <strong>inovações</strong>, e é por isso que eu estou imerso neste mundo desde que era jovem. Eventualmente, decidi me dedicar completamente e buscar um diploma neste campo.', + paragraph_4: + 'Eu venho estudando desenvolvimento de <strong>Backend & APIs</strong> usando <strong>Java</strong>, <strong>Golang</strong> e <strong>Spring Boot</strong> através de cursos/bootcamps e trabalhando em alguns <a href={{link}} class="about-link"> projetos pessoais </a>. Tenho como objetivo contribuir o máximo possível, desenvolvendo continuamente mais conhecimento em áreas e tecnologias que eu aprecio.', + paragraph_5: + "<strong><i>Como eu sempre estou tentando aprender novas coisas</i></strong>, gosto de compartilhar o que descubro durante meus estudos. <a href={{link}} class='about-link'>Meu blog</a> é onde experimento novas tecnologias e explico as soluções para os desafios que encontro. O objetivo é documentar o processo e, quem sabe, ajudar outras pessoas a resolverem problemas também.", + }, + topic_2: { + title: 'Além do código', + paragraph_1: + 'Além da minha paixão por tecnologia, no meu tempo livre gosto de <strong>ouvir música</strong>, <strong>ler</strong>, <strong>jogar videogame</strong>, e <strong>brincar com meus gatos.</strong>.', + paragraph_2: + 'Também tenho interesse por <strong>fotografia</strong> and <strong>culinária</strong>.', + }, + topic_3: { + title: 'Toolbox', + paragraph_1: + 'Uma coleção de <strong>linguagens de programação</strong>, <strong>frameworks</strong> e <strong>ferramentas</strong> que eu utilizo:', + }, + topic_4: { + title: 'Status do Github', + paragraph_1: + 'Confira minhas estatísticas do GitHub para ver minhas <strong>contribuições</strong> e <strong>repositórios</strong>.', + }, + topic_5: { + title: 'Contato', + paragraph_1: 'Sinta-se à vontade para se conectar comigo através do:', + }, + }, +}; diff --git a/src/i18n/pt/blog.ts b/src/i18n/pt/blog.ts new file mode 100644 index 00000000..9d81e839 --- /dev/null +++ b/src/i18n/pt/blog.ts @@ -0,0 +1,7 @@ +export const blog = { + title: 'Blog', + description: + 'Explore meu blog de desenvolvedor com pensamentos, ideias e outras coisas.', + no_post_found: + 'Nenhuma postagem encontrada! 🕵️‍♂️ Parece que eles estão se escondendo... <br> Que tal tentar um idioma diferente?', +}; diff --git a/src/i18n/pt/categories.ts b/src/i18n/pt/categories.ts new file mode 100644 index 00000000..0f695494 --- /dev/null +++ b/src/i18n/pt/categories.ts @@ -0,0 +1,11 @@ +export const categories = { + title: 'Categorias', + description: 'Explore todas as categorias do meu blog pessoal', + category: { + title: 'Categoria: {{category}}', + description: 'Explore todos os posts categorizados com: {{category}}', + description_one: 'Explore {{count}} post categorizado com "{{category}}"', + description_other: + 'Explore {{count}} posts categorizados com "{{category}}"', + }, +}; diff --git a/src/i18n/pt/common.ts b/src/i18n/pt/common.ts new file mode 100644 index 00000000..3ab1539f --- /dev/null +++ b/src/i18n/pt/common.ts @@ -0,0 +1,31 @@ +export const common = { + title: 'Desenvolvedor de Software', + description: + 'Olá! Sou Lucas Josino, um Desenvolvedor de Software apaixonado por Java e Golang, e que mora no Brasil.', + header: { + homepage: 'Início', + homepage_tooltip: + 'Início <br> <kbd aria-label="alt">Alt</kbd> + <kbd aria-label="h">H</kbd>', + blog: 'Blog', + projects: 'Projetos', + about: 'Sobre', + blog_link_alt: 'Ir para a página de postagens', + projects_link_alt: 'Ir para a página de projetos', + about_link_alt: 'Ir para a página de sobre', + change_language: 'Trocar de idioma', + change_language_tooltip: + 'Trocar de idioma <br> <kbd aria-label="alt">Alt</kbd> + <kbd aria-label="l">L</kbd>', + change_language_tooltip_disabled: 'Tradução não disponível', + change_theme: 'Trocar de tema', + change_theme_tooltip: + 'Trocar de tema <br> <kbd aria-label="alt">Alt</kbd> + <kbd aria-label="t">T</kbd>', + }, + footer: { + powered: 'Desenvolvido com ', + links: { + rss: 'RSS', + tags: 'Tags', + source_code: 'Código do site', + }, + }, +}; diff --git a/src/i18n/pt/home.ts b/src/i18n/pt/home.ts new file mode 100644 index 00000000..f1414baa --- /dev/null +++ b/src/i18n/pt/home.ts @@ -0,0 +1,14 @@ +export const home = { + welcome: + 'Olá 👋, Sou <strong>Lucas Josino</strong>, um <strong>Brasileiro 🇧🇷</strong> de 21 anos... - Sobre ➞', + see_more: 'Ver mais', + see_more_alt: 'Ver mais posts', + posts: { + title: 'Posts', + see_more_alt: 'Ver mais posts', + }, + projects: { + title: 'Projetos', + see_more_alt: 'Ver mais projetos', + }, +}; diff --git a/src/i18n/pt/index.ts b/src/i18n/pt/index.ts new file mode 100644 index 00000000..7ff2baf9 --- /dev/null +++ b/src/i18n/pt/index.ts @@ -0,0 +1,23 @@ +import { s404 } from './404'; +import { about } from './about'; +import { blog } from './blog'; +import { categories } from './categories'; +import { common } from './common'; +import { home } from './home'; +import { post } from './post'; +import { project } from './project'; +import { projects } from './projects'; +import { tags } from './tags'; + +export const ptLocale = { + '404': s404, + about, + blog, + categories, + common, + home, + post, + projects, + project, + tags, +}; diff --git a/src/i18n/pt/post.ts b/src/i18n/pt/post.ts new file mode 100644 index 00000000..848e801f --- /dev/null +++ b/src/i18n/pt/post.ts @@ -0,0 +1,22 @@ +export const post = { + card: { + read_post: 'Ler post', + see_more_posts_from_this_category: 'Ver todos os posts com esta categoria', + }, + tags: 'Tags', + tags_alt: 'Ver todas as tags', + tags_see_more_alt: 'Veja mais posts com a tag "{{tag}}"', + comments: 'Comentários', + comments_go_alt: 'Ir para os comentários', + related_posts: 'Posts relacionados', + see_post_history: 'Ver histórico de postagens', + last_updated: 'Última atualização: ', + share: { + title: 'Gostou deste post? Sinta-se à vontade para compartilhar!', + linkedin_alt: 'Compartilhar no LinkedIn', + twitter_alt: 'Compartilhar no Twitter', + reddit_alt: 'Compartilhar no Reddit', + bluesky_alt: 'Compartilhar no Bluesky', + copy_link_alt: 'Copiar link', + }, +}; diff --git a/src/i18n/pt/project.ts b/src/i18n/pt/project.ts new file mode 100644 index 00000000..b0f1ac3f --- /dev/null +++ b/src/i18n/pt/project.ts @@ -0,0 +1,39 @@ +export const project = { + title: 'Projeto', + target: 'Alvo', + type: 'Tipo', + status: 'Status', + language: 'Linguagem', + article: 'Artigo', + article_alt: 'Ver artigo', + images: 'Imagens', + images_alt: 'Ver imagens', + code_alt: 'Ver código', + preview_alt: 'Ver preview', + details: 'Detalhes', + see_more_alt: 'Ver mais', + project_status: { + in_progress: { + title: 'Em Progresso', + description: 'O trabalho no projeto está em andamento.', + }, + on_hold: { + title: 'Em Espera', + description: 'O projeto foi temporariamente pausado.', + }, + completed: { + title: 'Concluído', + description: 'O projeto foi finalizado.', + }, + inactive: { + title: 'Inativo', + description: + 'O projeto não está atualmente ativo, mas pode ser retomado no futuro.', + }, + active: { + title: 'Ativo', + description: + 'O projeto está atualmente ativo e o trabalho está em andamento.', + }, + }, +}; diff --git a/src/i18n/pt/projects.ts b/src/i18n/pt/projects.ts new file mode 100644 index 00000000..1cebbdaa --- /dev/null +++ b/src/i18n/pt/projects.ts @@ -0,0 +1,8 @@ +export const projects = { + title: 'Projetos', + description: + 'Descubra os projetos dos quais participei e aqueles em que estou ativamente envolvido.', + repositories: 'Repositórios', + org: 'Org', + org_alt: 'O projeto é uma coleção de projetos relacionados.', +}; diff --git a/src/i18n/pt/tags.ts b/src/i18n/pt/tags.ts new file mode 100644 index 00000000..cf6a2c41 --- /dev/null +++ b/src/i18n/pt/tags.ts @@ -0,0 +1,10 @@ +export const tags = { + title: 'Tags', + description: 'Explore todas as tags do meu blog pessoal', + tag: { + title: 'Tag: {{tag}}', + description: 'Explore todos os posts marcados com: {{tag}}', + description_one: 'Explore {{count}} post marcado com "{{tag}}"', + description_other: 'Explore {{count}} posts marcados com "{{tag}}"', + }, +}; diff --git a/src/i18n/schema.ts b/src/i18n/schema.ts new file mode 100644 index 00000000..91d0efdd --- /dev/null +++ b/src/i18n/schema.ts @@ -0,0 +1,154 @@ +export interface i18nSchema { + '404': { + description: string; + help_message: string; + go_back: string; + go_back_alt: string; + links: { + github_alt: string; + email_alt: string; + copy_email_tooltip: string; + copy_email_success_tooltip: string; + }; + }; + about: { + title: string; + article: { + topic_1: { + title: string; + paragraph_1: string; + paragraph_2: string; + paragraph_3: string; + paragraph_4: string; + paragraph_5: string; + }; + topic_2: { title: string; paragraph_1: string; paragraph_2: string }; + topic_3: { title: string; paragraph_1: string }; + topic_4: { title: string; paragraph_1: string }; + topic_5: { title: string; paragraph_1: string }; + }; + }; + blog: { + title: string; + description: string; + no_post_found: string; + }; + post: { + card: { + read_post: string; + see_more_posts_from_this_category: string; + }; + tags: string; + tags_alt: string; + tags_see_more_alt: string; + comments: string; + comments_go_alt: string; + related_posts: string; + see_post_history: string; + last_updated: string; + share: { + title: string; + linkedin_alt: string; + twitter_alt: string; + reddit_alt: string; + bluesky_alt: string; + copy_link_alt: string; + }; + }; + categories: { + title: string; + description: string; + category: { + title: string; + description: string; + description_one: string; + description_other: string; + }; + }; + common: { + title: string; + description: string; + header: { + homepage: string; + homepage_tooltip: string; + blog: string; + projects: string; + about: string; + blog_link_alt: string; + projects_link_alt: string; + about_link_alt: string; + change_language: string; + change_language_tooltip: string; + change_language_tooltip_disabled: string; + change_theme: string; + change_theme_tooltip: string; + }; + footer: { + powered: string; + links: { rss: string; tags: string; source_code: string }; + }; + }; + home: { + welcome: string; + see_more: string; + posts: { title: string; see_more_alt: string }; + projects: { + title: string; + see_more_alt: string; + }; + }; + projects: { + title: string; + description: string; + repositories: string; + org: string; + org_alt: string; + }; + project: { + title: string; + target: string; + type: string; + status: string; + language: string; + article: string; + article_alt: string; + images: string; + images_alt: string; + code_alt: string; + preview_alt: string; + details: string; + see_more_alt: string; + project_status: { + in_progress: { + title: string; + description: string; + }; + on_hold: { + title: string; + description: string; + }; + completed: { + title: string; + description: string; + }; + inactive: { + title: string; + description: string; + }; + active: { + title: string; + description: string; + }; + }; + }; + tags: { + title: string; + description: string; + tag: { + title: string; + description: string; + description_one: string; + description_other: string; + }; + }; +} diff --git a/src/i18n/types.ts b/src/i18n/types.ts new file mode 100644 index 00000000..a04f911c --- /dev/null +++ b/src/i18n/types.ts @@ -0,0 +1,31 @@ +import type { locales } from './config'; +import type { i18nSchema } from './schema'; + +/** + * Locales as a type + */ +export type Locale = (typeof locales)[number]; + +/** + * Locale and slug extracted from a path + */ +export type LocaleSlug = { + locale: Locale; + slug: string; +}; + +/** + * Get the nested keys of an object + */ +export type NestedKeys<T> = T extends object + ? { + [K in keyof T]: T[K] extends object + ? `${string & K}` | `${string & K}.${NestedKeys<T[K]>}` + : `${string & K}`; + }[keyof T] + : never; + +/** + * Translation keys of the i18n schema + */ +export type TranslationKeys = NestedKeys<i18nSchema>; diff --git a/src/icons/bsky.svg b/src/icons/bsky.svg deleted file mode 100644 index 9654c27d..00000000 --- a/src/icons/bsky.svg +++ /dev/null @@ -1 +0,0 @@ -<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Bluesky diff --git a/src/layouts/Layout.astro b/src/layouts/Layout.astro index 11350b72..7f059508 100644 --- a/src/layouts/Layout.astro +++ b/src/layouts/Layout.astro @@ -1,15 +1,26 @@ --- +import I18NHead from '@components/core/I18nHead.astro'; import headConfig from '@constants/head'; import '@styles/global.css'; +import { useLocale } from 'i18n'; +import { defaultLocale } from 'i18n/config'; +import type { LocaleSlug } from 'i18n/types'; +import { + getOpenGraphImage, + formatOpenGraphFileName, + cleanOpenGraphUrl, +} from 'open-graph'; export interface Props { + enableOpenGraph?: boolean; title: string; description: string; - banner?: string; + image?: string; robots?: string; shortlink?: string; type?: string; locale?: string; + locales?: LocaleSlug[]; article?: { title: string; description: string; @@ -20,88 +31,91 @@ export interface Props { }; } -const { title, description, banner, robots, shortlink, locale, article } = - Astro.props as Props; +const { locale: pathLocale, t } = useLocale(Astro.url.pathname); + +const { + robots, + shortlink, + article, + enableOpenGraph = true, + locales, +} = Astro.props as Props; + +let { locale, title, description, image } = Astro.props as Props; + +if (!locale) { + locale = pathLocale; +} + +title = article?.title || title + ' | ' + headConfig.name; +description = article?.description || description + headConfig.endDescription; +const canonical = new URL(Astro.url.pathname, Astro.url.origin); + +if (enableOpenGraph && !image) { + const path = Astro.url.pathname; + const fileName = formatOpenGraphFileName(path); + + const options = { + top: t('common.title').toLocaleUpperCase(), + title, + color: '#555555', + slug: path === '/' ? '' : cleanOpenGraphUrl(path), + }; + image = await getOpenGraphImage('default', options, fileName); +} + +image = Astro.url.origin + image || headConfig.image; --- - + - + - + + + + - + - - + + - + - - - + + + + - { - import.meta.env.PROD && ( - + { + import.meta.env.PROD && ( + diff --git a/src/pages/about.astro b/src/pages/about.astro new file mode 100644 index 00000000..bb20ab9f --- /dev/null +++ b/src/pages/about.astro @@ -0,0 +1,177 @@ +--- +import Divider from '@components/core/Divider.astro'; +import Title from '@components/core/Title.astro'; +import Tooltip from '@components/core/Tooltip.astro'; +import Container from '@components/data/Container.astro'; +import Socials from '@components/data/Socials.astro'; +import { languages } from '@constants/languages'; +import Layout from '@layouts/Layout.astro'; +import { Icon } from 'astro-icon/components'; +import { useLocale } from 'i18n'; + +const { t, localizePath } = useLocale(Astro.url.pathname); + +const title = t('about.title'); +const description = t('common.description'); +--- + + + + + <Divider height="1px" width="80%" /> + <article class="about-article"> + <section class="about-section section-text"> + <p><Fragment set:html={t('about.article.topic_1.paragraph_1')} /></p> + <p> + <Fragment set:html={t('about.article.topic_1.paragraph_2')} /> + </p> + <p> + <Fragment set:html={t('about.article.topic_1.paragraph_3')} /> + </p> + <p> + <Fragment + set:html={t('about.article.topic_1.paragraph_4', { + link: localizePath('/projects/'), + })} + /> + </p> + <p> + <Fragment + set:html={t('about.article.topic_1.paragraph_5', { + link: localizePath('/blog/'), + })} + /> + </p> + + <h2 id="beyond-the-code">{t('about.article.topic_2.title')}</h2> + <p> + <Fragment set:html={t('about.article.topic_2.paragraph_1')} /> + </p> + <p> + <Fragment set:html={t('about.article.topic_2.paragraph_2')} /> + </p> + + <h2 id="toolbox">{t('about.article.topic_3.title')}</h2> + <p><Fragment set:html={t('about.article.topic_3.paragraph_1')} /></p> + <div class="about-languages"> + { + languages.map((lang) => { + return ( + <Tooltip message={lang.name}> + <Icon + name={lang.icon} + font-size="3em" + class="about-languages-language" + /> + </Tooltip> + ); + }) + } + </div> + + <h2 id="github-stats">{t('about.article.topic_4.title')}</h2> + <p><Fragment set:html={t('about.article.topic_4.paragraph_1')} /></p> + <p class="about-stats"> + <img + src="https://raw.githubusercontent.com/LucJosin/github-stats-transparent/output/generated/overview.svg" + alt="Github Overview" + /> + <img + src="https://raw.githubusercontent.com/LucJosin/github-stats-transparent/output/generated/languages.svg" + alt="Github Languages" + /> + </p> + + <h2 id="github-stats">{t('about.article.topic_5.title')}</h2> + <p>{t('about.article.topic_5.paragraph_1')}</p> + <div class="about-contact"> + <Socials showName={true} showTooltip={false} justifyContent="left" /> + </div> + </section> + </article> + </Container> +</Layout> + +<style> + .about-article { + width: 100%; + line-height: 1.65em; + color: var(--description-text-color); + } + + .section-text h2 { + margin: 1rem 0 0 0; + color: var(--primary-text-color); + } + + .section-text ul { + margin: 0; + } + + .section-text { + display: flex; + flex-direction: column; + gap: 1rem; + } + + .section-text ul { + display: inline; + } + + .about-languages, + .about-stats { + width: 100%; + display: flex; + flex-wrap: wrap; + gap: 1rem; + } + + .about-stats img { + width: min-content; + } + + .about-languages-language { + border: var(--border-size) solid var(--border-color); + border-radius: var(--border-radius); + padding: 0.5rem; + } + + .about-languages-language:hover { + border: var(--border-size) solid var(--primary-color); + background-color: var(--border-color); + color: var(--primary-color); + cursor: pointer; + } + + :global(strong) { + color: var(--primary-text-color); + } + + :global(.about-link) { + color: var(--primary-text-color); + text-decoration: underline; + font-weight: 500; + transition: opacity 0.2s; + line-break: normal; + text-decoration-line: underline; + text-decoration-color: var(--primary-text-color); + text-decoration-thickness: 0.125rem; + text-decoration-style: dashed; + text-underline-offset: 0.25rem; + } + + :global(.about-link:hover) { + opacity: 0.7; + } + + .about-languages-language:hover > [data-icon] { + fill: var(--secondary-text-color); + color: var(--secondary-text-color); + } + + @media (max-width: 640px) { + .about-languages { + justify-content: center; + } + } +</style> diff --git a/src/pages/blog/[...slug].astro b/src/pages/blog/[...slug].astro index 721d43b5..97bec77d 100644 --- a/src/pages/blog/[...slug].astro +++ b/src/pages/blog/[...slug].astro @@ -1,35 +1,35 @@ --- +import PostLayout from '@layouts/PostLayout.astro'; +import { getStaticBlogPaths } from '@lib/blog'; import '@styles/markdown.css'; import '@styles/post.css'; import '@styles/remark/remark-alert-blocks.css'; import '@styles/remark/remark-code-highlight.css'; +import '@styles/remark/remark-codeset.css'; import '@styles/remark/remark-image-caption.css'; import '@styles/remark/remark-post-reference.css'; import '@styles/remark/remark-readme-stats.css'; -import '@styles/remark/remark-codeset.css'; -import { type CollectionEntry } from 'astro:content'; -import PostLayout from '@layouts/PostLayout.astro'; -import { getAllPosts } from '@lib/blog'; +import '@styles/remark/remark-slider.css'; -export async function getStaticPaths() { - const posts = await getAllPosts(true, false); - return posts.map((post) => ({ - params: { slug: post.slug }, - props: { post }, - })); -} +export const getStaticPaths = getStaticBlogPaths(); -interface Props { - post: CollectionEntry<'blog'>; -} const { post } = Astro.props; +let { locales } = Astro.props; const { Content } = await post.render(); + +locales = locales.map((post) => { + return { + locale: post.locale, + slug: `/blog/${post.slug}`, + }; +}); --- <PostLayout title={post.data.title} description={post.data.description} post={post} + locales={locales} > <article class="post-content post-content-lg"> <Content /> diff --git a/src/pages/blog/categories/[...category].astro b/src/pages/blog/categories/[...category].astro index 45b44842..6b85095b 100644 --- a/src/pages/blog/categories/[...category].astro +++ b/src/pages/blog/categories/[...category].astro @@ -5,42 +5,39 @@ import PostCard from '@components/core/Post/PostCard.astro'; import Title from '@components/core/Title.astro'; import Container from '@components/data/Container.astro'; import Layout from '@layouts/Layout.astro'; -import { getAllPosts, getUniqueCategories } from '@lib/blog'; +import { getStaticCategoryPaths } from '@lib/blog'; import { getFormatedDate } from '@lib/date'; import type { CollectionEntry } from 'astro:content'; +import { useLocale } from 'i18n'; -export async function getStaticPaths() { - const allPosts = await getAllPosts(); - const uniqueCategories = await getUniqueCategories(); - - return uniqueCategories.map((category) => { - const filteredPosts = allPosts.filter( - (post) => post.data.category === category - ); - return { - params: { category }, - props: { posts: filteredPosts }, - }; - }); -} +export const getStaticPaths = getStaticCategoryPaths(); interface Props { posts: CollectionEntry<'blog'>[]; } +const { t, localizePath } = useLocale(Astro.url.pathname); + const { category } = Astro.params; const { posts } = Astro.props; --- <Layout - title={'Category: ' + category} - description={`Explore all posts categorized with: ${category}`} + title={t('categories.category.title', { category })} + description={t('categories.description', { category })} shortlink="/blog" + enableOpenGraph={false} > <Container> - <Title title={'Category: ' + category} fontSize="2.5em" /> + <Title + title={t('categories.category.title', { category })} + fontSize="2.5em" + /> <Description - value={`Explore ${posts.length} post(s) categorized with "${category}"`} + value={t('categories.category.description', { + count: posts.length, + category, + })} margin="0" width="80%" /> @@ -54,7 +51,7 @@ const { posts } = Astro.props; title={post.data.title} description={post.data.description} category={post.data.category} - href={`${post.slug}/`} + href={localizePath(`/blog/${post.data.permSlug}`)} publishedAt={getFormatedDate(post.data.publishedAt)} tags={post.data.tags} body={post.body} diff --git a/src/pages/blog/categories/index.astro b/src/pages/blog/categories/index.astro index c9414acb..4f309145 100644 --- a/src/pages/blog/categories/index.astro +++ b/src/pages/blog/categories/index.astro @@ -5,23 +5,23 @@ import Title from '@components/core/Title.astro'; import Container from '@components/data/Container.astro'; import Tags from '@components/data/Tags.astro'; import Layout from '@layouts/Layout.astro'; -import { getUniqueCategories } from '@lib/blog'; +import { getAllPosts, getUniqueCategories } from '@lib/blog'; +import { useLocale } from 'i18n'; -const categories = await getUniqueCategories(); +const { t, locale } = useLocale(Astro.url.pathname); + +const allPosts = await getAllPosts(true, true, locale); +const categories = await getUniqueCategories(allPosts); + +const title = t('tags.title'); +const description = t('tags.description'); --- -<Layout - title="Categories" - description="Explore all categories of my personal blog" -> +<Layout title={title} description={description}> <Container> - <Title title="Categories" fontSize="2.5em" /> - <Description - value="Explore all categories of my personal blog" - margin="0" - width="80%" - /> - <Divider height="1px" width="80%" /> + <Title title={title} fontSize="2.5em" /> + <Description value={description} margin="0" width="80%" /> + <Divider width="80%" /> <Tags values={categories} target="categories" center showLength active /> </Container> </Layout> diff --git a/src/pages/blog/index.astro b/src/pages/blog/index.astro index 30d3d4f1..f3487189 100644 --- a/src/pages/blog/index.astro +++ b/src/pages/blog/index.astro @@ -6,11 +6,13 @@ import Title from '@components/core/Title.astro'; import Container from '@components/data/Container.astro'; import Layout from '@layouts/Layout.astro'; import { getAllPosts } from '@lib/blog'; +import { useLocale } from 'i18n'; -const posts = await getAllPosts(); -const title = 'Blog'; -const description = - 'Explore my developer blog with thoughts, ideas and other stuff.'; +const { t, localizePath, locale } = useLocale(Astro.url.pathname); +const posts = await getAllPosts(true, true, locale); + +const title = t('blog.title'); +const description = t('blog.description'); --- <Layout title={title} description={description} shortlink="/blog"> @@ -20,20 +22,24 @@ const description = <Divider height="1px" width="80%" /> <div class="blog-posts"> { - posts.map((post) => { - return ( - <PostCard - image={post.data.image.src} - title={post.data.title} - description={post.data.description} - category={post.data.category} - href={`${post.slug}/`} - publishedAt={post.data.publishedAt} - tags={post.data.tags} - body={post.body} - /> - ); - }) + posts.length > 0 ? ( + posts.map((post) => { + return ( + <PostCard + image={post.data.image.src} + title={post.data.title} + description={post.data.description} + category={post.data.category} + href={localizePath(`/blog/${post.data.permSlug}`)} + publishedAt={post.data.publishedAt} + tags={post.data.tags} + body={post.body} + /> + ); + }) + ) : ( + <p set:html={t('blog.no_post_found')} class="blog-posts-empty" /> + ) } </div> </Container> @@ -46,4 +52,12 @@ const description = flex-direction: column; gap: 1rem; } + + .blog-posts-empty { + display: flex; + flex-direction: column; + align-items: center; + text-align: center; + color: var(--description-text-color); + } </style> diff --git a/src/pages/blog/tags/[...tag].astro b/src/pages/blog/tags/[...tag].astro index 23ee2482..98891af1 100644 --- a/src/pages/blog/tags/[...tag].astro +++ b/src/pages/blog/tags/[...tag].astro @@ -5,45 +5,35 @@ import PostCard from '@components/core/Post/PostCard.astro'; import Title from '@components/core/Title.astro'; import Container from '@components/data/Container.astro'; import Layout from '@layouts/Layout.astro'; -import { getAllPosts, getUniqueTags } from '@lib/blog'; +import { getStaticTagPaths } from '@lib/blog'; import { getFormatedDate } from '@lib/date'; import type { CollectionEntry } from 'astro:content'; +import { useLocale } from 'i18n'; -export async function getStaticPaths() { - const allPosts = await getAllPosts(); - const uniqueTags = await getUniqueTags(); - - return uniqueTags.map((tag) => { - const filteredPosts = allPosts.filter((post) => - post.data.tags.includes(tag) - ); - return { - params: { tag }, - props: { posts: filteredPosts }, - }; - }); -} +export const getStaticPaths = getStaticTagPaths(); interface Props { posts: CollectionEntry<'blog'>[]; } +const { t, localizePath } = useLocale(Astro.url.pathname); + const { tag } = Astro.params; const { posts } = Astro.props; + +const title = t('tags.tag.title', { tag }); +const description = t('tags.tag.description', { tag, count: posts.length }); --- <Layout - title={'Tag: ' + tag} - description={`Explore all posts tagged with: ${tag}`} + title={title} + description={t('tags.tag.description', { tag })} shortlink="/blog" + enableOpenGraph={false} > <Container> - <Title title={'Tag: ' + tag} fontSize="2.5em" /> - <Description - value={`Explore ${posts.length} post(s) tagged with "${tag}"`} - margin="0" - width="80%" - /> + <Title title={title} fontSize="2.5em" /> + <Description value={description} margin="0" width="80%" /> <Divider height="1px" width="80%" /> <div class="tag-posts"> { @@ -54,7 +44,7 @@ const { posts } = Astro.props; title={post.data.title} description={post.data.description} category={post.data.category} - href={`${post.slug}/`} + href={localizePath(`/blog/${post.data.permSlug}`)} publishedAt={getFormatedDate(post.data.publishedAt)} tags={post.data.tags} body={post.body} diff --git a/src/pages/blog/tags/index.astro b/src/pages/blog/tags/index.astro index c4d49f10..6823b81b 100644 --- a/src/pages/blog/tags/index.astro +++ b/src/pages/blog/tags/index.astro @@ -5,20 +5,23 @@ import Title from '@components/core/Title.astro'; import Container from '@components/data/Container.astro'; import Tags from '@components/data/Tags.astro'; import Layout from '@layouts/Layout.astro'; -import { getUniqueTags } from '@lib/blog'; +import { getAllPosts, getUniqueTags } from '@lib/blog'; +import { useLocale } from 'i18n'; -const tags = await getUniqueTags(); +const { t, locale } = useLocale(Astro.url.pathname); + +const allPosts = await getAllPosts(true, true, locale); +const tags = await getUniqueTags(allPosts); + +const title = t('tags.title'); +const description = t('tags.description'); --- -<Layout title="Tags" description="Explore all tags of my personal blog"> +<Layout title={title} description={description}> <Container> - <Title title="Tags" fontSize="2.5em" /> - <Description - value="Explore all tags of my personal blog" - margin="0" - width="80%" - /> - <Divider height="1px" width="80%" /> + <Title title={title} fontSize="2.5em" /> + <Description value={description} margin="0" width="80%" /> + <Divider width="80%" /> <Tags values={tags} target="tags" center showLength active /> </Container> </Layout> diff --git a/src/pages/index.astro b/src/pages/index.astro index 6f620271..40d0f7c7 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -1,42 +1,54 @@ --- import Avatar from '@components/core/Avatar.astro'; import Divider from '@components/core/Divider.astro'; -import ThemeIcon from '@components/core/ThemeIcon.astro'; import Title from '@components/core/Title.astro'; import Container from '@components/data/Container.astro'; import Posts from '@components/data/Posts.astro'; import Projects from '@components/data/Projects.astro'; import Socials from '@components/data/Socials.astro'; import Layout from '@layouts/Layout.astro'; +import { useLocale } from 'i18n'; + +const { t, localizePath } = useLocale(Astro.url.pathname); + +const title = t('common.title'); +const description = t('common.description'); --- -<Layout - title="Backend Developer" - description="Hi!, I'm Lucas Josino. Backend Developer. I'm currently working with Java (Spring Boot) development." - shortlink="/" -> - <ThemeIcon position="absolute" /> - <Container maxWidth="35rem" hasHeader={false}> - <div class="profile"> +<Layout title={title} description={description} shortlink="/"> + <Container gap="1.5rem"> + <section class="profile-section"> <Avatar /> <Title title="Lucas Josino" margin="0.2em 0" fontSize="1.4em" /> - <span>Backend Developer</span> - <span>Java · Spring Boot</span> - </div> - <Divider width="80%" margin="1.5rem 0 0 0" /> - <Socials /> - <Projects /> + <span>{title}</span> + <span>Java · Golang · Spring Boot</span> + <p class="profile-description"> + <a href={localizePath('/about/')} set:html={t('home.welcome')} /> + </p> + <Socials hasTitle={false} /> + </section> + <Divider width="80%" margin="0" /> <Posts /> + <Projects /> </Container> </Layout> <style> - .profile { + .profile-section { text-align: center; display: flex; flex-direction: column; align-items: center; - gap: 0.2rem; - margin-top: 4rem; + gap: 0.5rem; + } + + .profile-description { + margin: 0.6rem 2rem; + } + + .profile-description a { + color: var(--description-text-color); + line-height: 1.5em; + gap: 0.2em; } </style> diff --git a/src/pages/projects/[...slug].astro b/src/pages/projects/[...slug].astro new file mode 100644 index 00000000..4e529e1f --- /dev/null +++ b/src/pages/projects/[...slug].astro @@ -0,0 +1,263 @@ +--- +import Divider from '@components/core/Divider.astro'; +import Container from '@components/data/Container.astro'; +import Tags from '@components/data/Tags.astro'; +import Layout from '@layouts/Layout.astro'; +import '@styles/markdown.css'; +import LinkBox from '@components/core/Link/LinkBox.astro'; +import { getStaticProjectPaths } from '@lib/projects'; +import { useLocale } from 'i18n'; +import { getOpenGraphImage } from 'open-graph'; +import MiniProjectCard from '@components/core/Project/MiniProjectCard.astro'; +import { getEntry } from 'astro:content'; +import BackToTop from '@components/core/BackToTop.astro'; + +export const getStaticPaths = getStaticProjectPaths(); + +const { locale, t } = useLocale(Astro.url.pathname); + +const { project } = Astro.props; +let { locales } = Astro.props; +const { Content } = await project.render(); + +locales = locales.map((post) => { + return { + locale: post.locale, + slug: `/projects/${post.slug}`, + }; +}); + +const imagePath = await getOpenGraphImage( + 'project', + { + title: project.data.title, + description: project.data.description, + language: project.data.language, + target: project.data.target?.join(', ') || project.data.codeLanguage, + color: project.data.color, + }, + project.slug +); +--- + +<Layout + title={`${project.data.title} - ${t('project.title')}`} + description={project.data.description} + locales={locales} + locale={locale} + image={imagePath} +> + <Container gap="1.5rem"> + <BackToTop /> + + <div class="project-initial"> + <h1 class="project-title">{project.data.title}</h1> + <div class="project-links"> + { + project.data.images && ( + <LinkBox + href="#images" + title={t('project.images')} + alt={t('project.images_alt')} + icon="mdi:images" + padding="0.6rem" + /> + ) + } + { + project.data.url && ( + <LinkBox + href={project.data.url} + title="Preview" + alt={t('project.preview_alt')} + icon="mdi:external-link" + isLocal={false} + padding="0.6rem" + /> + ) + } + { + project.data.git && ( + <LinkBox + href={project.data.git} + title="GitHub" + alt={t('project.code_alt')} + icon="simple-icons:github" + isLocal={false} + padding="0.6rem" + /> + ) + } + { + project.data.article && ( + <LinkBox + href={project.data.article} + title={t('project.article')} + alt={t('project.article_alt')} + icon="mdi:file-document-outline" + padding="0.6rem" + /> + ) + } + </div> + </div> + { + project.data.thumbnail && ( + <div class="project-image"> + <img src={project.data.thumbnail} alt="Project 1" /> + </div> + ) + } + <Divider /> + <article class="post-content post-content-lg"> + <Content /> + </article> + <Divider margin="0 1rem" /> + <div class="project-info"> + <div class="project-info-item project-category"> + <h3>{t('project.target')}</h3> + <p>{project.data.target?.join(', ')}</p> + </div> + <div class="project-info-item project-category"> + <h3>{t('project.type')}</h3> + <p>{project.data.category}</p> + </div> + <div class="project-info-item project-stauts"> + <h3>{t('project.status')}</h3> + <p>{t(`project.project_status.${project.data.status}.title`)}</p> + </div> + <div class="project-info-item project-language"> + <h3>{t('project.language')}</h3> + <p>{project.data.codeLanguage}</p> + </div> + </div> + <div class="project-tags"> + <h3>Tags</h3> + <Tags values={project.data.tags} target="tags" /> + </div> + { + project.data.images && ( + <div class="project-images-container"> + <h2 id="images">{t('project.images')}</h2> + <div class="project-images"> + {project.data.images.map((image, index) => ( + <img src={image} alt={`Image ${index}`} class="project-image" /> + ))} + </div> + </div> + ) + } + { + project.data.subProjects && ( + <div class="project-subprojects-container"> + <h2>{t('projects.repositories')}</h2> + <div class="project-subprojects"> + {project.data.subProjects.map(async (sub) => { + const subProject = await getEntry(sub); + return ( + <MiniProjectCard + slug={subProject.data.permSlug} + title={subProject.data.title} + description={subProject.data.description} + url={subProject.data.url} + git={subProject.data.git} + codeLanguage={subProject.data.codeLanguage} + icon={subProject.data.icon} + /> + ); + })} + </div> + </div> + ) + } + </Container> +</Layout> + +<style> + .project-initial { + width: 100%; + display: flex; + justify-content: space-between; + flex-wrap: wrap; + gap: 1rem; + } + + .project-links { + display: flex; + flex-wrap: wrap; + gap: 1rem; + align-items: center; + } + + .project-info-item { + flex: 1; + } + + .project-tags { + width: 100%; + } + + .project-title { + font-size: 2.5em; + } + + .project-info { + width: 100%; + display: flex; + flex-wrap: wrap; + gap: 1rem 3rem; + } + + .project-images-container { + width: 100%; + } + + .project-images { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); + gap: 1rem; + } + + .project-subprojects-container { + width: 100%; + display: flex; + flex-direction: column; + flex-wrap: wrap; + gap: 1rem; + } + + .project-subprojects { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); + gap: 1rem; + } + + /* @media (max-width: 520px) { + .project-title { + width: 100%; + text-align: center; + } + + .project-links { + width: 100%; + justify-content: center; + } + } */ +</style> + +<script> + import { + listenToBackToTop, + showHideBackToTopButton, + } from '@lib/browser/back-to-top'; + import mediumZoom from 'medium-zoom'; + + window.onscroll = () => { + listenToBackToTop(); + showHideBackToTopButton(); + }; + + mediumZoom(document.querySelectorAll('img') as NodeListOf<HTMLImageElement>, { + background: '#000000e0', + }); +</script> diff --git a/src/pages/projects/index.astro b/src/pages/projects/index.astro index cb564215..5eb13713 100644 --- a/src/pages/projects/index.astro +++ b/src/pages/projects/index.astro @@ -4,12 +4,15 @@ import Divider from '@components/core/Divider.astro'; import ProjectCard from '@components/core/Project/ProjectCard.astro'; import Title from '@components/core/Title.astro'; import Container from '@components/data/Container.astro'; -import { projects } from '@constants/projects'; import Layout from '@layouts/Layout.astro'; +import { getAllProjects } from '@lib/projects'; +import { useLocale } from 'i18n'; -const title = 'Projects'; -const description = - "Discover the projects I've been a part of and those I'm actively involved in."; +const { locale, t } = useLocale(Astro.url.pathname); +const projects = await getAllProjects(true, locale); + +const title = t('projects.title'); +const description = t('projects.description'); --- <Layout title={title} description={description} shortlink="/projects"> @@ -36,3 +39,10 @@ const description = gap: 1rem; } </style> + +<script> + import mediumZoom from 'medium-zoom'; + mediumZoom(document.querySelectorAll('img') as NodeListOf<HTMLImageElement>, { + background: '#000000e0', + }); +</script> diff --git a/src/pages/pt/404.astro b/src/pages/pt/404.astro new file mode 100644 index 00000000..80d55cdc --- /dev/null +++ b/src/pages/pt/404.astro @@ -0,0 +1,6 @@ +--- +import Page from '../404.astro'; +const { props } = Astro; +--- + +<Page {...props} /> diff --git a/src/pages/pt/_context.ts b/src/pages/pt/_context.ts new file mode 100644 index 00000000..64dc4d6e --- /dev/null +++ b/src/pages/pt/_context.ts @@ -0,0 +1 @@ +export const contextLocale = 'pt'; diff --git a/src/pages/pt/about.astro b/src/pages/pt/about.astro new file mode 100644 index 00000000..09fccadf --- /dev/null +++ b/src/pages/pt/about.astro @@ -0,0 +1,6 @@ +--- +import Page from '../about.astro'; +const { props } = Astro; +--- + +<Page {...props} /> diff --git a/src/pages/pt/blog/[...slug].astro b/src/pages/pt/blog/[...slug].astro new file mode 100644 index 00000000..2c6cbdb5 --- /dev/null +++ b/src/pages/pt/blog/[...slug].astro @@ -0,0 +1,13 @@ +--- +import { getStaticBlogPaths } from '@lib/blog'; +import Page from '../../blog/[...slug].astro'; +import { contextLocale } from '../_context'; + +export const getStaticPaths = getStaticBlogPaths({ + locale: contextLocale, +}); + +const { props } = Astro; +--- + +<Page {...props} /> diff --git a/src/pages/pt/blog/categories/[...category].astro b/src/pages/pt/blog/categories/[...category].astro new file mode 100644 index 00000000..d51a0949 --- /dev/null +++ b/src/pages/pt/blog/categories/[...category].astro @@ -0,0 +1,13 @@ +--- +import { getStaticCategoryPaths } from '@lib/blog'; +import Page from '../../../blog/categories/[...category].astro'; +import { contextLocale } from '../../_context'; + +export const getStaticPaths = getStaticCategoryPaths({ + locale: contextLocale, +}); + +const { props } = Astro; +--- + +<Page {...props} /> diff --git a/src/pages/pt/blog/categories/index.astro b/src/pages/pt/blog/categories/index.astro new file mode 100644 index 00000000..0250df41 --- /dev/null +++ b/src/pages/pt/blog/categories/index.astro @@ -0,0 +1,6 @@ +--- +import Page from '../../../blog/categories/index.astro'; +const { props } = Astro; +--- + +<Page {...props} /> diff --git a/src/pages/pt/blog/index.astro b/src/pages/pt/blog/index.astro new file mode 100644 index 00000000..95543aa4 --- /dev/null +++ b/src/pages/pt/blog/index.astro @@ -0,0 +1,6 @@ +--- +import Page from '../../blog/index.astro'; +const { props } = Astro; +--- + +<Page {...props} /> diff --git a/src/pages/pt/blog/tags/[...tag].astro b/src/pages/pt/blog/tags/[...tag].astro new file mode 100644 index 00000000..e7d93993 --- /dev/null +++ b/src/pages/pt/blog/tags/[...tag].astro @@ -0,0 +1,13 @@ +--- +import { getStaticTagPaths } from '@lib/blog'; +import Page from '../../../blog/tags/[...tag].astro'; +import { contextLocale } from '../../_context'; + +export const getStaticPaths = getStaticTagPaths({ + locale: contextLocale, +}); + +const { props } = Astro; +--- + +<Page {...props} /> diff --git a/src/pages/pt/blog/tags/index.astro b/src/pages/pt/blog/tags/index.astro new file mode 100644 index 00000000..b61285e3 --- /dev/null +++ b/src/pages/pt/blog/tags/index.astro @@ -0,0 +1,6 @@ +--- +import Page from '../../../blog/tags/index.astro'; +const { props } = Astro; +--- + +<Page {...props} /> diff --git a/src/pages/pt/index.astro b/src/pages/pt/index.astro new file mode 100644 index 00000000..792c8c68 --- /dev/null +++ b/src/pages/pt/index.astro @@ -0,0 +1,6 @@ +--- +import Page from '../index.astro'; +const { props } = Astro; +--- + +<Page {...props} /> diff --git a/src/pages/pt/projects/[...slug].astro b/src/pages/pt/projects/[...slug].astro new file mode 100644 index 00000000..79c14665 --- /dev/null +++ b/src/pages/pt/projects/[...slug].astro @@ -0,0 +1,13 @@ +--- +import { getStaticProjectPaths } from '@lib/projects'; +import Page from '../../projects/[...slug].astro'; +import { contextLocale } from '../_context'; + +export const getStaticPaths = getStaticProjectPaths({ + locale: contextLocale, +}); + +const { props } = Astro; +--- + +<Page {...props} /> diff --git a/src/pages/pt/projects/index.astro b/src/pages/pt/projects/index.astro new file mode 100644 index 00000000..76437b5f --- /dev/null +++ b/src/pages/pt/projects/index.astro @@ -0,0 +1,6 @@ +--- +import Page from '../../projects/index.astro'; +const { props } = Astro; +--- + +<Page {...props} /> diff --git a/src/pages/rss.xml.ts b/src/pages/rss.xml.ts index 1c7d8aa0..96897c25 100644 --- a/src/pages/rss.xml.ts +++ b/src/pages/rss.xml.ts @@ -6,6 +6,7 @@ export async function GET() { const posts = await getAllPosts(); const domain = headConfig.canonical; return rss({ + trailingSlash: true, title: 'Lucas Josino', description: 'Explore my developer blog with thoughts, ideas and other stuff.', @@ -19,9 +20,14 @@ export async function GET() { return { title: post.title, description: post.description, - link: `${domain}/blog/${item.slug}`, + link: createUrl(domain, post.language, item.data.permSlug), pubDate: new Date(post.publishedAt), - commentsUrl: `${domain}/blog/${item.slug}/#comments`, + commentsUrl: createUrl( + domain, + post.language, + item.data.permSlug, + 'comments' + ), author: `Lucas Josino (contact@lucasjosino.com)`, categories: [post.category], enclosure: { @@ -45,3 +51,14 @@ export async function GET() { `<lastBuildDate>${new Date().toUTCString()}</lastBuildDate>`, }); } + +function createUrl( + domain: string, + locale: string, + slug: string, + anchor?: string +) { + return locale === 'en' + ? `${domain}/blog/${slug}/${anchor ? `#${anchor}` : ''}` + : `${domain}/${locale}/blog/${slug}/${anchor ? `#${anchor}` : ''}`; +} diff --git a/src/styles/global.css b/src/styles/global.css index 018d4bc3..715d731c 100644 --- a/src/styles/global.css +++ b/src/styles/global.css @@ -23,6 +23,8 @@ --transition-duration: 0.2s; --card-padding: 0.8rem; + + --background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 304 304' width='304' height='304'%3E%3Cpath fill='%23404040' fill-opacity='0.03' d='M44.1 224a5 5 0 1 1 0 2H0v-2h44.1zm160 48a5 5 0 1 1 0 2H82v-2h122.1zm57.8-46a5 5 0 1 1 0-2H304v2h-42.1zm0 16a5 5 0 1 1 0-2H304v2h-42.1zm6.2-114a5 5 0 1 1 0 2h-86.2a5 5 0 1 1 0-2h86.2zm-256-48a5 5 0 1 1 0 2H0v-2h12.1zm185.8 34a5 5 0 1 1 0-2h86.2a5 5 0 1 1 0 2h-86.2zM258 12.1a5 5 0 1 1-2 0V0h2v12.1zm-64 208a5 5 0 1 1-2 0v-54.2a5 5 0 1 1 2 0v54.2zm48-198.2V80h62v2h-64V21.9a5 5 0 1 1 2 0zm16 16V64h46v2h-48V37.9a5 5 0 1 1 2 0zm-128 96V208h16v12.1a5 5 0 1 1-2 0V210h-16v-76.1a5 5 0 1 1 2 0zm-5.9-21.9a5 5 0 1 1 0 2H114v48H85.9a5 5 0 1 1 0-2H112v-48h12.1zm-6.2 130a5 5 0 1 1 0-2H176v-74.1a5 5 0 1 1 2 0V242h-60.1zm-16-64a5 5 0 1 1 0-2H114v48h10.1a5 5 0 1 1 0 2H112v-48h-10.1zM66 284.1a5 5 0 1 1-2 0V274H50v30h-2v-32h18v12.1zM236.1 176a5 5 0 1 1 0 2H226v94h48v32h-2v-30h-48v-98h12.1zm25.8-30a5 5 0 1 1 0-2H274v44.1a5 5 0 1 1-2 0V146h-10.1zm-64 96a5 5 0 1 1 0-2H208v-80h16v-14h-42.1a5 5 0 1 1 0-2H226v18h-16v80h-12.1zm86.2-210a5 5 0 1 1 0 2H272V0h2v32h10.1zM98 101.9V146H53.9a5 5 0 1 1 0-2H96v-42.1a5 5 0 1 1 2 0zM53.9 34a5 5 0 1 1 0-2H80V0h2v34H53.9zm60.1 3.9V66H82v64H69.9a5 5 0 1 1 0-2H80V64h32V37.9a5 5 0 1 1 2 0zM101.9 82a5 5 0 1 1 0-2H128V37.9a5 5 0 1 1 2 0V82h-28.1zm16-64a5 5 0 1 1 0-2H146v44.1a5 5 0 1 1-2 0V18h-26.1zm102.2 270a5 5 0 1 1 0 2H98v14h-2v-16h124.1zM242 149.9V160h16v34h-16v62h48v48h-2v-46h-48v-66h16v-30h-16v-12.1a5 5 0 1 1 2 0zM53.9 18a5 5 0 1 1 0-2H64V2H48V0h18v18H53.9zm112 32a5 5 0 1 1 0-2H192V0h50v2h-48v48h-28.1zm-48-48a5 5 0 0 1-9.8-2h2.07a3 3 0 1 0 5.66 0H178v34h-18V21.9a5 5 0 1 1 2 0V32h14V2h-58.1zm0 96a5 5 0 1 1 0-2H137l32-32h39V21.9a5 5 0 1 1 2 0V66h-40.17l-32 32H117.9zm28.1 90.1a5 5 0 1 1-2 0v-76.51L175.59 80H224V21.9a5 5 0 1 1 2 0V82h-49.59L146 112.41v75.69zm16 32a5 5 0 1 1-2 0v-99.51L184.59 96H300.1a5 5 0 0 1 3.9-3.9v2.07a3 3 0 0 0 0 5.66v2.07a5 5 0 0 1-3.9-3.9H185.41L162 121.41v98.69zm-144-64a5 5 0 1 1-2 0v-3.51l48-48V48h32V0h2v50H66v55.41l-48 48v2.69zM50 53.9v43.51l-48 48V208h26.1a5 5 0 1 1 0 2H0v-65.41l48-48V53.9a5 5 0 1 1 2 0zm-16 16V89.41l-34 34v-2.82l32-32V69.9a5 5 0 1 1 2 0zM12.1 32a5 5 0 1 1 0 2H9.41L0 43.41V40.6L8.59 32h3.51zm265.8 18a5 5 0 1 1 0-2h18.69l7.41-7.41v2.82L297.41 50H277.9zm-16 160a5 5 0 1 1 0-2H288v-71.41l16-16v2.82l-14 14V210h-28.1zm-208 32a5 5 0 1 1 0-2H64v-22.59L40.59 194H21.9a5 5 0 1 1 0-2H41.41L66 216.59V242H53.9zm150.2 14a5 5 0 1 1 0 2H96v-56.6L56.6 162H37.9a5 5 0 1 1 0-2h19.5L98 200.6V256h106.1zm-150.2 2a5 5 0 1 1 0-2H80v-46.59L48.59 178H21.9a5 5 0 1 1 0-2H49.41L82 208.59V258H53.9zM34 39.8v1.61L9.41 66H0v-2h8.59L32 40.59V0h2v39.8zM2 300.1a5 5 0 0 1 3.9 3.9H3.83A3 3 0 0 0 0 302.17V256h18v48h-2v-46H2v42.1zM34 241v63h-2v-62H0v-2h34v1zM17 18H0v-2h16V0h2v18h-1zm273-2h14v2h-16V0h2v16zm-32 273v15h-2v-14h-14v14h-2v-16h18v1zM0 92.1A5.02 5.02 0 0 1 6 97a5 5 0 0 1-6 4.9v-2.07a3 3 0 1 0 0-5.66V92.1zM80 272h2v32h-2v-32zm37.9 32h-2.07a3 3 0 0 0-5.66 0h-2.07a5 5 0 0 1 9.8 0zM5.9 0A5.02 5.02 0 0 1 0 5.9V3.83A3 3 0 0 0 3.83 0H5.9zm294.2 0h2.07A3 3 0 0 0 304 3.83V5.9a5 5 0 0 1-3.9-5.9zm3.9 300.1v2.07a3 3 0 0 0-1.83 1.83h-2.07a5 5 0 0 1 3.9-3.9zM97 100a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0-16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-48 32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm32 48a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm32-16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0-32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm32 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0-16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16-64a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 96a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16-144a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16-32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16-16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-96 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16-32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm96 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16-64a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16-16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-32 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0-16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM49 36a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-32 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm32 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM33 68a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16-48a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 240a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16-64a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16-32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm80-176a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16-16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm32 48a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16-16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0-32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm112 176a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM17 180a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0-32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM17 84a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm32 64a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16-16a3 3 0 1 0 0-6 3 3 0 0 0 0 6z'%3E%3C/path%3E%3C/svg%3E"); } :root[data-theme="dark"] { @@ -39,6 +41,8 @@ --primary-text-color: #fff; --secondary-text-color: #121212; --description-text-color: #cfcfcf; + + --background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 304 304' width='304' height='304'%3E%3Cpath fill='%23ffffff' fill-opacity='0.02' d='M44.1 224a5 5 0 1 1 0 2H0v-2h44.1zm160 48a5 5 0 1 1 0 2H82v-2h122.1zm57.8-46a5 5 0 1 1 0-2H304v2h-42.1zm0 16a5 5 0 1 1 0-2H304v2h-42.1zm6.2-114a5 5 0 1 1 0 2h-86.2a5 5 0 1 1 0-2h86.2zm-256-48a5 5 0 1 1 0 2H0v-2h12.1zm185.8 34a5 5 0 1 1 0-2h86.2a5 5 0 1 1 0 2h-86.2zM258 12.1a5 5 0 1 1-2 0V0h2v12.1zm-64 208a5 5 0 1 1-2 0v-54.2a5 5 0 1 1 2 0v54.2zm48-198.2V80h62v2h-64V21.9a5 5 0 1 1 2 0zm16 16V64h46v2h-48V37.9a5 5 0 1 1 2 0zm-128 96V208h16v12.1a5 5 0 1 1-2 0V210h-16v-76.1a5 5 0 1 1 2 0zm-5.9-21.9a5 5 0 1 1 0 2H114v48H85.9a5 5 0 1 1 0-2H112v-48h12.1zm-6.2 130a5 5 0 1 1 0-2H176v-74.1a5 5 0 1 1 2 0V242h-60.1zm-16-64a5 5 0 1 1 0-2H114v48h10.1a5 5 0 1 1 0 2H112v-48h-10.1zM66 284.1a5 5 0 1 1-2 0V274H50v30h-2v-32h18v12.1zM236.1 176a5 5 0 1 1 0 2H226v94h48v32h-2v-30h-48v-98h12.1zm25.8-30a5 5 0 1 1 0-2H274v44.1a5 5 0 1 1-2 0V146h-10.1zm-64 96a5 5 0 1 1 0-2H208v-80h16v-14h-42.1a5 5 0 1 1 0-2H226v18h-16v80h-12.1zm86.2-210a5 5 0 1 1 0 2H272V0h2v32h10.1zM98 101.9V146H53.9a5 5 0 1 1 0-2H96v-42.1a5 5 0 1 1 2 0zM53.9 34a5 5 0 1 1 0-2H80V0h2v34H53.9zm60.1 3.9V66H82v64H69.9a5 5 0 1 1 0-2H80V64h32V37.9a5 5 0 1 1 2 0zM101.9 82a5 5 0 1 1 0-2H128V37.9a5 5 0 1 1 2 0V82h-28.1zm16-64a5 5 0 1 1 0-2H146v44.1a5 5 0 1 1-2 0V18h-26.1zm102.2 270a5 5 0 1 1 0 2H98v14h-2v-16h124.1zM242 149.9V160h16v34h-16v62h48v48h-2v-46h-48v-66h16v-30h-16v-12.1a5 5 0 1 1 2 0zM53.9 18a5 5 0 1 1 0-2H64V2H48V0h18v18H53.9zm112 32a5 5 0 1 1 0-2H192V0h50v2h-48v48h-28.1zm-48-48a5 5 0 0 1-9.8-2h2.07a3 3 0 1 0 5.66 0H178v34h-18V21.9a5 5 0 1 1 2 0V32h14V2h-58.1zm0 96a5 5 0 1 1 0-2H137l32-32h39V21.9a5 5 0 1 1 2 0V66h-40.17l-32 32H117.9zm28.1 90.1a5 5 0 1 1-2 0v-76.51L175.59 80H224V21.9a5 5 0 1 1 2 0V82h-49.59L146 112.41v75.69zm16 32a5 5 0 1 1-2 0v-99.51L184.59 96H300.1a5 5 0 0 1 3.9-3.9v2.07a3 3 0 0 0 0 5.66v2.07a5 5 0 0 1-3.9-3.9H185.41L162 121.41v98.69zm-144-64a5 5 0 1 1-2 0v-3.51l48-48V48h32V0h2v50H66v55.41l-48 48v2.69zM50 53.9v43.51l-48 48V208h26.1a5 5 0 1 1 0 2H0v-65.41l48-48V53.9a5 5 0 1 1 2 0zm-16 16V89.41l-34 34v-2.82l32-32V69.9a5 5 0 1 1 2 0zM12.1 32a5 5 0 1 1 0 2H9.41L0 43.41V40.6L8.59 32h3.51zm265.8 18a5 5 0 1 1 0-2h18.69l7.41-7.41v2.82L297.41 50H277.9zm-16 160a5 5 0 1 1 0-2H288v-71.41l16-16v2.82l-14 14V210h-28.1zm-208 32a5 5 0 1 1 0-2H64v-22.59L40.59 194H21.9a5 5 0 1 1 0-2H41.41L66 216.59V242H53.9zm150.2 14a5 5 0 1 1 0 2H96v-56.6L56.6 162H37.9a5 5 0 1 1 0-2h19.5L98 200.6V256h106.1zm-150.2 2a5 5 0 1 1 0-2H80v-46.59L48.59 178H21.9a5 5 0 1 1 0-2H49.41L82 208.59V258H53.9zM34 39.8v1.61L9.41 66H0v-2h8.59L32 40.59V0h2v39.8zM2 300.1a5 5 0 0 1 3.9 3.9H3.83A3 3 0 0 0 0 302.17V256h18v48h-2v-46H2v42.1zM34 241v63h-2v-62H0v-2h34v1zM17 18H0v-2h16V0h2v18h-1zm273-2h14v2h-16V0h2v16zm-32 273v15h-2v-14h-14v14h-2v-16h18v1zM0 92.1A5.02 5.02 0 0 1 6 97a5 5 0 0 1-6 4.9v-2.07a3 3 0 1 0 0-5.66V92.1zM80 272h2v32h-2v-32zm37.9 32h-2.07a3 3 0 0 0-5.66 0h-2.07a5 5 0 0 1 9.8 0zM5.9 0A5.02 5.02 0 0 1 0 5.9V3.83A3 3 0 0 0 3.83 0H5.9zm294.2 0h2.07A3 3 0 0 0 304 3.83V5.9a5 5 0 0 1-3.9-5.9zm3.9 300.1v2.07a3 3 0 0 0-1.83 1.83h-2.07a5 5 0 0 1 3.9-3.9zM97 100a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0-16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-48 32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm32 48a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm32-16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0-32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm32 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0-16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16-64a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 96a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16-144a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16-32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16-16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-96 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16-32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm96 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16-64a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16-16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-32 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0-16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM49 36a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-32 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm32 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM33 68a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16-48a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 240a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16-64a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16-32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm80-176a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16-16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm32 48a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16-16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0-32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm112 176a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM17 180a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0-32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM17 84a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm32 64a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16-16a3 3 0 1 0 0-6 3 3 0 0 0 0 6z'%3E%3C/path%3E%3C/svg%3E"); } html, @@ -63,6 +67,15 @@ body { scroll-behavior: smooth !important; scroll-padding-top: 2rem; transition: background-color 0.35s; + position: relative; +} + +body::before { + content: ''; + position: absolute; + inset: 0; + background-image: var(--background-image); + mask-image: linear-gradient(0deg, transparent 70%, var(--primary-color)); } * { diff --git a/src/styles/markdown.css b/src/styles/markdown.css index 3ba67a24..f46ee511 100644 --- a/src/styles/markdown.css +++ b/src/styles/markdown.css @@ -7,6 +7,7 @@ border: 1px var(--contrast-color) solid; border-radius: var(--border-radius); padding: 1rem; + background-color: var(--secondary-color); } .post-content [class~='lead'] { @@ -195,29 +196,31 @@ .post-content .rwd-table-wrapper { overflow: auto; -} - -.post-content table { - overflow-x: auto; margin: 2rem 0; } .post-content table { + overflow-x: auto; + margin: 0; + position: relative; width: 100%; table-layout: auto; text-align: left; - margin: 0 0 0.5em 0; font-size: 0.875em; line-height: 1.7142857; border-collapse: collapse; } -.post-content table::-webkit-scrollbar, -.post-content table::-webkit-scrollbar-track { - background-color: inherit; - border-radius: calc(0.3rem + 1.5px); - border-top-left-radius: 0; - border-top-right-radius: 0; +.post-content table::before { + content: ''; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + border-radius: 12px; + border: 1px solid var(--contrast-color); + pointer-events: none; } .post-content table::-webkit-scrollbar, @@ -235,7 +238,9 @@ border-radius: 10px; } +/* Table header styles */ .post-content thead { + background-color: var(--secondary-color); color: var(--primary-text-color); font-weight: 600; border-bottom-width: 1px; @@ -244,24 +249,18 @@ .post-content thead th { vertical-align: bottom; - padding-right: 0.5714286em; - padding-bottom: 0.5714286em; - padding-left: 0.5714286em; - border: 1px solid var(--contrast-color); -} - -.post-content tbody tr { - border-bottom-width: 1px; - border-bottom-color: var(--contrast-color); + padding: 0.5714286em; } .post-content tbody td { vertical-align: top; - padding-top: 0.5714286em; - padding-right: 0.5714286em; - padding-bottom: 0.5714286em; - padding-left: 0.5714286em; - border: 1px solid var(--contrast-color); + padding: 0.5714286em; + border-top: 1px solid var(--contrast-color); + border-left: 1px solid var(--contrast-color); +} + +.post-content tbody tr td:first-child { + border-left: none; } .post-content { diff --git a/src/styles/remark/remark-slider.css b/src/styles/remark/remark-slider.css new file mode 100644 index 00000000..25b8ebd8 --- /dev/null +++ b/src/styles/remark/remark-slider.css @@ -0,0 +1,78 @@ +.remark-slider { + display: flex; + overflow: hidden; + position: relative; +} + +.remark-slider .remark-slider-caption { + min-width: 100%; + transition: transform 0.5s ease; +} + +.remark-slider .remark-slider-caption figcaption { + text-align: center; +} + +.remark-slider:hover .prev, +.remark-slider:hover .next, +.remark-slider:hover .slide-index { + pointer-events: all; + opacity: 1; +} + +.remark-slider>.prev, +.next { + position: absolute; + top: 50%; + transform: translateY(-50%); + background-color: var(--primary-color); + color: var(--primary-text-color); + padding: 0.4rem 0.6rem; + cursor: pointer; + font-size: 18px; + border-radius: var(--border-radius); + display: flex; + align-items: center; + justify-content: center; + border: var(--border-size) solid rgba(var(--contrast-color-rgb), 0.5); + pointer-events: none; + opacity: 0.2; + transition: opacity 0.4s ease; +} + +.remark-slider .prev { + left: 0.5rem; +} + +.remark-slider .next { + right: 0.5rem; +} + +.remark-slider .slide-index { + position: absolute; + bottom: 7rem; + left: 50%; + transform: translateX(-50%); + background-color: var(--primary-color); + color: var(--primary-text-color); + padding: 5px 10px; + border-radius: 5px; + font-size: 14px; + border: var(--border-size) solid rgba(var(--contrast-color-rgb), 0.5); + pointer-events: none; + opacity: 0.2; + transition: opacity 0.4s ease; +} + +@media (max-width: 768px) { + .remark-slider .slide-index { + pointer-events: all; + opacity: 1; + } + + .remark-slider .next, + .remark-slider .prev { + pointer-events: all; + opacity: 1; + } +} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index 2c14e6bd..fde741aa 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,5 +1,5 @@ { - "extends": "astro/tsconfigs/base", + "extends": "astro/tsconfigs/strict", "compilerOptions": { "jsx": "react-jsx", // Enable top-level await, and other modern ESM features. @@ -28,7 +28,5 @@ "@lib/*": ["lib/*"] }, "jsxImportSource": "react" - }, - "jsx": "react-jsx", - "jsxImportSource": "react" + } } diff --git a/yarn.lock b/yarn.lock index 95cb5ee4..97e511f4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -31,27 +31,20 @@ __metadata: languageName: node linkType: hard -"@antfu/install-pkg@npm:^0.1.1": - version: 0.1.1 - resolution: "@antfu/install-pkg@npm:0.1.1" +"@antfu/install-pkg@npm:^0.4.0": + version: 0.4.1 + resolution: "@antfu/install-pkg@npm:0.4.1" dependencies: - execa: ^5.1.1 - find-up: ^5.0.0 - checksum: a463af6a0df3cf0769fd88ec94d135ca54e4f7329422fa3815bf1e71fb4ca510ec02bb39935bec65a15a8d8df5e76bf8e6a7df0c7c6cc512aefa3bec85ad903f - languageName: node - linkType: hard - -"@antfu/utils@npm:^0.7.5": - version: 0.7.7 - resolution: "@antfu/utils@npm:0.7.7" - checksum: 58b7c52e7531b0bed421b52d414331909c1db9fa97532a70ac0e35d7216153d9e25c654594326cad68a529c75379e4d52e3ea377273d28302302ab0f97189284 + package-manager-detector: ^0.2.0 + tinyexec: ^0.3.0 + checksum: 3ffd59fa5a21dcb4951a037f5c91dfbfc152adfef9e7ba231a968f108aa28c1cd22213c437a8d34f2bfea8c2b9a6df20447eb04be15b534a8e9e21a9dcf203c0 languageName: node linkType: hard -"@astrojs/compiler@npm:^1.5.5": - version: 1.8.1 - resolution: "@astrojs/compiler@npm:1.8.1" - checksum: d581efd4c518328d9c827aeb45cf3a5fd5f9f67f609609d6984b3367e8cf354837219d5ebddbebad4f30e6d6f9a28949b7f2b4ef2d6690989f7b7a36a8debd71 +"@antfu/utils@npm:^0.7.10": + version: 0.7.10 + resolution: "@antfu/utils@npm:0.7.10" + checksum: b93dd9e2c7e96ae6dca8a07c1fc5e7165ea9c7a89e78ecb75959bc9a8e769d3f565aea1b5c43db7374dd1f405cc277b6d14d85f884886f9d424dd6144d9203f2 languageName: node linkType: hard @@ -62,6 +55,13 @@ __metadata: languageName: node linkType: hard +"@astrojs/compiler@npm:^2.10.3, @astrojs/compiler@npm:^2.9.1": + version: 2.10.3 + resolution: "@astrojs/compiler@npm:2.10.3" + checksum: 73a6fea1465a2a845a35bed139189e5886730f4bea44292c64cc7cab0747b9ce517ce3380d258d6008148cdb855b6200b0fdc9546961fb113920fc2d7e8d3539 + languageName: node + linkType: hard + "@astrojs/compiler@npm:^2.8.0": version: 2.8.0 resolution: "@astrojs/compiler@npm:2.8.0" @@ -76,6 +76,13 @@ __metadata: languageName: node linkType: hard +"@astrojs/internal-helpers@npm:0.4.1": + version: 0.4.1 + resolution: "@astrojs/internal-helpers@npm:0.4.1" + checksum: dfd5fb2020b101aee18daae3550ba3649e3851f0e0a52de40023b990dda1a835a8b66e40c9c4ef13aca6d376e6b9ee625a0c49d1d0157edb4c57dbae4be5b889 + languageName: node + linkType: hard + "@astrojs/markdown-remark@npm:5.1.0": version: 5.1.0 resolution: "@astrojs/markdown-remark@npm:5.1.0" @@ -102,7 +109,33 @@ __metadata: languageName: node linkType: hard -"@astrojs/prism@npm:^3.1.0": +"@astrojs/markdown-remark@npm:5.3.0": + version: 5.3.0 + resolution: "@astrojs/markdown-remark@npm:5.3.0" + dependencies: + "@astrojs/prism": 3.1.0 + github-slugger: ^2.0.0 + hast-util-from-html: ^2.0.3 + hast-util-to-text: ^4.0.2 + import-meta-resolve: ^4.1.0 + mdast-util-definitions: ^6.0.0 + rehype-raw: ^7.0.0 + rehype-stringify: ^10.0.1 + remark-gfm: ^4.0.0 + remark-parse: ^11.0.0 + remark-rehype: ^11.1.1 + remark-smartypants: ^3.0.2 + shiki: ^1.22.0 + unified: ^11.0.5 + unist-util-remove-position: ^5.0.0 + unist-util-visit: ^5.0.0 + unist-util-visit-parents: ^6.0.1 + vfile: ^6.0.3 + checksum: a0b94ac15d7e0b4285980bf33e92500d7882330ba62f38fe442480c1d1c7b24e31e0ecc250211a648eb024392211e0bf63b2cfc404089e38d5f5694b554afcf9 + languageName: node + linkType: hard + +"@astrojs/prism@npm:3.1.0, @astrojs/prism@npm:^3.1.0": version: 3.1.0 resolution: "@astrojs/prism@npm:3.1.0" dependencies: @@ -201,6 +234,17 @@ __metadata: languageName: node linkType: hard +"@babel/code-frame@npm:^7.25.9, @babel/code-frame@npm:^7.26.0": + version: 7.26.2 + resolution: "@babel/code-frame@npm:7.26.2" + dependencies: + "@babel/helper-validator-identifier": ^7.25.9 + js-tokens: ^4.0.0 + picocolors: ^1.0.0 + checksum: db13f5c42d54b76c1480916485e6900748bbcb0014a8aca87f50a091f70ff4e0d0a6db63cade75eb41fcc3d2b6ba0a7f89e343def4f96f00269b41b8ab8dd7b8 + languageName: node + linkType: hard + "@babel/compat-data@npm:^7.22.5, @babel/compat-data@npm:^7.22.6, @babel/compat-data@npm:^7.22.9": version: 7.22.9 resolution: "@babel/compat-data@npm:7.22.9" @@ -222,6 +266,13 @@ __metadata: languageName: node linkType: hard +"@babel/compat-data@npm:^7.25.9": + version: 7.26.2 + resolution: "@babel/compat-data@npm:7.26.2" + checksum: d52fae9b0dc59b409d6005ae6b172e89329f46d68136130065ebe923a156fc633e0f1c8600b3e319b9e0f99fd948f64991a5419e2e9431d00d9d235d5f7a7618 + languageName: node + linkType: hard + "@babel/core@npm:^7.12.10": version: 7.22.10 resolution: "@babel/core@npm:7.22.10" @@ -291,6 +342,29 @@ __metadata: languageName: node linkType: hard +"@babel/core@npm:^7.26.0": + version: 7.26.0 + resolution: "@babel/core@npm:7.26.0" + dependencies: + "@ampproject/remapping": ^2.2.0 + "@babel/code-frame": ^7.26.0 + "@babel/generator": ^7.26.0 + "@babel/helper-compilation-targets": ^7.25.9 + "@babel/helper-module-transforms": ^7.26.0 + "@babel/helpers": ^7.26.0 + "@babel/parser": ^7.26.0 + "@babel/template": ^7.25.9 + "@babel/traverse": ^7.25.9 + "@babel/types": ^7.26.0 + convert-source-map: ^2.0.0 + debug: ^4.1.0 + gensync: ^1.0.0-beta.2 + json5: ^2.2.3 + semver: ^6.3.1 + checksum: b296084cfd818bed8079526af93b5dfa0ba70282532d2132caf71d4060ab190ba26d3184832a45accd82c3c54016985a4109ab9118674347a7e5e9bc464894e6 + languageName: node + linkType: hard + "@babel/generator@npm:^7.22.10": version: 7.22.10 resolution: "@babel/generator@npm:7.22.10" @@ -327,6 +401,19 @@ __metadata: languageName: node linkType: hard +"@babel/generator@npm:^7.25.9, @babel/generator@npm:^7.26.0": + version: 7.26.2 + resolution: "@babel/generator@npm:7.26.2" + dependencies: + "@babel/parser": ^7.26.2 + "@babel/types": ^7.26.0 + "@jridgewell/gen-mapping": ^0.3.5 + "@jridgewell/trace-mapping": ^0.3.25 + jsesc: ^3.0.2 + checksum: 6ff850b7d6082619f8c2f518d993cf7254cfbaa20b026282cbef5c9b2197686d076a432b18e36c4d1a42721c016df4f77a8f62c67600775d9683621d534b91b4 + languageName: node + linkType: hard + "@babel/helper-annotate-as-pure@npm:^7.22.5": version: 7.22.5 resolution: "@babel/helper-annotate-as-pure@npm:7.22.5" @@ -345,6 +432,15 @@ __metadata: languageName: node linkType: hard +"@babel/helper-annotate-as-pure@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/helper-annotate-as-pure@npm:7.25.9" + dependencies: + "@babel/types": ^7.25.9 + checksum: 41edda10df1ae106a9b4fe617bf7c6df77db992992afd46192534f5cff29f9e49a303231733782dd65c5f9409714a529f215325569f14282046e9d3b7a1ffb6c + languageName: node + linkType: hard + "@babel/helper-builder-binary-assignment-operator-visitor@npm:^7.22.5": version: 7.22.10 resolution: "@babel/helper-builder-binary-assignment-operator-visitor@npm:7.22.10" @@ -393,6 +489,19 @@ __metadata: languageName: node linkType: hard +"@babel/helper-compilation-targets@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/helper-compilation-targets@npm:7.25.9" + dependencies: + "@babel/compat-data": ^7.25.9 + "@babel/helper-validator-option": ^7.25.9 + browserslist: ^4.24.0 + lru-cache: ^5.1.1 + semver: ^6.3.1 + checksum: 3af536e2db358b38f968abdf7d512d425d1018fef2f485d6f131a57a7bcaed32c606b4e148bb230e1508fa42b5b2ac281855a68eb78270f54698c48a83201b9b + languageName: node + linkType: hard + "@babel/helper-create-class-features-plugin@npm:^7.12.1, @babel/helper-create-class-features-plugin@npm:^7.22.5": version: 7.22.10 resolution: "@babel/helper-create-class-features-plugin@npm:7.22.10" @@ -548,6 +657,16 @@ __metadata: languageName: node linkType: hard +"@babel/helper-module-imports@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/helper-module-imports@npm:7.25.9" + dependencies: + "@babel/traverse": ^7.25.9 + "@babel/types": ^7.25.9 + checksum: 1b411ce4ca825422ef7065dffae7d8acef52023e51ad096351e3e2c05837e9bf9fca2af9ca7f28dc26d596a588863d0fedd40711a88e350b736c619a80e704e6 + languageName: node + linkType: hard + "@babel/helper-module-transforms@npm:^7.22.5, @babel/helper-module-transforms@npm:^7.22.9": version: 7.22.9 resolution: "@babel/helper-module-transforms@npm:7.22.9" @@ -593,6 +712,19 @@ __metadata: languageName: node linkType: hard +"@babel/helper-module-transforms@npm:^7.26.0": + version: 7.26.0 + resolution: "@babel/helper-module-transforms@npm:7.26.0" + dependencies: + "@babel/helper-module-imports": ^7.25.9 + "@babel/helper-validator-identifier": ^7.25.9 + "@babel/traverse": ^7.25.9 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 942eee3adf2b387443c247a2c190c17c4fd45ba92a23087abab4c804f40541790d51ad5277e4b5b1ed8d5ba5b62de73857446b7742f835c18ebd350384e63917 + languageName: node + linkType: hard + "@babel/helper-optimise-call-expression@npm:^7.22.5": version: 7.22.5 resolution: "@babel/helper-optimise-call-expression@npm:7.22.5" @@ -616,6 +748,13 @@ __metadata: languageName: node linkType: hard +"@babel/helper-plugin-utils@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/helper-plugin-utils@npm:7.25.9" + checksum: e19ec8acf0b696756e6d84531f532c5fe508dce57aa68c75572a77798bd04587a844a9a6c8ea7d62d673e21fdc174d091c9097fb29aea1c1b49f9c6eaa80f022 + languageName: node + linkType: hard + "@babel/helper-remap-async-to-generator@npm:^7.22.5, @babel/helper-remap-async-to-generator@npm:^7.22.9": version: 7.22.9 resolution: "@babel/helper-remap-async-to-generator@npm:7.22.9" @@ -709,6 +848,13 @@ __metadata: languageName: node linkType: hard +"@babel/helper-string-parser@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/helper-string-parser@npm:7.25.9" + checksum: 6435ee0849e101681c1849868278b5aee82686ba2c1e27280e5e8aca6233af6810d39f8e4e693d2f2a44a3728a6ccfd66f72d71826a94105b86b731697cdfa99 + languageName: node + linkType: hard + "@babel/helper-validator-identifier@npm:^7.22.15": version: 7.22.15 resolution: "@babel/helper-validator-identifier@npm:7.22.15" @@ -737,6 +883,13 @@ __metadata: languageName: node linkType: hard +"@babel/helper-validator-identifier@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/helper-validator-identifier@npm:7.25.9" + checksum: 5b85918cb1a92a7f3f508ea02699e8d2422fe17ea8e82acd445006c0ef7520fbf48e3dbcdaf7b0a1d571fc3a2715a29719e5226636cb6042e15fe6ed2a590944 + languageName: node + linkType: hard + "@babel/helper-validator-option@npm:^7.22.5": version: 7.22.5 resolution: "@babel/helper-validator-option@npm:7.22.5" @@ -758,6 +911,13 @@ __metadata: languageName: node linkType: hard +"@babel/helper-validator-option@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/helper-validator-option@npm:7.25.9" + checksum: 9491b2755948ebbdd68f87da907283698e663b5af2d2b1b02a2765761974b1120d5d8d49e9175b167f16f72748ffceec8c9cf62acfbee73f4904507b246e2b3d + languageName: node + linkType: hard + "@babel/helper-wrap-function@npm:^7.22.9": version: 7.22.10 resolution: "@babel/helper-wrap-function@npm:7.22.10" @@ -801,6 +961,16 @@ __metadata: languageName: node linkType: hard +"@babel/helpers@npm:^7.26.0": + version: 7.26.0 + resolution: "@babel/helpers@npm:7.26.0" + dependencies: + "@babel/template": ^7.25.9 + "@babel/types": ^7.26.0 + checksum: d77fe8d45033d6007eadfa440355c1355eed57902d5a302f450827ad3d530343430a21210584d32eef2f216ae463d4591184c6fc60cf205bbf3a884561469200 + languageName: node + linkType: hard + "@babel/highlight@npm:^7.22.10": version: 7.22.10 resolution: "@babel/highlight@npm:7.22.10" @@ -882,6 +1052,17 @@ __metadata: languageName: node linkType: hard +"@babel/parser@npm:^7.25.4, @babel/parser@npm:^7.25.9, @babel/parser@npm:^7.26.0, @babel/parser@npm:^7.26.2": + version: 7.26.2 + resolution: "@babel/parser@npm:7.26.2" + dependencies: + "@babel/types": ^7.26.0 + bin: + parser: ./bin/babel-parser.js + checksum: c88b5ea0adf357ef909cdc2c31e284a154943edc59f63f6e8a4c20bf773a1b2f3d8c2205e59c09ca7cdad91e7466300114548876529277a80651b6436a48d5d9 + languageName: node + linkType: hard + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:^7.22.5": version: 7.22.5 resolution: "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:7.22.5" @@ -1059,6 +1240,17 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-syntax-jsx@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-syntax-jsx@npm:7.25.9" + dependencies: + "@babel/helper-plugin-utils": ^7.25.9 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: bb609d1ffb50b58f0c1bac8810d0e46a4f6c922aa171c458f3a19d66ee545d36e782d3bffbbc1fed0dc65a558bdce1caf5279316583c0fff5a2c1658982a8563 + languageName: node + linkType: hard + "@babel/plugin-syntax-logical-assignment-operators@npm:^7.10.4": version: 7.10.4 resolution: "@babel/plugin-syntax-logical-assignment-operators@npm:7.10.4" @@ -1699,6 +1891,21 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-react-jsx@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-react-jsx@npm:7.25.9" + dependencies: + "@babel/helper-annotate-as-pure": ^7.25.9 + "@babel/helper-module-imports": ^7.25.9 + "@babel/helper-plugin-utils": ^7.25.9 + "@babel/plugin-syntax-jsx": ^7.25.9 + "@babel/types": ^7.25.9 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 5c6523c3963e3c6cf4c3cc2768a3766318af05b8f6c17aff52a4010e2c170e87b2fcdc94e9c9223ae12158664df4852ce81b9c8d042c15ea8fd83d6375f9f30f + languageName: node + linkType: hard + "@babel/plugin-transform-react-pure-annotations@npm:^7.22.5": version: 7.22.5 resolution: "@babel/plugin-transform-react-pure-annotations@npm:7.22.5" @@ -2029,6 +2236,17 @@ __metadata: languageName: node linkType: hard +"@babel/template@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/template@npm:7.25.9" + dependencies: + "@babel/code-frame": ^7.25.9 + "@babel/parser": ^7.25.9 + "@babel/types": ^7.25.9 + checksum: 103641fea19c7f4e82dc913aa6b6ac157112a96d7c724d513288f538b84bae04fb87b1f1e495ac1736367b1bc30e10f058b30208fb25f66038e1f1eb4e426472 + languageName: node + linkType: hard + "@babel/traverse@npm:^7.22.10": version: 7.22.10 resolution: "@babel/traverse@npm:7.22.10" @@ -2083,6 +2301,21 @@ __metadata: languageName: node linkType: hard +"@babel/traverse@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/traverse@npm:7.25.9" + dependencies: + "@babel/code-frame": ^7.25.9 + "@babel/generator": ^7.25.9 + "@babel/parser": ^7.25.9 + "@babel/template": ^7.25.9 + "@babel/types": ^7.25.9 + debug: ^4.3.1 + globals: ^11.1.0 + checksum: 901d325662ff1dd9bc51de00862e01055fa6bc374f5297d7e3731f2f0e268bbb1d2141f53fa82860aa308ee44afdcf186a948f16c83153927925804b95a9594d + languageName: node + linkType: hard + "@babel/types@npm:^7.0.0, @babel/types@npm:^7.20.7, @babel/types@npm:^7.22.10, @babel/types@npm:^7.22.5, @babel/types@npm:^7.4.4": version: 7.22.10 resolution: "@babel/types@npm:7.22.10" @@ -2138,6 +2371,16 @@ __metadata: languageName: node linkType: hard +"@babel/types@npm:^7.25.4, @babel/types@npm:^7.25.9, @babel/types@npm:^7.26.0": + version: 7.26.0 + resolution: "@babel/types@npm:7.26.0" + dependencies: + "@babel/helper-string-parser": ^7.25.9 + "@babel/helper-validator-identifier": ^7.25.9 + checksum: a3dd37dabac693018872da96edb8c1843a605c1bfacde6c3f504fba79b972426a6f24df70aa646356c0c1b19bdd2c722c623c684a996c002381071680602280d + languageName: node + linkType: hard + "@ctrl/tinycolor@npm:^3.6.0": version: 3.6.1 resolution: "@ctrl/tinycolor@npm:3.6.1" @@ -2518,10 +2761,10 @@ __metadata: languageName: node linkType: hard -"@eslint/js@npm:8.57.0": - version: 8.57.0 - resolution: "@eslint/js@npm:8.57.0" - checksum: 315dc65b0e9893e2bff139bddace7ea601ad77ed47b4550e73da8c9c2d2766c7a575c3cddf17ef85b8fd6a36ff34f91729d0dcca56e73ca887c10df91a41b0bb +"@eslint/js@npm:8.57.1": + version: 8.57.1 + resolution: "@eslint/js@npm:8.57.1" + checksum: 2afb77454c06e8316793d2e8e79a0154854d35e6782a1217da274ca60b5044d2c69d6091155234ed0551a1e408f86f09dd4ece02752c59568fa403e60611e880 languageName: node linkType: hard @@ -2538,9 +2781,9 @@ __metadata: languageName: node linkType: hard -"@expressive-code/core@npm:^0.35.3": - version: 0.35.3 - resolution: "@expressive-code/core@npm:0.35.3" +"@expressive-code/core@npm:^0.38.1": + version: 0.38.1 + resolution: "@expressive-code/core@npm:0.38.1" dependencies: "@ctrl/tinycolor": ^4.0.4 hast-util-select: ^6.0.2 @@ -2551,16 +2794,16 @@ __metadata: postcss-nested: ^6.0.1 unist-util-visit: ^5.0.0 unist-util-visit-parents: ^6.0.1 - checksum: 384f357ce89fcffdf4994ba6237d02faa7bf7d61314b392d56bdfed5812581501bc8664060455cc3359f1820b884232aa5a86ef6d4d61234f722a47ab8134186 + checksum: f7fcf5b2449cad7a21e514710a6b1d7cca21d419e4526c7be4a78c1a04b9287a11a81c1631c266ea16fbc8adb7fe7d364cb8b513473bd92da7429a6410dc5349 languageName: node linkType: hard -"@expressive-code/plugin-frames@npm:^0.35.3": - version: 0.35.3 - resolution: "@expressive-code/plugin-frames@npm:0.35.3" +"@expressive-code/plugin-frames@npm:^0.38.1": + version: 0.38.1 + resolution: "@expressive-code/plugin-frames@npm:0.38.1" dependencies: - "@expressive-code/core": ^0.35.3 - checksum: 82182cac445493a00bd4ba9b25c3de796943ff4988f871a3c409ad3d0594b8c6c844523c299897874b0064abb4bedd7c06f682188358ba888e53b803ee1f8852 + "@expressive-code/core": ^0.38.1 + checksum: ec07b2bda2a83983e750ca24f479ebd78d379594394cda13fcdd2c5fe8578f8a852ff5d2c7ff944cebe5e2e326bb3f8c7d32f6b1599c2a8be302da277609ffeb languageName: node linkType: hard @@ -2574,22 +2817,22 @@ __metadata: languageName: node linkType: hard -"@expressive-code/plugin-shiki@npm:^0.35.3": - version: 0.35.3 - resolution: "@expressive-code/plugin-shiki@npm:0.35.3" +"@expressive-code/plugin-shiki@npm:^0.38.1": + version: 0.38.1 + resolution: "@expressive-code/plugin-shiki@npm:0.38.1" dependencies: - "@expressive-code/core": ^0.35.3 - shiki: ^1.1.7 - checksum: 51b09591cb5bdeaa4bb0f1d77304ada1a802b0cf24f35315744f91b26bf13d56f3057212635de88c51799932f265a4a2c7cde4bda0e8e434988913538bb2774e + "@expressive-code/core": ^0.38.1 + shiki: ^1.22.2 + checksum: 7000d108aa4cd163bde0e13f913c05f51f9d53091d9e079a6f50ca00304d3052674068a8fb437a2b077f2fada94d513157c02fd2887332d8ae8b9f439c30d0a4 languageName: node linkType: hard -"@expressive-code/plugin-text-markers@npm:^0.35.3": - version: 0.35.3 - resolution: "@expressive-code/plugin-text-markers@npm:0.35.3" +"@expressive-code/plugin-text-markers@npm:^0.38.1": + version: 0.38.1 + resolution: "@expressive-code/plugin-text-markers@npm:0.38.1" dependencies: - "@expressive-code/core": ^0.35.3 - checksum: c681f33b61ebb4a4c3130ef76b035046004a7ef4465a7572bba6a7bc50278120ae87663d3aea9c5936f7cb9ceacf026ae7982b04ef04354dec42a941969fd3de + "@expressive-code/core": ^0.38.1 + checksum: cd3c4253c2edf97d11c96d3805ccd7bb35bbd8c65141d78cdd150fff559dd7fc429a2dab69e69027727086a8abd9db6ea7d547a676915b83de983f0081e679ec languageName: node linkType: hard @@ -2600,14 +2843,14 @@ __metadata: languageName: node linkType: hard -"@humanwhocodes/config-array@npm:^0.11.14": - version: 0.11.14 - resolution: "@humanwhocodes/config-array@npm:0.11.14" +"@humanwhocodes/config-array@npm:^0.13.0": + version: 0.13.0 + resolution: "@humanwhocodes/config-array@npm:0.13.0" dependencies: - "@humanwhocodes/object-schema": ^2.0.2 + "@humanwhocodes/object-schema": ^2.0.3 debug: ^4.3.1 minimatch: ^3.0.5 - checksum: 861ccce9eaea5de19546653bccf75bf09fe878bc39c3aab00aeee2d2a0e654516adad38dd1098aab5e3af0145bbcbf3f309bdf4d964f8dab9dcd5834ae4c02f2 + checksum: eae69ff9134025dd2924f0b430eb324981494be26f0fddd267a33c28711c4db643242cf9fddf7dadb9d16c96b54b2d2c073e60a56477df86e0173149313bd5d6 languageName: node linkType: hard @@ -2618,10 +2861,10 @@ __metadata: languageName: node linkType: hard -"@humanwhocodes/object-schema@npm:^2.0.2": - version: 2.0.2 - resolution: "@humanwhocodes/object-schema@npm:2.0.2" - checksum: 2fc11503361b5fb4f14714c700c02a3f4c7c93e9acd6b87a29f62c522d90470f364d6161b03d1cc618b979f2ae02aed1106fd29d302695d8927e2fc8165ba8ee +"@humanwhocodes/object-schema@npm:^2.0.3": + version: 2.0.3 + resolution: "@humanwhocodes/object-schema@npm:2.0.3" + checksum: d3b78f6c5831888c6ecc899df0d03bcc25d46f3ad26a11d7ea52944dc36a35ef543fad965322174238d677a43d5c694434f6607532cff7077062513ad7022631 languageName: node linkType: hard @@ -2652,21 +2895,31 @@ __metadata: languageName: node linkType: hard -"@iconify/tools@npm:^3.0.1": - version: 3.0.7 - resolution: "@iconify/tools@npm:3.0.7" +"@iconify-json/tabler@npm:^1.1.118": + version: 1.1.118 + resolution: "@iconify-json/tabler@npm:1.1.118" + dependencies: + "@iconify/types": "*" + checksum: 66763f337e96db5344afbd3db4209d84adba448fc77adf4717934167bc7a94c5725a44a7b73f49c8b824a4e215ac7aa7cb136971ca9ca084d314ffe6fd26e07f + languageName: node + linkType: hard + +"@iconify/tools@npm:^4.0.5": + version: 4.0.7 + resolution: "@iconify/tools@npm:4.0.7" dependencies: "@iconify/types": ^2.0.0 - "@iconify/utils": ^2.1.10 - "@types/cheerio": ^0.22.32 - "@types/tar": ^6.1.6 - cheerio: ^1.0.0-rc.12 + "@iconify/utils": ^2.1.32 + "@types/tar": ^6.1.13 + axios: ^1.7.7 + cheerio: 1.0.0 + domhandler: ^5.0.3 extract-zip: ^2.0.1 - local-pkg: ^0.4.3 - pathe: ^1.1.1 - svgo: 3.0.3 - tar: ^6.2.0 - checksum: 97fb40715250d6a31335d3e21455763e4a89bdda0fcbad383e95425492164a1244705acfafae72ecaaebc51cfe5ee0c64d7a131275cb1a18b5f8b04153c4d707 + local-pkg: ^0.5.0 + pathe: ^1.1.2 + svgo: ^3.3.2 + tar: ^6.2.1 + checksum: 4be0c934cdc97aac639406ade6214c9a2f77dbda29c0410331f32e8c0f016f17cfab96137e4e10a3575d5ce8357f4edac41250258bffac72b28b6a5d73f1a523 languageName: node linkType: hard @@ -2677,18 +2930,18 @@ __metadata: languageName: node linkType: hard -"@iconify/utils@npm:^2.1.10, @iconify/utils@npm:^2.1.5": - version: 2.1.22 - resolution: "@iconify/utils@npm:2.1.22" +"@iconify/utils@npm:^2.1.30, @iconify/utils@npm:^2.1.32": + version: 2.1.33 + resolution: "@iconify/utils@npm:2.1.33" dependencies: - "@antfu/install-pkg": ^0.1.1 - "@antfu/utils": ^0.7.5 + "@antfu/install-pkg": ^0.4.0 + "@antfu/utils": ^0.7.10 "@iconify/types": ^2.0.0 - debug: ^4.3.4 + debug: ^4.3.6 kolorist: ^1.8.0 local-pkg: ^0.5.0 - mlly: ^1.5.0 - checksum: d481819b841f07bf189afc963ddb3f85e08c6af0dad2ff829e8d3875dfa8c4753e4e6fca6c2f657db6cf66a756119ea5ab5813ab2d812092352ac08261c5cd60 + mlly: ^1.7.1 + checksum: 2d8bed71aa350954ea6f6c23e3c02263d3058c270ab5c71cae5cbc7c9c0ceb1ba986378696f5854b00a94fbfd5cd9afdd0ba8ae360efe352560a14ecc46a9649 languageName: node linkType: hard @@ -2966,6 +3219,13 @@ __metadata: languageName: node linkType: hard +"@jridgewell/sourcemap-codec@npm:^1.5.0": + version: 1.5.0 + resolution: "@jridgewell/sourcemap-codec@npm:1.5.0" + checksum: 05df4f2538b3b0f998ea4c1cd34574d0feba216fa5d4ccaef0187d12abf82eafe6021cec8b49f9bb4d90f2ba4582ccc581e72986a5fcf4176ae0cfeb04cf52ec + languageName: node + linkType: hard + "@jridgewell/trace-mapping@npm:^0.3.17": version: 0.3.19 resolution: "@jridgewell/trace-mapping@npm:0.3.19" @@ -3008,32 +3268,33 @@ __metadata: "@iconify-json/ic": ^1.1.17 "@iconify-json/mdi": ^1.1.64 "@iconify-json/simple-icons": ^1.1.93 + "@iconify-json/tabler": ^1.1.118 "@lucjosin/remark-alert-blocks": ./plugins/remark-alert-blocks "@lucjosin/remark-code-highlight": ./plugins/remark-code-highlight "@lucjosin/remark-code-set": ./plugins/remark-code-set "@lucjosin/remark-image-caption": ./plugins/remark-image-caption "@lucjosin/remark-post-reference": ./plugins/remark-post-reference "@lucjosin/remark-readme-stats": ./plugins/remark-readme-stats + "@lucjosin/remark-slider": ./plugins/remark-slider "@resvg/resvg-js": ^2.5.0 "@swup/astro": ^1.3.2 "@types/react": ^18.2.29 "@types/react-dom": ^18.2.14 "@typescript-eslint/eslint-plugin": ^6.8.0 "@typescript-eslint/parser": ^6.8.0 - astro: ^4.10.1 - astro-compress: ^2.2.27 - astro-expressive-code: ^0.35.3 - astro-icon: ^1.1.0 - astro-meta-tags: ^0.3.0 + astro: ^4.16.8 + astro-compress: ^2.3.5 + astro-expressive-code: ^0.38.1 + astro-icon: ^1.1.1 + astro-meta-tags: ^0.3.1 astro-rename: ^1.1.2 astro-robots-txt: ^1.0.0 eslint: ^8.57.0 eslint-config-prettier: ^9.1.0 eslint-plugin-astro: ^0.31.4 - javascript-time-ago: ^2.5.10 medium-zoom: ^1.1.0 - prettier: ^3.3.1 - prettier-plugin-astro: ^0.14.0 + prettier: ^3.3.3 + prettier-plugin-astro: ^0.14.1 react: ^18.3.1 react-dom: ^18.3.1 reading-time: ^1.5.0 @@ -3043,10 +3304,10 @@ __metadata: remark-collapse: ^0.1.2 remark-numbered-footnote-labels: ^1.1.0 remark-toc: ^9.0.0 - satori: ^0.10.13 - satori-html: ^0.3.2 + satori: ^0.11.3 + satori-og: ^1.0.0 svgo: 2.8.0 - typescript: ^5.4.5 + typescript: ^5.6.3 languageName: unknown linkType: soft @@ -3063,10 +3324,10 @@ __metadata: "@lucjosin/remark-code-highlight@file:./plugins/remark-code-highlight::locator=%40lucjosin%2Flucasjosino.com%40workspace%3A.": version: 1.0.0 - resolution: "@lucjosin/remark-code-highlight@file:./plugins/remark-code-highlight#./plugins/remark-code-highlight::hash=7d2582&locator=%40lucjosin%2Flucasjosino.com%40workspace%3A." + resolution: "@lucjosin/remark-code-highlight@file:./plugins/remark-code-highlight#./plugins/remark-code-highlight::hash=0ea171&locator=%40lucjosin%2Flucasjosino.com%40workspace%3A." dependencies: unist-util-visit: ^5.0.0 - checksum: f1b2fa9304b1890d451d6a6083e9a98ecd20049cb5c407360243d50b0d495b9007270f657c4e9ce6f4156493317ac3840b0bcdb43c16b40d9ce5d735e30ff1b5 + checksum: 35049c1ef1ba69c3530766dfa8c71ab1965d11b5592e316ad751c7e3909cc612bc8d8b3fd9ec85c9e0c2f2a111ad928ed748ce1186a2f6ec9b5734c67268eaf3 languageName: node linkType: hard @@ -3084,10 +3345,10 @@ __metadata: "@lucjosin/remark-image-caption@file:./plugins/remark-image-caption::locator=%40lucjosin%2Flucasjosino.com%40workspace%3A.": version: 1.0.0 - resolution: "@lucjosin/remark-image-caption@file:./plugins/remark-image-caption#./plugins/remark-image-caption::hash=bc7280&locator=%40lucjosin%2Flucasjosino.com%40workspace%3A." + resolution: "@lucjosin/remark-image-caption@file:./plugins/remark-image-caption#./plugins/remark-image-caption::hash=1bc00f&locator=%40lucjosin%2Flucasjosino.com%40workspace%3A." dependencies: unist-util-visit: ^5.0.0 - checksum: 5871ce8a80324142401b61b404795e27bf109451ee0425f2d99f486608f9411f03bdd6fc9991575945c6b46cfb917e6854060ea4d95d62ee7ab9a15d366df64a + checksum: 7302f8b5fab380f781f66751bc9269bddea42d31f201a10a0b1d60a32aba6de3e3af6fbc54b607a9de3d7e3ff20c0b1d279911272af5eb18eae9e5c907423396 languageName: node linkType: hard @@ -3111,6 +3372,15 @@ __metadata: languageName: node linkType: hard +"@lucjosin/remark-slider@file:./plugins/remark-slider::locator=%40lucjosin%2Flucasjosino.com%40workspace%3A.": + version: 1.0.0 + resolution: "@lucjosin/remark-slider@file:./plugins/remark-slider#./plugins/remark-slider::hash=2013e4&locator=%40lucjosin%2Flucasjosino.com%40workspace%3A." + dependencies: + unist-util-visit: ^5.0.0 + checksum: 581147e48f6f250a84a8d548f6eabb14d4a8c3db0d2796f76be598becb809345f2aa404fc12e843a012fce0c785daad6f2e489fa483b73658ff63270c0bd77ac + languageName: node + linkType: hard + "@nodelib/fs.scandir@npm:2.1.5": version: 2.1.5 resolution: "@nodelib/fs.scandir@npm:2.1.5" @@ -3147,6 +3417,13 @@ __metadata: languageName: node linkType: hard +"@oslojs/encoding@npm:^1.1.0": + version: 1.1.0 + resolution: "@oslojs/encoding@npm:1.1.0" + checksum: 9122ad5fa5c3557c1205825b11ea51facbaf08153a47c349c6b1a613b6797e9b22f290d31f5b6faaa45ece39a2437ecdb866815c73beb182e2b203d1f2201e98 + languageName: node + linkType: hard + "@pkgjs/parseargs@npm:^0.11.0": version: 0.11.0 resolution: "@pkgjs/parseargs@npm:0.11.0" @@ -3168,22 +3445,14 @@ __metadata: languageName: node linkType: hard -"@playform/pipe@npm:0.0.5": - version: 0.0.5 - resolution: "@playform/pipe@npm:0.0.5" +"@playform/pipe@npm:0.1.1": + version: 0.1.1 + resolution: "@playform/pipe@npm:0.1.1" dependencies: - "@types/node": 20.12.12 - deepmerge-ts: 7.0.1 + "@types/node": 22.5.0 + deepmerge-ts: 7.1.0 fast-glob: 3.3.2 - peerDependencies: - "@playform/build": 0.0.9 - "@playform/document": 0.0.7 - peerDependenciesMeta: - "@playform/build": - optional: true - "@playform/document": - optional: true - checksum: 4c371ef6ad38d6686904ce2014f182f5c3a6222b18453a26f3fcc212e65b49a5d9b703404e452928a2be9288889e0bb543490da2c6585173620eb24b27ca54dd + checksum: da8673890cca5ae2598bb01243f8a7fd6bd4810b557828bebf586341ef6ebabda424dd4a45d9fb2a1cfa93f82429be4d9909f144834569ce453144d78dc94172 languageName: node linkType: hard @@ -3194,6 +3463,13 @@ __metadata: languageName: node linkType: hard +"@resvg/resvg-js-android-arm-eabi@npm:2.6.2": + version: 2.6.2 + resolution: "@resvg/resvg-js-android-arm-eabi@npm:2.6.2" + conditions: os=android & cpu=arm + languageName: node + linkType: hard + "@resvg/resvg-js-android-arm64@npm:2.5.0": version: 2.5.0 resolution: "@resvg/resvg-js-android-arm64@npm:2.5.0" @@ -3201,6 +3477,13 @@ __metadata: languageName: node linkType: hard +"@resvg/resvg-js-android-arm64@npm:2.6.2": + version: 2.6.2 + resolution: "@resvg/resvg-js-android-arm64@npm:2.6.2" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + "@resvg/resvg-js-darwin-arm64@npm:2.5.0": version: 2.5.0 resolution: "@resvg/resvg-js-darwin-arm64@npm:2.5.0" @@ -3208,6 +3491,13 @@ __metadata: languageName: node linkType: hard +"@resvg/resvg-js-darwin-arm64@npm:2.6.2": + version: 2.6.2 + resolution: "@resvg/resvg-js-darwin-arm64@npm:2.6.2" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + "@resvg/resvg-js-darwin-x64@npm:2.5.0": version: 2.5.0 resolution: "@resvg/resvg-js-darwin-x64@npm:2.5.0" @@ -3215,6 +3505,13 @@ __metadata: languageName: node linkType: hard +"@resvg/resvg-js-darwin-x64@npm:2.6.2": + version: 2.6.2 + resolution: "@resvg/resvg-js-darwin-x64@npm:2.6.2" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + "@resvg/resvg-js-linux-arm-gnueabihf@npm:2.5.0": version: 2.5.0 resolution: "@resvg/resvg-js-linux-arm-gnueabihf@npm:2.5.0" @@ -3222,6 +3519,13 @@ __metadata: languageName: node linkType: hard +"@resvg/resvg-js-linux-arm-gnueabihf@npm:2.6.2": + version: 2.6.2 + resolution: "@resvg/resvg-js-linux-arm-gnueabihf@npm:2.6.2" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + "@resvg/resvg-js-linux-arm64-gnu@npm:2.5.0": version: 2.5.0 resolution: "@resvg/resvg-js-linux-arm64-gnu@npm:2.5.0" @@ -3229,6 +3533,13 @@ __metadata: languageName: node linkType: hard +"@resvg/resvg-js-linux-arm64-gnu@npm:2.6.2": + version: 2.6.2 + resolution: "@resvg/resvg-js-linux-arm64-gnu@npm:2.6.2" + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + "@resvg/resvg-js-linux-arm64-musl@npm:2.5.0": version: 2.5.0 resolution: "@resvg/resvg-js-linux-arm64-musl@npm:2.5.0" @@ -3236,6 +3547,13 @@ __metadata: languageName: node linkType: hard +"@resvg/resvg-js-linux-arm64-musl@npm:2.6.2": + version: 2.6.2 + resolution: "@resvg/resvg-js-linux-arm64-musl@npm:2.6.2" + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + "@resvg/resvg-js-linux-x64-gnu@npm:2.5.0": version: 2.5.0 resolution: "@resvg/resvg-js-linux-x64-gnu@npm:2.5.0" @@ -3243,6 +3561,13 @@ __metadata: languageName: node linkType: hard +"@resvg/resvg-js-linux-x64-gnu@npm:2.6.2": + version: 2.6.2 + resolution: "@resvg/resvg-js-linux-x64-gnu@npm:2.6.2" + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + "@resvg/resvg-js-linux-x64-musl@npm:2.5.0": version: 2.5.0 resolution: "@resvg/resvg-js-linux-x64-musl@npm:2.5.0" @@ -3250,6 +3575,13 @@ __metadata: languageName: node linkType: hard +"@resvg/resvg-js-linux-x64-musl@npm:2.6.2": + version: 2.6.2 + resolution: "@resvg/resvg-js-linux-x64-musl@npm:2.6.2" + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + "@resvg/resvg-js-win32-arm64-msvc@npm:2.5.0": version: 2.5.0 resolution: "@resvg/resvg-js-win32-arm64-msvc@npm:2.5.0" @@ -3257,6 +3589,13 @@ __metadata: languageName: node linkType: hard +"@resvg/resvg-js-win32-arm64-msvc@npm:2.6.2": + version: 2.6.2 + resolution: "@resvg/resvg-js-win32-arm64-msvc@npm:2.6.2" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + "@resvg/resvg-js-win32-ia32-msvc@npm:2.5.0": version: 2.5.0 resolution: "@resvg/resvg-js-win32-ia32-msvc@npm:2.5.0" @@ -3264,6 +3603,13 @@ __metadata: languageName: node linkType: hard +"@resvg/resvg-js-win32-ia32-msvc@npm:2.6.2": + version: 2.6.2 + resolution: "@resvg/resvg-js-win32-ia32-msvc@npm:2.6.2" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + "@resvg/resvg-js-win32-x64-msvc@npm:2.5.0": version: 2.5.0 resolution: "@resvg/resvg-js-win32-x64-msvc@npm:2.5.0" @@ -3271,6 +3617,13 @@ __metadata: languageName: node linkType: hard +"@resvg/resvg-js-win32-x64-msvc@npm:2.6.2": + version: 2.6.2 + resolution: "@resvg/resvg-js-win32-x64-msvc@npm:2.6.2" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + "@resvg/resvg-js@npm:^2.5.0": version: 2.5.0 resolution: "@resvg/resvg-js@npm:2.5.0" @@ -3316,6 +3669,51 @@ __metadata: languageName: node linkType: hard +"@resvg/resvg-js@npm:^2.6.2": + version: 2.6.2 + resolution: "@resvg/resvg-js@npm:2.6.2" + dependencies: + "@resvg/resvg-js-android-arm-eabi": 2.6.2 + "@resvg/resvg-js-android-arm64": 2.6.2 + "@resvg/resvg-js-darwin-arm64": 2.6.2 + "@resvg/resvg-js-darwin-x64": 2.6.2 + "@resvg/resvg-js-linux-arm-gnueabihf": 2.6.2 + "@resvg/resvg-js-linux-arm64-gnu": 2.6.2 + "@resvg/resvg-js-linux-arm64-musl": 2.6.2 + "@resvg/resvg-js-linux-x64-gnu": 2.6.2 + "@resvg/resvg-js-linux-x64-musl": 2.6.2 + "@resvg/resvg-js-win32-arm64-msvc": 2.6.2 + "@resvg/resvg-js-win32-ia32-msvc": 2.6.2 + "@resvg/resvg-js-win32-x64-msvc": 2.6.2 + dependenciesMeta: + "@resvg/resvg-js-android-arm-eabi": + optional: true + "@resvg/resvg-js-android-arm64": + optional: true + "@resvg/resvg-js-darwin-arm64": + optional: true + "@resvg/resvg-js-darwin-x64": + optional: true + "@resvg/resvg-js-linux-arm-gnueabihf": + optional: true + "@resvg/resvg-js-linux-arm64-gnu": + optional: true + "@resvg/resvg-js-linux-arm64-musl": + optional: true + "@resvg/resvg-js-linux-x64-gnu": + optional: true + "@resvg/resvg-js-linux-x64-musl": + optional: true + "@resvg/resvg-js-win32-arm64-msvc": + optional: true + "@resvg/resvg-js-win32-ia32-msvc": + optional: true + "@resvg/resvg-js-win32-x64-msvc": + optional: true + checksum: 30b872317c6116802a11fedf83d27d56bd663a44c934a5f90f0692e271501d9d98219046b9cb4660bdba6e6ca93d0c438cb4b5a45df396ff0ec936ed0985101d + languageName: node + linkType: hard + "@rollup/plugin-alias@npm:^3.1.1": version: 3.1.9 resolution: "@rollup/plugin-alias@npm:3.1.9" @@ -3411,6 +3809,22 @@ __metadata: languageName: node linkType: hard +"@rollup/pluginutils@npm:^5.1.3": + version: 5.1.3 + resolution: "@rollup/pluginutils@npm:5.1.3" + dependencies: + "@types/estree": ^1.0.0 + estree-walker: ^2.0.2 + picomatch: ^4.0.2 + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + checksum: a6e9bac8ae94da39679dae390b53b43fe7a218f8fa2bfecf86e59be4da4ba02ac004f166daf55f03506e49108399394f13edeb62cce090f8cfc967b29f4738bf + languageName: node + linkType: hard + "@rollup/rollup-android-arm-eabi@npm:4.17.2": version: 4.17.2 resolution: "@rollup/rollup-android-arm-eabi@npm:4.17.2" @@ -3418,6 +3832,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-android-arm-eabi@npm:4.24.4": + version: 4.24.4 + resolution: "@rollup/rollup-android-arm-eabi@npm:4.24.4" + conditions: os=android & cpu=arm + languageName: node + linkType: hard + "@rollup/rollup-android-arm64@npm:4.17.2": version: 4.17.2 resolution: "@rollup/rollup-android-arm64@npm:4.17.2" @@ -3425,6 +3846,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-android-arm64@npm:4.24.4": + version: 4.24.4 + resolution: "@rollup/rollup-android-arm64@npm:4.24.4" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + "@rollup/rollup-darwin-arm64@npm:4.17.2": version: 4.17.2 resolution: "@rollup/rollup-darwin-arm64@npm:4.17.2" @@ -3432,6 +3860,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-darwin-arm64@npm:4.24.4": + version: 4.24.4 + resolution: "@rollup/rollup-darwin-arm64@npm:4.24.4" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + "@rollup/rollup-darwin-x64@npm:4.17.2": version: 4.17.2 resolution: "@rollup/rollup-darwin-x64@npm:4.17.2" @@ -3439,13 +3874,41 @@ __metadata: languageName: node linkType: hard -"@rollup/rollup-linux-arm-gnueabihf@npm:4.17.2": +"@rollup/rollup-darwin-x64@npm:4.24.4": + version: 4.24.4 + resolution: "@rollup/rollup-darwin-x64@npm:4.24.4" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"@rollup/rollup-freebsd-arm64@npm:4.24.4": + version: 4.24.4 + resolution: "@rollup/rollup-freebsd-arm64@npm:4.24.4" + conditions: os=freebsd & cpu=arm64 + languageName: node + linkType: hard + +"@rollup/rollup-freebsd-x64@npm:4.24.4": + version: 4.24.4 + resolution: "@rollup/rollup-freebsd-x64@npm:4.24.4" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + +"@rollup/rollup-linux-arm-gnueabihf@npm:4.17.2": version: 4.17.2 resolution: "@rollup/rollup-linux-arm-gnueabihf@npm:4.17.2" conditions: os=linux & cpu=arm & libc=glibc languageName: node linkType: hard +"@rollup/rollup-linux-arm-gnueabihf@npm:4.24.4": + version: 4.24.4 + resolution: "@rollup/rollup-linux-arm-gnueabihf@npm:4.24.4" + conditions: os=linux & cpu=arm & libc=glibc + languageName: node + linkType: hard + "@rollup/rollup-linux-arm-musleabihf@npm:4.17.2": version: 4.17.2 resolution: "@rollup/rollup-linux-arm-musleabihf@npm:4.17.2" @@ -3453,6 +3916,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-arm-musleabihf@npm:4.24.4": + version: 4.24.4 + resolution: "@rollup/rollup-linux-arm-musleabihf@npm:4.24.4" + conditions: os=linux & cpu=arm & libc=musl + languageName: node + linkType: hard + "@rollup/rollup-linux-arm64-gnu@npm:4.17.2": version: 4.17.2 resolution: "@rollup/rollup-linux-arm64-gnu@npm:4.17.2" @@ -3460,6 +3930,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-arm64-gnu@npm:4.24.4": + version: 4.24.4 + resolution: "@rollup/rollup-linux-arm64-gnu@npm:4.24.4" + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + "@rollup/rollup-linux-arm64-musl@npm:4.17.2": version: 4.17.2 resolution: "@rollup/rollup-linux-arm64-musl@npm:4.17.2" @@ -3467,6 +3944,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-arm64-musl@npm:4.24.4": + version: 4.24.4 + resolution: "@rollup/rollup-linux-arm64-musl@npm:4.24.4" + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + "@rollup/rollup-linux-powerpc64le-gnu@npm:4.17.2": version: 4.17.2 resolution: "@rollup/rollup-linux-powerpc64le-gnu@npm:4.17.2" @@ -3474,6 +3958,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-powerpc64le-gnu@npm:4.24.4": + version: 4.24.4 + resolution: "@rollup/rollup-linux-powerpc64le-gnu@npm:4.24.4" + conditions: os=linux & cpu=ppc64 & libc=glibc + languageName: node + linkType: hard + "@rollup/rollup-linux-riscv64-gnu@npm:4.17.2": version: 4.17.2 resolution: "@rollup/rollup-linux-riscv64-gnu@npm:4.17.2" @@ -3481,6 +3972,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-riscv64-gnu@npm:4.24.4": + version: 4.24.4 + resolution: "@rollup/rollup-linux-riscv64-gnu@npm:4.24.4" + conditions: os=linux & cpu=riscv64 & libc=glibc + languageName: node + linkType: hard + "@rollup/rollup-linux-s390x-gnu@npm:4.17.2": version: 4.17.2 resolution: "@rollup/rollup-linux-s390x-gnu@npm:4.17.2" @@ -3488,6 +3986,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-s390x-gnu@npm:4.24.4": + version: 4.24.4 + resolution: "@rollup/rollup-linux-s390x-gnu@npm:4.24.4" + conditions: os=linux & cpu=s390x & libc=glibc + languageName: node + linkType: hard + "@rollup/rollup-linux-x64-gnu@npm:4.17.2": version: 4.17.2 resolution: "@rollup/rollup-linux-x64-gnu@npm:4.17.2" @@ -3495,6 +4000,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-x64-gnu@npm:4.24.4": + version: 4.24.4 + resolution: "@rollup/rollup-linux-x64-gnu@npm:4.24.4" + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + "@rollup/rollup-linux-x64-musl@npm:4.17.2": version: 4.17.2 resolution: "@rollup/rollup-linux-x64-musl@npm:4.17.2" @@ -3502,6 +4014,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-x64-musl@npm:4.24.4": + version: 4.24.4 + resolution: "@rollup/rollup-linux-x64-musl@npm:4.24.4" + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + "@rollup/rollup-win32-arm64-msvc@npm:4.17.2": version: 4.17.2 resolution: "@rollup/rollup-win32-arm64-msvc@npm:4.17.2" @@ -3509,6 +4028,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-win32-arm64-msvc@npm:4.24.4": + version: 4.24.4 + resolution: "@rollup/rollup-win32-arm64-msvc@npm:4.24.4" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + "@rollup/rollup-win32-ia32-msvc@npm:4.17.2": version: 4.17.2 resolution: "@rollup/rollup-win32-ia32-msvc@npm:4.17.2" @@ -3516,6 +4042,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-win32-ia32-msvc@npm:4.24.4": + version: 4.24.4 + resolution: "@rollup/rollup-win32-ia32-msvc@npm:4.24.4" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + "@rollup/rollup-win32-x64-msvc@npm:4.17.2": version: 4.17.2 resolution: "@rollup/rollup-win32-x64-msvc@npm:4.17.2" @@ -3523,10 +4056,24 @@ __metadata: languageName: node linkType: hard -"@shikijs/core@npm:1.1.7": - version: 1.1.7 - resolution: "@shikijs/core@npm:1.1.7" - checksum: 120002e1bb6223b7b0d69772f1c12e30ef4c0fdc7a3caa96387450ee9e4630fba45729e16cee1cf47a292b2e2f669becdf2e69415ade5de0f02de3b1a099cda0 +"@rollup/rollup-win32-x64-msvc@npm:4.24.4": + version: 4.24.4 + resolution: "@rollup/rollup-win32-x64-msvc@npm:4.24.4" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + +"@shikijs/core@npm:1.22.2": + version: 1.22.2 + resolution: "@shikijs/core@npm:1.22.2" + dependencies: + "@shikijs/engine-javascript": 1.22.2 + "@shikijs/engine-oniguruma": 1.22.2 + "@shikijs/types": 1.22.2 + "@shikijs/vscode-textmate": ^9.3.0 + "@types/hast": ^3.0.4 + hast-util-to-html: ^9.0.3 + checksum: a49c4b93079e4637997b13a4942a6e445e80b5ca1b800ce880f8c39545cd02e4c5c3fda20fa651a509066751a62d614ece76fa7ae1ae2aa28f5f68f54defb627 languageName: node linkType: hard @@ -3544,6 +4091,44 @@ __metadata: languageName: node linkType: hard +"@shikijs/engine-javascript@npm:1.22.2": + version: 1.22.2 + resolution: "@shikijs/engine-javascript@npm:1.22.2" + dependencies: + "@shikijs/types": 1.22.2 + "@shikijs/vscode-textmate": ^9.3.0 + oniguruma-to-js: 0.4.3 + checksum: 162f089f7ec7bc8e6877e1047bdf339a7446b7407ad0bffcb4b7372263ae5aae0be429f1c87054326be79d4e1bbe55849c010ea4aa499e83816ce009e490938b + languageName: node + linkType: hard + +"@shikijs/engine-oniguruma@npm:1.22.2": + version: 1.22.2 + resolution: "@shikijs/engine-oniguruma@npm:1.22.2" + dependencies: + "@shikijs/types": 1.22.2 + "@shikijs/vscode-textmate": ^9.3.0 + checksum: cbda50d13c72e6ce4754c0d3b76e07a9e56b6a6c957f0cc662db7bd36ca532af3ca5b0926307e118bc67db7d8d79730930e0451f9d7f18b82bf502bdf9cac39d + languageName: node + linkType: hard + +"@shikijs/types@npm:1.22.2": + version: 1.22.2 + resolution: "@shikijs/types@npm:1.22.2" + dependencies: + "@shikijs/vscode-textmate": ^9.3.0 + "@types/hast": ^3.0.4 + checksum: 1e9b63aac5ab4c7ea403acecb76d9bad21d3ca8e66878ddd2f4c4d8804b253b8fbe5b67ab31d874f198ac0bf94b1a70beeb578dac0640cac3aa6dad72192fa9c + languageName: node + linkType: hard + +"@shikijs/vscode-textmate@npm:^9.3.0": + version: 9.3.0 + resolution: "@shikijs/vscode-textmate@npm:9.3.0" + checksum: 6635b4f41f958db502545d7c55cb51b803986cff38402963404cfd725449dc6ad760b6c342e916fc620f998b67baa23bea52299d379f20837fc47af9271d601d + languageName: node + linkType: hard + "@shuding/opentype.js@npm:1.4.0-beta.0": version: 1.4.0-beta.0 resolution: "@shuding/opentype.js@npm:1.4.0-beta.0" @@ -3851,15 +4436,6 @@ __metadata: languageName: node linkType: hard -"@types/cheerio@npm:^0.22.32": - version: 0.22.35 - resolution: "@types/cheerio@npm:0.22.35" - dependencies: - "@types/node": "*" - checksum: 34ef8f0f754bd022e7d686c7295fdba997766a796257add2377be256f215f2e12fe74218125570e61344dbd3de0a952495181981af1eeb8eebeb5cf886c62f1f - languageName: node - linkType: hard - "@types/cookie@npm:^0.6.0": version: 0.6.0 resolution: "@types/cookie@npm:0.6.0" @@ -3913,6 +4489,13 @@ __metadata: languageName: node linkType: hard +"@types/estree@npm:1.0.6": + version: 1.0.6 + resolution: "@types/estree@npm:1.0.6" + checksum: 8825d6e729e16445d9a1dd2fb1db2edc5ed400799064cd4d028150701031af012ba30d6d03fe9df40f4d7a437d0de6d2b256020152b7b09bde9f2e420afdffd9 + languageName: node + linkType: hard + "@types/hast@npm:^2.0.0": version: 2.3.4 resolution: "@types/hast@npm:2.3.4" @@ -3931,6 +4514,15 @@ __metadata: languageName: node linkType: hard +"@types/hast@npm:^3.0.4": + version: 3.0.4 + resolution: "@types/hast@npm:3.0.4" + dependencies: + "@types/unist": "*" + checksum: 7a973e8d16fcdf3936090fa2280f408fb2b6a4f13b42edeb5fbd614efe042b82eac68e298e556d50f6b4ad585a3a93c353e9c826feccdc77af59de8dd400d044 + languageName: node + linkType: hard + "@types/html-minifier-terser@npm:7.0.2": version: 7.0.2 resolution: "@types/html-minifier-terser@npm:7.0.2" @@ -3970,6 +4562,15 @@ __metadata: languageName: node linkType: hard +"@types/nlcst@npm:^2.0.0": + version: 2.0.3 + resolution: "@types/nlcst@npm:2.0.3" + dependencies: + "@types/unist": "*" + checksum: 8f4172da36e60645bf2392ccd42bd2a950ec677b8e79f49cc2c5d1f2c673ea106ae7004a559eb3084a07dbf6cc1e01d10f536eb990558ff5f52d1af69b9c557c + languageName: node + linkType: hard + "@types/node@npm:*": version: 18.7.13 resolution: "@types/node@npm:18.7.13" @@ -3977,12 +4578,12 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:20.12.12": - version: 20.12.12 - resolution: "@types/node@npm:20.12.12" +"@types/node@npm:22.5.0": + version: 22.5.0 + resolution: "@types/node@npm:22.5.0" dependencies: - undici-types: ~5.26.4 - checksum: 5373983874b9af7c216e7ca5d26b32a8d9829c703a69f1e66f2113598b5be8582c0e009ca97369f1ec9a6282b3f92812208d06eb1e9fc3bd9b939b022303d042 + undici-types: ~6.19.2 + checksum: 3710b6f42416796061cf47cff0a37955f2ca0afc63ab281cc23e46b3ec8dffcabc66b970e4ee34fff5e2082617bed47610b4a1122c7b3880f551d3c673c40f84 languageName: node linkType: hard @@ -4077,13 +4678,13 @@ __metadata: languageName: node linkType: hard -"@types/tar@npm:^6.1.6": - version: 6.1.11 - resolution: "@types/tar@npm:6.1.11" +"@types/tar@npm:^6.1.13": + version: 6.1.13 + resolution: "@types/tar@npm:6.1.13" dependencies: "@types/node": "*" minipass: ^4.0.0 - checksum: 9b79f61f9179db65ecd3f5e9c0d2152839ad13381d39c38c3a9408aa1f3a2b061ba195e7d758be1863294a0ce69df6659f0e3e09f440c9f5309bded58bc87c89 + checksum: bb3910936a6b37f093e38b73a52b0544fd73079685f5ea72e5c049fddc3770e58d80cf6d714425853f0746290221852c1a7ca89ffdb9614f3b2a858a3bf5436a languageName: node linkType: hard @@ -4320,6 +4921,24 @@ __metadata: languageName: node linkType: hard +"acorn@npm:^8.12.1": + version: 8.12.1 + resolution: "acorn@npm:8.12.1" + bin: + acorn: bin/acorn + checksum: 677880034aee5bdf7434cc2d25b641d7bedb0b5ef47868a78dadabedccf58e1c5457526d9d8249cd253f2df087e081c3fe7d903b448d8e19e5131a3065b83c07 + languageName: node + linkType: hard + +"acorn@npm:^8.14.0": + version: 8.14.0 + resolution: "acorn@npm:8.14.0" + bin: + acorn: bin/acorn + checksum: 8755074ba55fff94e84e81c72f1013c2d9c78e973c31231c8ae505a5f966859baf654bddd75046bffd73ce816b149298977fff5077a3033dedba0ae2aad152d4 + languageName: node + linkType: hard + "acorn@npm:^8.8.0": version: 8.8.0 resolution: "acorn@npm:8.8.0" @@ -4440,6 +5059,13 @@ __metadata: languageName: node linkType: hard +"ansi-styles@npm:^6.2.1": + version: 6.2.1 + resolution: "ansi-styles@npm:6.2.1" + checksum: ef940f2f0ced1a6347398da88a91da7930c33ecac3c77b72c5905f8b8fe402c52e6fde304ff5347f616e27a742da3f1dc76de98f6866c69251ad0b07a66776d9 + languageName: node + linkType: hard + "anymatch@npm:~3.1.2": version: 3.1.3 resolution: "anymatch@npm:3.1.3" @@ -4499,6 +5125,13 @@ __metadata: languageName: node linkType: hard +"aria-query@npm:^5.3.2": + version: 5.3.2 + resolution: "aria-query@npm:5.3.2" + checksum: d971175c85c10df0f6d14adfe6f1292409196114ab3c62f238e208b53103686f46cc70695a4f775b73bc65f6a09b6a092fd963c4f3a5a7d690c8fc5094925717 + languageName: node + linkType: hard + "array-buffer-byte-length@npm:^1.0.0": version: 1.0.0 resolution: "array-buffer-byte-length@npm:1.0.0" @@ -4516,6 +5149,13 @@ __metadata: languageName: node linkType: hard +"array-iterate@npm:^2.0.0": + version: 2.0.1 + resolution: "array-iterate@npm:2.0.1" + checksum: 932ddaab031ccec1a67a66d7663b1fa31828607fd673d5a00d61746610a290d3f13874c1ccc206c506ad17e47f477436914f9fd3cd311574b8b0a635d0ad31c9 + languageName: node + linkType: hard + "array-union@npm:^2.1.0": version: 2.1.0 resolution: "array-union@npm:2.1.0" @@ -4537,22 +5177,25 @@ __metadata: languageName: node linkType: hard -"astro-compress@npm:^2.2.27": - version: 2.2.27 - resolution: "astro-compress@npm:2.2.27" +"astro-compress@npm:^2.3.5": + version: 2.3.5 + resolution: "astro-compress@npm:2.3.5" dependencies: - "@playform/pipe": 0.0.5 + "@playform/pipe": 0.1.1 "@types/csso": 5.0.4 "@types/html-minifier-terser": 7.0.2 astro: "*" + commander: 12.1.0 csso: 5.0.5 + deepmerge-ts: 7.1.3 + fast-glob: 3.3.2 html-minifier-terser: 7.2.0 kleur: 4.1.5 - lightningcss: 1.25.1 - sharp: 0.33.4 + lightningcss: 1.27.0 + sharp: 0.33.5 svgo: 3.3.2 - terser: 5.31.1 - checksum: bdf75ab9fda5712bb40d996fcef9915e2c627eb5275916b8c953cada853affe8c3f25e27b3291c50751824f018268a81532fb7faa97f154055673fb381648d93 + terser: 5.36.0 + checksum: 7152bdc0126f920da7d3be88c2f83b708534d3f221a6b430ac0d24fe712b30747b9a532f63a59aa4cf8aab72dce32448264dcbc4cce3ff57076f18c37ba03760 languageName: node linkType: hard @@ -4573,34 +5216,34 @@ __metadata: languageName: node linkType: hard -"astro-expressive-code@npm:^0.35.3": - version: 0.35.3 - resolution: "astro-expressive-code@npm:0.35.3" +"astro-expressive-code@npm:^0.38.1": + version: 0.38.1 + resolution: "astro-expressive-code@npm:0.38.1" dependencies: - rehype-expressive-code: ^0.35.3 + rehype-expressive-code: ^0.38.1 peerDependencies: - astro: ^4.0.0-beta || ^3.3.0 - checksum: d5a00ab16ef007634853c694d869872618bec95b3f228a2524312680596a9b210ca34057d22befefd3e4d8fd586858c1a9cfb93d9073db1c3166b931195bab4e + astro: ^4.0.0-beta || ^5.0.0-beta || ^3.3.0 + checksum: 5ff8d8373a4872d757e4b4fc7c163c3944a89686b584063c3d469dae55e06c305d4d385e119c3372ffd64164413ed480c0ad6bf4337c8f4fa698dcabed812850 languageName: node linkType: hard -"astro-icon@npm:^1.1.0": - version: 1.1.0 - resolution: "astro-icon@npm:1.1.0" +"astro-icon@npm:^1.1.1": + version: 1.1.1 + resolution: "astro-icon@npm:1.1.1" dependencies: - "@iconify/tools": ^3.0.1 + "@iconify/tools": ^4.0.5 "@iconify/types": ^2.0.0 - "@iconify/utils": ^2.1.5 - checksum: 79257229b329ac69f031910d74aa34372eb087817238e7ed73e8afde95e57dc4e0a79b3f6f73e8e5b29c6dfe6712892a59fa66a5dcb8561bfdbcaa87582452dc + "@iconify/utils": ^2.1.30 + checksum: 2e88a3b90984b1131591e472c2bb91fc628f679bfb50e597aef63b2af3fdf32298ea89284317002f5ef52f5016c43053fa722898089a389f1b285983cceb01bf languageName: node linkType: hard -"astro-meta-tags@npm:^0.3.0": - version: 0.3.0 - resolution: "astro-meta-tags@npm:0.3.0" +"astro-meta-tags@npm:^0.3.1": + version: 0.3.1 + resolution: "astro-meta-tags@npm:0.3.1" peerDependencies: - astro: ^4.0.0 - checksum: b920c24f028fe7fe59971606383112d674d1920ed9d013486ef608f180e765e2cc00ae053630c17912be4090656590a931ad8ad4a9582df15640fdc6a6cbb741 + astro: ^4.0.0 || ^5.0.0-beta.0 + checksum: ffb41f5e9ec745f7fbf8ea6946697a96bac169b9035246abb8537dcfe7f8c2d7efa1c7cd69380463000e8ec99a46d9c4cda449d593f82b597eb3bed57a15a63b languageName: node linkType: hard @@ -4628,7 +5271,7 @@ __metadata: languageName: node linkType: hard -"astro@npm:*, astro@npm:^4.10.1": +"astro@npm:*": version: 4.10.1 resolution: "astro@npm:4.10.1" dependencies: @@ -4705,6 +5348,82 @@ __metadata: languageName: node linkType: hard +"astro@npm:^4.16.8": + version: 4.16.8 + resolution: "astro@npm:4.16.8" + dependencies: + "@astrojs/compiler": ^2.10.3 + "@astrojs/internal-helpers": 0.4.1 + "@astrojs/markdown-remark": 5.3.0 + "@astrojs/telemetry": 3.1.0 + "@babel/core": ^7.26.0 + "@babel/plugin-transform-react-jsx": ^7.25.9 + "@babel/types": ^7.26.0 + "@oslojs/encoding": ^1.1.0 + "@rollup/pluginutils": ^5.1.3 + "@types/babel__core": ^7.20.5 + "@types/cookie": ^0.6.0 + acorn: ^8.14.0 + aria-query: ^5.3.2 + axobject-query: ^4.1.0 + boxen: 8.0.1 + ci-info: ^4.0.0 + clsx: ^2.1.1 + common-ancestor-path: ^1.0.1 + cookie: ^0.7.2 + cssesc: ^3.0.0 + debug: ^4.3.7 + deterministic-object-hash: ^2.0.2 + devalue: ^5.1.1 + diff: ^5.2.0 + dlv: ^1.1.3 + dset: ^3.1.4 + es-module-lexer: ^1.5.4 + esbuild: ^0.21.5 + estree-walker: ^3.0.3 + fast-glob: ^3.3.2 + flattie: ^1.1.1 + github-slugger: ^2.0.0 + gray-matter: ^4.0.3 + html-escaper: ^3.0.3 + http-cache-semantics: ^4.1.1 + js-yaml: ^4.1.0 + kleur: ^4.1.5 + magic-string: ^0.30.12 + magicast: ^0.3.5 + micromatch: ^4.0.8 + mrmime: ^2.0.0 + neotraverse: ^0.6.18 + ora: ^8.1.0 + p-limit: ^6.1.0 + p-queue: ^8.0.1 + preferred-pm: ^4.0.0 + prompts: ^2.4.2 + rehype: ^13.0.2 + semver: ^7.6.3 + sharp: ^0.33.3 + shiki: ^1.22.2 + tinyexec: ^0.3.1 + tsconfck: ^3.1.4 + unist-util-visit: ^5.0.0 + vfile: ^6.0.3 + vite: ^5.4.10 + vitefu: ^1.0.3 + which-pm: ^3.0.0 + xxhash-wasm: ^1.0.2 + yargs-parser: ^21.1.1 + zod: ^3.23.8 + zod-to-json-schema: ^3.23.5 + zod-to-ts: ^1.2.0 + dependenciesMeta: + sharp: + optional: true + bin: + astro: astro.js + checksum: a8e94f8e46c4ab19c8456769be9c12f39646827b1c868e6c97c4c64c5d9792f12fc7ffaf73f95687e15cca1464d7b8b1c8692bb83c0a100b986d59de0d230bfe + languageName: node + linkType: hard + "astrojs-compiler-sync@npm:^0.3.0": version: 0.3.3 resolution: "astrojs-compiler-sync@npm:0.3.3" @@ -4723,6 +5442,13 @@ __metadata: languageName: node linkType: hard +"asynckit@npm:^0.4.0": + version: 0.4.0 + resolution: "asynckit@npm:0.4.0" + checksum: 7b78c451df768adba04e2d02e63e2d0bf3b07adcd6e42b4cf665cb7ce899bedd344c69a1dcbce355b5f972d597b25aaa1c1742b52cffd9caccb22f348114f6be + languageName: node + linkType: hard + "asyncro@npm:^3.0.0": version: 3.0.0 resolution: "asyncro@npm:3.0.0" @@ -4755,6 +5481,17 @@ __metadata: languageName: node linkType: hard +"axios@npm:^1.7.7": + version: 1.7.7 + resolution: "axios@npm:1.7.7" + dependencies: + follow-redirects: ^1.15.6 + form-data: ^4.0.0 + proxy-from-env: ^1.1.0 + checksum: 882d4fe0ec694a07c7f5c1f68205eb6dc5a62aecdb632cc7a4a3d0985188ce3030e0b277e1a8260ac3f194d314ae342117660a151fabffdc5081ca0b5a8b47fe + languageName: node + linkType: hard + "axobject-query@npm:^4.0.0": version: 4.0.0 resolution: "axobject-query@npm:4.0.0" @@ -4764,6 +5501,13 @@ __metadata: languageName: node linkType: hard +"axobject-query@npm:^4.1.0": + version: 4.1.0 + resolution: "axobject-query@npm:4.1.0" + checksum: 7d1e87bf0aa7ae7a76cd39ab627b7c48fda3dc40181303d9adce4ba1d5b5ce73b5e5403ee6626ec8e91090448c887294d6144e24b6741a976f5be9347e3ae1df + languageName: node + linkType: hard + "babel-plugin-macros@npm:^3.0.1": version: 3.1.0 resolution: "babel-plugin-macros@npm:3.1.0" @@ -4878,6 +5622,22 @@ __metadata: languageName: node linkType: hard +"boxen@npm:8.0.1": + version: 8.0.1 + resolution: "boxen@npm:8.0.1" + dependencies: + ansi-align: ^3.0.1 + camelcase: ^8.0.0 + chalk: ^5.3.0 + cli-boxes: ^3.0.0 + string-width: ^7.2.0 + type-fest: ^4.21.0 + widest-line: ^5.0.0 + wrap-ansi: ^9.0.0 + checksum: f42d9e628e03e5c84ac9cda3173f75cadbdf60ed94fc06aaeef79f7c84a8181c4d79a8f40253192a1613993036c81811ad6957f346e5aa6abb7e9d1d799cbfd5 + languageName: node + linkType: hard + "boxen@npm:^7.1.1": version: 7.1.1 resolution: "boxen@npm:7.1.1" @@ -4922,6 +5682,15 @@ __metadata: languageName: node linkType: hard +"braces@npm:^3.0.3": + version: 3.0.3 + resolution: "braces@npm:3.0.3" + dependencies: + fill-range: ^7.1.1 + checksum: b95aa0b3bd909f6cd1720ffcf031aeaf46154dd88b4da01f9a1d3f7ea866a79eba76a6d01cbc3c422b2ee5cdc39a4f02491058d5df0d7bf6e6a162a832df1f69 + languageName: node + linkType: hard + "brotli-size@npm:^4.0.0": version: 4.0.0 resolution: "brotli-size@npm:4.0.0" @@ -4959,6 +5728,20 @@ __metadata: languageName: node linkType: hard +"browserslist@npm:^4.24.0": + version: 4.24.2 + resolution: "browserslist@npm:4.24.2" + dependencies: + caniuse-lite: ^1.0.30001669 + electron-to-chromium: ^1.5.41 + node-releases: ^2.0.18 + update-browserslist-db: ^1.1.1 + bin: + browserslist: cli.js + checksum: cf64085f12132d38638f38937a255edb82c7551b164a98577b055dd79719187a816112f7b97b9739e400c4954cd66479c0d7a843cb816e346f4795dc24fd5d97 + languageName: node + linkType: hard + "buffer-crc32@npm:~0.2.3": version: 0.2.13 resolution: "buffer-crc32@npm:0.2.13" @@ -5041,6 +5824,13 @@ __metadata: languageName: node linkType: hard +"camelcase@npm:^8.0.0": + version: 8.0.0 + resolution: "camelcase@npm:8.0.0" + checksum: 6da7abe997af29e80052f17aa21628c7cce14af364cef9f07a2a44d59614dd6f361d405f121938e673424d673697a8c53ad17be8c4b03b0a727307c4db8b5b5e + languageName: node + linkType: hard + "camelize@npm:^1.0.0": version: 1.0.1 resolution: "camelize@npm:1.0.1" @@ -5074,6 +5864,13 @@ __metadata: languageName: node linkType: hard +"caniuse-lite@npm:^1.0.30001669": + version: 1.0.30001677 + resolution: "caniuse-lite@npm:1.0.30001677" + checksum: 34099726620baf4f14fbbe88fec38517208cbe9a47009350b59c7cbbbbd45fcf355afe25d5fa277179660eb0f35f103e68806a07bb33d38bbddb7fde0a4302e4 + languageName: node + linkType: hard + "ccount@npm:^2.0.0": version: 2.0.1 resolution: "ccount@npm:2.0.1" @@ -5171,6 +5968,25 @@ __metadata: languageName: node linkType: hard +"cheerio@npm:1.0.0": + version: 1.0.0 + resolution: "cheerio@npm:1.0.0" + dependencies: + cheerio-select: ^2.1.0 + dom-serializer: ^2.0.0 + domhandler: ^5.0.3 + domutils: ^3.1.0 + encoding-sniffer: ^0.2.0 + htmlparser2: ^9.1.0 + parse5: ^7.1.2 + parse5-htmlparser2-tree-adapter: ^7.0.0 + parse5-parser-stream: ^7.1.2 + undici: ^6.19.5 + whatwg-mimetype: ^4.0.0 + checksum: ade4344811dcad5b5d78392506ef6bab1900c13a65222c869e745a38370d287f4b94838ac6d752883a84d937edb62b5bd0deaf70e6f38054acbfe3da4881574a + languageName: node + linkType: hard + "cheerio@npm:^1.0.0-rc.12": version: 1.0.0-rc.12 resolution: "cheerio@npm:1.0.0-rc.12" @@ -5251,6 +6067,15 @@ __metadata: languageName: node linkType: hard +"cli-cursor@npm:^5.0.0": + version: 5.0.0 + resolution: "cli-cursor@npm:5.0.0" + dependencies: + restore-cursor: ^5.0.0 + checksum: 1eb9a3f878b31addfe8d82c6d915ec2330cec8447ab1f117f4aa34f0137fbb3137ec3466e1c9a65bcb7557f6e486d343f2da57f253a2f668d691372dfa15c090 + languageName: node + linkType: hard + "cli-spinners@npm:^2.9.2": version: 2.9.2 resolution: "cli-spinners@npm:2.9.2" @@ -5344,6 +6169,15 @@ __metadata: languageName: node linkType: hard +"combined-stream@npm:^1.0.8": + version: 1.0.8 + resolution: "combined-stream@npm:1.0.8" + dependencies: + delayed-stream: ~1.0.0 + checksum: 49fa4aeb4916567e33ea81d088f6584749fc90c7abec76fd516bf1c5aa5c79f3584b5ba3de6b86d26ddd64bae5329c4c7479343250cfe71c75bb366eae53bb7c + languageName: node + linkType: hard + "comma-separated-tokens@npm:^2.0.0": version: 2.0.3 resolution: "comma-separated-tokens@npm:2.0.3" @@ -5351,6 +6185,13 @@ __metadata: languageName: node linkType: hard +"commander@npm:12.1.0": + version: 12.1.0 + resolution: "commander@npm:12.1.0" + checksum: 68e9818b00fc1ed9cdab9eb16905551c2b768a317ae69a5e3c43924c2b20ac9bb65b27e1cab36aeda7b6496376d4da908996ba2c0b5d79463e0fb1e77935d514 + languageName: node + linkType: hard + "commander@npm:^10.0.0": version: 10.0.1 resolution: "commander@npm:10.0.1" @@ -5402,6 +6243,13 @@ __metadata: languageName: node linkType: hard +"confbox@npm:^0.1.8": + version: 0.1.8 + resolution: "confbox@npm:0.1.8" + checksum: 5c7718ab22cf9e35a31c21ef124156076ae8c9dc65e6463d54961caf5a1d529284485a0fdf83fd23b27329f3b75b0c8c07d2e36c699f5151a2efe903343f976a + languageName: node + linkType: hard + "console-control-strings@npm:^1.1.0": version: 1.1.0 resolution: "console-control-strings@npm:1.1.0" @@ -5441,6 +6289,13 @@ __metadata: languageName: node linkType: hard +"cookie@npm:^0.7.2": + version: 0.7.2 + resolution: "cookie@npm:0.7.2" + checksum: 9bf8555e33530affd571ea37b615ccad9b9a34febbf2c950c86787088eb00a8973690833b0f8ebd6b69b753c62669ea60cec89178c1fb007bf0749abed74f93e + languageName: node + linkType: hard + "core-js-compat@npm:^3.31.0": version: 3.32.0 resolution: "core-js-compat@npm:3.32.0" @@ -5511,6 +6366,13 @@ __metadata: languageName: node linkType: hard +"css-gradient-parser@npm:^0.0.16": + version: 0.0.16 + resolution: "css-gradient-parser@npm:0.0.16" + checksum: b9f4df01264166f42191374a2dc768df87c7ea67dd49ad082af6b86df299902113d8b5a3be24f5cc7a441dbf28bdcf91531691c56a0cd9f2b0c95669f4a6e6c0 + languageName: node + linkType: hard + "css-select@npm:^4.1.3": version: 4.3.0 resolution: "css-select@npm:4.3.0" @@ -5565,7 +6427,7 @@ __metadata: languageName: node linkType: hard -"css-tree@npm:^2.2.1, css-tree@npm:^2.3.1": +"css-tree@npm:^2.3.1": version: 2.3.1 resolution: "css-tree@npm:2.3.1" dependencies: @@ -5699,6 +6561,30 @@ __metadata: languageName: node linkType: hard +"debug@npm:^4.3.6": + version: 4.3.6 + resolution: "debug@npm:4.3.6" + dependencies: + ms: 2.1.2 + peerDependenciesMeta: + supports-color: + optional: true + checksum: 1630b748dea3c581295e02137a9f5cbe2c1d85fea35c1e6597a65ca2b16a6fce68cec61b299d480787ef310ba927dc8c92d3061faba0ad06c6a724672f66be7f + languageName: node + linkType: hard + +"debug@npm:^4.3.7": + version: 4.3.7 + resolution: "debug@npm:4.3.7" + dependencies: + ms: ^2.1.3 + peerDependenciesMeta: + supports-color: + optional: true + checksum: 822d74e209cd910ef0802d261b150314bbcf36c582ccdbb3e70f0894823c17e49a50d3e66d96b633524263975ca16b6a833f3e3b7e030c157169a5fabac63160 + languageName: node + linkType: hard + "decode-named-character-reference@npm:^1.0.0": version: 1.0.2 resolution: "decode-named-character-reference@npm:1.0.2" @@ -5715,10 +6601,17 @@ __metadata: languageName: node linkType: hard -"deepmerge-ts@npm:7.0.1": - version: 7.0.1 - resolution: "deepmerge-ts@npm:7.0.1" - checksum: c770ce45a56960c8d2a4138208e64a87ce7a5921c9725e5f19169c09942dabdd4e8fca4f491dbf3d1adff00c748ab2bf8889e50b525ba2e44a4a1d9b925addbe +"deepmerge-ts@npm:7.1.0": + version: 7.1.0 + resolution: "deepmerge-ts@npm:7.1.0" + checksum: 8c36d7e88b12248e138ba0f959c03e5b6d008842acbc7bb3c43a0513b4b942f936352b8910ac75bcbe1fc61d3975b4e0ab5b13b2492f0ede06f95553c637479e + languageName: node + linkType: hard + +"deepmerge-ts@npm:7.1.3": + version: 7.1.3 + resolution: "deepmerge-ts@npm:7.1.3" + checksum: e2f0a209afc5fcd2afe8ec3792f2765f81ffc1935ca99ae4e55cfe0ea57042056d356aeff79de76d48f5068838d372e5dd4da4044236d176290d6849ca048165 languageName: node linkType: hard @@ -5746,6 +6639,13 @@ __metadata: languageName: node linkType: hard +"delayed-stream@npm:~1.0.0": + version: 1.0.0 + resolution: "delayed-stream@npm:1.0.0" + checksum: 46fe6e83e2cb1d85ba50bd52803c68be9bd953282fa7096f51fc29edd5d67ff84ff753c51966061e5ba7cb5e47ef6d36a91924eddb7f3f3483b1c560f77a0020 + languageName: node + linkType: hard + "delegate-it@npm:^6.0.0": version: 6.0.1 resolution: "delegate-it@npm:6.0.1" @@ -5801,6 +6701,13 @@ __metadata: languageName: node linkType: hard +"devalue@npm:^5.1.1": + version: 5.1.1 + resolution: "devalue@npm:5.1.1" + checksum: 3b6a655e97b59b528d68f89d644b4bd7be9cd502e49ed9ae990caac56b93dc015790e2d099f264b1533d7235e14ec9513e92a7bc1b5031d355064bb37dcc99ca + languageName: node + linkType: hard + "devlop@npm:^1.0.0, devlop@npm:^1.1.0": version: 1.1.0 resolution: "devlop@npm:1.1.0" @@ -5909,7 +6816,7 @@ __metadata: languageName: node linkType: hard -"domutils@npm:^3.0.1": +"domutils@npm:^3.0.1, domutils@npm:^3.1.0": version: 3.1.0 resolution: "domutils@npm:3.1.0" dependencies: @@ -5937,6 +6844,13 @@ __metadata: languageName: node linkType: hard +"dset@npm:^3.1.4": + version: 3.1.4 + resolution: "dset@npm:3.1.4" + checksum: 9a7677e9ffd3c13ad850f7cf367aa94b39984006510e84c3c09b7b88bba0a5b3b7196d85a99d0c4cae4e47d67bdeca43dc1834a41d80f31bcdc86dd26121ecec + languageName: node + linkType: hard + "duplexer@npm:0.1.1": version: 0.1.1 resolution: "duplexer@npm:0.1.1" @@ -5983,6 +6897,13 @@ __metadata: languageName: node linkType: hard +"electron-to-chromium@npm:^1.5.41": + version: 1.5.50 + resolution: "electron-to-chromium@npm:1.5.50" + checksum: 971f49d0c3f8484225a2ee86f86074c2ef1a3c46c2bad9b2151202c03f5de2f6f0fc41029d0bc634e6d01d067673cbf4916a7f9753f5ec1d5b177cbaca9b2e5a + languageName: node + linkType: hard + "emoji-regex@npm:^10.2.1": version: 10.2.1 resolution: "emoji-regex@npm:10.2.1" @@ -6011,6 +6932,16 @@ __metadata: languageName: node linkType: hard +"encoding-sniffer@npm:^0.2.0": + version: 0.2.0 + resolution: "encoding-sniffer@npm:0.2.0" + dependencies: + iconv-lite: ^0.6.3 + whatwg-encoding: ^3.1.1 + checksum: 05ad76b674066e62abc80427eb9e89ecf5ed50f4d20c392f7465992d309215687e3ae1ae8b5d5694fb258f4517c759694c3b413d6c724e1024e1cf98750390eb + languageName: node + linkType: hard + "encoding@npm:^0.1.13": version: 0.1.13 resolution: "encoding@npm:0.1.13" @@ -6120,6 +7051,13 @@ __metadata: languageName: node linkType: hard +"es-module-lexer@npm:^1.5.4": + version: 1.5.4 + resolution: "es-module-lexer@npm:1.5.4" + checksum: a0cf04fb92d052647ac7d818d1913b98d3d3d0f5b9d88f0eafb993436e4c3e2c958599db68839d57f2dfa281fdf0f60e18d448eb78fc292c33c0f25635b6854f + languageName: node + linkType: hard + "es-set-tostringtag@npm:^2.0.1": version: 2.0.1 resolution: "es-set-tostringtag@npm:2.0.1" @@ -6222,7 +7160,7 @@ __metadata: languageName: node linkType: hard -"esbuild@npm:^0.21.4": +"esbuild@npm:^0.21.3, esbuild@npm:^0.21.4, esbuild@npm:^0.21.5": version: 0.21.5 resolution: "esbuild@npm:0.21.5" dependencies: @@ -6309,6 +7247,13 @@ __metadata: languageName: node linkType: hard +"escalade@npm:^3.2.0": + version: 3.2.0 + resolution: "escalade@npm:3.2.0" + checksum: 47b029c83de01b0d17ad99ed766347b974b0d628e848de404018f3abee728e987da0d2d370ad4574aa3d5b5bfc368754fd085d69a30f8e75903486ec4b5b709e + languageName: node + linkType: hard + "escape-html@npm:^1.0.3": version: 1.0.3 resolution: "escape-html@npm:1.0.3" @@ -6401,14 +7346,14 @@ __metadata: linkType: hard "eslint@npm:^8.57.0": - version: 8.57.0 - resolution: "eslint@npm:8.57.0" + version: 8.57.1 + resolution: "eslint@npm:8.57.1" dependencies: "@eslint-community/eslint-utils": ^4.2.0 "@eslint-community/regexpp": ^4.6.1 "@eslint/eslintrc": ^2.1.4 - "@eslint/js": 8.57.0 - "@humanwhocodes/config-array": ^0.11.14 + "@eslint/js": 8.57.1 + "@humanwhocodes/config-array": ^0.13.0 "@humanwhocodes/module-importer": ^1.0.1 "@nodelib/fs.walk": ^1.2.8 "@ungap/structured-clone": ^1.2.0 @@ -6444,7 +7389,7 @@ __metadata: text-table: ^0.2.0 bin: eslint: bin/eslint.js - checksum: 3a48d7ff85ab420a8447e9810d8087aea5b1df9ef68c9151732b478de698389ee656fd895635b5f2871c89ee5a2652b3f343d11e9db6f8486880374ebc74a2d9 + checksum: e2489bb7f86dd2011967759a09164e65744ef7688c310bc990612fc26953f34cc391872807486b15c06833bdff737726a23e9b4cdba5de144c311377dc41d91b languageName: node linkType: hard @@ -6519,7 +7464,7 @@ __metadata: languageName: node linkType: hard -"estree-walker@npm:^2.0.1": +"estree-walker@npm:^2.0.1, estree-walker@npm:^2.0.2": version: 2.0.2 resolution: "estree-walker@npm:2.0.2" checksum: 6151e6f9828abe2259e57f5fd3761335bb0d2ebd76dc1a01048ccee22fabcfef3c0859300f6d83ff0d1927849368775ec5a6d265dde2f6de5a1be1721cd94efc @@ -6556,23 +7501,6 @@ __metadata: languageName: node linkType: hard -"execa@npm:^5.1.1": - version: 5.1.1 - resolution: "execa@npm:5.1.1" - dependencies: - cross-spawn: ^7.0.3 - get-stream: ^6.0.0 - human-signals: ^2.1.0 - is-stream: ^2.0.0 - merge-stream: ^2.0.0 - npm-run-path: ^4.0.1 - onetime: ^5.1.2 - signal-exit: ^3.0.3 - strip-final-newline: ^2.0.0 - checksum: fba9022c8c8c15ed862847e94c252b3d946036d7547af310e344a527e59021fd8b6bb0723883ea87044dc4f0201f949046993124a42ccb0855cae5bf8c786343 - languageName: node - linkType: hard - "execa@npm:^8.0.1": version: 8.0.1 resolution: "execa@npm:8.0.1" @@ -6597,15 +7525,15 @@ __metadata: languageName: node linkType: hard -"expressive-code@npm:^0.35.3": - version: 0.35.3 - resolution: "expressive-code@npm:0.35.3" +"expressive-code@npm:^0.38.1": + version: 0.38.1 + resolution: "expressive-code@npm:0.38.1" dependencies: - "@expressive-code/core": ^0.35.3 - "@expressive-code/plugin-frames": ^0.35.3 - "@expressive-code/plugin-shiki": ^0.35.3 - "@expressive-code/plugin-text-markers": ^0.35.3 - checksum: fb44380688980707c1fed3e69196f3a7555c553f38e20ed04a604126158c80b325e19a2722a31f1d74a2b55ef6fe852f616ee18743a62b2bd992b699f48e1d92 + "@expressive-code/core": ^0.38.1 + "@expressive-code/plugin-frames": ^0.38.1 + "@expressive-code/plugin-shiki": ^0.38.1 + "@expressive-code/plugin-text-markers": ^0.38.1 + checksum: 94d439437c5038c28ffd7c932653b4dd67e0013d49eeb9dd5927e6d2f1feb06dca72e18c8e85637f04b471970f47043900f3a2227f00d9e4a64d6814385c0f62 languageName: node linkType: hard @@ -6776,6 +7704,15 @@ __metadata: languageName: node linkType: hard +"fill-range@npm:^7.1.1": + version: 7.1.1 + resolution: "fill-range@npm:7.1.1" + dependencies: + to-regex-range: ^5.0.1 + checksum: b4abfbca3839a3d55e4ae5ec62e131e2e356bf4859ce8480c64c4876100f4df292a63e5bb1618e1d7460282ca2b305653064f01654474aa35c68000980f17798 + languageName: node + linkType: hard + "find-cache-dir@npm:^3.3.2": version: 3.3.2 resolution: "find-cache-dir@npm:3.3.2" @@ -6787,6 +7724,13 @@ __metadata: languageName: node linkType: hard +"find-up-simple@npm:^1.0.0": + version: 1.0.0 + resolution: "find-up-simple@npm:1.0.0" + checksum: 91c3d51c1111b5eb4e6e6d71d21438f6571a37a69dc288d4222b98996756e2f472fa5393a4dddb5e1a84929405d87e86f4bdce798ba84ee513b79854960ec140 + languageName: node + linkType: hard + "find-up@npm:^4.0.0": version: 4.1.0 resolution: "find-up@npm:4.1.0" @@ -6848,6 +7792,16 @@ __metadata: languageName: node linkType: hard +"follow-redirects@npm:^1.15.6": + version: 1.15.9 + resolution: "follow-redirects@npm:1.15.9" + peerDependenciesMeta: + debug: + optional: true + checksum: 859e2bacc7a54506f2bf9aacb10d165df78c8c1b0ceb8023f966621b233717dab56e8d08baadc3ad3b9db58af290413d585c999694b7c146aaf2616340c3d2a6 + languageName: node + linkType: hard + "for-each@npm:^0.3.3": version: 0.3.3 resolution: "for-each@npm:0.3.3" @@ -6867,6 +7821,17 @@ __metadata: languageName: node linkType: hard +"form-data@npm:^4.0.0": + version: 4.0.1 + resolution: "form-data@npm:4.0.1" + dependencies: + asynckit: ^0.4.0 + combined-stream: ^1.0.8 + mime-types: ^2.1.12 + checksum: ccee458cd5baf234d6b57f349fe9cc5f9a2ea8fd1af5ecda501a18fd1572a6dd3bf08a49f00568afd995b6a65af34cb8dec083cf9d582c4e621836499498dd84 + languageName: node + linkType: hard + "fraction.js@npm:^4.2.0": version: 4.2.0 resolution: "fraction.js@npm:4.2.0" @@ -7041,13 +8006,6 @@ __metadata: languageName: node linkType: hard -"get-stream@npm:^6.0.0": - version: 6.0.1 - resolution: "get-stream@npm:6.0.1" - checksum: e04ecece32c92eebf5b8c940f51468cd53554dcbb0ea725b2748be583c9523d00128137966afce410b9b051eb2ef16d657cd2b120ca8edafcf5a65e81af63cad - languageName: node - linkType: hard - "get-stream@npm:^8.0.1": version: 8.0.1 resolution: "get-stream@npm:8.0.1" @@ -7339,6 +8297,20 @@ __metadata: languageName: node linkType: hard +"hast-util-from-html@npm:^2.0.3": + version: 2.0.3 + resolution: "hast-util-from-html@npm:2.0.3" + dependencies: + "@types/hast": ^3.0.0 + devlop: ^1.1.0 + hast-util-from-parse5: ^8.0.0 + parse5: ^7.0.0 + vfile: ^6.0.0 + vfile-message: ^4.0.0 + checksum: 50f589f25a82868d611668421ff1d7997778743b34fbde77cd74d152350162b5045090c65ee3c3e2b4d51568f35426a0fc851ee1965723e1abf466f7f9d0bd83 + languageName: node + linkType: hard + "hast-util-from-parse5@npm:^7.0.0": version: 7.1.0 resolution: "hast-util-from-parse5@npm:7.1.0" @@ -7539,6 +8511,25 @@ __metadata: languageName: node linkType: hard +"hast-util-to-html@npm:^9.0.3": + version: 9.0.3 + resolution: "hast-util-to-html@npm:9.0.3" + dependencies: + "@types/hast": ^3.0.0 + "@types/unist": ^3.0.0 + ccount: ^2.0.0 + comma-separated-tokens: ^2.0.0 + hast-util-whitespace: ^3.0.0 + html-void-elements: ^3.0.0 + mdast-util-to-hast: ^13.0.0 + property-information: ^6.0.0 + space-separated-tokens: ^2.0.0 + stringify-entities: ^4.0.0 + zwitch: ^2.0.4 + checksum: e0b6f6fdba5f0075a593a0b1f0807c11a24ccfcb8403caea7d71eaffd7a958c995917e69fccc9055fbfa05a8b9d6b1cab306200bb82ad143530fdf4f33dcc311 + languageName: node + linkType: hard + "hast-util-to-parse5@npm:^7.0.0": version: 7.0.0 resolution: "hast-util-to-parse5@npm:7.0.0" @@ -7577,7 +8568,7 @@ __metadata: languageName: node linkType: hard -"hast-util-to-text@npm:^4.0.0, hast-util-to-text@npm:^4.0.1": +"hast-util-to-text@npm:^4.0.0, hast-util-to-text@npm:^4.0.1, hast-util-to-text@npm:^4.0.2": version: 4.0.2 resolution: "hast-util-to-text@npm:4.0.2" dependencies: @@ -7714,6 +8705,18 @@ __metadata: languageName: node linkType: hard +"htmlparser2@npm:^9.1.0": + version: 9.1.0 + resolution: "htmlparser2@npm:9.1.0" + dependencies: + domelementtype: ^2.3.0 + domhandler: ^5.0.3 + domutils: ^3.1.0 + entities: ^4.5.0 + checksum: e5f8d5193967e4a500226f37bdf2c0f858cecb39dde14d0439f24bf2c461a4342778740d988fbaba652b0e4cb6052f7f2e99e69fc1a329a86c629032bb76e7c8 + languageName: node + linkType: hard + "http-cache-semantics@npm:^4.1.1": version: 4.1.1 resolution: "http-cache-semantics@npm:4.1.1" @@ -7742,13 +8745,6 @@ __metadata: languageName: node linkType: hard -"human-signals@npm:^2.1.0": - version: 2.1.0 - resolution: "human-signals@npm:2.1.0" - checksum: b87fd89fce72391625271454e70f67fe405277415b48bcc0117ca73d31fa23a4241787afdc8d67f5a116cf37258c052f59ea82daffa72364d61351423848e3b8 - languageName: node - linkType: hard - "human-signals@npm:^5.0.0": version: 5.0.0 resolution: "human-signals@npm:5.0.0" @@ -7765,7 +8761,7 @@ __metadata: languageName: node linkType: hard -"iconv-lite@npm:^0.6.2": +"iconv-lite@npm:0.6.3, iconv-lite@npm:^0.6.2, iconv-lite@npm:^0.6.3": version: 0.6.3 resolution: "iconv-lite@npm:0.6.3" dependencies: @@ -7839,6 +8835,13 @@ __metadata: languageName: node linkType: hard +"import-meta-resolve@npm:^4.1.0": + version: 4.1.0 + resolution: "import-meta-resolve@npm:4.1.0" + checksum: 6497af27bf3ee384ad4efd4e0ec3facf9a114863f35a7b35f248659f32faa5e1ae07baa74d603069f35734ae3718a78b3f66926f98dc9a62e261e7df37854a62 + languageName: node + linkType: hard + "imurmurhash@npm:^0.1.4": version: 0.1.4 resolution: "imurmurhash@npm:0.1.4" @@ -8144,13 +9147,6 @@ __metadata: languageName: node linkType: hard -"is-stream@npm:^2.0.0": - version: 2.0.1 - resolution: "is-stream@npm:2.0.1" - checksum: b8e05ccdf96ac330ea83c12450304d4a591f9958c11fd17bed240af8d5ffe08aedafa4c0f4cfccd4d28dc9d4d129daca1023633d5c11601a6cbc77521f6fae66 - languageName: node - linkType: hard - "is-stream@npm:^3.0.0": version: 3.0.0 resolution: "is-stream@npm:3.0.0" @@ -8267,15 +9263,6 @@ __metadata: languageName: node linkType: hard -"javascript-time-ago@npm:^2.5.10": - version: 2.5.10 - resolution: "javascript-time-ago@npm:2.5.10" - dependencies: - relative-time-format: ^1.1.6 - checksum: f0ddb6ba9361b96b3ec08fc4720fe84c45c8f71b044968e5c2a3c57d816b4b5d260a9513d25ed77ce9832ab5ac4a5bdd3f21bd0bebb4266b1292e19f39b070c6 - languageName: node - linkType: hard - "jest-worker@npm:^26.2.1": version: 26.6.2 resolution: "jest-worker@npm:26.6.2" @@ -8326,6 +9313,15 @@ __metadata: languageName: node linkType: hard +"jsesc@npm:^3.0.2": + version: 3.0.2 + resolution: "jsesc@npm:3.0.2" + bin: + jsesc: bin/jsesc + checksum: a36d3ca40574a974d9c2063bf68c2b6141c20da8f2a36bd3279fc802563f35f0527a6c828801295bdfb2803952cf2cf387786c2c90ed564f88d5782475abfe3c + languageName: node + linkType: hard + "jsesc@npm:~0.5.0": version: 0.5.0 resolution: "jsesc@npm:0.5.0" @@ -8423,83 +9419,91 @@ __metadata: languageName: node linkType: hard -"lightningcss-darwin-arm64@npm:1.25.1": - version: 1.25.1 - resolution: "lightningcss-darwin-arm64@npm:1.25.1" +"lightningcss-darwin-arm64@npm:1.27.0": + version: 1.27.0 + resolution: "lightningcss-darwin-arm64@npm:1.27.0" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"lightningcss-darwin-x64@npm:1.25.1": - version: 1.25.1 - resolution: "lightningcss-darwin-x64@npm:1.25.1" +"lightningcss-darwin-x64@npm:1.27.0": + version: 1.27.0 + resolution: "lightningcss-darwin-x64@npm:1.27.0" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"lightningcss-freebsd-x64@npm:1.25.1": - version: 1.25.1 - resolution: "lightningcss-freebsd-x64@npm:1.25.1" +"lightningcss-freebsd-x64@npm:1.27.0": + version: 1.27.0 + resolution: "lightningcss-freebsd-x64@npm:1.27.0" conditions: os=freebsd & cpu=x64 languageName: node linkType: hard -"lightningcss-linux-arm-gnueabihf@npm:1.25.1": - version: 1.25.1 - resolution: "lightningcss-linux-arm-gnueabihf@npm:1.25.1" +"lightningcss-linux-arm-gnueabihf@npm:1.27.0": + version: 1.27.0 + resolution: "lightningcss-linux-arm-gnueabihf@npm:1.27.0" conditions: os=linux & cpu=arm languageName: node linkType: hard -"lightningcss-linux-arm64-gnu@npm:1.25.1": - version: 1.25.1 - resolution: "lightningcss-linux-arm64-gnu@npm:1.25.1" +"lightningcss-linux-arm64-gnu@npm:1.27.0": + version: 1.27.0 + resolution: "lightningcss-linux-arm64-gnu@npm:1.27.0" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"lightningcss-linux-arm64-musl@npm:1.25.1": - version: 1.25.1 - resolution: "lightningcss-linux-arm64-musl@npm:1.25.1" +"lightningcss-linux-arm64-musl@npm:1.27.0": + version: 1.27.0 + resolution: "lightningcss-linux-arm64-musl@npm:1.27.0" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"lightningcss-linux-x64-gnu@npm:1.25.1": - version: 1.25.1 - resolution: "lightningcss-linux-x64-gnu@npm:1.25.1" +"lightningcss-linux-x64-gnu@npm:1.27.0": + version: 1.27.0 + resolution: "lightningcss-linux-x64-gnu@npm:1.27.0" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"lightningcss-linux-x64-musl@npm:1.25.1": - version: 1.25.1 - resolution: "lightningcss-linux-x64-musl@npm:1.25.1" +"lightningcss-linux-x64-musl@npm:1.27.0": + version: 1.27.0 + resolution: "lightningcss-linux-x64-musl@npm:1.27.0" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"lightningcss-win32-x64-msvc@npm:1.25.1": - version: 1.25.1 - resolution: "lightningcss-win32-x64-msvc@npm:1.25.1" +"lightningcss-win32-arm64-msvc@npm:1.27.0": + version: 1.27.0 + resolution: "lightningcss-win32-arm64-msvc@npm:1.27.0" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + +"lightningcss-win32-x64-msvc@npm:1.27.0": + version: 1.27.0 + resolution: "lightningcss-win32-x64-msvc@npm:1.27.0" conditions: os=win32 & cpu=x64 languageName: node linkType: hard -"lightningcss@npm:1.25.1": - version: 1.25.1 - resolution: "lightningcss@npm:1.25.1" +"lightningcss@npm:1.27.0": + version: 1.27.0 + resolution: "lightningcss@npm:1.27.0" dependencies: detect-libc: ^1.0.3 - lightningcss-darwin-arm64: 1.25.1 - lightningcss-darwin-x64: 1.25.1 - lightningcss-freebsd-x64: 1.25.1 - lightningcss-linux-arm-gnueabihf: 1.25.1 - lightningcss-linux-arm64-gnu: 1.25.1 - lightningcss-linux-arm64-musl: 1.25.1 - lightningcss-linux-x64-gnu: 1.25.1 - lightningcss-linux-x64-musl: 1.25.1 - lightningcss-win32-x64-msvc: 1.25.1 + lightningcss-darwin-arm64: 1.27.0 + lightningcss-darwin-x64: 1.27.0 + lightningcss-freebsd-x64: 1.27.0 + lightningcss-linux-arm-gnueabihf: 1.27.0 + lightningcss-linux-arm64-gnu: 1.27.0 + lightningcss-linux-arm64-musl: 1.27.0 + lightningcss-linux-x64-gnu: 1.27.0 + lightningcss-linux-x64-musl: 1.27.0 + lightningcss-win32-arm64-msvc: 1.27.0 + lightningcss-win32-x64-msvc: 1.27.0 dependenciesMeta: lightningcss-darwin-arm64: optional: true @@ -8517,9 +9521,11 @@ __metadata: optional: true lightningcss-linux-x64-musl: optional: true + lightningcss-win32-arm64-msvc: + optional: true lightningcss-win32-x64-msvc: optional: true - checksum: b62d37ee5d82da3e6c9a06f1677d2bc208bd68022bc60b8449b1a858643be1c4715bac87e0a42b50dd85c3c848fdba1239c2f4e167313508edd07d9ab4073063 + checksum: 3761a4feb67ca250bf1b1cb1982a3d212dee56ea345dd487592908648e70d8c17da2f5918affaf08b6cdc4e4702eee29d800ff29e16d194e7af6300af1b28409 languageName: node linkType: hard @@ -8566,13 +9572,6 @@ __metadata: languageName: node linkType: hard -"local-pkg@npm:^0.4.3": - version: 0.4.3 - resolution: "local-pkg@npm:0.4.3" - checksum: 7825aca531dd6afa3a3712a0208697aa4a5cd009065f32e3fb732aafcc42ed11f277b5ac67229222e96f4def55197171cdf3d5522d0381b489d2e5547b407d55 - languageName: node - linkType: hard - "local-pkg@npm:^0.5.0": version: 0.5.0 resolution: "local-pkg@npm:0.5.0" @@ -8723,6 +9722,26 @@ __metadata: languageName: node linkType: hard +"magic-string@npm:^0.30.12": + version: 0.30.12 + resolution: "magic-string@npm:0.30.12" + dependencies: + "@jridgewell/sourcemap-codec": ^1.5.0 + checksum: 3f0d23b74371765f0e6cad4284eebba0ac029c7a55e39292de5aa92281afb827138cb2323d24d2924f6b31f138c3783596c5ccaa98653fe9cf122e1f81325b59 + languageName: node + linkType: hard + +"magicast@npm:^0.3.5": + version: 0.3.5 + resolution: "magicast@npm:0.3.5" + dependencies: + "@babel/parser": ^7.25.4 + "@babel/types": ^7.25.4 + source-map-js: ^1.2.0 + checksum: 668f07ade907a44bccfc9a9321588473f6d5fa25329aa26b9ad9a3bf87cc2e6f9c482cbdd3e33c0b9ab9b79c065630c599cc055a12f881c8c924ee0d7282cdce + languageName: node + linkType: hard + "make-dir@npm:^3.0.2": version: 3.1.0 resolution: "make-dir@npm:3.1.0" @@ -9420,6 +10439,32 @@ __metadata: languageName: node linkType: hard +"micromatch@npm:^4.0.8": + version: 4.0.8 + resolution: "micromatch@npm:4.0.8" + dependencies: + braces: ^3.0.3 + picomatch: ^2.3.1 + checksum: 79920eb634e6f400b464a954fcfa589c4e7c7143209488e44baf627f9affc8b1e306f41f4f0deedde97e69cb725920879462d3e750ab3bd3c1aed675bb3a8966 + languageName: node + linkType: hard + +"mime-db@npm:1.52.0": + version: 1.52.0 + resolution: "mime-db@npm:1.52.0" + checksum: 0d99a03585f8b39d68182803b12ac601d9c01abfa28ec56204fa330bc9f3d1c5e14beb049bafadb3dbdf646dfb94b87e24d4ec7b31b7279ef906a8ea9b6a513f + languageName: node + linkType: hard + +"mime-types@npm:^2.1.12": + version: 2.1.35 + resolution: "mime-types@npm:2.1.35" + dependencies: + mime-db: 1.52.0 + checksum: 89a5b7f1def9f3af5dad6496c5ed50191ae4331cc5389d7c521c8ad28d5fdad2d06fd81baf38fed813dc4e46bb55c8145bb0ff406330818c9cf712fb2e9b3836 + languageName: node + linkType: hard + "mimic-fn@npm:^2.1.0": version: 2.1.0 resolution: "mimic-fn@npm:2.1.0" @@ -9434,6 +10479,13 @@ __metadata: languageName: node linkType: hard +"mimic-function@npm:^5.0.0": + version: 5.0.1 + resolution: "mimic-function@npm:5.0.1" + checksum: eb5893c99e902ccebbc267c6c6b83092966af84682957f79313311edb95e8bb5f39fb048d77132b700474d1c86d90ccc211e99bae0935447a4834eb4c882982c + languageName: node + linkType: hard + "minimatch@npm:^3.0.5, minimatch@npm:^3.1.1, minimatch@npm:^3.1.2": version: 3.1.2 resolution: "minimatch@npm:3.1.2" @@ -9561,7 +10613,7 @@ __metadata: languageName: node linkType: hard -"mlly@npm:^1.2.0, mlly@npm:^1.4.2, mlly@npm:^1.5.0": +"mlly@npm:^1.2.0, mlly@npm:^1.4.2": version: 1.6.1 resolution: "mlly@npm:1.6.1" dependencies: @@ -9573,6 +10625,18 @@ __metadata: languageName: node linkType: hard +"mlly@npm:^1.7.1, mlly@npm:^1.7.2": + version: 1.7.2 + resolution: "mlly@npm:1.7.2" + dependencies: + acorn: ^8.12.1 + pathe: ^1.1.2 + pkg-types: ^1.2.0 + ufo: ^1.5.4 + checksum: 66a92b0ac4f76cac22d2d6688338fece01f2ac4afd7816cd4224525c1f9032c452075730c54c3ef7558485455d704b7141060e517785c93b276b2faa3bb04199 + languageName: node + linkType: hard + "morphdom@npm:^2.7.0": version: 2.7.0 resolution: "morphdom@npm:2.7.0" @@ -9601,7 +10665,7 @@ __metadata: languageName: node linkType: hard -"ms@npm:^2.0.0": +"ms@npm:^2.0.0, ms@npm:^2.1.3": version: 2.1.3 resolution: "ms@npm:2.1.3" checksum: aa92de608021b242401676e35cfa5aa42dd70cbdc082b916da7fb925c542173e36bce97ea3e804923fe92c0ad991434e4a38327e15a1b5b5f945d66df615ae6d @@ -9649,6 +10713,13 @@ __metadata: languageName: node linkType: hard +"neotraverse@npm:^0.6.18": + version: 0.6.18 + resolution: "neotraverse@npm:0.6.18" + checksum: 6ec0855db8d484a33672ba4533617bab4944167c881a6ab35a987bf3b92f12159eac5c19ad9cc203c193b279cc1a09f0bd7c7fb7752f9950625cbd866071ef72 + languageName: node + linkType: hard + "nlcst-to-string@npm:^2.0.0": version: 2.0.4 resolution: "nlcst-to-string@npm:2.0.4" @@ -9665,6 +10736,15 @@ __metadata: languageName: node linkType: hard +"nlcst-to-string@npm:^4.0.0": + version: 4.0.0 + resolution: "nlcst-to-string@npm:4.0.0" + dependencies: + "@types/nlcst": ^2.0.0 + checksum: a780ca517548582016b6a92216962500de1179ace37cc7a9afbddd219e6893f253eab564f4c2292a13cf2ade27a669c6222b3eb27671cf647e15b6abf2eb1827 + languageName: node + linkType: hard + "no-case@npm:^3.0.4": version: 3.0.4 resolution: "no-case@npm:3.0.4" @@ -9710,6 +10790,13 @@ __metadata: languageName: node linkType: hard +"node-releases@npm:^2.0.18": + version: 2.0.18 + resolution: "node-releases@npm:2.0.18" + checksum: ef55a3d853e1269a6d6279b7692cd6ff3e40bc74947945101138745bfdc9a5edabfe72cb19a31a8e45752e1910c4c65c77d931866af6357f242b172b7283f5b3 + languageName: node + linkType: hard + "nopt@npm:^6.0.0": version: 6.0.0 resolution: "nopt@npm:6.0.0" @@ -9749,15 +10836,6 @@ __metadata: languageName: node linkType: hard -"npm-run-path@npm:^4.0.1": - version: 4.0.1 - resolution: "npm-run-path@npm:4.0.1" - dependencies: - path-key: ^3.0.0 - checksum: 5374c0cea4b0bbfdfae62da7bbdf1e1558d338335f4cacf2515c282ff358ff27b2ecb91ffa5330a8b14390ac66a1e146e10700440c1ab868208430f56b5f4d23 - languageName: node - linkType: hard - "npm-run-path@npm:^5.1.0": version: 5.1.0 resolution: "npm-run-path@npm:5.1.0" @@ -9844,7 +10922,7 @@ __metadata: languageName: node linkType: hard -"onetime@npm:^5.1.0, onetime@npm:^5.1.2": +"onetime@npm:^5.1.0": version: 5.1.2 resolution: "onetime@npm:5.1.2" dependencies: @@ -9862,6 +10940,24 @@ __metadata: languageName: node linkType: hard +"onetime@npm:^7.0.0": + version: 7.0.0 + resolution: "onetime@npm:7.0.0" + dependencies: + mimic-function: ^5.0.0 + checksum: eb08d2da9339819e2f9d52cab9caf2557d80e9af8c7d1ae86e1a0fef027d00a88e9f5bd67494d350df360f7c559fbb44e800b32f310fb989c860214eacbb561c + languageName: node + linkType: hard + +"oniguruma-to-js@npm:0.4.3": + version: 0.4.3 + resolution: "oniguruma-to-js@npm:0.4.3" + dependencies: + regex: ^4.3.2 + checksum: 563d2e3490d415628f7a273fd417d16a69d19e53454821ed9654ee84877ecaf532c60d710f670edb4cde7448e505e3a70c6ab89d641769394b4238248ea71816 + languageName: node + linkType: hard + "open-graph-scraper@npm:^6.3.0": version: 6.3.0 resolution: "open-graph-scraper@npm:6.3.0" @@ -9925,6 +11021,23 @@ __metadata: languageName: node linkType: hard +"ora@npm:^8.1.0": + version: 8.1.1 + resolution: "ora@npm:8.1.1" + dependencies: + chalk: ^5.3.0 + cli-cursor: ^5.0.0 + cli-spinners: ^2.9.2 + is-interactive: ^2.0.0 + is-unicode-supported: ^2.0.0 + log-symbols: ^6.0.0 + stdin-discarder: ^0.2.2 + string-width: ^7.2.0 + strip-ansi: ^7.1.0 + checksum: 0cb79b9d8458ef0878e43d692fddb078c0885c82bbfa45e46de366f71fd506a75d8f9d5df71859624f7f0fe488c17d2e6882d7a35126214cf1a0e0c0f51248c4 + languageName: node + linkType: hard + "p-finally@npm:^1.0.0": version: 1.0.0 resolution: "p-finally@npm:1.0.0" @@ -9959,6 +11072,15 @@ __metadata: languageName: node linkType: hard +"p-limit@npm:^6.1.0": + version: 6.1.0 + resolution: "p-limit@npm:6.1.0" + dependencies: + yocto-queue: ^1.1.1 + checksum: 0c98d8fc1006b70fc7423232a47e8d026dc69279b06fe7ff8b4c0cc8023de2b6bb8991b609d93c3dec691a7a362ab0f0157df521d931a01fec192a5e404b9ee5 + languageName: node + linkType: hard + "p-locate@npm:^4.1.0": version: 4.1.0 resolution: "p-locate@npm:4.1.0" @@ -10029,6 +11151,13 @@ __metadata: languageName: node linkType: hard +"package-manager-detector@npm:^0.2.0": + version: 0.2.2 + resolution: "package-manager-detector@npm:0.2.2" + checksum: acc0d5a8b6b2a265474c1bac2b3569b6e57fe13db4d764b75cf5fcd11463a44f0ce00bb5dc439a78a1999993780385f431d36ceea51b51a35ce40d512b7388c6 + languageName: node + linkType: hard + "pako@npm:^0.2.5": version: 0.2.9 resolution: "pako@npm:0.2.9" @@ -10088,6 +11217,20 @@ __metadata: languageName: node linkType: hard +"parse-latin@npm:^7.0.0": + version: 7.0.0 + resolution: "parse-latin@npm:7.0.0" + dependencies: + "@types/nlcst": ^2.0.0 + "@types/unist": ^3.0.0 + nlcst-to-string: ^4.0.0 + unist-util-modify-children: ^4.0.0 + unist-util-visit-children: ^3.0.0 + vfile: ^6.0.0 + checksum: 71b5af8857750aeaa240c1688331ba37e5320de3f5c4225bf2b816554cbf5a987ce999e180074553acab7868a9c43deff1adb6cebd01ac6f258dcbdce4803824 + languageName: node + linkType: hard + "parse5-htmlparser2-tree-adapter@npm:^7.0.0": version: 7.0.0 resolution: "parse5-htmlparser2-tree-adapter@npm:7.0.0" @@ -10098,6 +11241,15 @@ __metadata: languageName: node linkType: hard +"parse5-parser-stream@npm:^7.1.2": + version: 7.1.2 + resolution: "parse5-parser-stream@npm:7.1.2" + dependencies: + parse5: ^7.0.0 + checksum: 75b232d460bce6bd0e35012750a78ef034f40ccf550b7c6cec3122395af6b4553202ad3663ad468cf537ead5a2e13b6727670395fd0ff548faccad1dc2dc93cf + languageName: node + linkType: hard + "parse5@npm:^6.0.0": version: 6.0.1 resolution: "parse5@npm:6.0.1" @@ -10114,6 +11266,15 @@ __metadata: languageName: node linkType: hard +"parse5@npm:^7.1.2": + version: 7.2.1 + resolution: "parse5@npm:7.2.1" + dependencies: + entities: ^4.5.0 + checksum: 11253cf8aa2e7fc41c004c64cba6f2c255f809663365db65bd7ad0e8cf7b89e436a563c20059346371cc543a6c1b567032088883ca6a2cbc88276c666b68236d + languageName: node + linkType: hard + "pascal-case@npm:^3.1.2": version: 3.1.2 resolution: "pascal-case@npm:3.1.2" @@ -10138,7 +11299,7 @@ __metadata: languageName: node linkType: hard -"path-key@npm:^3.0.0, path-key@npm:^3.1.0": +"path-key@npm:^3.1.0": version: 3.1.1 resolution: "path-key@npm:3.1.1" checksum: 55cd7a9dd4b343412a8386a743f9c746ef196e57c823d90ca3ab917f90ab9f13dd0ded27252ba49dbdfcab2b091d998bc446f6220cd3cea65db407502a740020 @@ -10190,7 +11351,7 @@ __metadata: languageName: node linkType: hard -"pathe@npm:^1.1.0, pathe@npm:^1.1.1, pathe@npm:^1.1.2": +"pathe@npm:^1.1.0, pathe@npm:^1.1.2": version: 1.1.2 resolution: "pathe@npm:1.1.2" checksum: ec5f778d9790e7b9ffc3e4c1df39a5bb1ce94657a4e3ad830c1276491ca9d79f189f47609884671db173400256b005f4955f7952f52a2aeb5834ad5fb4faf134 @@ -10211,6 +11372,13 @@ __metadata: languageName: node linkType: hard +"picocolors@npm:^1.1.0": + version: 1.1.1 + resolution: "picocolors@npm:1.1.1" + checksum: e1cf46bf84886c79055fdfa9dcb3e4711ad259949e3565154b004b260cd356c5d54b31a1437ce9782624bf766272fe6b0154f5f0c744fb7af5d454d2b60db045 + languageName: node + linkType: hard + "picomatch@npm:^2.0.4, picomatch@npm:^2.2.1, picomatch@npm:^2.2.2, picomatch@npm:^2.3.1": version: 2.3.1 resolution: "picomatch@npm:2.3.1" @@ -10218,6 +11386,13 @@ __metadata: languageName: node linkType: hard +"picomatch@npm:^4.0.2": + version: 4.0.2 + resolution: "picomatch@npm:4.0.2" + checksum: a7a5188c954f82c6585720e9143297ccd0e35ad8072231608086ca950bee672d51b0ef676254af0788205e59bd4e4deb4e7708769226bed725bf13370a7d1464 + languageName: node + linkType: hard + "pify@npm:^4.0.1": version: 4.0.1 resolution: "pify@npm:4.0.1" @@ -10252,6 +11427,17 @@ __metadata: languageName: node linkType: hard +"pkg-types@npm:^1.2.0": + version: 1.2.1 + resolution: "pkg-types@npm:1.2.1" + dependencies: + confbox: ^0.1.8 + mlly: ^1.7.2 + pathe: ^1.1.2 + checksum: d2e3ad7aef36cc92b17403e61c04db521bf0beb175ccb4d432c284239f00ec32ff37feb072a260613e9ff727911cff1127a083fd52f91b9bec6b62970f385702 + languageName: node + linkType: hard + "postcss-calc@npm:^8.2.3": version: 8.2.4 resolution: "postcss-calc@npm:8.2.4" @@ -10759,6 +11945,17 @@ __metadata: languageName: node linkType: hard +"postcss@npm:^8.4.43": + version: 8.4.47 + resolution: "postcss@npm:8.4.47" + dependencies: + nanoid: ^3.3.7 + picocolors: ^1.1.0 + source-map-js: ^1.2.1 + checksum: f78440a9d8f97431dd2ab1ab8e1de64f12f3eff38a3d8d4a33919b96c381046a314658d2de213a5fa5eb296b656de76a3ec269fdea27f16d5ab465b916a0f52c + languageName: node + linkType: hard + "preferred-pm@npm:^3.1.3": version: 3.1.3 resolution: "preferred-pm@npm:3.1.3" @@ -10771,6 +11968,17 @@ __metadata: languageName: node linkType: hard +"preferred-pm@npm:^4.0.0": + version: 4.0.0 + resolution: "preferred-pm@npm:4.0.0" + dependencies: + find-up-simple: ^1.0.0 + find-yarn-workspace-root2: 1.2.16 + which-pm: ^3.0.0 + checksum: c0838f89c158ba887693e630a3de88cb1a5cba990e5292fb05424734fe3e2a3ca84e7fdbfc6b418e120ac63cd4c12566789ae464eda4282e3d6a1498ef112e62 + languageName: node + linkType: hard + "prelude-ls@npm:^1.2.1": version: 1.2.1 resolution: "prelude-ls@npm:1.2.1" @@ -10778,14 +11986,14 @@ __metadata: languageName: node linkType: hard -"prettier-plugin-astro@npm:^0.14.0": - version: 0.14.0 - resolution: "prettier-plugin-astro@npm:0.14.0" +"prettier-plugin-astro@npm:^0.14.1": + version: 0.14.1 + resolution: "prettier-plugin-astro@npm:0.14.1" dependencies: - "@astrojs/compiler": ^1.5.5 + "@astrojs/compiler": ^2.9.1 prettier: ^3.0.0 sass-formatter: ^0.7.6 - checksum: ea51d5518e92fbf282e0f1f4f28090bcafc24cda7487ac588b90f0b54bc1fa3be1acfbc4cc51555915ab21d3035414cb89cc7c865f500169971c10a8089b78ce + checksum: 7cd6b03c65fac8329328a7f56168b596c846dfd282e4b2dbf597d2e731bcf463a2fba73ef0f0c8196713d96c3a04b744dd5e89f185028951e0354150202b3870 languageName: node linkType: hard @@ -10807,12 +12015,12 @@ __metadata: languageName: node linkType: hard -"prettier@npm:^3.3.1": - version: 3.3.1 - resolution: "prettier@npm:3.3.1" +"prettier@npm:^3.3.3": + version: 3.3.3 + resolution: "prettier@npm:3.3.3" bin: prettier: bin/prettier.cjs - checksum: 10987ff39e23d9359a76a441431dfe3ee26cc444540dc1577e8109e31394231fc1187d47a1e4ebc98bd605885c50ec681e9f2674e489c3313708c30b6ef5e119 + checksum: bc8604354805acfdde6106852d14b045bb20827ad76a5ffc2455b71a8257f94de93f17f14e463fe844808d2ccc87248364a5691488a3304f1031326e62d9276e languageName: node linkType: hard @@ -10880,6 +12088,13 @@ __metadata: languageName: node linkType: hard +"proxy-from-env@npm:^1.1.0": + version: 1.1.0 + resolution: "proxy-from-env@npm:1.1.0" + checksum: ed7fcc2ba0a33404958e34d95d18638249a68c430e30fcb6c478497d72739ba64ce9810a24f53a7d921d0c065e5b78e3822759800698167256b04659366ca4d4 + languageName: node + linkType: hard + "pump@npm:^3.0.0": version: 3.0.0 resolution: "pump@npm:3.0.0" @@ -11009,6 +12224,13 @@ __metadata: languageName: node linkType: hard +"regex@npm:^4.3.2": + version: 4.4.0 + resolution: "regex@npm:4.4.0" + checksum: 3ee7e223949343cb081b4117a64460a0c98bd4378285075605f3c32d71e2a5cabd9296b18df0468573b2f8038a25607ac36087ae6d6b6a1d9e118be5c214aba7 + languageName: node + linkType: hard + "regexp.prototype.flags@npm:^1.4.3, regexp.prototype.flags@npm:^1.5.0": version: 1.5.0 resolution: "regexp.prototype.flags@npm:1.5.0" @@ -11059,12 +12281,12 @@ __metadata: languageName: node linkType: hard -"rehype-expressive-code@npm:^0.35.3": - version: 0.35.3 - resolution: "rehype-expressive-code@npm:0.35.3" +"rehype-expressive-code@npm:^0.38.1": + version: 0.38.1 + resolution: "rehype-expressive-code@npm:0.38.1" dependencies: - expressive-code: ^0.35.3 - checksum: 082fa28e6bf8ad47cc7f556972a270b7b9f391c875c91a7b64dbf90c3ee49110a16df2d56b4e9104d1ccfc71c85dbbd6be8a7edcb7c81337e434b04710b3ffde + expressive-code: ^0.38.1 + checksum: f947af2f109b975bffbdcb853fc26365ccc2657768ad8336b5704251f3065707d4ea70a657c27b00bfebd6ba6a62d7833df888c5565bfab591d6e2588521b43e languageName: node linkType: hard @@ -11128,6 +12350,17 @@ __metadata: languageName: node linkType: hard +"rehype-stringify@npm:^10.0.1": + version: 10.0.1 + resolution: "rehype-stringify@npm:10.0.1" + dependencies: + "@types/hast": ^3.0.0 + hast-util-to-html: ^9.0.0 + unified: ^11.0.0 + checksum: 239d1ca75d6dcf4bb863202697ceb000ad746f9c0e99c5df3e49397bb09af73adaa6b934a2c852c9bd5e8ab80ca1e35c51a4b2c565999599576c691ad06c149d + languageName: node + linkType: hard + "rehype@npm:^13.0.1": version: 13.0.1 resolution: "rehype@npm:13.0.1" @@ -11140,17 +12373,22 @@ __metadata: languageName: node linkType: hard -"relateurl@npm:^0.2.7": - version: 0.2.7 - resolution: "relateurl@npm:0.2.7" - checksum: 5891e792eae1dfc3da91c6fda76d6c3de0333a60aa5ad848982ebb6dccaa06e86385fb1235a1582c680a3d445d31be01c6bfc0804ebbcab5aaf53fa856fde6b6 +"rehype@npm:^13.0.2": + version: 13.0.2 + resolution: "rehype@npm:13.0.2" + dependencies: + "@types/hast": ^3.0.0 + rehype-parse: ^9.0.0 + rehype-stringify: ^10.0.0 + unified: ^11.0.0 + checksum: d0a1b6df542174b7dbec40119c47b33411d9fde9c51a5e42fc75e40d45f80ab7a2825a122f3b5f6defc372077ea1547ca9097dcfaed718d4784022f25df20c9c languageName: node linkType: hard -"relative-time-format@npm:^1.1.6": - version: 1.1.6 - resolution: "relative-time-format@npm:1.1.6" - checksum: b0c14f2d81bb086d0bcedabab78cff0cd31d3ad5040db88f0dc671361c33bf5ec924fe897e9308a43c2f569b114dd543557b9df659f7a06e2d06d392b539d5d7 +"relateurl@npm:^0.2.7": + version: 0.2.7 + resolution: "relateurl@npm:0.2.7" + checksum: 5891e792eae1dfc3da91c6fda76d6c3de0333a60aa5ad848982ebb6dccaa06e86385fb1235a1582c680a3d445d31be01c6bfc0804ebbcab5aaf53fa856fde6b6 languageName: node linkType: hard @@ -11212,6 +12450,19 @@ __metadata: languageName: node linkType: hard +"remark-rehype@npm:^11.1.1": + version: 11.1.1 + resolution: "remark-rehype@npm:11.1.1" + dependencies: + "@types/hast": ^3.0.0 + "@types/mdast": ^4.0.0 + mdast-util-to-hast: ^13.0.0 + unified: ^11.0.0 + vfile: ^6.0.0 + checksum: e199dff098ae6a560e13dd1778dec9c61440f979cc931c4ca4dcde0d58e51c0723243a901c1842379b189083cf4d74f224f57833738095ffa9535179d7cf3f01 + languageName: node + linkType: hard + "remark-smartypants@npm:^2.0.0": version: 2.0.0 resolution: "remark-smartypants@npm:2.0.0" @@ -11223,6 +12474,18 @@ __metadata: languageName: node linkType: hard +"remark-smartypants@npm:^3.0.2": + version: 3.0.2 + resolution: "remark-smartypants@npm:3.0.2" + dependencies: + retext: ^9.0.0 + retext-smartypants: ^6.0.0 + unified: ^11.0.4 + unist-util-visit: ^5.0.0 + checksum: c2d16ad997f5ebbf1c13b13e56192c6d39d0f9dcff3a00f2015d27fe18efb38f5d1b5f48229c57b2656ae53cd1e6ec1c1f686216bae159cb04337cb4ce7da345 + languageName: node + linkType: hard + "remark-stringify@npm:^11.0.0": version: 11.0.0 resolution: "remark-stringify@npm:11.0.0" @@ -11365,6 +12628,16 @@ __metadata: languageName: node linkType: hard +"restore-cursor@npm:^5.0.0": + version: 5.1.0 + resolution: "restore-cursor@npm:5.1.0" + dependencies: + onetime: ^7.0.0 + signal-exit: ^4.1.0 + checksum: 838dd54e458d89cfbc1a923b343c1b0f170a04100b4ce1733e97531842d7b440463967e521216e8ab6c6f8e89df877acc7b7f4c18ec76e99fb9bf5a60d358d2c + languageName: node + linkType: hard + "retext-latin@npm:^3.0.0": version: 3.1.0 resolution: "retext-latin@npm:3.1.0" @@ -11377,6 +12650,17 @@ __metadata: languageName: node linkType: hard +"retext-latin@npm:^4.0.0": + version: 4.0.0 + resolution: "retext-latin@npm:4.0.0" + dependencies: + "@types/nlcst": ^2.0.0 + parse-latin: ^7.0.0 + unified: ^11.0.0 + checksum: 924e2e4b588e75f2884d6fd81bdd647e1848b47bcf0e2b503873752e8fa80b2d2c9bcc1ae76141334145cbaacb383df26b637ed76d07b8c8b251d4cd340dec41 + languageName: node + linkType: hard + "retext-smartypants@npm:^5.1.0": version: 5.2.0 resolution: "retext-smartypants@npm:5.2.0" @@ -11389,6 +12673,17 @@ __metadata: languageName: node linkType: hard +"retext-smartypants@npm:^6.0.0": + version: 6.1.0 + resolution: "retext-smartypants@npm:6.1.0" + dependencies: + "@types/nlcst": ^2.0.0 + nlcst-to-string: ^4.0.0 + unist-util-visit: ^5.0.0 + checksum: d987560ddbc765b22dfe4db0ec078097c8cc7c955394b0ad582b08b25ef169f5d58d6d3950f84c8b4e5b0d065bfad3c59ca540129a5f9f3c30cb664a86bda368 + languageName: node + linkType: hard + "retext-stringify@npm:^3.0.0": version: 3.1.0 resolution: "retext-stringify@npm:3.1.0" @@ -11400,6 +12695,17 @@ __metadata: languageName: node linkType: hard +"retext-stringify@npm:^4.0.0": + version: 4.0.0 + resolution: "retext-stringify@npm:4.0.0" + dependencies: + "@types/nlcst": ^2.0.0 + nlcst-to-string: ^4.0.0 + unified: ^11.0.0 + checksum: a98ede08708a3d859a07798cab5653ae312526a1e439f7066d5403c5ea0d23a53348565b3971433670cfc7d0ce95a58a535e4b68dc10834c45a74b4de37e72b1 + languageName: node + linkType: hard + "retext@npm:^8.1.0": version: 8.1.0 resolution: "retext@npm:8.1.0" @@ -11412,6 +12718,18 @@ __metadata: languageName: node linkType: hard +"retext@npm:^9.0.0": + version: 9.0.0 + resolution: "retext@npm:9.0.0" + dependencies: + "@types/nlcst": ^2.0.0 + retext-latin: ^4.0.0 + retext-stringify: ^4.0.0 + unified: ^11.0.0 + checksum: 191b5e5434cb5aeb5dd8947ceaebcd07637a73bae4170540941d256257898e0e65e411a839f1060888794daa575bf22e5cb4a6d3fd0bb3cc325e21b8b5423008 + languageName: node + linkType: hard + "retry@npm:^0.12.0": version: 0.12.0 resolution: "retry@npm:0.12.0" @@ -11605,6 +12923,75 @@ __metadata: languageName: node linkType: hard +"rollup@npm:^4.20.0": + version: 4.24.4 + resolution: "rollup@npm:4.24.4" + dependencies: + "@rollup/rollup-android-arm-eabi": 4.24.4 + "@rollup/rollup-android-arm64": 4.24.4 + "@rollup/rollup-darwin-arm64": 4.24.4 + "@rollup/rollup-darwin-x64": 4.24.4 + "@rollup/rollup-freebsd-arm64": 4.24.4 + "@rollup/rollup-freebsd-x64": 4.24.4 + "@rollup/rollup-linux-arm-gnueabihf": 4.24.4 + "@rollup/rollup-linux-arm-musleabihf": 4.24.4 + "@rollup/rollup-linux-arm64-gnu": 4.24.4 + "@rollup/rollup-linux-arm64-musl": 4.24.4 + "@rollup/rollup-linux-powerpc64le-gnu": 4.24.4 + "@rollup/rollup-linux-riscv64-gnu": 4.24.4 + "@rollup/rollup-linux-s390x-gnu": 4.24.4 + "@rollup/rollup-linux-x64-gnu": 4.24.4 + "@rollup/rollup-linux-x64-musl": 4.24.4 + "@rollup/rollup-win32-arm64-msvc": 4.24.4 + "@rollup/rollup-win32-ia32-msvc": 4.24.4 + "@rollup/rollup-win32-x64-msvc": 4.24.4 + "@types/estree": 1.0.6 + fsevents: ~2.3.2 + dependenciesMeta: + "@rollup/rollup-android-arm-eabi": + optional: true + "@rollup/rollup-android-arm64": + optional: true + "@rollup/rollup-darwin-arm64": + optional: true + "@rollup/rollup-darwin-x64": + optional: true + "@rollup/rollup-freebsd-arm64": + optional: true + "@rollup/rollup-freebsd-x64": + optional: true + "@rollup/rollup-linux-arm-gnueabihf": + optional: true + "@rollup/rollup-linux-arm-musleabihf": + optional: true + "@rollup/rollup-linux-arm64-gnu": + optional: true + "@rollup/rollup-linux-arm64-musl": + optional: true + "@rollup/rollup-linux-powerpc64le-gnu": + optional: true + "@rollup/rollup-linux-riscv64-gnu": + optional: true + "@rollup/rollup-linux-s390x-gnu": + optional: true + "@rollup/rollup-linux-x64-gnu": + optional: true + "@rollup/rollup-linux-x64-musl": + optional: true + "@rollup/rollup-win32-arm64-msvc": + optional: true + "@rollup/rollup-win32-ia32-msvc": + optional: true + "@rollup/rollup-win32-x64-msvc": + optional: true + fsevents: + optional: true + bin: + rollup: dist/bin/rollup + checksum: b1bdf61837180696ba893bbd13f80db44c93ed642e931677d29ebeeae7a4c276dcebf1ad96013eb5c976fcae7473b70c01e5efa1ac6cfbbc24b0bca7911c09c9 + languageName: node + linkType: hard + "run-parallel@npm:^1.1.9": version: 1.2.0 resolution: "run-parallel@npm:1.2.0" @@ -11690,22 +13077,42 @@ __metadata: languageName: node linkType: hard -"satori-html@npm:^0.3.2": - version: 0.3.2 - resolution: "satori-html@npm:0.3.2" +"satori-og@npm:^1.0.0": + version: 1.0.0 + resolution: "satori-og@npm:1.0.0" + dependencies: + "@resvg/resvg-js": ^2.6.2 + satori: ^0.10.14 + checksum: 059ac1337ffee5b1004de4d64d372ea0172884ba615124025e47f092b51a78dc3cc8b4763e812f9e92d9e6974c7c1641d9e3a5ee25ffb02850920df2a1a0575a + languageName: node + linkType: hard + +"satori@npm:^0.10.14": + version: 0.10.14 + resolution: "satori@npm:0.10.14" dependencies: - ultrahtml: ^1.2.0 - checksum: ca39ceb7618325a2edc709582e0e764c821502720760a524843c09bdf518b87c8414d87933d4e6517404524a9836040751b423aaf5e6a355aa6a33469dcebc91 + "@shuding/opentype.js": 1.4.0-beta.0 + css-background-parser: ^0.1.0 + css-box-shadow: 1.0.0-3 + css-to-react-native: ^3.0.0 + emoji-regex: ^10.2.1 + escape-html: ^1.0.3 + linebreak: ^1.1.0 + parse-css-color: ^0.2.1 + postcss-value-parser: ^4.2.0 + yoga-wasm-web: ^0.3.3 + checksum: 3cbfb995e6eba0f934bbac17e043a4ab9c66cd6c8e2202065dcf4a3810d107af6d1a6de27eaca34a3e3fd5d0a642fa7fc12361212e84963833b442de39f2f67a languageName: node linkType: hard -"satori@npm:^0.10.13": - version: 0.10.13 - resolution: "satori@npm:0.10.13" +"satori@npm:^0.11.3": + version: 0.11.3 + resolution: "satori@npm:0.11.3" dependencies: "@shuding/opentype.js": 1.4.0-beta.0 css-background-parser: ^0.1.0 css-box-shadow: 1.0.0-3 + css-gradient-parser: ^0.0.16 css-to-react-native: ^3.0.0 emoji-regex: ^10.2.1 escape-html: ^1.0.3 @@ -11713,7 +13120,7 @@ __metadata: parse-css-color: ^0.2.1 postcss-value-parser: ^4.2.0 yoga-wasm-web: ^0.3.3 - checksum: d44d05eacc1e223353cb7bbfc6b7ab2596f93fc183e80f70583bbe66a0f8e64c01d5ad0d1fc18169f1513d54eb13d2d0f406aa7f21490d9bc1f7924c4d321d4f + checksum: 3b70f20c2a78d0be17c630397c1ac497d13c9a16d6255ae2bd6aadd6404dda585ee309affb23bf89d0178a51d3ecf087a1d1e701af71e250bbb9d9b4664e17d4 languageName: node linkType: hard @@ -11779,6 +13186,15 @@ __metadata: languageName: node linkType: hard +"semver@npm:^7.6.3": + version: 7.6.3 + resolution: "semver@npm:7.6.3" + bin: + semver: bin/semver.js + checksum: 4110ec5d015c9438f322257b1c51fe30276e5f766a3f64c09edd1d7ea7118ecbc3f379f3b69032bacf13116dc7abc4ad8ce0d7e2bd642e26b0d271b56b61a7d8 + languageName: node + linkType: hard + "serialize-javascript@npm:^4.0.0": version: 4.0.0 resolution: "serialize-javascript@npm:4.0.0" @@ -11913,12 +13329,17 @@ __metadata: languageName: node linkType: hard -"shiki@npm:^1.1.7": - version: 1.1.7 - resolution: "shiki@npm:1.1.7" +"shiki@npm:^1.22.0, shiki@npm:^1.22.2": + version: 1.22.2 + resolution: "shiki@npm:1.22.2" dependencies: - "@shikijs/core": 1.1.7 - checksum: 4cf122e594a663cf834027b8a4c36c0ada51886a1cae9e089fd7bd396a6061825e32d63ead8be687214d295561918952e9be48815362b74953acf884a0bb12c5 + "@shikijs/core": 1.22.2 + "@shikijs/engine-javascript": 1.22.2 + "@shikijs/engine-oniguruma": 1.22.2 + "@shikijs/types": 1.22.2 + "@shikijs/vscode-textmate": ^9.3.0 + "@types/hast": ^3.0.4 + checksum: 874448fb5352d4aa558d1646154ec20e72242a7dc50345d2dc1b8d227e1209edcd049033ff15955aab0ee701a8588bbcaed8d1cfc0724cde6aa3407af6881cb5 languageName: node linkType: hard @@ -11942,7 +13363,7 @@ __metadata: languageName: node linkType: hard -"signal-exit@npm:^3.0.2, signal-exit@npm:^3.0.3, signal-exit@npm:^3.0.7": +"signal-exit@npm:^3.0.2, signal-exit@npm:^3.0.7": version: 3.0.7 resolution: "signal-exit@npm:3.0.7" checksum: a2f098f247adc367dffc27845853e9959b9e88b01cb301658cfe4194352d8d2bb32e18467c786a7fe15f1d44b233ea35633d076d5e737870b7139949d1ab6318 @@ -12042,6 +13463,13 @@ __metadata: languageName: node linkType: hard +"source-map-js@npm:^1.2.1": + version: 1.2.1 + resolution: "source-map-js@npm:1.2.1" + checksum: 4eb0cd997cdf228bc253bcaff9340afeb706176e64868ecd20efbe6efea931465f43955612346d6b7318789e5265bdc419bc7669c1cebe3db0eb255f57efa76b + languageName: node + linkType: hard + "source-map-support@npm:~0.5.20": version: 0.5.21 resolution: "source-map-support@npm:0.5.21" @@ -12103,7 +13531,7 @@ __metadata: languageName: node linkType: hard -"stdin-discarder@npm:^0.2.1": +"stdin-discarder@npm:^0.2.1, stdin-discarder@npm:^0.2.2": version: 0.2.2 resolution: "stdin-discarder@npm:0.2.2" checksum: 642ffd05bd5b100819d6b24a613d83c6e3857c6de74eb02fc51506fa61dc1b0034665163831873868157c4538d71e31762bcf319be86cea04c3aba5336470478 @@ -12150,6 +13578,17 @@ __metadata: languageName: node linkType: hard +"string-width@npm:^7.2.0": + version: 7.2.0 + resolution: "string-width@npm:7.2.0" + dependencies: + emoji-regex: ^10.3.0 + get-east-asian-width: ^1.0.0 + strip-ansi: ^7.1.0 + checksum: 42f9e82f61314904a81393f6ef75b832c39f39761797250de68c041d8ba4df2ef80db49ab6cd3a292923a6f0f409b8c9980d120f7d32c820b4a8a84a2598a295 + languageName: node + linkType: hard + "string.prototype.codepointat@npm:^0.2.1": version: 0.2.1 resolution: "string.prototype.codepointat@npm:0.2.1" @@ -12275,13 +13714,6 @@ __metadata: languageName: node linkType: hard -"strip-final-newline@npm:^2.0.0": - version: 2.0.0 - resolution: "strip-final-newline@npm:2.0.0" - checksum: 69412b5e25731e1938184b5d489c32e340605bb611d6140344abc3421b7f3c6f9984b21dff296dfcf056681b82caa3bb4cc996a965ce37bcfad663e92eae9c64 - languageName: node - linkType: hard - "strip-final-newline@npm:^3.0.0": version: 3.0.0 resolution: "strip-final-newline@npm:3.0.0" @@ -12389,23 +13821,7 @@ __metadata: languageName: node linkType: hard -"svgo@npm:3.0.3": - version: 3.0.3 - resolution: "svgo@npm:3.0.3" - dependencies: - "@trysound/sax": 0.2.0 - commander: ^7.2.0 - css-select: ^5.1.0 - css-tree: ^2.2.1 - csso: 5.0.5 - picocolors: ^1.0.0 - bin: - svgo: ./bin/svgo - checksum: 0e34c70b9ff429e6c6773a0607063c2893fa655fffe3d0c2ea236764e54f77c6eb0cfc510a05ae11f589e343b59aef5ad210022aa49cd81eb6ad16446e2e0388 - languageName: node - linkType: hard - -"svgo@npm:3.3.2": +"svgo@npm:3.3.2, svgo@npm:^3.3.2": version: 3.3.2 resolution: "svgo@npm:3.3.2" dependencies: @@ -12455,7 +13871,7 @@ __metadata: languageName: node linkType: hard -"tar@npm:^6.1.11, tar@npm:^6.1.2, tar@npm:^6.2.0": +"tar@npm:^6.1.11, tar@npm:^6.1.2": version: 6.2.0 resolution: "tar@npm:6.2.0" dependencies: @@ -12469,9 +13885,23 @@ __metadata: languageName: node linkType: hard -"terser@npm:5.31.1": - version: 5.31.1 - resolution: "terser@npm:5.31.1" +"tar@npm:^6.2.1": + version: 6.2.1 + resolution: "tar@npm:6.2.1" + dependencies: + chownr: ^2.0.0 + fs-minipass: ^2.0.0 + minipass: ^5.0.0 + minizlib: ^2.1.1 + mkdirp: ^1.0.3 + yallist: ^4.0.0 + checksum: f1322768c9741a25356c11373bce918483f40fa9a25c69c59410c8a1247632487edef5fe76c5f12ac51a6356d2f1829e96d2bc34098668a2fc34d76050ac2b6c + languageName: node + linkType: hard + +"terser@npm:5.36.0": + version: 5.36.0 + resolution: "terser@npm:5.36.0" dependencies: "@jridgewell/source-map": ^0.3.3 acorn: ^8.8.2 @@ -12479,7 +13909,7 @@ __metadata: source-map-support: ~0.5.20 bin: terser: bin/terser - checksum: 6ab57e62e9cd690dc99b3d0ee2e07289cd3408109a950c7118bf39e32851a5bf08b67fe19e0ac43a5a98813792ac78101bf25e5aa524f05ae8bb4e0131d0feef + checksum: 489afd31901a2b170f7766948a3aa0e25da0acb41e9e35bd9f9b4751dfa2fc846e485f6fb9d34f0839a96af77f675b5fbf0a20c9aa54e0b8d7c219cf0b55e508 languageName: node linkType: hard @@ -12528,6 +13958,13 @@ __metadata: languageName: node linkType: hard +"tinyexec@npm:^0.3.0, tinyexec@npm:^0.3.1": + version: 0.3.1 + resolution: "tinyexec@npm:0.3.1" + checksum: 691b531d464bdc09eeba934e43d8ac2a74c9d22a4bec9cd7f4991375c64e22712f7e5a95ba243a9369a478afd34d41171359012a2248ea49615cd2816ab12959 + languageName: node + linkType: hard + "to-fast-properties@npm:^2.0.0": version: 2.0.0 resolution: "to-fast-properties@npm:2.0.0" @@ -12581,6 +14018,20 @@ __metadata: languageName: node linkType: hard +"tsconfck@npm:^3.1.4": + version: 3.1.4 + resolution: "tsconfck@npm:3.1.4" + peerDependencies: + typescript: ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true + bin: + tsconfck: bin/tsconfck.js + checksum: 007b92ca65e95c3511cf52d78020fedb322b98862474507d129d14f28eaf43f2d9ff6337da643ba6fd67a2041884f81191d1e384006c579fd4cac6597063cf1b + languageName: node + linkType: hard + "tslib@npm:^2.0.3": version: 2.6.1 resolution: "tslib@npm:2.6.1" @@ -12618,6 +14069,13 @@ __metadata: languageName: node linkType: hard +"type-fest@npm:^4.21.0": + version: 4.26.1 + resolution: "type-fest@npm:4.26.1" + checksum: 7188db3bca82afa62c69a8043fb7c5eb74e63c45e7e28efb986da1629d844286f7181bc5a8185f38989fffff0d6c96be66fd13529b01932d1b6ebe725181d31a + languageName: node + linkType: hard + "typed-array-buffer@npm:^1.0.0": version: 1.0.0 resolution: "typed-array-buffer@npm:1.0.0" @@ -12682,13 +14140,13 @@ __metadata: languageName: node linkType: hard -"typescript@npm:^5.4.5": - version: 5.4.5 - resolution: "typescript@npm:5.4.5" +"typescript@npm:^5.6.3": + version: 5.6.3 + resolution: "typescript@npm:5.6.3" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: 53c879c6fa1e3bcb194b274d4501ba1985894b2c2692fa079db03c5a5a7140587a1e04e1ba03184605d35f439b40192d9e138eb3279ca8eee313c081c8bcd9b0 + checksum: ba302f8822777ebefb28b554105f3e074466b671e7444ec6b75dadc008a62f46f373d9e57ceced1c433756d06c8b7dc569a7eefdf3a9573122a49205ff99021a languageName: node linkType: hard @@ -12702,13 +14160,13 @@ __metadata: languageName: node linkType: hard -"typescript@patch:typescript@^5.4.5#~builtin<compat/typescript>": - version: 5.4.5 - resolution: "typescript@patch:typescript@npm%3A5.4.5#~builtin<compat/typescript>::version=5.4.5&hash=29ae49" +"typescript@patch:typescript@^5.6.3#~builtin<compat/typescript>": + version: 5.6.3 + resolution: "typescript@patch:typescript@npm%3A5.6.3#~builtin<compat/typescript>::version=5.6.3&hash=29ae49" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: 2373c693f3b328f3b2387c3efafe6d257b057a142f9a79291854b14ff4d5367d3d730810aee981726b677ae0fd8329b23309da3b6aaab8263dbdccf1da07a3ba + checksum: ade87bce2363ee963eed0e4ca8a312ea02c81873ebd53609bc3f6dc0a57f6e61ad7e3fb8cbb7f7ab8b5081cbee801b023f7c4823ee70b1c447eae050e6c7622b languageName: node linkType: hard @@ -12719,7 +14177,14 @@ __metadata: languageName: node linkType: hard -"ultrahtml@npm:^1.2.0, ultrahtml@npm:^1.3.0": +"ufo@npm:^1.5.4": + version: 1.5.4 + resolution: "ufo@npm:1.5.4" + checksum: f244703b7d4f9f0df4f9af23921241ab73410b591f4e5b39c23e3147f3159b139a4b1fb5903189c306129f7a16b55995dac0008e0fbae88a37c3e58cbc34d833 + languageName: node + linkType: hard + +"ultrahtml@npm:^1.3.0": version: 1.5.2 resolution: "ultrahtml@npm:1.5.2" checksum: f3df055d684a9ef4b62765faa1973b93fa0d45cc0cb3b642bf3c60d5bda1ad34b6fedfb686dad4c21c9109d799e1da9f50f31170b9b92330409530c3162e31f3 @@ -12738,10 +14203,10 @@ __metadata: languageName: node linkType: hard -"undici-types@npm:~5.26.4": - version: 5.26.5 - resolution: "undici-types@npm:5.26.5" - checksum: 3192ef6f3fd5df652f2dc1cd782b49d6ff14dc98e5dced492aa8a8c65425227da5da6aafe22523c67f035a272c599bb89cfe803c1db6311e44bed3042fc25487 +"undici-types@npm:~6.19.2": + version: 6.19.8 + resolution: "undici-types@npm:6.19.8" + checksum: de51f1b447d22571cf155dfe14ff6d12c5bdaec237c765085b439c38ca8518fc360e88c70f99469162bf2e14188a7b0bcb06e1ed2dc031042b984b0bb9544017 languageName: node linkType: hard @@ -12754,6 +14219,13 @@ __metadata: languageName: node linkType: hard +"undici@npm:^6.19.5": + version: 6.20.1 + resolution: "undici@npm:6.20.1" + checksum: 3bb1405b406fa0e913ff4ec6fd310c9b4d950b7064ba5949b2f616c1f13070d26f5558aefb4b56b2eafb555925443ce44cb801e143d2417ecf12ddf8d5c05cf6 + languageName: node + linkType: hard + "unherit@npm:^3.0.0": version: 3.0.0 resolution: "unherit@npm:3.0.0" @@ -12847,6 +14319,21 @@ __metadata: languageName: node linkType: hard +"unified@npm:^11.0.5": + version: 11.0.5 + resolution: "unified@npm:11.0.5" + dependencies: + "@types/unist": ^3.0.0 + bail: ^2.0.0 + devlop: ^1.0.0 + extend: ^3.0.0 + is-plain-obj: ^4.0.0 + trough: ^2.0.0 + vfile: ^6.0.0 + checksum: b3bf7fd6f568cc261e074dae21188483b0f2a8ab858d62e6e85b75b96cc655f59532906ae3c64d56a9b257408722d71f1d4135292b3d7ee02907c8b592fb3cf0 + languageName: node + linkType: hard + "unique-filename@npm:^3.0.0": version: 3.0.0 resolution: "unique-filename@npm:3.0.0" @@ -12907,6 +14394,16 @@ __metadata: languageName: node linkType: hard +"unist-util-modify-children@npm:^4.0.0": + version: 4.0.0 + resolution: "unist-util-modify-children@npm:4.0.0" + dependencies: + "@types/unist": ^3.0.0 + array-iterate: ^2.0.0 + checksum: 4cb8a7d9365e6726df82a444d556177e99f582c32c1f5223b96f31b477502b53365ec5231fdab355d77ba21cd90822e594ba030b3ba06ea0786842d409d28fd3 + languageName: node + linkType: hard + "unist-util-position@npm:^4.0.0": version: 4.0.3 resolution: "unist-util-position@npm:4.0.3" @@ -12960,6 +14457,15 @@ __metadata: languageName: node linkType: hard +"unist-util-visit-children@npm:^3.0.0": + version: 3.0.0 + resolution: "unist-util-visit-children@npm:3.0.0" + dependencies: + "@types/unist": ^3.0.0 + checksum: a900485e2778e053b6bb674437db67cc1b2dcdb21bb69dca9fac49edf6b2662ec04c6871c6cd40b623700421ac1bbc9d1265ca2cc8a91ba56f57b0da5ac3b2c9 + languageName: node + linkType: hard + "unist-util-visit-parents@npm:^3.0.0": version: 3.1.1 resolution: "unist-util-visit-parents@npm:3.1.1" @@ -13058,6 +14564,20 @@ __metadata: languageName: node linkType: hard +"update-browserslist-db@npm:^1.1.1": + version: 1.1.1 + resolution: "update-browserslist-db@npm:1.1.1" + dependencies: + escalade: ^3.2.0 + picocolors: ^1.1.0 + peerDependencies: + browserslist: ">= 4.21.0" + bin: + update-browserslist-db: cli.js + checksum: 2ea11bd2562122162c3e438d83a1f9125238c0844b6d16d366e3276d0c0acac6036822dc7df65fc5a89c699cdf9f174acf439c39bedf3f9a2f3983976e4b4c3e + languageName: node + linkType: hard + "uri-js@npm:^4.2.2": version: 4.4.1 resolution: "uri-js@npm:4.4.1" @@ -13153,6 +14673,16 @@ __metadata: languageName: node linkType: hard +"vfile@npm:^6.0.3": + version: 6.0.3 + resolution: "vfile@npm:6.0.3" + dependencies: + "@types/unist": ^3.0.0 + vfile-message: ^4.0.0 + checksum: 152b6729be1af70df723efb65c1a1170fd483d41086557da3651eea69a1dd1f0c22ea4344834d56d30734b9185bcab63e22edc81d3f0e9bed8aa4660d61080af + languageName: node + linkType: hard + "vite@npm:^5.2.12": version: 5.2.13 resolution: "vite@npm:5.2.13" @@ -13193,6 +14723,49 @@ __metadata: languageName: node linkType: hard +"vite@npm:^5.4.10": + version: 5.4.10 + resolution: "vite@npm:5.4.10" + dependencies: + esbuild: ^0.21.3 + fsevents: ~2.3.3 + postcss: ^8.4.43 + rollup: ^4.20.0 + peerDependencies: + "@types/node": ^18.0.0 || >=20.0.0 + less: "*" + lightningcss: ^1.21.0 + sass: "*" + sass-embedded: "*" + stylus: "*" + sugarss: "*" + terser: ^5.4.0 + dependenciesMeta: + fsevents: + optional: true + peerDependenciesMeta: + "@types/node": + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + bin: + vite: bin/vite.js + checksum: 4db3b8ca3eddbc312d0a95f505d16656e74c6dfa68d3b5eb54b6d6b0f7be1df348d469c43dc69db27dadc06b802f029d654da48f392324efd665ef2c0ca9ba9e + languageName: node + linkType: hard + "vitefu@npm:^0.2.5": version: 0.2.5 resolution: "vitefu@npm:0.2.5" @@ -13205,6 +14778,18 @@ __metadata: languageName: node linkType: hard +"vitefu@npm:^1.0.3": + version: 1.0.3 + resolution: "vitefu@npm:1.0.3" + peerDependencies: + vite: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0-beta.0 + peerDependenciesMeta: + vite: + optional: true + checksum: 06f871a80c1d25573c197392b15dfeb6aab62cc61fbb2ed84f473df966385e65f6c6238b1dd43cf1b1a04b5edc0c59dc26a03226ca1811f8bd51c08caadf8a07 + languageName: node + linkType: hard + "web-namespaces@npm:^2.0.0": version: 2.0.1 resolution: "web-namespaces@npm:2.0.1" @@ -13212,6 +14797,22 @@ __metadata: languageName: node linkType: hard +"whatwg-encoding@npm:^3.1.1": + version: 3.1.1 + resolution: "whatwg-encoding@npm:3.1.1" + dependencies: + iconv-lite: 0.6.3 + checksum: f75a61422421d991e4aec775645705beaf99a16a88294d68404866f65e92441698a4f5b9fa11dd609017b132d7b286c3c1534e2de5b3e800333856325b549e3c + languageName: node + linkType: hard + +"whatwg-mimetype@npm:^4.0.0": + version: 4.0.0 + resolution: "whatwg-mimetype@npm:4.0.0" + checksum: f97edd4b4ee7e46a379f3fb0e745de29fe8b839307cc774300fd49059fcdd560d38cb8fe21eae5575b8f39b022f23477cc66e40b0355c2851ce84760339cef30 + languageName: node + linkType: hard + "which-boxed-primitive@npm:^1.0.2": version: 1.0.2 resolution: "which-boxed-primitive@npm:1.0.2" @@ -13252,6 +14853,15 @@ __metadata: languageName: node linkType: hard +"which-pm@npm:^3.0.0": + version: 3.0.0 + resolution: "which-pm@npm:3.0.0" + dependencies: + load-yaml-file: ^0.2.0 + checksum: bc0bc08a2a07af8bb3b759bc82fa5f712332261726412112f87b26d4e73e5e76f1bd6d462ef7f27ba06b7f8172ce5f08b12d44e2b27caa01d555231471849961 + languageName: node + linkType: hard + "which-typed-array@npm:^1.1.10, which-typed-array@npm:^1.1.11": version: 1.1.11 resolution: "which-typed-array@npm:1.1.11" @@ -13294,6 +14904,15 @@ __metadata: languageName: node linkType: hard +"widest-line@npm:^5.0.0": + version: 5.0.0 + resolution: "widest-line@npm:5.0.0" + dependencies: + string-width: ^7.0.0 + checksum: 07f6527b961b88d40ac250596c06fada00cbe049080c6cc8ef4d7bc4f4ab03d7eb1a1c2e5585dd0d8b6ec99ba6f168d5b236edd8ba9221aeb8d914451f0235f9 + languageName: node + linkType: hard + "wrap-ansi-cjs@npm:wrap-ansi@^7.0.0, wrap-ansi@npm:^7.0.0": version: 7.0.0 resolution: "wrap-ansi@npm:7.0.0" @@ -13316,6 +14935,17 @@ __metadata: languageName: node linkType: hard +"wrap-ansi@npm:^9.0.0": + version: 9.0.0 + resolution: "wrap-ansi@npm:9.0.0" + dependencies: + ansi-styles: ^6.2.1 + string-width: ^7.0.0 + strip-ansi: ^7.1.0 + checksum: b2d43b76b3d8dcbdd64768165e548aad3e54e1cae4ecd31bac9966faaa7cf0b0345677ad6879db10ba58eb446ba8fa44fb82b4951872fd397f096712467a809f + languageName: node + linkType: hard + "wrappy@npm:1": version: 1.0.2 resolution: "wrappy@npm:1.0.2" @@ -13323,6 +14953,13 @@ __metadata: languageName: node linkType: hard +"xxhash-wasm@npm:^1.0.2": + version: 1.0.2 + resolution: "xxhash-wasm@npm:1.0.2" + checksum: 11fec6e6196e37ad96cc958b7a4477dc30caf5b4da889a02a84f6f663ab8cd3c9be6ae405e66f0af0404301f27c39375191c5254f0409a793020e2093afd1409 + languageName: node + linkType: hard + "y18n@npm:^5.0.5": version: 5.0.8 resolution: "y18n@npm:5.0.8" @@ -13404,6 +15041,13 @@ __metadata: languageName: node linkType: hard +"yocto-queue@npm:^1.1.1": + version: 1.1.1 + resolution: "yocto-queue@npm:1.1.1" + checksum: f2e05b767ed3141e6372a80af9caa4715d60969227f38b1a4370d60bffe153c9c5b33a862905609afc9b375ec57cd40999810d20e5e10229a204e8bde7ef255c + languageName: node + linkType: hard + "yoga-wasm-web@npm:^0.3.3": version: 0.3.3 resolution: "yoga-wasm-web@npm:0.3.3" @@ -13420,6 +15064,25 @@ __metadata: languageName: node linkType: hard +"zod-to-json-schema@npm:^3.23.5": + version: 3.23.5 + resolution: "zod-to-json-schema@npm:3.23.5" + peerDependencies: + zod: ^3.23.3 + checksum: 3ac37128d1b989b027e55684201e1da90237f0955dc9bb40da013bc60f2ed23c57026df2fdc14da187be4d53873daad08210807c28c0dde4375c9df0e5fe7901 + languageName: node + linkType: hard + +"zod-to-ts@npm:^1.2.0": + version: 1.2.0 + resolution: "zod-to-ts@npm:1.2.0" + peerDependencies: + typescript: ^4.9.4 || ^5.0.2 + zod: ^3 + checksum: 0dee72ec8cf25a24fed047dcb2dcd41b86a07684836c6bc6e2b2e6140bab0f306fc7390e09161c68a2bd702cd8a57bd5ac013969fff75fa3c0439a6de1413424 + languageName: node + linkType: hard + "zod@npm:^3.22.2": version: 3.22.2 resolution: "zod@npm:3.22.2"