-
Notifications
You must be signed in to change notification settings - Fork 42
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: Include individual text values for each font #149
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,11 @@ | ||
import { resolve } from 'pathe' | ||
import type { MetaObject } from '@nuxt/schema' | ||
import { defineNuxtModule, isNuxt2, resolvePath, useLogger } from '@nuxt/kit' | ||
import { constructURL, download, isValidURL, parse, merge, DownloadOptions, GoogleFonts } from 'google-fonts-helper' | ||
import { constructURL, download, isValidURL, parse, merge, DownloadOptions, GoogleFonts, FamilyWeight, FamilyStyles } from 'google-fonts-helper' | ||
import { name, version } from '../package.json' | ||
|
||
type NuxtAppHead = Required<MetaObject> | ||
type FamilyStylesExtended = FamilyStyles & { text?: string } | ||
|
||
export interface ModuleOptions extends DownloadOptions, GoogleFonts { | ||
prefetch?: boolean | ||
|
@@ -41,7 +42,7 @@ export default defineNuxtModule<ModuleOptions>({ | |
fontsDir: 'fonts', | ||
fontsPath: '../fonts' | ||
}, | ||
async setup (options, nuxt) { | ||
async setup(options, nuxt) { | ||
// If user hasn't set the display value manually and isn't using | ||
// a preload, set the default display value to 'swap' | ||
if (options.display === undefined && !options.preload) { | ||
|
@@ -65,12 +66,30 @@ export default defineNuxtModule<ModuleOptions>({ | |
.map(link => parse(String(link.href))) | ||
) | ||
|
||
|
||
// construct google fonts url | ||
const url = constructURL(merge(options, ...fontsParsed)) | ||
const fontOptionsList = Object.entries(merge(options, ...fontsParsed).families!).map(([font, value]: [string, FamilyStylesExtended|FamilyWeight] ) => { | ||
let currentOptions = options | ||
if (typeof value === 'object' && !Array.isArray(value) && value.text) { | ||
value | ||
currentOptions = { | ||
...currentOptions, | ||
text: value.text | ||
} | ||
delete value.text | ||
} | ||
|
||
if (!url) { | ||
logger.warn('No provided fonts.') | ||
return { | ||
...currentOptions, | ||
families: { [font]: value }, | ||
} | ||
}); | ||
|
||
|
||
const urls = fontOptionsList.map((result) => constructURL(result)).filter((url) => url !== false) as string[]; | ||
|
||
if (!urls.length) { | ||
logger.warn('No provided fonts.') | ||
return | ||
} | ||
|
||
|
@@ -80,36 +99,39 @@ export default defineNuxtModule<ModuleOptions>({ | |
// download | ||
if (options.download) { | ||
const outputDir = await resolvePath(options.outputDir) | ||
const outputFonts: string[] = [] | ||
|
||
try { | ||
const downloader = download(url, { | ||
base64: options.base64, | ||
overwriting: options.overwriting, | ||
outputDir, | ||
stylePath: options.stylePath, | ||
fontsDir: options.fontsDir, | ||
fontsPath: options.fontsPath | ||
}) | ||
|
||
const outputFonts: string[] = [] | ||
|
||
downloader.hook('download-css:done', (url) => { | ||
logger.success(url) | ||
}) | ||
|
||
downloader.hook('download-font:done', (font) => { | ||
const fontName = font.outputFont.replace(`-${font.outputFont.replace(/.*-/, '')}`, '') | ||
|
||
if (!outputFonts.includes(fontName)) { | ||
outputFonts.push(fontName) | ||
logger.info(fontName) | ||
} | ||
}) | ||
for (const url of urls) { | ||
const downloader = download(url, { | ||
base64: options.base64, | ||
overwriting: options.overwriting, | ||
outputDir, | ||
stylePath: options.stylePath, | ||
fontsDir: options.fontsDir, | ||
fontsPath: options.fontsPath | ||
}) | ||
|
||
|
||
downloader.hook('download-css:done', (url) => { | ||
logger.success(url) | ||
}) | ||
|
||
downloader.hook('download-font:done', (font) => { | ||
const fontName = font.outputFont.replace(`-${font.outputFont.replace(/.*-/, '')}`, '') | ||
|
||
if (!outputFonts.includes(fontName)) { | ||
outputFonts.push(fontName) | ||
logger.info(fontName) | ||
} | ||
}) | ||
|
||
logger.start('Downloading fonts...') | ||
await downloader.execute() | ||
logger.success('Download fonts completed.') | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add outside |
||
logger.log('') | ||
} | ||
|
||
logger.start('Downloading fonts...') | ||
await downloader.execute() | ||
logger.success('Download fonts completed.') | ||
logger.log('') | ||
|
||
if (options.inject) { | ||
nuxt.options.css.push(resolve(outputDir, options.stylePath)) | ||
|
@@ -158,66 +180,73 @@ export default defineNuxtModule<ModuleOptions>({ | |
// https://developer.mozilla.org/en-US/docs/Web/HTML/Link_types/preload | ||
// optionally increase loading priority | ||
if (options.preload) { | ||
head.link.push({ | ||
key: 'gf-preload', | ||
rel: 'preload', | ||
as: 'style', | ||
href: url | ||
}) | ||
for (const url of urls) { | ||
|
||
head.link.push({ | ||
key: 'gf-preload', | ||
rel: 'preload', | ||
as: 'style', | ||
href: url | ||
}) | ||
} | ||
} | ||
|
||
// append CSS | ||
if (options.useStylesheet) { | ||
head.link.push({ | ||
key: 'gf-style', | ||
rel: 'stylesheet', | ||
href: url | ||
}) | ||
|
||
for (const url of urls) { | ||
head.link.push({ | ||
key: 'gf-style', | ||
rel: 'stylesheet', | ||
href: url | ||
}) | ||
} | ||
return | ||
} | ||
|
||
if (isNuxt2()) { | ||
// JS to inject CSS | ||
head.script.push({ | ||
for (const url of urls) { | ||
head.script.push({ | ||
key: 'gf-script', | ||
innerHTML: `(function(){var l=document.createElement('link');l.rel="stylesheet";l.href="${url}";document.querySelector("head").appendChild(l);})();` | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe create a script to create the stylesheet. |
||
}) | ||
|
||
// no-JS fallback | ||
head.noscript.push({ | ||
key: 'gf-noscript', | ||
innerHTML: `<link rel="stylesheet" href="${url}">`, | ||
tagPosition: 'bodyOpen' | ||
}) | ||
|
||
// Disable sanitazions | ||
// @ts-ignore | ||
head.__dangerouslyDisableSanitizersByTagID = head.__dangerouslyDisableSanitizersByTagID || {} | ||
// @ts-ignore | ||
head.__dangerouslyDisableSanitizersByTagID['gf-script'] = ['innerHTML'] | ||
// @ts-ignore | ||
head.__dangerouslyDisableSanitizersByTagID['gf-noscript'] = ['innerHTML'] | ||
Comment on lines
+221
to
+227
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add outside |
||
} | ||
return | ||
} | ||
|
||
// JS to inject CSS | ||
for (const url of urls) { | ||
head.script.unshift({ | ||
key: 'gf-script', | ||
innerHTML: `(function(){var l=document.createElement('link');l.rel="stylesheet";l.href="${url}";document.querySelector("head").appendChild(l);})();` | ||
children: `(function(){ | ||
var h=document.querySelector("head"); | ||
var m=h.querySelector('meta[name="head:count"]'); | ||
if(m){m.setAttribute('content',Number(m.getAttribute('content'))+1);} | ||
else{m=document.createElement('meta');m.setAttribute('name','head:count');m.setAttribute('content','1');h.append(m);} | ||
var l=document.createElement('link');l.rel='stylesheet';l.href='${url}';h.appendChild(l); | ||
})();` | ||
Comment on lines
+236
to
+242
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe create a script to create the stylesheet. |
||
}) | ||
|
||
// no-JS fallback | ||
head.noscript.push({ | ||
key: 'gf-noscript', | ||
innerHTML: `<link rel="stylesheet" href="${url}">`, | ||
children: `<link rel="stylesheet" href="${url}">`, | ||
tagPosition: 'bodyOpen' | ||
}) | ||
|
||
// Disable sanitazions | ||
// @ts-ignore | ||
head.__dangerouslyDisableSanitizersByTagID = head.__dangerouslyDisableSanitizersByTagID || {} | ||
// @ts-ignore | ||
head.__dangerouslyDisableSanitizersByTagID['gf-script'] = ['innerHTML'] | ||
// @ts-ignore | ||
head.__dangerouslyDisableSanitizersByTagID['gf-noscript'] = ['innerHTML'] | ||
|
||
return | ||
} | ||
|
||
// JS to inject CSS | ||
head.script.unshift({ | ||
key: 'gf-script', | ||
children: `(function(){ | ||
var h=document.querySelector("head"); | ||
var m=h.querySelector('meta[name="head:count"]'); | ||
if(m){m.setAttribute('content',Number(m.getAttribute('content'))+1);} | ||
else{m=document.createElement('meta');m.setAttribute('name','head:count');m.setAttribute('content','1');h.append(m);} | ||
var l=document.createElement('link');l.rel='stylesheet';l.href='${url}';h.appendChild(l); | ||
})();` | ||
}) | ||
|
||
// no-JS fallback | ||
head.noscript.push({ | ||
children: `<link rel="stylesheet" href="${url}">`, | ||
tagPosition: 'bodyOpen' | ||
}) | ||
} | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add outside
for