Create local integration for load config.yaml and more
This commit is contained in:
1
src/env.d.ts
vendored
1
src/env.d.ts
vendored
@@ -2,3 +2,4 @@
|
|||||||
/// <reference path="../.astro/types.d.ts" />
|
/// <reference path="../.astro/types.d.ts" />
|
||||||
/// <reference types="astro/client" />
|
/// <reference types="astro/client" />
|
||||||
/// <reference types="vite/client" />
|
/// <reference types="vite/client" />
|
||||||
|
/// <reference types="../integration/types.d.ts" />
|
||||||
|
4
src/integration/README.md
Normal file
4
src/integration/README.md
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
This folder will become an integration for **AstroWind**.
|
||||||
|
|
||||||
|
We are working to allow updates to template instances.
|
||||||
|
These are changes on the way to new **AstroWind v2**
|
115
src/integration/index.mjs
Normal file
115
src/integration/index.mjs
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
import fs from 'node:fs';
|
||||||
|
import os from 'node:os';
|
||||||
|
|
||||||
|
import yaml from 'js-yaml';
|
||||||
|
|
||||||
|
import configBuilder from "./utils/configBuilder"
|
||||||
|
|
||||||
|
const tasksIntegration = () => {
|
||||||
|
let config;
|
||||||
|
return {
|
||||||
|
name: 'AstroWind:tasks',
|
||||||
|
|
||||||
|
hooks: {
|
||||||
|
'astro:config:setup': async ({
|
||||||
|
// command,
|
||||||
|
config,
|
||||||
|
// injectRoute,
|
||||||
|
// isRestart,
|
||||||
|
logger,
|
||||||
|
updateConfig,
|
||||||
|
addWatchFile
|
||||||
|
}) => {
|
||||||
|
|
||||||
|
const buildLogger = logger.fork("astrowind");
|
||||||
|
|
||||||
|
const virtualModuleId = 'astrowind:config';
|
||||||
|
const resolvedVirtualModuleId = '\0' + virtualModuleId;
|
||||||
|
|
||||||
|
const fileConfig = yaml.load(fs.readFileSync('src/config.yaml', 'utf8'));
|
||||||
|
const { SITE, I18N, METADATA, APP_BLOG, UI, ANALYTICS } = configBuilder(fileConfig);
|
||||||
|
|
||||||
|
updateConfig({
|
||||||
|
site: SITE.site,
|
||||||
|
base: SITE.base,
|
||||||
|
|
||||||
|
trailingSlash: SITE.trailingSlash ? 'always' : 'never',
|
||||||
|
|
||||||
|
vite: {
|
||||||
|
plugins: [
|
||||||
|
{
|
||||||
|
name: 'vite-plugin-astrowind-config',
|
||||||
|
resolveId(id) {
|
||||||
|
if (id === virtualModuleId) {
|
||||||
|
return resolvedVirtualModuleId;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
load(id) {
|
||||||
|
if (id === resolvedVirtualModuleId) {
|
||||||
|
return `
|
||||||
|
export const SITE = ${JSON.stringify(SITE)};
|
||||||
|
export const I18N = ${JSON.stringify(I18N)};
|
||||||
|
export const METADATA = ${JSON.stringify(METADATA)};
|
||||||
|
export const APP_BLOG = ${JSON.stringify(APP_BLOG)};
|
||||||
|
export const UI = ${JSON.stringify(UI)};
|
||||||
|
export const ANALYTICS = ${JSON.stringify(ANALYTICS)};
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
addWatchFile(new URL('./src/config.yaml', config.root));
|
||||||
|
|
||||||
|
buildLogger.info("Astrowind `src/config.yaml` has been loaded.")
|
||||||
|
},
|
||||||
|
'astro:config:done': async ({ config: cfg }) => {
|
||||||
|
config = cfg;
|
||||||
|
},
|
||||||
|
|
||||||
|
'astro:build:done': async ({ logger }) => {
|
||||||
|
|
||||||
|
const buildLogger = logger.fork("astrowind");
|
||||||
|
buildLogger.info("Updating `robots.txt` with `sitemap-index.xml` ...")
|
||||||
|
|
||||||
|
try {
|
||||||
|
const outDir = config.outDir;
|
||||||
|
const publicDir = config.publicDir;
|
||||||
|
const sitemapName = 'sitemap-index.xml';
|
||||||
|
const sitemapFile = new URL(sitemapName, outDir);
|
||||||
|
const robotsTxtFile = new URL('robots.txt', publicDir);
|
||||||
|
const robotsTxtFileInOut = new URL('robots.txt', outDir);
|
||||||
|
|
||||||
|
const hasIntegration =
|
||||||
|
Array.isArray(config?.integrations) &&
|
||||||
|
config.integrations?.find((e) => e?.name === '@astrojs/sitemap') !== undefined;
|
||||||
|
const sitemapExists = fs.existsSync(sitemapFile);
|
||||||
|
|
||||||
|
if (hasIntegration && sitemapExists) {
|
||||||
|
const robotsTxt = fs.readFileSync(robotsTxtFile, { encoding: 'utf8', flags: 'a+' });
|
||||||
|
const sitemapUrl = new URL(sitemapName, String(new URL(config.base, config.site)));
|
||||||
|
const pattern = /^Sitemap:(.*)$/m;
|
||||||
|
|
||||||
|
if (!pattern.test(robotsTxt)) {
|
||||||
|
fs.appendFileSync(robotsTxtFileInOut, `${os.EOL}${os.EOL}Sitemap: ${sitemapUrl}`, {
|
||||||
|
encoding: 'utf8',
|
||||||
|
flags: 'w',
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
fs.writeFileSync(robotsTxtFileInOut, robotsTxt.replace(pattern, `Sitemap: ${sitemapUrl}`), {
|
||||||
|
encoding: 'utf8',
|
||||||
|
flags: 'w',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
/* empty */
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export default tasksIntegration;
|
10
src/integration/types.d.ts
vendored
Normal file
10
src/integration/types.d.ts
vendored
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
declare module 'astrowind:config' {
|
||||||
|
import type { SiteConfig, I18NConfig, MetaDataConfig, AppBlogConfig, UIConfig, AnalyticsConfig } from "./config"
|
||||||
|
|
||||||
|
export const SITE: SiteConfig;
|
||||||
|
export const I18N : I18NConfig;
|
||||||
|
export const METADATA: MetaDataConfig;
|
||||||
|
export const APP_BLOG : AppBlogConfig;
|
||||||
|
export const UI : UIConfig;
|
||||||
|
export const ANALYTICS : AnalyticsConfig;
|
||||||
|
}
|
228
src/integration/utils/configBuilder.ts
Normal file
228
src/integration/utils/configBuilder.ts
Normal file
@@ -0,0 +1,228 @@
|
|||||||
|
import merge from 'lodash.merge';
|
||||||
|
|
||||||
|
import type { MetaData } from '~/types';
|
||||||
|
|
||||||
|
type Config = {
|
||||||
|
site?: SiteConfig;
|
||||||
|
metadata?: MetaDataConfig;
|
||||||
|
i18n?: I18NConfig;
|
||||||
|
apps?: {
|
||||||
|
blog?: AppBlogConfig;
|
||||||
|
};
|
||||||
|
ui?: unknown;
|
||||||
|
analytics?: unknown;
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface SiteConfig {
|
||||||
|
name: string;
|
||||||
|
site?: string;
|
||||||
|
base?: string;
|
||||||
|
trailingSlash?: boolean;
|
||||||
|
googleSiteVerificationId?: string;
|
||||||
|
}
|
||||||
|
export interface MetaDataConfig extends Omit<MetaData, 'title'> {
|
||||||
|
title?: {
|
||||||
|
default: string;
|
||||||
|
template: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
export interface I18NConfig {
|
||||||
|
language: string;
|
||||||
|
textDirection: string;
|
||||||
|
dateFormatter?: Intl.DateTimeFormat;
|
||||||
|
}
|
||||||
|
export interface AppBlogConfig {
|
||||||
|
isEnabled: boolean;
|
||||||
|
postsPerPage: number;
|
||||||
|
isRelatedPostsEnabled: boolean;
|
||||||
|
relatedPostsCount: number;
|
||||||
|
post: {
|
||||||
|
isEnabled: boolean;
|
||||||
|
permalink: string;
|
||||||
|
robots: {
|
||||||
|
index: boolean;
|
||||||
|
follow: boolean;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
list: {
|
||||||
|
isEnabled: boolean;
|
||||||
|
pathname: string;
|
||||||
|
robots: {
|
||||||
|
index: boolean;
|
||||||
|
follow: boolean;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
category: {
|
||||||
|
isEnabled: boolean;
|
||||||
|
pathname: string;
|
||||||
|
robots: {
|
||||||
|
index: boolean;
|
||||||
|
follow: boolean;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
tag: {
|
||||||
|
isEnabled: boolean;
|
||||||
|
pathname: string;
|
||||||
|
robots: {
|
||||||
|
index: boolean;
|
||||||
|
follow: boolean;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
export interface AnalyticsConfig {
|
||||||
|
vendors: {
|
||||||
|
googleAnalytics: {
|
||||||
|
id?: string;
|
||||||
|
partytown?: boolean;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UIConfig {}
|
||||||
|
|
||||||
|
const DEFAULT_SITE_NAME = 'Website';
|
||||||
|
|
||||||
|
const getSite = (config: Config) => {
|
||||||
|
const _default = {
|
||||||
|
name: DEFAULT_SITE_NAME,
|
||||||
|
site: undefined,
|
||||||
|
base: '/',
|
||||||
|
trailingSlash: false,
|
||||||
|
|
||||||
|
googleSiteVerificationId: '',
|
||||||
|
};
|
||||||
|
|
||||||
|
return merge({}, _default, config?.site ?? {}) as SiteConfig;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getMetadata = (config: Config) => {
|
||||||
|
const siteConfig = getSite(config);
|
||||||
|
|
||||||
|
const _default = {
|
||||||
|
title: {
|
||||||
|
default: siteConfig?.name || DEFAULT_SITE_NAME,
|
||||||
|
template: '%s',
|
||||||
|
},
|
||||||
|
description: '',
|
||||||
|
robots: {
|
||||||
|
index: false,
|
||||||
|
follow: false,
|
||||||
|
},
|
||||||
|
openGraph: {
|
||||||
|
type: 'website',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
return merge({}, _default, config?.metadata ?? {}) as MetaDataConfig;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getI18N = (config: Config) => {
|
||||||
|
const _default = {
|
||||||
|
language: 'en',
|
||||||
|
textDirection: 'ltr',
|
||||||
|
};
|
||||||
|
|
||||||
|
const value = merge({}, _default, config?.i18n ?? {});
|
||||||
|
|
||||||
|
return value as I18NConfig;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getAppBlog = (config: Config) => {
|
||||||
|
const _default = {
|
||||||
|
isEnabled: false,
|
||||||
|
postsPerPage: 6,
|
||||||
|
isRelatedPostsEnabled: false,
|
||||||
|
relatedPostsCount: 4,
|
||||||
|
post: {
|
||||||
|
isEnabled: true,
|
||||||
|
permalink: '/blog/%slug%',
|
||||||
|
robots: {
|
||||||
|
index: true,
|
||||||
|
follow: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
list: {
|
||||||
|
isEnabled: true,
|
||||||
|
pathname: 'blog',
|
||||||
|
robots: {
|
||||||
|
index: true,
|
||||||
|
follow: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
category: {
|
||||||
|
isEnabled: true,
|
||||||
|
pathname: 'category',
|
||||||
|
robots: {
|
||||||
|
index: true,
|
||||||
|
follow: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
tag: {
|
||||||
|
isEnabled: true,
|
||||||
|
pathname: 'tag',
|
||||||
|
robots: {
|
||||||
|
index: false,
|
||||||
|
follow: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
return merge({}, _default, config?.apps?.blog ?? {}) as AppBlogConfig;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getUI = (config: Config) => {
|
||||||
|
const _default = {
|
||||||
|
theme: 'system',
|
||||||
|
classes: {},
|
||||||
|
tokens: {
|
||||||
|
default: {
|
||||||
|
fonts: {},
|
||||||
|
colors: {
|
||||||
|
default: 'rgb(16 16 16)',
|
||||||
|
heading: 'rgb(0 0 0)',
|
||||||
|
muted: 'rgb(16 16 16 / 66%)',
|
||||||
|
bgPage: 'rgb(255 255 255)',
|
||||||
|
primary: 'rgb(1 97 239)',
|
||||||
|
secondary: 'rgb(1 84 207)',
|
||||||
|
accent: 'rgb(109 40 217)',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
dark: {
|
||||||
|
fonts: {},
|
||||||
|
colors: {
|
||||||
|
default: 'rgb(229 236 246)',
|
||||||
|
heading: 'rgb(247, 248, 248)',
|
||||||
|
muted: 'rgb(229 236 246 / 66%)',
|
||||||
|
bgPage: 'rgb(3 6 32)',
|
||||||
|
primary: 'rgb(1 97 239)',
|
||||||
|
secondary: 'rgb(1 84 207)',
|
||||||
|
accent: 'rgb(109 40 217)',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
return merge({}, _default, config?.ui ?? {});
|
||||||
|
};
|
||||||
|
|
||||||
|
const getAnalytics = (config: Config) => {
|
||||||
|
const _default = {
|
||||||
|
vendors: {
|
||||||
|
googleAnalytics: {
|
||||||
|
id: undefined,
|
||||||
|
partytown: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
return merge({}, _default, config?.analytics ?? {}) as AnalyticsConfig;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default (config: Config) => ({
|
||||||
|
SITE: getSite(config),
|
||||||
|
I18N: getI18N(config),
|
||||||
|
METADATA: getMetadata(config),
|
||||||
|
APP_BLOG: getAppBlog(config),
|
||||||
|
UI: getUI(config),
|
||||||
|
ANALYTICS: getAnalytics(config),
|
||||||
|
});
|
Reference in New Issue
Block a user