diff --git a/README.md b/README.md index 36dc6b3..619a177 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,7 @@ -# typedoc-plugin-pages +# typedoc-plugin-loopingz-pages + +The project is a fork of [typedoc-plugin-pages](https://github.com/mipatterson/typedoc-plugin-pages) +The original author seems to be busy, so creating the fork > A TypeDoc plugin that lets you integrate your own pages into the documentation output diff --git a/docs-source/configuration/configuration-file.md b/docs-source/configuration/configuration-file.md index da78a9f..f9b84a1 100644 --- a/docs-source/configuration/configuration-file.md +++ b/docs-source/configuration/configuration-file.md @@ -18,11 +18,16 @@ If you are configuring TypeDoc via the `typedoc.json` configuration file, you ca "theme": "pages-plugin", "pages": { "groups": [], - "output": "pages" + "output": "pages", + "autoDetectPageTitle": true } } ``` +``` +autoDetectPageTitle: boolean // Use title from first line of Markdown files +``` + ## 2. Use a dedicated `pagesconfig.json` file If you are not using a `typedoc.json` configuration file, or if you would like to separate your plugin configuration from the TypeDoc configuration, you can define your plugin configuration in a `pagesconfig.json` file in the directory where TypeDoc will be executed from: diff --git a/package.json b/package.json index b5629fa..9fc5eb4 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "typedoc-plugin-pages", + "name": "typedoc-plugin-loopingz-pages", "version": "0.0.1", "description": "A TypeDoc plugin that lets you integrate your own pages into the documentation output", "main": "dist/plugin/index.js", diff --git a/src/options/models/child-page-definition.ts b/src/options/models/child-page-definition.ts index 6699f34..285fdea 100644 --- a/src/options/models/child-page-definition.ts +++ b/src/options/models/child-page-definition.ts @@ -7,5 +7,5 @@ export interface ChildPageDefinition { output?: string; source: string; - title: string; + title?: string; } diff --git a/src/options/models/plugin-options.ts b/src/options/models/plugin-options.ts index a8ad3a8..851826d 100644 --- a/src/options/models/plugin-options.ts +++ b/src/options/models/plugin-options.ts @@ -70,10 +70,18 @@ export interface PluginOptions { */ replaceGlobalsPage?: boolean; + /** + * Use first line title '# Title' if markdown starts with '# ' + * + * This defaults to false + */ + autoDetectPageTitle?: boolean; + /** * Root directory where all page source files live * * By default this will point to the directory that TypeDoc is run from. */ source?: string; + } diff --git a/src/options/option-validator.ts b/src/options/option-validator.ts index d2d40f5..8d464c1 100644 --- a/src/options/option-validator.ts +++ b/src/options/option-validator.ts @@ -7,7 +7,7 @@ import { ChildPageDefinition, PageDefinition, PageGroupDefinition, PluginOptions import { defaultOptionAndValidateIsArray, defaultOptionAndValidateIsBoolean, defaultOptionAndValidateIsString, validateOptionIsArray, validateOptionIsString } from "./validation-utilities"; import * as Constants from "../constants"; -import { join } from "path"; +import { basename, join } from "path"; import { ensurePathHasExtension, getFilename } from "../utilities/path-utilities"; /** @@ -78,8 +78,8 @@ export class OptionValidator { private _validatePage(definition: PageDefinition|ChildPageDefinition, sourcePrefix: string, isChild: boolean): void { try { - validateOptionIsString(definition, "title"); validateOptionIsString(definition, "source"); + defaultOptionAndValidateIsString(definition, "title", basename(definition.source)); defaultOptionAndValidateIsString(definition, "output", getFilename(definition.source, true)); // Use source file name as default output file name diff --git a/src/pages/models/base-item.ts b/src/pages/models/base-item.ts index ffb5ef7..d198b45 100644 --- a/src/pages/models/base-item.ts +++ b/src/pages/models/base-item.ts @@ -3,7 +3,7 @@ * @module Models */ -import { join } from "path"; +import { basename, join } from "path"; import { ChildPageDefinition, PageDefinition, PageGroupDefinition, PageSectionDefinition } from "../../options/models/"; // TODO: Document this @@ -12,7 +12,7 @@ export abstract class BaseItem { protected _url: string; constructor(definition: PageDefinition|ChildPageDefinition|PageSectionDefinition|PageGroupDefinition, urlPrefix: string) { - this._title = definition.title; + this._title = definition.title || basename(definition.source); this._url = join(urlPrefix, definition.output); } diff --git a/src/pages/models/page-base.ts b/src/pages/models/page-base.ts index b2f80da..f04a444 100644 --- a/src/pages/models/page-base.ts +++ b/src/pages/models/page-base.ts @@ -31,6 +31,14 @@ export abstract class PageBase extends BaseItem { } } + public computeTitle(): void { + const content = this.contents; + if (content.startsWith("# ")) { + this._title = content.substr(2, content.indexOf("\n")-2); + this._contents = content.substr(content.indexOf("\n")+1); + } + } + public abstract get parent(): Page|PageGroup; public get source(): string { diff --git a/src/pages/page-dictionary-factory.ts b/src/pages/page-dictionary-factory.ts index fb6bd77..e488b19 100644 --- a/src/pages/page-dictionary-factory.ts +++ b/src/pages/page-dictionary-factory.ts @@ -9,8 +9,11 @@ import { getFilename } from "../utilities/path-utilities"; import { ChildPage, Page, PageDictionary, PageGroup, PageSection } from "./models/"; // TODO: document this -export class PageDictionaryFactory { +export class PageDictionaryFactory { + private options: PluginOptions; + public buildDictionary(options: PluginOptions): PageDictionary { + this.options = options; const groups: PageGroup[] = []; for (const group of options.groups) { @@ -50,7 +53,10 @@ export class PageDictionaryFactory { private _parsePage(definition: PageDefinition, parent: PageGroup): void { const page = new Page(definition, parent); - + if (this.options.autoDetectPageTitle) { + page.computeTitle(); + } + // Get directory name for any child pages or sub-sections const subDirectory = join(parent.url, getFilename(definition.output, true)); @@ -70,6 +76,9 @@ export class PageDictionaryFactory { } private _parseChildPage(definition: ChildPageDefinition, urlPrefix: string, parent: Page): void { - new ChildPage(definition, urlPrefix, parent); + const page = new ChildPage(definition, urlPrefix, parent); + if (this.options.autoDetectPageTitle) { + page.computeTitle(); + } } } diff --git a/test/unit/models/page.test.ts b/test/unit/models/page.test.ts index ccd02de..568bcb3 100644 --- a/test/unit/models/page.test.ts +++ b/test/unit/models/page.test.ts @@ -86,6 +86,18 @@ describe("Page", () => { expect(() => sut.contents).toThrow(); }) + + test("returns the contents of the file with title substitution", () => { + const readFileSyncMock = jest.fn(); + readFileSyncMock.mockReturnValue("# Title\nfile contents"); + (fs as any).readFileSync = readFileSyncMock; + + sut.computeTitle(); + expect(sut.contents).toBe("file contents"); + console.log(sut.title); + expect(sut.title).toBe("Title"); + expect(readFileSyncMock).toHaveBeenCalledWith(definition.source, "utf8"); + }); }); describe("url", () => {