Skip to content

Commit

Permalink
Create local integration for load config.yaml and more
Browse files Browse the repository at this point in the history
  • Loading branch information
prototypa committed Mar 29, 2024
1 parent 6fba1d5 commit 39dd121
Show file tree
Hide file tree
Showing 5 changed files with 358 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/env.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
/// <reference path="../.astro/types.d.ts" />
/// <reference types="astro/client" />
/// <reference types="vite/client" />
/// <reference types="../integration/types.d.ts" />
4 changes: 4 additions & 0 deletions src/integration/README.md
Original file line number Diff line number Diff line change
@@ -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 changes: 115 additions & 0 deletions src/integration/index.mjs
Original file line number Diff line number Diff line change
@@ -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 changes: 10 additions & 0 deletions src/integration/types.d.ts
Original file line number Diff line number Diff line change
@@ -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 changes: 228 additions & 0 deletions src/integration/utils/configBuilder.ts
Original file line number Diff line number Diff line change
@@ -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),
});

0 comments on commit 39dd121

Please sign in to comment.