Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ but intended to evolve over time with _community_ contributions.

Trying to figure out how to make it work? Or how to use it in your scenario?

1. Review the [README](README.md)
1. Review the [README](https://github.com/FortAwesome/react-fontawesome?tab=readme-ov-file)
2. Get familiar with the documentation for the [SVG with JavaScript](https://fontawesome.com/how-to-use/svg-with-js) implementation,
the framework upon which this component is built. Sometimes the answers you need may be there.
3. Post any remaining questions on [StackOverflow](https://stackoverflow.com/questions/tagged/react-fontawesome) with the tag `react-fontawesome`.
Expand Down
6 changes: 3 additions & 3 deletions docs/src/API-Reference-Readme.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Overview <i color="#428fdc" class="fa-solid fa-font-awesome" aria-label="FontAwesome"></i>
# Overview <i color="#428fdc" class="fa-solid fa-font-awesome"></i>

This documentation serves purely as an API Reference for the modules contained in the latest version of the `react-fontawesome` library.

Expand All @@ -15,8 +15,8 @@ For more detailed documentation on how to use FontAwesome with React in general,

In the side-bar menu, the top level items are the two key module entry points that are exported by the library:

- `index` - includes anything exported via the main entry point
- `main` - includes anything exported via the main entry point
- e.g. `import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'`
- `components/rsc/CustomPrefixProvider` - special module for using custom FA prefixes with server-side rendering
- `CustomPrefixProvider` - special module for using custom FA prefixes with server-side rendering
- e.g. `import { CustomPrefixProvider } from '@fortawesome/react-fontawesome/components/rsc/CustomPrefixProvider'`
- `<internal>` - refers to types and interfaces that are used internally within the package but are not exported by the package to consumers
6 changes: 3 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions src/components/rsc/CustomPrefixProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
/** @module CustomPrefixProvider */

'use client'

import { config } from '@fortawesome/fontawesome-svg-core'
Expand Down
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/** @module main */
export * from './components/FontAwesomeIcon'
export * from './components/FontAwesomeLayers'
export * from './types/animation-props'
Expand Down
116 changes: 110 additions & 6 deletions typedoc.config.mjs
Original file line number Diff line number Diff line change
@@ -1,40 +1,138 @@
import { cp, mkdir, readdir } from 'node:fs/promises'
import path from 'node:path'
import fs from 'node:fs'
import { JSX } from 'typedoc'

/**
* Custom TypeDoc plugin to insert FontAwesome into the generated documentation.
* @type {(app: import('typedoc').Application) => void}
* Custom TypeDoc plugin.
* @param {import('typedoc').Application} app
*/
function customPlugin(app) {
/**
* Remove `.html` from internal links while preserving query/hash fragments.
* External links are left untouched.
* @param {string} href
*/
function toExtensionlessHref(href, ignoreAbsolute = true) {
// Ignore absolute/protocol links and special schemes.
if (
ignoreAbsolute &&
(/^(?:[a-z][a-z\d+.-]*:)?\/\//i.test(href) ||
/^[a-z][a-z\d+.-]*:/i.test(href))
) {
return href
}

const [withoutHash, hash = ''] = href.split('#', 2)
const [pathname, query = ''] = withoutHash.split('?', 2)

let nextPath = pathname
if (nextPath.endsWith('/index.html')) {
nextPath = nextPath.slice(0, -'index.html'.length)
} else if (nextPath === 'index.html') {
nextPath = './'
} else if (nextPath.endsWith('.html')) {
nextPath = nextPath.slice(0, -'.html'.length)
}

const rebuilt = `${nextPath}${query ? `?${query}` : ''}`
return `${rebuilt}${hash ? `#${hash}` : ''}`
}

// Insert FontAwesome CSS into the head of the generated documentation
app.renderer.hooks.on('head.end', (_context) => {
return JSX.createElement('link', {
rel: 'stylesheet',
href: 'https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@7.2.0/css/fontawesome.min.css',
})
})

// Insert FontAwesome JS into the body of the generated documentation
app.renderer.hooks.on('body.end', (_context) => {
return JSX.createElement('script', {
src: 'https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@7.2.0/js/all.min.js',
defer: true,
})
})

// Rewrite generated internal links to extensionless paths.
app.renderer.on('endPage', (page) => {
if (!page.contents) {
return
}

page.contents = page.contents.replaceAll(
/href="([^"]+)"/g,
(_match, href) => {
return `href="${toExtensionlessHref(href)}"`
},
)
})

app.renderer.postRenderAsyncJobs.push(async (event) => {
// Create `name/index.html` aliases for root-level `name.html` pages.
const rootEntries = await readdir(event.outputDirectory, {
withFileTypes: true,
})
const rootHtmlFiles = rootEntries.filter(
(entry) =>
entry.isFile() &&
entry.name.endsWith('.html') &&
entry.name !== 'index.html' &&
entry.name !== '404.html',
)

await Promise.all(
rootHtmlFiles.map(async (entry) => {
const fileName = entry.name
const basename = fileName.slice(0, -'.html'.length)
const source = path.join(event.outputDirectory, fileName)
const targetDir = path.join(event.outputDirectory, basename)
const target = path.join(targetDir, 'index.html')

await mkdir(targetDir, { recursive: true })
await cp(source, target)
}),
)

// Rewrite the `.html` extension from the generated `sitemap.xml` as well.
const sitemapPath = path.join(event.outputDirectory, 'sitemap.xml')
try {
const sitemapContents = fs.readFileSync(sitemapPath).toString('utf-8')
const rewritten = sitemapContents
.toString()
.replaceAll(/<loc>([^<]+)<\/loc>/g, (_match, loc) => {
return `<loc>${toExtensionlessHref(loc, false)}</loc>`
})
await fs.writeFile(sitemapPath, rewritten, () => {})
} catch (err) {
// If the sitemap doesn't exist, ignore the error and continue.
if (err.code !== 'ENOENT') {
throw err
}
}
})
}

/** @type {Partial<import('typedoc').TypeDocOptions> & Partial<import('typedoc-plugin-merge-modules').Config> & import('typedoc-plugin-umami-analytics').Config} */
const config = {
cleanOutputDir: true,
commentStyle: 'all',
customFooterHtml:
'Built with <i color="#f31e1e" class="fa-solid fa-heart" aria-label="love"></i> by the <a href="https://fontawesome.com/">FontAwesome Team</a> and <a href="https://github.com/FortAwesome/react-fontawesome/graphs/contributors">community contributors</a>.',
entryPoints: ['./src/index.ts', './src/components/rsc/*.tsx'],
entryPointStrategy: 'resolve',
// entryPointStrategy: 'resolve',
excludeExternals: true,
excludeNotDocumented: false,
// Ensure references from @fortawesome packages are not considered external and therefore excluded, e.g. svg-core & common-types (we want them included)
externalPattern: ['**/node_modules/!(@fortawesome)/**'],
githubPages: true,
gitRemote: 'origin',
gitRevision: 'main',
favicon: './docs/src/assets/favicon.ico',
hideGenerator: true,
hostedBaseUrl: 'https://fortawesome.github.io/react-fontawesome/',
markdownLinkExternal: true,
mergeModulesMergeMode: 'module',
mergeModulesRenameDefaults: true,
name: 'FontAwesome React API Reference',
Expand All @@ -53,20 +151,26 @@ const config = {
'typedoc-plugin-umami-analytics',
customPlugin,
],
projectDocuments: ['./CHANGELOG.md'],
projectDocuments: [
'./CHANGELOG.md',
'./CONTRIBUTING.md',
'./CODE_OF_CONDUCT.md',
],
readme: './docs/src/API-Reference-Readme.md',
router: 'structure',
router: 'structure-dir',
sort: [
'required-first',
'kind',
'instance-first',
'alphabetical-ignoring-documents',
],
tsconfig: './tsconfig.json',
sourceLinkExternal: true,
theme: 'typedoc-github-theme',
tsconfig: './tsconfig.json',
umamiScriptURL: 'https://analytics.charlesharwood.dev/script.js',
umamiWebsiteID: 'd0b01ae4-f0b1-4f6c-8967-6a9c1504cd49',
useFirstParagraphOfCommentAsSummary: true,
visibilityFilters: {},
}

export default config
Loading