add template in hard
This commit is contained in:
4
front/vendor/README.md
vendored
Normal file
4
front/vendor/README.md
vendored
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**
|
114
front/vendor/integration/index.mjs
vendored
Normal file
114
front/vendor/integration/index.mjs
vendored
Normal file
@ -0,0 +1,114 @@
|
||||
import fs from 'node:fs';
|
||||
import os from 'node:os';
|
||||
|
||||
import configBuilder from './utils/configBuilder';
|
||||
import loadConfig from './utils/loadConfig';
|
||||
|
||||
export default ({ config: _themeConfig = 'src/config.yaml' } = {}) => {
|
||||
let cfg;
|
||||
return {
|
||||
name: 'astrowind-integration',
|
||||
|
||||
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 rawJsonConfig = await loadConfig(_themeConfig);
|
||||
const { SITE, I18N, METADATA, APP_BLOG, UI, ANALYTICS } = configBuilder(rawJsonConfig);
|
||||
|
||||
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)};
|
||||
`;
|
||||
}
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
if (typeof _themeConfig === 'string') {
|
||||
addWatchFile(new URL(_themeConfig, config.root));
|
||||
|
||||
buildLogger.info(`Astrowind \`${_themeConfig}\` has been loaded.`);
|
||||
} else {
|
||||
buildLogger.info(`Astrowind config has been loaded.`);
|
||||
}
|
||||
},
|
||||
'astro:config:done': async ({ config }) => {
|
||||
cfg = config;
|
||||
},
|
||||
|
||||
'astro:build:done': async ({ logger }) => {
|
||||
const buildLogger = logger.fork('astrowind');
|
||||
buildLogger.info('Updating `robots.txt` with `sitemap-index.xml` ...');
|
||||
|
||||
try {
|
||||
const outDir = cfg.outDir;
|
||||
const publicDir = cfg.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(cfg?.integrations) &&
|
||||
cfg.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(cfg.base, cfg.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 */
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
10
front/vendor/integration/types.d.ts
vendored
Normal file
10
front/vendor/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;
|
||||
}
|
201
front/vendor/integration/utils/configBuilder.ts
vendored
Normal file
201
front/vendor/integration/utils/configBuilder.ts
vendored
Normal file
@ -0,0 +1,201 @@
|
||||
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',
|
||||
};
|
||||
|
||||
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),
|
||||
});
|
16
front/vendor/integration/utils/loadConfig.ts
vendored
Normal file
16
front/vendor/integration/utils/loadConfig.ts
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
import fs from 'node:fs';
|
||||
import yaml from 'js-yaml';
|
||||
|
||||
const loadConfig = async (configPathOrData: string | object) => {
|
||||
if (typeof configPathOrData === 'string') {
|
||||
const content = fs.readFileSync(configPathOrData, 'utf8');
|
||||
if (configPathOrData.endsWith('.yaml') || configPathOrData.endsWith('.yml')) {
|
||||
return yaml.load(content);
|
||||
}
|
||||
return content;
|
||||
}
|
||||
|
||||
return configPathOrData;
|
||||
};
|
||||
|
||||
export default loadConfig;
|
Reference in New Issue
Block a user