generated from rdilweb/template-docusaurus-plugin
-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Reece Dunham <me@rdil.rocks>
- Loading branch information
Showing
5 changed files
with
334 additions
and
107 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,129 +1,190 @@ | ||
import type { LoadContext, Props } from "@docusaurus/types" | ||
import type { LoadContext } from "@docusaurus/types" | ||
import type commander from "commander" | ||
import axios from "axios" | ||
import { writeFileSync } from "fs" | ||
import { join } from "path" | ||
import { sync as delFile } from "rimraf" | ||
import chalk from "chalk" | ||
import milli from "pretty-ms" | ||
|
||
/** | ||
* The plugin's options. | ||
*/ | ||
export interface RemoteContentPluginOptions { | ||
/** | ||
* Delete local content after everything? | ||
*/ | ||
performCleanup?: boolean | ||
|
||
/** | ||
* Is this instance for the docs plugin? | ||
*/ | ||
docsIntegration?: boolean | ||
/** | ||
* Is this instance for the blog plugin? | ||
*/ | ||
blogIntegration?: boolean | ||
|
||
/** | ||
* The base url for the source of the content. | ||
*/ | ||
sourceBaseUrl: string | ||
/** | ||
* Specify the document paths from the sourceBaseUrl | ||
* in a string array or function that returns a string array. | ||
*/ | ||
documents?: string[] | (() => string[]) | ||
/** | ||
* Delete local content after everything? | ||
*/ | ||
performCleanup?: boolean | ||
/** | ||
* CLI only mode | ||
*/ | ||
noRuntimeDownloads?: boolean | ||
|
||
/** | ||
* Is this instance for the docs plugin? | ||
*/ | ||
docsIntegration?: boolean | ||
/** | ||
* Is this instance for the blog plugin? | ||
*/ | ||
blogIntegration?: boolean | ||
|
||
/** | ||
* The base url for the source of the content. | ||
*/ | ||
sourceBaseUrl: string | ||
/** | ||
* Specify the document paths from the sourceBaseUrl | ||
* in a string array or function that returns a string array. | ||
*/ | ||
documents?: string[] | (() => string[]) | ||
} | ||
|
||
export type LoadableContent = void | ||
|
||
interface Collectable { | ||
url: string | ||
identifier: string | ||
url: string | ||
identifier: string | ||
} | ||
|
||
// @ts-ignore | ||
export default class PluginRemoteContent extends Plugin<LoadableContent, RemoteContentPluginOptions> { | ||
name = "docusaurus-plugin-remote-content" | ||
|
||
options: RemoteContentPluginOptions | ||
context: LoadContext | ||
|
||
constructor(context: LoadContext, options: RemoteContentPluginOptions) { | ||
super(options, context) | ||
|
||
this.options = options | ||
this.context = context | ||
|
||
this.onLoad() | ||
} | ||
|
||
onLoad(): void { | ||
let { blogIntegration, docsIntegration, sourceBaseUrl, documents } = this.options | ||
|
||
if (!([blogIntegration, docsIntegration].includes(true))) { | ||
throw new Error("No integrations enabled! Please enable one of the blogIntegration, docsIntegration, or pagesIntegration fields in your remote-content plugin options.") | ||
} | ||
|
||
if (documents === undefined) { | ||
throw new Error("The documents field is undefined, so I don't know what to fetch!") | ||
} | ||
|
||
if (sourceBaseUrl === undefined) { | ||
throw new Error("The sourceBaseUrl field is undefined, so I don't know where to fetch from!") | ||
} | ||
|
||
if (!sourceBaseUrl.endsWith("/")) { | ||
sourceBaseUrl = `${sourceBaseUrl}/` | ||
export default function pluginRemoteContent( | ||
context: LoadContext, | ||
options: RemoteContentPluginOptions | ||
): any { | ||
let { | ||
blogIntegration, | ||
docsIntegration, | ||
sourceBaseUrl, | ||
documents, | ||
noRuntimeDownloads, | ||
performCleanup, | ||
} = options | ||
|
||
if (![blogIntegration, docsIntegration].includes(true)) { | ||
throw new Error( | ||
"No integrations enabled! Please enable either the blogIntegration or docsIntegration fields in your remote-content plugin options." | ||
) | ||
} | ||
|
||
if (documents === undefined) { | ||
throw new Error( | ||
"The documents field is undefined, so I don't know what to fetch!" | ||
) | ||
} | ||
|
||
if (sourceBaseUrl === undefined) { | ||
throw new Error( | ||
"The sourceBaseUrl field is undefined, so I don't know where to fetch from!" | ||
) | ||
} | ||
|
||
if (!sourceBaseUrl.endsWith("/")) { | ||
sourceBaseUrl = `${sourceBaseUrl}/` | ||
} | ||
|
||
function findCollectables(): Collectable[] { | ||
const a: Collectable[] = [] | ||
|
||
if (docsIntegration === true || blogIntegration === true) { | ||
;((typeof documents == "function" | ||
? documents.call(context.siteConfig) | ||
: documents) as string[]).forEach((d) => { | ||
if (d.endsWith("md")) { | ||
a.push({ url: `${sourceBaseUrl}/${d}`, identifier: d }) | ||
} else { | ||
a.push({ url: `${sourceBaseUrl}/${d}.md`, identifier: `${d}.md` }) | ||
} | ||
}) | ||
} | ||
|
||
findCollectables(): Collectable[] { | ||
const { documents, sourceBaseUrl } = this.options | ||
const a: Collectable[] = [] | ||
|
||
if (this.options.docsIntegration === true) { | ||
( | ||
(typeof documents == "function" ? documents.call(this.context.siteConfig) : documents) as string[] | ||
).forEach((d) => { | ||
if (d.endsWith("md")) { | ||
a.push({ url: `${sourceBaseUrl}/${d}`, identifier: d }) | ||
} else { | ||
a.push({ url: `${sourceBaseUrl}/${d}.md`, identifier: `${d}.md` }) | ||
} | ||
}) | ||
} | ||
return a | ||
} | ||
|
||
return a | ||
function getTargetDirectory(): string { | ||
if (docsIntegration) { | ||
return join(context.siteDir, "docs") | ||
} | ||
|
||
async loadContent(): Promise<LoadableContent> { | ||
const c = this.findCollectables() | ||
let loc = "" | ||
|
||
if (this.options.docsIntegration) { | ||
loc = join(this.context.siteDir, "docs") | ||
} | ||
|
||
if (this.options.blogIntegration) { | ||
loc = join(this.context.siteDir, "blog") | ||
} | ||
|
||
for (let i = 0; i < c.length; i++) { | ||
writeFileSync(join(loc, c[i].identifier), await (await axios({ url: c[i].url })).data) | ||
} | ||
if (blogIntegration) { | ||
return join(context.siteDir, "blog") | ||
} | ||
|
||
async contentLoaded(): Promise<void> { | ||
// The contentLoaded hook is done after loadContent hook is done. | ||
} | ||
return "" | ||
} | ||
|
||
async postBuild(props: Props): Promise<void> { | ||
// After docusaurus <build> finish. | ||
} | ||
// 'this' is a huge mess in JS, so we avoid that where we can, such as here. | ||
const pluginReturn = { | ||
name: `docusaurus-plugin-remote-content-${ | ||
[blogIntegration && "blog", docsIntegration && "docs"].filter(Boolean)[0] | ||
}`, | ||
|
||
async loadContent(): Promise<LoadableContent> { | ||
if ([false, undefined].includes(noRuntimeDownloads)) { | ||
return await pluginReturn.fetchContent() | ||
} | ||
}, | ||
|
||
async postBuild(): Promise<void> { | ||
if (performCleanup !== false) { | ||
return await pluginReturn.cleanContent() | ||
} | ||
}, | ||
|
||
async fetchContent(): Promise<void> { | ||
const c = findCollectables() | ||
|
||
for (let i = 0; i < c.length; i++) { | ||
writeFileSync( | ||
join(getTargetDirectory(), c[i].identifier), | ||
await (await axios({ url: c[i].url })).data | ||
) | ||
} | ||
}, | ||
|
||
async cleanContent(): Promise<void> { | ||
const c = findCollectables() | ||
|
||
for (let i = 0; i < c.length; i++) { | ||
delFile(join(getTargetDirectory(), c[i].identifier)) | ||
} | ||
}, | ||
|
||
extendCli(cli: commander.CommanderStatic): void { | ||
cli | ||
.command("dothing") | ||
.description("Does something") | ||
.action(() => {}) | ||
} | ||
const t = [blogIntegration && "blog", docsIntegration && "docs"].filter( | ||
Boolean | ||
)[0] | ||
|
||
cli | ||
.command(`download-remote-${t}`) | ||
.description(`Downloads the remote ${t} data.`) | ||
.action(() => { | ||
;(async () => { | ||
const startTime = new Date() | ||
await pluginReturn.fetchContent() | ||
console.log( | ||
chalk`{green Successfully fetched content in} {white ${milli( | ||
(new Date() as any) - (startTime as any) | ||
)}}{green !}` | ||
) | ||
})() | ||
}) | ||
|
||
cli | ||
.command(`clear-remote-${t}`) | ||
.description(`Removes the local copy of the remote ${t} data.`) | ||
.action(() => { | ||
;(async () => { | ||
const startTime = new Date() | ||
await pluginReturn.cleanContent() | ||
console.log( | ||
chalk`{green Successfully deleted content in} {white ${milli( | ||
(new Date() as any) - (startTime as any) | ||
)}}{green !}` | ||
) | ||
})() | ||
}) | ||
}, | ||
} | ||
|
||
return pluginReturn | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,3 +18,5 @@ | |
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* | ||
|
||
docs/api.md |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.