Merge pull request #3 from MethodBlack/feature/redesign
Feature/redesign
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -6,6 +6,7 @@ dist/
|
||||
|
||||
# dependencies
|
||||
node_modules/
|
||||
.netlify
|
||||
|
||||
# logs
|
||||
npm-debug.log*
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
const onRequest = undefined;
|
||||
|
||||
export { onRequest };
|
||||
@@ -1,401 +0,0 @@
|
||||
import { isRemotePath, joinPaths } from '@astrojs/internal-helpers/path';
|
||||
import { A as AstroError, E as ExpectedImage, L as LocalImageUsedWrongly, M as MissingImageDimension, U as UnsupportedImageFormat, I as IncompatibleDescriptorOptions, a as UnsupportedImageConversion, b as InvalidImageService, c as ExpectedImageOptions, d as MissingSharp } from '../astro_0a673d7a.mjs';
|
||||
|
||||
const VALID_SUPPORTED_FORMATS = [
|
||||
"jpeg",
|
||||
"jpg",
|
||||
"png",
|
||||
"tiff",
|
||||
"webp",
|
||||
"gif",
|
||||
"svg",
|
||||
"avif"
|
||||
];
|
||||
const DEFAULT_OUTPUT_FORMAT = "webp";
|
||||
const DEFAULT_HASH_PROPS = ["src", "width", "height", "format", "quality"];
|
||||
|
||||
function isLocalService(service) {
|
||||
if (!service) {
|
||||
return false;
|
||||
}
|
||||
return "transform" in service;
|
||||
}
|
||||
function parseQuality(quality) {
|
||||
let result = parseInt(quality);
|
||||
if (Number.isNaN(result)) {
|
||||
return quality;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
const baseService = {
|
||||
propertiesToHash: DEFAULT_HASH_PROPS,
|
||||
validateOptions(options) {
|
||||
if (!options.src || typeof options.src !== "string" && typeof options.src !== "object") {
|
||||
throw new AstroError({
|
||||
...ExpectedImage,
|
||||
message: ExpectedImage.message(
|
||||
JSON.stringify(options.src),
|
||||
typeof options.src,
|
||||
JSON.stringify(options, (_, v) => v === void 0 ? null : v)
|
||||
)
|
||||
});
|
||||
}
|
||||
if (!isESMImportedImage(options.src)) {
|
||||
if (options.src.startsWith("/@fs/") || !isRemotePath(options.src) && !options.src.startsWith("/")) {
|
||||
throw new AstroError({
|
||||
...LocalImageUsedWrongly,
|
||||
message: LocalImageUsedWrongly.message(options.src)
|
||||
});
|
||||
}
|
||||
let missingDimension;
|
||||
if (!options.width && !options.height) {
|
||||
missingDimension = "both";
|
||||
} else if (!options.width && options.height) {
|
||||
missingDimension = "width";
|
||||
} else if (options.width && !options.height) {
|
||||
missingDimension = "height";
|
||||
}
|
||||
if (missingDimension) {
|
||||
throw new AstroError({
|
||||
...MissingImageDimension,
|
||||
message: MissingImageDimension.message(missingDimension, options.src)
|
||||
});
|
||||
}
|
||||
} else {
|
||||
if (!VALID_SUPPORTED_FORMATS.includes(options.src.format)) {
|
||||
throw new AstroError({
|
||||
...UnsupportedImageFormat,
|
||||
message: UnsupportedImageFormat.message(
|
||||
options.src.format,
|
||||
options.src.src,
|
||||
VALID_SUPPORTED_FORMATS
|
||||
)
|
||||
});
|
||||
}
|
||||
if (options.widths && options.densities) {
|
||||
throw new AstroError(IncompatibleDescriptorOptions);
|
||||
}
|
||||
if (options.src.format === "svg") {
|
||||
options.format = "svg";
|
||||
}
|
||||
if (options.src.format === "svg" && options.format !== "svg" || options.src.format !== "svg" && options.format === "svg") {
|
||||
throw new AstroError(UnsupportedImageConversion);
|
||||
}
|
||||
}
|
||||
if (!options.format) {
|
||||
options.format = DEFAULT_OUTPUT_FORMAT;
|
||||
}
|
||||
if (options.width)
|
||||
options.width = Math.round(options.width);
|
||||
if (options.height)
|
||||
options.height = Math.round(options.height);
|
||||
return options;
|
||||
},
|
||||
getHTMLAttributes(options) {
|
||||
const { targetWidth, targetHeight } = getTargetDimensions(options);
|
||||
const { src, width, height, format, quality, densities, widths, formats, ...attributes } = options;
|
||||
return {
|
||||
...attributes,
|
||||
width: targetWidth,
|
||||
height: targetHeight,
|
||||
loading: attributes.loading ?? "lazy",
|
||||
decoding: attributes.decoding ?? "async"
|
||||
};
|
||||
},
|
||||
getSrcSet(options) {
|
||||
const srcSet = [];
|
||||
const { targetWidth } = getTargetDimensions(options);
|
||||
const { widths, densities } = options;
|
||||
const targetFormat = options.format ?? DEFAULT_OUTPUT_FORMAT;
|
||||
let imageWidth = options.width;
|
||||
let maxWidth = Infinity;
|
||||
if (isESMImportedImage(options.src)) {
|
||||
imageWidth = options.src.width;
|
||||
maxWidth = imageWidth;
|
||||
}
|
||||
const {
|
||||
width: transformWidth,
|
||||
height: transformHeight,
|
||||
...transformWithoutDimensions
|
||||
} = options;
|
||||
const allWidths = [];
|
||||
if (densities) {
|
||||
const densityValues = densities.map((density) => {
|
||||
if (typeof density === "number") {
|
||||
return density;
|
||||
} else {
|
||||
return parseFloat(density);
|
||||
}
|
||||
});
|
||||
const densityWidths = densityValues.sort().map((density) => Math.round(targetWidth * density));
|
||||
allWidths.push(
|
||||
...densityWidths.map((width, index) => ({
|
||||
maxTargetWidth: Math.min(width, maxWidth),
|
||||
descriptor: `${densityValues[index]}x`
|
||||
}))
|
||||
);
|
||||
} else if (widths) {
|
||||
allWidths.push(
|
||||
...widths.map((width) => ({
|
||||
maxTargetWidth: Math.min(width, maxWidth),
|
||||
descriptor: `${width}w`
|
||||
}))
|
||||
);
|
||||
}
|
||||
for (const { maxTargetWidth, descriptor } of allWidths) {
|
||||
const srcSetTransform = { ...transformWithoutDimensions };
|
||||
if (maxTargetWidth !== imageWidth) {
|
||||
srcSetTransform.width = maxTargetWidth;
|
||||
} else {
|
||||
if (options.width && options.height) {
|
||||
srcSetTransform.width = options.width;
|
||||
srcSetTransform.height = options.height;
|
||||
}
|
||||
}
|
||||
srcSet.push({
|
||||
transform: srcSetTransform,
|
||||
descriptor,
|
||||
attributes: {
|
||||
type: `image/${targetFormat}`
|
||||
}
|
||||
});
|
||||
}
|
||||
return srcSet;
|
||||
},
|
||||
getURL(options, imageConfig) {
|
||||
const searchParams = new URLSearchParams();
|
||||
if (isESMImportedImage(options.src)) {
|
||||
searchParams.append("href", options.src.src);
|
||||
} else if (isRemoteAllowed(options.src, imageConfig)) {
|
||||
searchParams.append("href", options.src);
|
||||
} else {
|
||||
return options.src;
|
||||
}
|
||||
const params = {
|
||||
w: "width",
|
||||
h: "height",
|
||||
q: "quality",
|
||||
f: "format"
|
||||
};
|
||||
Object.entries(params).forEach(([param, key]) => {
|
||||
options[key] && searchParams.append(param, options[key].toString());
|
||||
});
|
||||
const imageEndpoint = joinPaths("/", "/_image");
|
||||
return `${imageEndpoint}?${searchParams}`;
|
||||
},
|
||||
parseURL(url) {
|
||||
const params = url.searchParams;
|
||||
if (!params.has("href")) {
|
||||
return void 0;
|
||||
}
|
||||
const transform = {
|
||||
src: params.get("href"),
|
||||
width: params.has("w") ? parseInt(params.get("w")) : void 0,
|
||||
height: params.has("h") ? parseInt(params.get("h")) : void 0,
|
||||
format: params.get("f"),
|
||||
quality: params.get("q")
|
||||
};
|
||||
return transform;
|
||||
}
|
||||
};
|
||||
function getTargetDimensions(options) {
|
||||
let targetWidth = options.width;
|
||||
let targetHeight = options.height;
|
||||
if (isESMImportedImage(options.src)) {
|
||||
const aspectRatio = options.src.width / options.src.height;
|
||||
if (targetHeight && !targetWidth) {
|
||||
targetWidth = Math.round(targetHeight * aspectRatio);
|
||||
} else if (targetWidth && !targetHeight) {
|
||||
targetHeight = Math.round(targetWidth / aspectRatio);
|
||||
} else if (!targetWidth && !targetHeight) {
|
||||
targetWidth = options.src.width;
|
||||
targetHeight = options.src.height;
|
||||
}
|
||||
}
|
||||
return {
|
||||
targetWidth,
|
||||
targetHeight
|
||||
};
|
||||
}
|
||||
|
||||
function matchPattern(url, remotePattern) {
|
||||
return matchProtocol(url, remotePattern.protocol) && matchHostname(url, remotePattern.hostname, true) && matchPort(url, remotePattern.port) && matchPathname(url, remotePattern.pathname, true);
|
||||
}
|
||||
function matchPort(url, port) {
|
||||
return !port || port === url.port;
|
||||
}
|
||||
function matchProtocol(url, protocol) {
|
||||
return !protocol || protocol === url.protocol.slice(0, -1);
|
||||
}
|
||||
function matchHostname(url, hostname, allowWildcard) {
|
||||
if (!hostname) {
|
||||
return true;
|
||||
} else if (!allowWildcard || !hostname.startsWith("*")) {
|
||||
return hostname === url.hostname;
|
||||
} else if (hostname.startsWith("**.")) {
|
||||
const slicedHostname = hostname.slice(2);
|
||||
return slicedHostname !== url.hostname && url.hostname.endsWith(slicedHostname);
|
||||
} else if (hostname.startsWith("*.")) {
|
||||
const slicedHostname = hostname.slice(1);
|
||||
const additionalSubdomains = url.hostname.replace(slicedHostname, "").split(".").filter(Boolean);
|
||||
return additionalSubdomains.length === 1;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function matchPathname(url, pathname, allowWildcard) {
|
||||
if (!pathname) {
|
||||
return true;
|
||||
} else if (!allowWildcard || !pathname.endsWith("*")) {
|
||||
return pathname === url.pathname;
|
||||
} else if (pathname.endsWith("/**")) {
|
||||
const slicedPathname = pathname.slice(0, -2);
|
||||
return slicedPathname !== url.pathname && url.pathname.startsWith(slicedPathname);
|
||||
} else if (pathname.endsWith("/*")) {
|
||||
const slicedPathname = pathname.slice(0, -1);
|
||||
const additionalPathChunks = url.pathname.replace(slicedPathname, "").split("/").filter(Boolean);
|
||||
return additionalPathChunks.length === 1;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function isESMImportedImage(src) {
|
||||
return typeof src === "object";
|
||||
}
|
||||
function isRemoteImage(src) {
|
||||
return typeof src === "string";
|
||||
}
|
||||
function isRemoteAllowed(src, {
|
||||
domains = [],
|
||||
remotePatterns = []
|
||||
}) {
|
||||
if (!isRemotePath(src))
|
||||
return false;
|
||||
const url = new URL(src);
|
||||
return domains.some((domain) => matchHostname(url, domain)) || remotePatterns.some((remotePattern) => matchPattern(url, remotePattern));
|
||||
}
|
||||
async function getConfiguredImageService() {
|
||||
if (!globalThis?.astroAsset?.imageService) {
|
||||
const { default: service } = await Promise.resolve().then(() => sharp$1).catch((e) => {
|
||||
const error = new AstroError(InvalidImageService);
|
||||
error.cause = e;
|
||||
throw error;
|
||||
});
|
||||
if (!globalThis.astroAsset)
|
||||
globalThis.astroAsset = {};
|
||||
globalThis.astroAsset.imageService = service;
|
||||
return service;
|
||||
}
|
||||
return globalThis.astroAsset.imageService;
|
||||
}
|
||||
async function getImage(options, imageConfig) {
|
||||
if (!options || typeof options !== "object") {
|
||||
throw new AstroError({
|
||||
...ExpectedImageOptions,
|
||||
message: ExpectedImageOptions.message(JSON.stringify(options))
|
||||
});
|
||||
}
|
||||
const service = await getConfiguredImageService();
|
||||
const resolvedOptions = {
|
||||
...options,
|
||||
src: typeof options.src === "object" && "then" in options.src ? (await options.src).default ?? await options.src : options.src
|
||||
};
|
||||
const clonedSrc = isESMImportedImage(resolvedOptions.src) ? (
|
||||
// @ts-expect-error - clone is a private, hidden prop
|
||||
resolvedOptions.src.clone ?? resolvedOptions.src
|
||||
) : resolvedOptions.src;
|
||||
resolvedOptions.src = clonedSrc;
|
||||
const validatedOptions = service.validateOptions ? await service.validateOptions(resolvedOptions, imageConfig) : resolvedOptions;
|
||||
const srcSetTransforms = service.getSrcSet ? await service.getSrcSet(validatedOptions, imageConfig) : [];
|
||||
let imageURL = await service.getURL(validatedOptions, imageConfig);
|
||||
let srcSets = await Promise.all(
|
||||
srcSetTransforms.map(async (srcSet) => ({
|
||||
transform: srcSet.transform,
|
||||
url: await service.getURL(srcSet.transform, imageConfig),
|
||||
descriptor: srcSet.descriptor,
|
||||
attributes: srcSet.attributes
|
||||
}))
|
||||
);
|
||||
if (isLocalService(service) && globalThis.astroAsset.addStaticImage && !(isRemoteImage(validatedOptions.src) && imageURL === validatedOptions.src)) {
|
||||
const propsToHash = service.propertiesToHash ?? DEFAULT_HASH_PROPS;
|
||||
imageURL = globalThis.astroAsset.addStaticImage(validatedOptions, propsToHash);
|
||||
srcSets = srcSetTransforms.map((srcSet) => ({
|
||||
transform: srcSet.transform,
|
||||
url: globalThis.astroAsset.addStaticImage(srcSet.transform, propsToHash),
|
||||
descriptor: srcSet.descriptor,
|
||||
attributes: srcSet.attributes
|
||||
}));
|
||||
}
|
||||
return {
|
||||
rawOptions: resolvedOptions,
|
||||
options: validatedOptions,
|
||||
src: imageURL,
|
||||
srcSet: {
|
||||
values: srcSets,
|
||||
attribute: srcSets.map((srcSet) => `${srcSet.url} ${srcSet.descriptor}`).join(", ")
|
||||
},
|
||||
attributes: service.getHTMLAttributes !== void 0 ? await service.getHTMLAttributes(validatedOptions, imageConfig) : {}
|
||||
};
|
||||
}
|
||||
|
||||
let sharp;
|
||||
const qualityTable = {
|
||||
low: 25,
|
||||
mid: 50,
|
||||
high: 80,
|
||||
max: 100
|
||||
};
|
||||
async function loadSharp() {
|
||||
let sharpImport;
|
||||
try {
|
||||
sharpImport = (await import('sharp')).default;
|
||||
} catch (e) {
|
||||
throw new AstroError(MissingSharp);
|
||||
}
|
||||
return sharpImport;
|
||||
}
|
||||
const sharpService = {
|
||||
validateOptions: baseService.validateOptions,
|
||||
getURL: baseService.getURL,
|
||||
parseURL: baseService.parseURL,
|
||||
getHTMLAttributes: baseService.getHTMLAttributes,
|
||||
getSrcSet: baseService.getSrcSet,
|
||||
async transform(inputBuffer, transformOptions) {
|
||||
if (!sharp)
|
||||
sharp = await loadSharp();
|
||||
const transform = transformOptions;
|
||||
if (transform.format === "svg")
|
||||
return { data: inputBuffer, format: "svg" };
|
||||
let result = sharp(inputBuffer, { failOnError: false, pages: -1 });
|
||||
result.rotate();
|
||||
if (transform.height && !transform.width) {
|
||||
result.resize({ height: Math.round(transform.height) });
|
||||
} else if (transform.width) {
|
||||
result.resize({ width: Math.round(transform.width) });
|
||||
}
|
||||
if (transform.format) {
|
||||
let quality = void 0;
|
||||
if (transform.quality) {
|
||||
const parsedQuality = parseQuality(transform.quality);
|
||||
if (typeof parsedQuality === "number") {
|
||||
quality = parsedQuality;
|
||||
} else {
|
||||
quality = transform.quality in qualityTable ? qualityTable[transform.quality] : void 0;
|
||||
}
|
||||
}
|
||||
result.toFormat(transform.format, { quality });
|
||||
}
|
||||
const { data, info } = await result.toBuffer({ resolveWithObject: true });
|
||||
return {
|
||||
data,
|
||||
format: info.format
|
||||
};
|
||||
}
|
||||
};
|
||||
var sharp_default = sharpService;
|
||||
|
||||
const sharp$1 = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
|
||||
__proto__: null,
|
||||
default: sharp_default
|
||||
}, Symbol.toStringTag, { value: 'Module' }));
|
||||
|
||||
export { getConfiguredImageService as a, isRemoteAllowed as b, getImage as g, isESMImportedImage as i };
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,6 +0,0 @@
|
||||
export { renderers } from '../renderers.mjs';
|
||||
export { onRequest } from '../_empty-middleware.mjs';
|
||||
|
||||
const page = () => import('./pages/generic_bd1b56a0.mjs');
|
||||
|
||||
export { page };
|
||||
@@ -1,6 +0,0 @@
|
||||
export { renderers } from '../renderers.mjs';
|
||||
export { onRequest } from '../_empty-middleware.mjs';
|
||||
|
||||
const page = () => import('./pages/index_1614b54d.mjs');
|
||||
|
||||
export { page };
|
||||
@@ -1,149 +0,0 @@
|
||||
import { isRemotePath } from '@astrojs/internal-helpers/path';
|
||||
import mime from 'mime/lite.js';
|
||||
import { i as isESMImportedImage, g as getImage$1, a as getConfiguredImageService, b as isRemoteAllowed } from '../astro/assets-service_f130ddc7.mjs';
|
||||
import { e as createAstro, f as createComponent, A as AstroError, g as ImageMissingAlt, r as renderTemplate, m as maybeRenderHead, h as addAttribute, s as spreadAttributes } from '../astro_0a673d7a.mjs';
|
||||
import 'html-escaper';
|
||||
import 'clsx';
|
||||
|
||||
const fnv1a52 = (str) => {
|
||||
const len = str.length;
|
||||
let i = 0, t0 = 0, v0 = 8997, t1 = 0, v1 = 33826, t2 = 0, v2 = 40164, t3 = 0, v3 = 52210;
|
||||
while (i < len) {
|
||||
v0 ^= str.charCodeAt(i++);
|
||||
t0 = v0 * 435;
|
||||
t1 = v1 * 435;
|
||||
t2 = v2 * 435;
|
||||
t3 = v3 * 435;
|
||||
t2 += v0 << 8;
|
||||
t3 += v1 << 8;
|
||||
t1 += t0 >>> 16;
|
||||
v0 = t0 & 65535;
|
||||
t2 += t1 >>> 16;
|
||||
v1 = t1 & 65535;
|
||||
v3 = t3 + (t2 >>> 16) & 65535;
|
||||
v2 = t2 & 65535;
|
||||
}
|
||||
return (v3 & 15) * 281474976710656 + v2 * 4294967296 + v1 * 65536 + (v0 ^ v3 >> 4);
|
||||
};
|
||||
const etag = (payload, weak = false) => {
|
||||
const prefix = weak ? 'W/"' : '"';
|
||||
return prefix + fnv1a52(payload).toString(36) + payload.length.toString(36) + '"';
|
||||
};
|
||||
|
||||
const $$Astro$1 = createAstro();
|
||||
const $$Image = createComponent(async ($$result, $$props, $$slots) => {
|
||||
const Astro2 = $$result.createAstro($$Astro$1, $$props, $$slots);
|
||||
Astro2.self = $$Image;
|
||||
const props = Astro2.props;
|
||||
if (props.alt === void 0 || props.alt === null) {
|
||||
throw new AstroError(ImageMissingAlt);
|
||||
}
|
||||
if (typeof props.width === "string") {
|
||||
props.width = parseInt(props.width);
|
||||
}
|
||||
if (typeof props.height === "string") {
|
||||
props.height = parseInt(props.height);
|
||||
}
|
||||
const image = await getImage(props);
|
||||
const additionalAttributes = {};
|
||||
if (image.srcSet.values.length > 0) {
|
||||
additionalAttributes.srcset = image.srcSet.attribute;
|
||||
}
|
||||
return renderTemplate`${maybeRenderHead()}<img${addAttribute(image.src, "src")}${spreadAttributes(additionalAttributes)}${spreadAttributes(image.attributes)}>`;
|
||||
}, "/Users/abhimanyu.rana@postman.com/Documents/Experiments/riseofmachine/node_modules/astro/components/Image.astro", void 0);
|
||||
|
||||
const $$Astro = createAstro();
|
||||
const $$Picture = createComponent(async ($$result, $$props, $$slots) => {
|
||||
const Astro2 = $$result.createAstro($$Astro, $$props, $$slots);
|
||||
Astro2.self = $$Picture;
|
||||
const defaultFormats = ["webp"];
|
||||
const defaultFallbackFormat = "png";
|
||||
const specialFormatsFallback = ["gif", "svg", "jpg", "jpeg"];
|
||||
const { formats = defaultFormats, pictureAttributes = {}, fallbackFormat, ...props } = Astro2.props;
|
||||
if (props.alt === void 0 || props.alt === null) {
|
||||
throw new AstroError(ImageMissingAlt);
|
||||
}
|
||||
const optimizedImages = await Promise.all(
|
||||
formats.map(
|
||||
async (format) => await getImage({ ...props, format, widths: props.widths, densities: props.densities })
|
||||
)
|
||||
);
|
||||
let resultFallbackFormat = fallbackFormat ?? defaultFallbackFormat;
|
||||
if (!fallbackFormat && isESMImportedImage(props.src) && specialFormatsFallback.includes(props.src.format)) {
|
||||
resultFallbackFormat = props.src.format;
|
||||
}
|
||||
const fallbackImage = await getImage({
|
||||
...props,
|
||||
format: resultFallbackFormat,
|
||||
widths: props.widths,
|
||||
densities: props.densities
|
||||
});
|
||||
const imgAdditionalAttributes = {};
|
||||
const sourceAdditionaAttributes = {};
|
||||
if (props.sizes) {
|
||||
sourceAdditionaAttributes.sizes = props.sizes;
|
||||
}
|
||||
if (fallbackImage.srcSet.values.length > 0) {
|
||||
imgAdditionalAttributes.srcset = fallbackImage.srcSet.attribute;
|
||||
}
|
||||
return renderTemplate`${maybeRenderHead()}<picture${spreadAttributes(pictureAttributes)}> ${Object.entries(optimizedImages).map(([_, image]) => {
|
||||
const srcsetAttribute = props.densities || !props.densities && !props.widths ? `${image.src}${image.srcSet.values.length > 0 ? ", " + image.srcSet.attribute : ""}` : image.srcSet.attribute;
|
||||
return renderTemplate`<source${addAttribute(srcsetAttribute, "srcset")}${addAttribute("image/" + image.options.format, "type")}${spreadAttributes(sourceAdditionaAttributes)}>`;
|
||||
})} <img${addAttribute(fallbackImage.src, "src")}${spreadAttributes(imgAdditionalAttributes)}${spreadAttributes(fallbackImage.attributes)}> </picture>`;
|
||||
}, "/Users/abhimanyu.rana@postman.com/Documents/Experiments/riseofmachine/node_modules/astro/components/Picture.astro", void 0);
|
||||
|
||||
const imageConfig = {"service":{"entrypoint":"astro/assets/services/sharp","config":{}},"domains":[],"remotePatterns":[]};
|
||||
new URL("file:///Users/abhimanyu.rana@postman.com/Documents/Experiments/riseofmachine/dist/");
|
||||
const getImage = async (options) => await getImage$1(options, imageConfig);
|
||||
|
||||
async function loadRemoteImage(src) {
|
||||
try {
|
||||
const res = await fetch(src);
|
||||
if (!res.ok) {
|
||||
return void 0;
|
||||
}
|
||||
return await res.arrayBuffer();
|
||||
} catch (err) {
|
||||
return void 0;
|
||||
}
|
||||
}
|
||||
const GET = async ({ request }) => {
|
||||
try {
|
||||
const imageService = await getConfiguredImageService();
|
||||
if (!("transform" in imageService)) {
|
||||
throw new Error("Configured image service is not a local service");
|
||||
}
|
||||
const url = new URL(request.url);
|
||||
const transform = await imageService.parseURL(url, imageConfig);
|
||||
if (!transform?.src) {
|
||||
throw new Error("Incorrect transform returned by `parseURL`");
|
||||
}
|
||||
let inputBuffer = void 0;
|
||||
const sourceUrl = isRemotePath(transform.src) ? new URL(transform.src) : new URL(transform.src, url.origin);
|
||||
if (isRemotePath(transform.src) && isRemoteAllowed(transform.src, imageConfig) === false) {
|
||||
return new Response("Forbidden", { status: 403 });
|
||||
}
|
||||
inputBuffer = await loadRemoteImage(sourceUrl);
|
||||
if (!inputBuffer) {
|
||||
return new Response("Not Found", { status: 404 });
|
||||
}
|
||||
const { data, format } = await imageService.transform(
|
||||
new Uint8Array(inputBuffer),
|
||||
transform,
|
||||
imageConfig
|
||||
);
|
||||
return new Response(data, {
|
||||
status: 200,
|
||||
headers: {
|
||||
"Content-Type": mime.getType(format) ?? `image/${format}`,
|
||||
"Cache-Control": "public, max-age=31536000",
|
||||
ETag: etag(data.toString()),
|
||||
Date: (/* @__PURE__ */ new Date()).toUTCString()
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
return new Response(`Server Error: ${err}`, { status: 500 });
|
||||
}
|
||||
};
|
||||
|
||||
export { GET };
|
||||
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
|
||||
{"version":1,"config":{"nodeModuleFormat":"esm"}}
|
||||
@@ -1,21 +0,0 @@
|
||||
import * as adapter from '@astrojs/netlify/netlify-functions.js';
|
||||
import { renderers } from './renderers.mjs';
|
||||
import { manifest } from './manifest_5baacc9b.mjs';
|
||||
|
||||
const _page0 = () => import('./chunks/generic_704749b9.mjs');
|
||||
const _page1 = () => import('./chunks/index_a63ce93d.mjs');const pageMap = new Map([["node_modules/astro/dist/assets/endpoint/generic.js", _page0],["src/pages/index.astro", _page1]]);
|
||||
const _manifest = Object.assign(manifest, {
|
||||
pageMap,
|
||||
renderers,
|
||||
});
|
||||
const _args = {};
|
||||
|
||||
const _exports = adapter.createExports(_manifest, _args);
|
||||
const handler = _exports['handler'];
|
||||
|
||||
const _start = 'start';
|
||||
if(_start in adapter) {
|
||||
adapter[_start](_manifest, _args);
|
||||
}
|
||||
|
||||
export { handler, pageMap };
|
||||
@@ -1,83 +0,0 @@
|
||||
import '@astrojs/internal-helpers/path';
|
||||
import 'cookie';
|
||||
import 'kleur/colors';
|
||||
import 'string-width';
|
||||
import 'mime';
|
||||
import 'html-escaper';
|
||||
import 'clsx';
|
||||
import './chunks/astro_0a673d7a.mjs';
|
||||
import { compile } from 'path-to-regexp';
|
||||
|
||||
if (typeof process !== "undefined") {
|
||||
let proc = process;
|
||||
if ("argv" in proc && Array.isArray(proc.argv)) {
|
||||
if (proc.argv.includes("--verbose")) ; else if (proc.argv.includes("--silent")) ; else ;
|
||||
}
|
||||
}
|
||||
|
||||
new TextEncoder();
|
||||
|
||||
function getRouteGenerator(segments, addTrailingSlash) {
|
||||
const template = segments.map((segment) => {
|
||||
return "/" + segment.map((part) => {
|
||||
if (part.spread) {
|
||||
return `:${part.content.slice(3)}(.*)?`;
|
||||
} else if (part.dynamic) {
|
||||
return `:${part.content}`;
|
||||
} else {
|
||||
return part.content.normalize().replace(/\?/g, "%3F").replace(/#/g, "%23").replace(/%5B/g, "[").replace(/%5D/g, "]").replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
||||
}
|
||||
}).join("");
|
||||
}).join("");
|
||||
let trailing = "";
|
||||
if (addTrailingSlash === "always" && segments.length) {
|
||||
trailing = "/";
|
||||
}
|
||||
const toPath = compile(template + trailing);
|
||||
return toPath;
|
||||
}
|
||||
|
||||
function deserializeRouteData(rawRouteData) {
|
||||
return {
|
||||
route: rawRouteData.route,
|
||||
type: rawRouteData.type,
|
||||
pattern: new RegExp(rawRouteData.pattern),
|
||||
params: rawRouteData.params,
|
||||
component: rawRouteData.component,
|
||||
generate: getRouteGenerator(rawRouteData.segments, rawRouteData._meta.trailingSlash),
|
||||
pathname: rawRouteData.pathname || void 0,
|
||||
segments: rawRouteData.segments,
|
||||
prerender: rawRouteData.prerender,
|
||||
redirect: rawRouteData.redirect,
|
||||
redirectRoute: rawRouteData.redirectRoute ? deserializeRouteData(rawRouteData.redirectRoute) : void 0,
|
||||
fallbackRoutes: rawRouteData.fallbackRoutes.map((fallback) => {
|
||||
return deserializeRouteData(fallback);
|
||||
})
|
||||
};
|
||||
}
|
||||
|
||||
function deserializeManifest(serializedManifest) {
|
||||
const routes = [];
|
||||
for (const serializedRoute of serializedManifest.routes) {
|
||||
routes.push({
|
||||
...serializedRoute,
|
||||
routeData: deserializeRouteData(serializedRoute.routeData)
|
||||
});
|
||||
const route = serializedRoute;
|
||||
route.routeData = deserializeRouteData(serializedRoute.routeData);
|
||||
}
|
||||
const assets = new Set(serializedManifest.assets);
|
||||
const componentMetadata = new Map(serializedManifest.componentMetadata);
|
||||
const clientDirectives = new Map(serializedManifest.clientDirectives);
|
||||
return {
|
||||
...serializedManifest,
|
||||
assets,
|
||||
componentMetadata,
|
||||
clientDirectives,
|
||||
routes
|
||||
};
|
||||
}
|
||||
|
||||
const manifest = deserializeManifest({"adapterName":"@astrojs/netlify/functions","routes":[{"file":"","links":[],"scripts":[],"styles":[],"routeData":{"type":"endpoint","route":"/_image","pattern":"^\\/_image$","segments":[[{"content":"_image","dynamic":false,"spread":false}]],"params":[],"component":"node_modules/astro/dist/assets/endpoint/generic.js","pathname":"/_image","prerender":false,"fallbackRoutes":[],"_meta":{"trailingSlash":"ignore"}}},{"file":"","links":[],"scripts":[{"type":"inline","value":"window.dataLayer=window.dataLayer||[];function r(){dataLayer.push(arguments)}r(\"js\",new Date);r(\"config\",\"G-BLXD7VCZH0\");const t=\"theme-preference\",c=()=>{e.value=e.value===\"light\"?\"dark\":\"light\",o()},l=()=>localStorage.getItem(t)?localStorage.getItem(t):window.matchMedia(\"(prefers-color-scheme: dark)\").matches?\"dark\":\"light\",o=()=>{localStorage.setItem(t,e.value),a()},a=()=>{document.firstElementChild.setAttribute(\"data-new-ui-theme\",e.value),document.querySelector(\"#theme-toggle\")?.setAttribute(\"aria-label\",e.value)},e={value:l()};a();window.onload=()=>{a(),document.querySelector(\"#theme-toggle\").addEventListener(\"click\",c)};window.matchMedia(\"(prefers-color-scheme: dark)\").addEventListener(\"change\",({matches:n})=>{e.value=n?\"dark\":\"light\",o()});\n"}],"styles":[{"type":"external","src":"/_astro/index.8985bd45.css"}],"routeData":{"route":"/","type":"page","pattern":"^\\/$","segments":[],"params":[],"component":"src/pages/index.astro","pathname":"/","prerender":false,"fallbackRoutes":[],"_meta":{"trailingSlash":"ignore"}}}],"base":"/","trailingSlash":"ignore","compressHTML":true,"componentMetadata":[["/Users/abhimanyu.rana@postman.com/Documents/Experiments/riseofmachine/src/pages/index.astro",{"propagation":"none","containsHead":true}]],"renderers":[],"clientDirectives":[["idle","(()=>{var i=t=>{let e=async()=>{await(await t())()};\"requestIdleCallback\"in window?window.requestIdleCallback(e):setTimeout(e,200)};(self.Astro||(self.Astro={})).idle=i;window.dispatchEvent(new Event(\"astro:idle\"));})();"],["load","(()=>{var e=async t=>{await(await t())()};(self.Astro||(self.Astro={})).load=e;window.dispatchEvent(new Event(\"astro:load\"));})();"],["media","(()=>{var s=(i,t)=>{let a=async()=>{await(await i())()};if(t.value){let e=matchMedia(t.value);e.matches?a():e.addEventListener(\"change\",a,{once:!0})}};(self.Astro||(self.Astro={})).media=s;window.dispatchEvent(new Event(\"astro:media\"));})();"],["only","(()=>{var e=async t=>{await(await t())()};(self.Astro||(self.Astro={})).only=e;window.dispatchEvent(new Event(\"astro:only\"));})();"],["visible","(()=>{var r=(i,c,s)=>{let n=async()=>{await(await i())()},t=new IntersectionObserver(e=>{for(let o of e)if(o.isIntersecting){t.disconnect(),n();break}});for(let e of s.children)t.observe(e)};(self.Astro||(self.Astro={})).visible=r;window.dispatchEvent(new Event(\"astro:visible\"));})();"]],"entryModules":{"\u0000@astrojs-ssr-virtual-entry":"entry.mjs","\u0000@astro-renderers":"renderers.mjs","\u0000empty-middleware":"_empty-middleware.mjs","/node_modules/astro/dist/assets/endpoint/generic.js":"chunks/pages/generic_bd1b56a0.mjs","/src/pages/index.astro":"chunks/pages/index_1614b54d.mjs","\u0000@astrojs-manifest":"manifest_5baacc9b.mjs","\u0000@astro-page:node_modules/astro/dist/assets/endpoint/generic@_@js":"chunks/generic_704749b9.mjs","\u0000@astro-page:src/pages/index@_@astro":"chunks/index_a63ce93d.mjs","/astro/hoisted.js?q=0":"_astro/hoisted.ae4d5e2a.js","astro:scripts/before-hydration.js":""},"assets":["/_astro/index.8985bd45.css","/icon.png","/icon2.png"]});
|
||||
|
||||
export { manifest };
|
||||
@@ -1,3 +0,0 @@
|
||||
const renderers = [];
|
||||
|
||||
export { renderers };
|
||||
@@ -1,8 +1,11 @@
|
||||
import { defineConfig } from 'astro/config';
|
||||
import netlify from "@astrojs/netlify/functions";
|
||||
|
||||
import react from "@astrojs/react";
|
||||
|
||||
// https://astro.build/config
|
||||
export default defineConfig({
|
||||
output: "server",
|
||||
adapter: netlify()
|
||||
});
|
||||
adapter: netlify(),
|
||||
integrations: [react()]
|
||||
});
|
||||
285
package-lock.json
generated
285
package-lock.json
generated
@@ -9,7 +9,12 @@
|
||||
"version": "0.1.0",
|
||||
"dependencies": {
|
||||
"@astrojs/netlify": "^3.1.1",
|
||||
"astro": "^4.0.3"
|
||||
"@astrojs/react": "^3.0.7",
|
||||
"@types/react": "^18.2.45",
|
||||
"@types/react-dom": "^18.2.18",
|
||||
"astro": "^4.0.3",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@new-ui/colors": "^1.2.11",
|
||||
@@ -88,6 +93,24 @@
|
||||
"node": ">=18.14.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@astrojs/react": {
|
||||
"version": "3.0.7",
|
||||
"resolved": "https://registry.npmjs.org/@astrojs/react/-/react-3.0.7.tgz",
|
||||
"integrity": "sha512-MpjuFw7YGta44OaQExKVCWyXjujUtUsp5Nst/wIjRHbkmBBlypdj+MF9/xqjsYM+vjcrByOGupmluRrFQO67YQ==",
|
||||
"dependencies": {
|
||||
"@vitejs/plugin-react": "^4.2.0",
|
||||
"ultrahtml": "^1.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.14.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "^17.0.50 || ^18.0.21",
|
||||
"@types/react-dom": "^17.0.17 || ^18.0.6",
|
||||
"react": "^17.0.2 || ^18.0.0",
|
||||
"react-dom": "^17.0.2 || ^18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@astrojs/telemetry": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@astrojs/telemetry/-/telemetry-3.0.4.tgz",
|
||||
@@ -111,9 +134,9 @@
|
||||
"integrity": "sha512-qDAKhFO4M1KzP7mxoJfiehf8oyf3EB158MxAa6z10NeD2pR3o4K3LlOQI8CfJgXE+BDBQcnaLvVCg/Mz/Gkg4Q=="
|
||||
},
|
||||
"node_modules/@babel/code-frame": {
|
||||
"version": "7.23.4",
|
||||
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.4.tgz",
|
||||
"integrity": "sha512-r1IONyb6Ia+jYR2vvIDhdWdlTGhqbBoFqLTQidzZ4kepUFH15ejXvFHxCVbtl7BOXIudsIubf4E81xeA3h3IXA==",
|
||||
"version": "7.23.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz",
|
||||
"integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==",
|
||||
"dependencies": {
|
||||
"@babel/highlight": "^7.23.4",
|
||||
"chalk": "^2.4.2"
|
||||
@@ -123,28 +146,28 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/compat-data": {
|
||||
"version": "7.23.3",
|
||||
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.3.tgz",
|
||||
"integrity": "sha512-BmR4bWbDIoFJmJ9z2cZ8Gmm2MXgEDgjdWgpKmKWUt54UGFJdlj31ECtbaDvCG/qVdG3AQ1SfpZEs01lUFbzLOQ==",
|
||||
"version": "7.23.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz",
|
||||
"integrity": "sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==",
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/core": {
|
||||
"version": "7.23.3",
|
||||
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.3.tgz",
|
||||
"integrity": "sha512-Jg+msLuNuCJDyBvFv5+OKOUjWMZgd85bKjbICd3zWrKAo+bJ49HJufi7CQE0q0uR8NGyO6xkCACScNqyjHSZew==",
|
||||
"version": "7.23.6",
|
||||
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.6.tgz",
|
||||
"integrity": "sha512-FxpRyGjrMJXh7X3wGLGhNDCRiwpWEF74sKjTLDJSG5Kyvow3QZaG0Adbqzi9ZrVjTWpsX+2cxWXD71NMg93kdw==",
|
||||
"dependencies": {
|
||||
"@ampproject/remapping": "^2.2.0",
|
||||
"@babel/code-frame": "^7.22.13",
|
||||
"@babel/generator": "^7.23.3",
|
||||
"@babel/helper-compilation-targets": "^7.22.15",
|
||||
"@babel/code-frame": "^7.23.5",
|
||||
"@babel/generator": "^7.23.6",
|
||||
"@babel/helper-compilation-targets": "^7.23.6",
|
||||
"@babel/helper-module-transforms": "^7.23.3",
|
||||
"@babel/helpers": "^7.23.2",
|
||||
"@babel/parser": "^7.23.3",
|
||||
"@babel/helpers": "^7.23.6",
|
||||
"@babel/parser": "^7.23.6",
|
||||
"@babel/template": "^7.22.15",
|
||||
"@babel/traverse": "^7.23.3",
|
||||
"@babel/types": "^7.23.3",
|
||||
"@babel/traverse": "^7.23.6",
|
||||
"@babel/types": "^7.23.6",
|
||||
"convert-source-map": "^2.0.0",
|
||||
"debug": "^4.1.0",
|
||||
"gensync": "^1.0.0-beta.2",
|
||||
@@ -168,11 +191,11 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/generator": {
|
||||
"version": "7.23.4",
|
||||
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.4.tgz",
|
||||
"integrity": "sha512-esuS49Cga3HcThFNebGhlgsrVLkvhqvYDTzgjfFFlHJcIfLe5jFmRRfCQ1KuBfc4Jrtn3ndLgKWAKjBE+IraYQ==",
|
||||
"version": "7.23.6",
|
||||
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz",
|
||||
"integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==",
|
||||
"dependencies": {
|
||||
"@babel/types": "^7.23.4",
|
||||
"@babel/types": "^7.23.6",
|
||||
"@jridgewell/gen-mapping": "^0.3.2",
|
||||
"@jridgewell/trace-mapping": "^0.3.17",
|
||||
"jsesc": "^2.5.1"
|
||||
@@ -193,13 +216,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helper-compilation-targets": {
|
||||
"version": "7.22.15",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz",
|
||||
"integrity": "sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==",
|
||||
"version": "7.23.6",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz",
|
||||
"integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==",
|
||||
"dependencies": {
|
||||
"@babel/compat-data": "^7.22.9",
|
||||
"@babel/helper-validator-option": "^7.22.15",
|
||||
"browserslist": "^4.21.9",
|
||||
"@babel/compat-data": "^7.23.5",
|
||||
"@babel/helper-validator-option": "^7.23.5",
|
||||
"browserslist": "^4.22.2",
|
||||
"lru-cache": "^5.1.1",
|
||||
"semver": "^6.3.1"
|
||||
},
|
||||
@@ -322,21 +345,21 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helper-validator-option": {
|
||||
"version": "7.22.15",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz",
|
||||
"integrity": "sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==",
|
||||
"version": "7.23.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz",
|
||||
"integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==",
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helpers": {
|
||||
"version": "7.23.4",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.4.tgz",
|
||||
"integrity": "sha512-HfcMizYz10cr3h29VqyfGL6ZWIjTwWfvYBMsBVGwpcbhNGe3wQ1ZXZRPzZoAHhd9OqHadHqjQ89iVKINXnbzuw==",
|
||||
"version": "7.23.6",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.6.tgz",
|
||||
"integrity": "sha512-wCfsbN4nBidDRhpDhvcKlzHWCTlgJYUUdSJfzXb2NuBssDSIjc3xcb+znA7l+zYsFljAcGM0aFkN40cR3lXiGA==",
|
||||
"dependencies": {
|
||||
"@babel/template": "^7.22.15",
|
||||
"@babel/traverse": "^7.23.4",
|
||||
"@babel/types": "^7.23.4"
|
||||
"@babel/traverse": "^7.23.6",
|
||||
"@babel/types": "^7.23.6"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
@@ -356,9 +379,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/parser": {
|
||||
"version": "7.23.4",
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.4.tgz",
|
||||
"integrity": "sha512-vf3Xna6UEprW+7t6EtOmFpHNAuxw3xqPZghy+brsnusscJRW5BMUzzHZc5ICjULee81WeUV2jjakG09MDglJXQ==",
|
||||
"version": "7.23.6",
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.6.tgz",
|
||||
"integrity": "sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ==",
|
||||
"bin": {
|
||||
"parser": "bin/babel-parser.js"
|
||||
},
|
||||
@@ -398,6 +421,34 @@
|
||||
"@babel/core": "^7.0.0-0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/plugin-transform-react-jsx-self": {
|
||||
"version": "7.23.3",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.23.3.tgz",
|
||||
"integrity": "sha512-qXRvbeKDSfwnlJnanVRp0SfuWE5DQhwQr5xtLBzp56Wabyo+4CMosF6Kfp+eOD/4FYpql64XVJ2W0pVLlJZxOQ==",
|
||||
"dependencies": {
|
||||
"@babel/helper-plugin-utils": "^7.22.5"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@babel/core": "^7.0.0-0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/plugin-transform-react-jsx-source": {
|
||||
"version": "7.23.3",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.23.3.tgz",
|
||||
"integrity": "sha512-91RS0MDnAWDNvGC6Wio5XYkyWI39FMFO+JK9+4AlgaTH+yWwVTsw7/sn6LK0lH7c5F+TFkpv/3LfCJ1Ydwof/g==",
|
||||
"dependencies": {
|
||||
"@babel/helper-plugin-utils": "^7.22.5"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@babel/core": "^7.0.0-0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/template": {
|
||||
"version": "7.22.15",
|
||||
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz",
|
||||
@@ -412,19 +463,19 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/traverse": {
|
||||
"version": "7.23.4",
|
||||
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.4.tgz",
|
||||
"integrity": "sha512-IYM8wSUwunWTB6tFC2dkKZhxbIjHoWemdK+3f8/wq8aKhbUscxD5MX72ubd90fxvFknaLPeGw5ycU84V1obHJg==",
|
||||
"version": "7.23.6",
|
||||
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.6.tgz",
|
||||
"integrity": "sha512-czastdK1e8YByZqezMPFiZ8ahwVMh/ESl9vPgvgdB9AmFMGP5jfpFax74AQgl5zj4XHzqeYAg2l8PuUeRS1MgQ==",
|
||||
"dependencies": {
|
||||
"@babel/code-frame": "^7.23.4",
|
||||
"@babel/generator": "^7.23.4",
|
||||
"@babel/code-frame": "^7.23.5",
|
||||
"@babel/generator": "^7.23.6",
|
||||
"@babel/helper-environment-visitor": "^7.22.20",
|
||||
"@babel/helper-function-name": "^7.23.0",
|
||||
"@babel/helper-hoist-variables": "^7.22.5",
|
||||
"@babel/helper-split-export-declaration": "^7.22.6",
|
||||
"@babel/parser": "^7.23.4",
|
||||
"@babel/types": "^7.23.4",
|
||||
"debug": "^4.1.0",
|
||||
"@babel/parser": "^7.23.6",
|
||||
"@babel/types": "^7.23.6",
|
||||
"debug": "^4.3.1",
|
||||
"globals": "^11.1.0"
|
||||
},
|
||||
"engines": {
|
||||
@@ -432,9 +483,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/types": {
|
||||
"version": "7.23.4",
|
||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.4.tgz",
|
||||
"integrity": "sha512-7uIFwVYpoplT5jp/kVv6EF93VaJ8H+Yn5IczYiaAi98ajzjfoZfslet/e0sLh+wVBjb2qqIut1b0S26VSafsSQ==",
|
||||
"version": "7.23.6",
|
||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.6.tgz",
|
||||
"integrity": "sha512-+uarb83brBzPKN38NX1MkB6vb6+mwvR6amUulqAE7ccQw1pEl+bCia9TbdG1lsnFP7lZySvUn37CHyXQdfTwzg==",
|
||||
"dependencies": {
|
||||
"@babel/helper-string-parser": "^7.23.4",
|
||||
"@babel/helper-validator-identifier": "^7.22.20",
|
||||
@@ -1133,6 +1184,34 @@
|
||||
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz",
|
||||
"integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA=="
|
||||
},
|
||||
"node_modules/@types/prop-types": {
|
||||
"version": "15.7.11",
|
||||
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.11.tgz",
|
||||
"integrity": "sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng=="
|
||||
},
|
||||
"node_modules/@types/react": {
|
||||
"version": "18.2.45",
|
||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.45.tgz",
|
||||
"integrity": "sha512-TtAxCNrlrBp8GoeEp1npd5g+d/OejJHFxS3OWmrPBMFaVQMSN0OFySozJio5BHxTuTeug00AVXVAjfDSfk+lUg==",
|
||||
"dependencies": {
|
||||
"@types/prop-types": "*",
|
||||
"@types/scheduler": "*",
|
||||
"csstype": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/react-dom": {
|
||||
"version": "18.2.18",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.18.tgz",
|
||||
"integrity": "sha512-TJxDm6OfAX2KJWJdMEVTwWke5Sc/E/RlnPGvGfS0W7+6ocy2xhDVQVh/KvC2Uf7kACs+gDytdusDSdWfWkaNzw==",
|
||||
"dependencies": {
|
||||
"@types/react": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/scheduler": {
|
||||
"version": "0.16.8",
|
||||
"resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.8.tgz",
|
||||
"integrity": "sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A=="
|
||||
},
|
||||
"node_modules/@types/unist": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz",
|
||||
@@ -1143,6 +1222,24 @@
|
||||
"resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz",
|
||||
"integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ=="
|
||||
},
|
||||
"node_modules/@vitejs/plugin-react": {
|
||||
"version": "4.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.2.1.tgz",
|
||||
"integrity": "sha512-oojO9IDc4nCUUi8qIR11KoQm0XFFLIwsRBwHRR4d/88IWghn1y6ckz/bJ8GHDCsYEJee8mDzqtJxh15/cisJNQ==",
|
||||
"dependencies": {
|
||||
"@babel/core": "^7.23.5",
|
||||
"@babel/plugin-transform-react-jsx-self": "^7.23.3",
|
||||
"@babel/plugin-transform-react-jsx-source": "^7.23.3",
|
||||
"@types/babel__core": "^7.20.5",
|
||||
"react-refresh": "^0.14.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^14.18.0 || >=16.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"vite": "^4.2.0 || ^5.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/acorn": {
|
||||
"version": "8.11.2",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz",
|
||||
@@ -1477,9 +1574,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/browserslist": {
|
||||
"version": "4.22.1",
|
||||
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.1.tgz",
|
||||
"integrity": "sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==",
|
||||
"version": "4.22.2",
|
||||
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.2.tgz",
|
||||
"integrity": "sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "opencollective",
|
||||
@@ -1495,9 +1592,9 @@
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"caniuse-lite": "^1.0.30001541",
|
||||
"electron-to-chromium": "^1.4.535",
|
||||
"node-releases": "^2.0.13",
|
||||
"caniuse-lite": "^1.0.30001565",
|
||||
"electron-to-chromium": "^1.4.601",
|
||||
"node-releases": "^2.0.14",
|
||||
"update-browserslist-db": "^1.0.13"
|
||||
},
|
||||
"bin": {
|
||||
@@ -1542,9 +1639,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/caniuse-lite": {
|
||||
"version": "1.0.30001565",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001565.tgz",
|
||||
"integrity": "sha512-xrE//a3O7TP0vaJ8ikzkD2c2NgcVUvsEe2IvFTntV4Yd1Z9FVzh+gW+enX96L0psrbaFMcVcH2l90xNuGDWc8w==",
|
||||
"version": "1.0.30001570",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001570.tgz",
|
||||
"integrity": "sha512-+3e0ASu4sw1SWaoCtvPeyXp+5PsjigkSt8OXZbF9StH5pQWbxEjLAZE3n8Aup5udop1uRiKA7a4utUk/uoSpUw==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "opencollective",
|
||||
@@ -1793,6 +1890,11 @@
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/csstype": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
|
||||
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="
|
||||
},
|
||||
"node_modules/debug": {
|
||||
"version": "4.3.4",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
||||
@@ -1917,9 +2019,9 @@
|
||||
"integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="
|
||||
},
|
||||
"node_modules/electron-to-chromium": {
|
||||
"version": "1.4.595",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.595.tgz",
|
||||
"integrity": "sha512-+ozvXuamBhDOKvMNUQvecxfbyICmIAwS4GpLmR0bsiSBlGnLaOcs2Cj7J8XSbW+YEaN3Xl3ffgpm+srTUWFwFQ=="
|
||||
"version": "1.4.614",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.614.tgz",
|
||||
"integrity": "sha512-X4ze/9Sc3QWs6h92yerwqv7aB/uU8vCjZcrMjA8N9R1pjMFRe44dLsck5FzLilOYvcXuDn93B+bpGYyufc70gQ=="
|
||||
},
|
||||
"node_modules/emoji-regex": {
|
||||
"version": "10.3.0",
|
||||
@@ -2844,6 +2946,17 @@
|
||||
"url": "https://github.com/sponsors/wooorm"
|
||||
}
|
||||
},
|
||||
"node_modules/loose-envify": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
|
||||
"integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
|
||||
"dependencies": {
|
||||
"js-tokens": "^3.0.0 || ^4.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"loose-envify": "cli.js"
|
||||
}
|
||||
},
|
||||
"node_modules/lru-cache": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
|
||||
@@ -3785,9 +3898,9 @@
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/node-releases": {
|
||||
"version": "2.0.13",
|
||||
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz",
|
||||
"integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ=="
|
||||
"version": "2.0.14",
|
||||
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz",
|
||||
"integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw=="
|
||||
},
|
||||
"node_modules/normalize-path": {
|
||||
"version": "3.0.0",
|
||||
@@ -4338,6 +4451,37 @@
|
||||
"rc": "cli.js"
|
||||
}
|
||||
},
|
||||
"node_modules/react": {
|
||||
"version": "18.2.0",
|
||||
"resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz",
|
||||
"integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==",
|
||||
"dependencies": {
|
||||
"loose-envify": "^1.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-dom": {
|
||||
"version": "18.2.0",
|
||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz",
|
||||
"integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==",
|
||||
"dependencies": {
|
||||
"loose-envify": "^1.1.0",
|
||||
"scheduler": "^0.23.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^18.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-refresh": {
|
||||
"version": "0.14.0",
|
||||
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz",
|
||||
"integrity": "sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ==",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/readable-stream": {
|
||||
"version": "3.6.2",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
|
||||
@@ -5033,6 +5177,14 @@
|
||||
"resolved": "https://registry.npmjs.org/sax/-/sax-1.3.0.tgz",
|
||||
"integrity": "sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA=="
|
||||
},
|
||||
"node_modules/scheduler": {
|
||||
"version": "0.23.0",
|
||||
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz",
|
||||
"integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==",
|
||||
"dependencies": {
|
||||
"loose-envify": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/section-matter": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz",
|
||||
@@ -5477,6 +5629,11 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/ultrahtml": {
|
||||
"version": "1.5.2",
|
||||
"resolved": "https://registry.npmjs.org/ultrahtml/-/ultrahtml-1.5.2.tgz",
|
||||
"integrity": "sha512-qh4mBffhlkiXwDAOxvSGxhL0QEQsTbnP9BozOK3OYPEGvPvdWzvAUaXNtUSMdNsKDtuyjEbyVUPFZ52SSLhLqw=="
|
||||
},
|
||||
"node_modules/unherit": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/unherit/-/unherit-3.0.1.tgz",
|
||||
|
||||
@@ -11,7 +11,12 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@astrojs/netlify": "^3.1.1",
|
||||
"astro": "^4.0.3"
|
||||
"@astrojs/react": "^3.0.7",
|
||||
"@types/react": "^18.2.45",
|
||||
"@types/react-dom": "^18.2.18",
|
||||
"astro": "^4.0.3",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@new-ui/colors": "^1.2.11",
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
---
|
||||
export interface Props {
|
||||
title: string;
|
||||
body: string;
|
||||
tag: string;
|
||||
href: string;
|
||||
}
|
||||
|
||||
const { href, title, body, tag } = Astro.props;
|
||||
---
|
||||
|
||||
<li class="link-card">
|
||||
<a href={href}>
|
||||
<h6 class="nu-c-h6 nu-u-mt-1 nu-u-mb-1">
|
||||
{title}
|
||||
</h6>
|
||||
<p class="nu-c-fs-small nu-u-mt-1 nu-u-mb-1">
|
||||
{body}
|
||||
</p>
|
||||
<p class="distribution">
|
||||
<span class="tag">{tag}</span>
|
||||
</p>
|
||||
</a>
|
||||
</li>
|
||||
<style>
|
||||
.link-card {
|
||||
list-style: none;
|
||||
display: flex;
|
||||
background-color: var(--background-secondary);
|
||||
background-position: 100%;
|
||||
border: 1px solid transparent;
|
||||
border-radius: var(--spacing-03);
|
||||
height: 136px;
|
||||
position: relative;
|
||||
box-shadow: 0px 2px 4px 0px rgba(22, 22, 22, 0.08), 0px 8px 12px -8px rgba(22, 22, 22, 0.08);
|
||||
}
|
||||
.link-card > a {
|
||||
width: 100%;
|
||||
text-decoration: none;
|
||||
padding: 0.8rem 1.2rem;
|
||||
color: var(--support-info);
|
||||
}
|
||||
p {
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
.link-card:is(:hover, :focus-within) {
|
||||
background-position: 0;
|
||||
border: 1px solid var(--border);
|
||||
}
|
||||
.link-card:is(:hover, :focus-within) h6 {}
|
||||
p.distribution {margin: var(--spacing-00); position: absolute; bottom: var(--spacing-06);}
|
||||
span.tag {
|
||||
background-color: var(--background-selected);
|
||||
padding: 2px 8px;
|
||||
border-radius: 24px;
|
||||
display: inline-block;
|
||||
color: var(--text-primary-alt);
|
||||
margin-top: var(--spacing-08);
|
||||
font-size: var(--desktop-caption);
|
||||
line-height: var(--lh-desktop-caption);
|
||||
font-family: var(--system-ui);
|
||||
}
|
||||
</style>
|
||||
47
src/components/Card.css
Normal file
47
src/components/Card.css
Normal file
@@ -0,0 +1,47 @@
|
||||
.link-card {
|
||||
list-style: none;
|
||||
display: flex;
|
||||
background-color: var(--background-secondary);
|
||||
background-position: 100%;
|
||||
border: 1px solid transparent;
|
||||
border-radius: var(--spacing-03);
|
||||
height: 136px;
|
||||
position: relative;
|
||||
box-shadow: 0px 2px 4px 0px rgba(22, 22, 22, 0.08), 0px 8px 12px -8px rgba(22, 22, 22, 0.08);
|
||||
}
|
||||
|
||||
.link-card>a {
|
||||
width: 100%;
|
||||
text-decoration: none;
|
||||
padding: 0.8rem 1.2rem;
|
||||
color: var(--support-info);
|
||||
}
|
||||
|
||||
p {
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.link-card:is(:hover, :focus-within) {
|
||||
background-position: 0;
|
||||
border: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.link-card:is(:hover, :focus-within) h6 {}
|
||||
|
||||
p.distribution {
|
||||
margin: var(--spacing-00);
|
||||
position: absolute;
|
||||
bottom: var(--spacing-06);
|
||||
}
|
||||
|
||||
span.tag {
|
||||
background-color: var(--background-selected);
|
||||
padding: 2px 8px;
|
||||
border-radius: 24px;
|
||||
display: inline-block;
|
||||
color: var(--text-primary-alt);
|
||||
margin-top: var(--spacing-08);
|
||||
font-size: var(--desktop-caption);
|
||||
line-height: var(--lh-desktop-caption);
|
||||
font-family: var(--system-ui);
|
||||
}
|
||||
19
src/components/Card.jsx
Normal file
19
src/components/Card.jsx
Normal file
@@ -0,0 +1,19 @@
|
||||
import "./Card.css";
|
||||
|
||||
export default function Card(props) {
|
||||
const {href, title, body, tag} = props;
|
||||
|
||||
return <li className="link-card">
|
||||
<a href={href}>
|
||||
<h6 className="nu-c-h6 nu-u-mt-1 nu-u-mb-1">
|
||||
{title}
|
||||
</h6>
|
||||
<p className="nu-c-fs-small nu-u-mt-1 nu-u-mb-1">
|
||||
{body}
|
||||
</p>
|
||||
<p className="distribution">
|
||||
<span className="tag">{tag}</span>
|
||||
</p>
|
||||
</a>
|
||||
</li>
|
||||
}
|
||||
6
src/components/CardsContainer.css
Normal file
6
src/components/CardsContainer.css
Normal file
@@ -0,0 +1,6 @@
|
||||
.link-card-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(24ch, 1fr));
|
||||
gap: var(--spacing-05);
|
||||
padding: var(--spacing-00);
|
||||
}
|
||||
33
src/components/CardsContainer.jsx
Normal file
33
src/components/CardsContainer.jsx
Normal file
@@ -0,0 +1,33 @@
|
||||
import Card from "./Card";
|
||||
import "./CardsContainer.css";
|
||||
|
||||
import data from "../data/tools.json"
|
||||
|
||||
export default function CardsContainer(props) {
|
||||
const { filter } = props;
|
||||
|
||||
return <section>
|
||||
<ul role="list" className="link-card-grid">
|
||||
{data.tools
|
||||
.filter(item => {
|
||||
if (filter === "all" || filter === item.category) {
|
||||
return item;
|
||||
}
|
||||
})
|
||||
.flatMap(item => item.content)
|
||||
.sort((a, b) => {
|
||||
return a.title < b.title ? -1 : 1;
|
||||
})
|
||||
.map(({url, title, body, tag}, i) => {
|
||||
return <Card
|
||||
key={i}
|
||||
href={url}
|
||||
title={title}
|
||||
body={body}
|
||||
tag={tag}
|
||||
/>
|
||||
})
|
||||
}
|
||||
</ul>
|
||||
</section>
|
||||
}
|
||||
3
src/components/CategoryNav.css
Normal file
3
src/components/CategoryNav.css
Normal file
@@ -0,0 +1,3 @@
|
||||
.nav {
|
||||
box-shadow: inset 0px -1px 0px var(--border-muted);
|
||||
}
|
||||
23
src/components/CategoryNav.jsx
Normal file
23
src/components/CategoryNav.jsx
Normal file
@@ -0,0 +1,23 @@
|
||||
import "./CategoryNav.css";
|
||||
import data from "../data/tools.json";
|
||||
|
||||
import CategoryNavItem from "./CategoryNavItem";
|
||||
|
||||
export default function CategoryNav({ filter, setFilter }) {
|
||||
const navItems = [
|
||||
{title: "🔥 All", category: "all"},
|
||||
...data.tools
|
||||
];
|
||||
|
||||
return <nav className="nav">
|
||||
{navItems.map((c, i) => {
|
||||
return <CategoryNavItem
|
||||
key={i}
|
||||
title={c.title}
|
||||
category={c.category}
|
||||
filter={filter}
|
||||
setFilter={setFilter}
|
||||
/>
|
||||
})}
|
||||
</nav>
|
||||
}
|
||||
18
src/components/CategoryNavItem.css
Normal file
18
src/components/CategoryNavItem.css
Normal file
@@ -0,0 +1,18 @@
|
||||
.nav__item {
|
||||
display: inline-block;
|
||||
text-decoration: none;
|
||||
border: none;
|
||||
outline: none;
|
||||
background: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.nav__item:hover {
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.nav__item.is-active {
|
||||
color: var(--text-primary);
|
||||
font-weight: 500;
|
||||
border-bottom: 2px solid var(--icon-primary);
|
||||
}
|
||||
26
src/components/CategoryNavItem.jsx
Normal file
26
src/components/CategoryNavItem.jsx
Normal file
@@ -0,0 +1,26 @@
|
||||
import { useState, useEffect, useCallback } from "react";
|
||||
import "./CategoryNavItem.css";
|
||||
|
||||
export default function CategoryNavItem(props) {
|
||||
const { title, category, filter, setFilter } = props;
|
||||
const [isActive, setIsActive] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
let subscription = true;
|
||||
|
||||
if (filter === category) {
|
||||
setIsActive(true);
|
||||
} else {
|
||||
setIsActive(false);
|
||||
}
|
||||
|
||||
return (() => (subscription = !subscription));
|
||||
}, [filter]);
|
||||
|
||||
return <button
|
||||
onClick={() => setFilter(category)}
|
||||
className={`nav__item nu-u-text--secondary-alt nu-c-fs-normal nu-u-py-5 nu-u-px-0 nu-u-me-8 nav__item--filter ${isActive ? 'is-active' : ''}`}
|
||||
dangerouslySetInnerHTML={{__html: title}}
|
||||
>
|
||||
</button>
|
||||
}
|
||||
13
src/components/Dashboard.jsx
Normal file
13
src/components/Dashboard.jsx
Normal file
@@ -0,0 +1,13 @@
|
||||
import { useState } from "react";
|
||||
import CategoryNav from "./CategoryNav";
|
||||
import CardsContainer from "./CardsContainer";
|
||||
|
||||
export default function Dashboard() {
|
||||
|
||||
const [filter, setFilter] = useState("all");
|
||||
|
||||
return <>
|
||||
<CategoryNav filter={filter} setFilter={setFilter} />
|
||||
<CardsContainer filter={filter} />
|
||||
</>
|
||||
}
|
||||
1132
src/data/tools.json
Normal file
1132
src/data/tools.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,9 +1,11 @@
|
||||
---
|
||||
export interface Props {
|
||||
site: string;
|
||||
title: string;
|
||||
tagline: string;
|
||||
}
|
||||
|
||||
const { title } = Astro.props;
|
||||
const { site, title, tagline } = Astro.props;
|
||||
---
|
||||
|
||||
<!DOCTYPE html>
|
||||
@@ -14,7 +16,7 @@ const { title } = Astro.props;
|
||||
<link rel="icon" type="image/svg+xml" href="/icon.png" />
|
||||
<script src="./theme.js"></script>
|
||||
<meta name="generator" content={Astro.generator} />
|
||||
<title>{title}</title>
|
||||
<title>{site} — {tagline}</title>
|
||||
</head>
|
||||
|
||||
<!-- Google tag (gtag.js) -->
|
||||
@@ -28,12 +30,21 @@ const { title } = Astro.props;
|
||||
</script>
|
||||
|
||||
<body>
|
||||
<button class="theme-toggle" id="theme-toggle" title="Toggles light & dark" aria-label="auto" aria-live="polite">
|
||||
<header class="nu-u-mb-10 nu-u-mt-12">
|
||||
<div class="container">
|
||||
<h1 class="nu-c-h3 nu-u-text--primary nu-u-mt-0 nu-u-mb-2 title">{title}</h1>
|
||||
<p class="nu-c-fs-normal nu-u-text--secondary">{tagline}</p>
|
||||
</div>
|
||||
</header>
|
||||
<div class="floating-nav btn-group">
|
||||
<a href="https://forms.gle/pzpG1cbxW6AA57uc9" target="_blank" class="submit-btn">Submit a new tool</a>
|
||||
<button class="theme-toggle" id="theme-toggle" title="Toggles light & dark" aria-label="auto" aria-live="polite">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none"><path fill="var(--icon-secondary)" fill-opacity=".16" d="M8.57 17.93A5.98 5.98 0 0 1 6 13c0-3.31 2.69-6 6-6s6 2.69 6 6c0 2.05-1.03 3.86-2.6 4.94"/><path stroke="var(--icon-secondary)" stroke-linecap="round" stroke-miterlimit="10" stroke-width="1.5" d="M12 4V2M3 13H1m22 0h-2m-1.222-7.778-1.414 1.414m-12.728 0L4.222 5.222M4 18h16M8 21h8m-7.43-3.07A5.98 5.98 0 0 1 6 13c0-3.31 2.69-6 6-6s6 2.69 6 6c0 2.05-1.03 3.86-2.6 4.94l-6.83-.01Z"/></svg>
|
||||
</button>
|
||||
</div>
|
||||
<slot />
|
||||
|
||||
<div class="footer">ᕦ(ò_óˇ)ᕤ <a href="https://forms.gle/pzpG1cbxW6AA57uc9" target="_blank" class="nu-u-link--subtle">Submit a new tool</a><br />Built with <a href="https://new-ui.com/?ref=riseofmachine" class="nu-u-link--subtle">New UI</a> </div>
|
||||
<div class="footer">ᕦ(ò_óˇ)ᕤ<br />Built with <a href="https://new-ui.com/?ref=riseofmachine" class="nu-u-link--subtle">New UI</a> </div>
|
||||
</body>
|
||||
</html>
|
||||
<style is:global>
|
||||
@@ -44,11 +55,55 @@ const { title } = Astro.props;
|
||||
}
|
||||
html { font-family: var(--system-ui); background-color: var(--background);}
|
||||
body { margin: 0; padding: 0;}
|
||||
main { margin: auto var(--spacing-09);}
|
||||
h1.title { margin-bottom: var(--spacing-10); color: var(--text-primary); margin-top: var(--spacing-12); }
|
||||
main, .container { margin: auto var(--spacing-09);}
|
||||
section { margin-bottom: var(--spacing-10);}
|
||||
p { margin-top: var(--spacing-00);}
|
||||
.nu-u-link--subtle { color: var(--text-secondary) !important;}
|
||||
.floating-nav {
|
||||
position: fixed;
|
||||
top: var(--spacing-07);
|
||||
right: var(--spacing-07);
|
||||
z-index: 999999;
|
||||
}
|
||||
.btn-group {
|
||||
display: flex;
|
||||
gap: var(--spacing-03);
|
||||
align-items: center;
|
||||
}
|
||||
.submit-btn {
|
||||
padding: 8px 24px;
|
||||
border: 1px solid var(--border-muted);
|
||||
outline: none;
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
cursor: pointer;
|
||||
color: var(--text-secondary);
|
||||
background-color: var(--background);
|
||||
box-shadow: none;
|
||||
border-radius: var(--spacing-03);
|
||||
|
||||
&:hover {
|
||||
background-color: var(--background-secondary);
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
&:active {
|
||||
background-color: var(--background);
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
&.disabled {
|
||||
background-color: var(--background);
|
||||
color: var(--icon-secondary);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
background-color: var(--background);
|
||||
outline: 1px solid var(--button-primary);
|
||||
color: var(--icon-secondary);
|
||||
}
|
||||
}
|
||||
.theme-toggle {
|
||||
z-index: 999;
|
||||
--icon-fill: var(--icon-secondary);
|
||||
@@ -62,14 +117,12 @@ const { title } = Astro.props;
|
||||
cursor: pointer;
|
||||
touch-action: manipulation;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
position: fixed;
|
||||
top: var(--spacing-07);
|
||||
right: var(--spacing-07);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border: 1px solid var(--border-muted);
|
||||
/* border: 1px solid var(--border-muted); */
|
||||
border-radius: var(--spacing-02);
|
||||
/* background-color: var(--background); */
|
||||
|
||||
@nest [data-theme="dark"] & { --icon-fill: var(--icon-secondary); --icon-fill-hover: var(--icon-secondary);}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,3 +1,7 @@
|
||||
{
|
||||
"extends": "astro/tsconfigs/strict"
|
||||
"extends": "astro/tsconfigs/strict",
|
||||
"compilerOptions": {
|
||||
"jsx": "react-jsx",
|
||||
"jsxImportSource": "react"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user