@oasisdigital/ng-doc-portal-plugin
TypeScript icon, indicating that this package has built-in type declarations

1.8.0 • Public • Published

NgDocPortalPlugin

The @oasisdigital/ng-doc-portal-plugin package allows you to create your own component documentation portal natively in Angular. This system makes use of the latest features of Angular (stand-alone components and lazy loading components) to provide an ergonomic development experience for documenting your angular components. Everything is built natively in angular so there are no hoops to jump through or different libraries/frameworks/syntaxes to learn!

This package is meant to be used in tangent with the @oasisdigital/ng-doc-portal package inside of an Nx Workspace.

Installation

npm

npm install --save @oasisdigital/ng-doc-portal

npm install --save-dev @oasisdigital/ng-doc-portal-plugin

yarn

yarn add @oasisdigital/ng-doc-portal

yarn add --dev @oasisdigital/ng-doc-portal-plugin

Generating a New ng-doc-portal Application

Run nx generate @oasisdigital/ng-doc-portal-plugin:app

You will need to provide a name for your new ng-doc-portal application via command line or the prompt.

By default the newly generated application will come with one example doc page named starting-example.doc-page.ts. The .doc-page.ts extension is the default file type that the ng-doc-portal compiler will look for (this can be modified).

Serve/Build ng-doc-portal Application

To start serving your new application you can run nx serve {name-of-application}.

To build your application you can run nx build {name-of-application}.

Adjusting the Angular Build/Serve Configuration Target

The serve and build commands are runnning the normal Angular serve/build underneath aliased to ng-serve and ng-build along with our custom compiler.

If you would like to specify which Angular configuration to use for your build/serve commands please adjust the ngConfigTarget property of the configurations object in your app's project.json build/serve objects.

Configuring Your ng-doc-portal Application

By default there will be a ng-doc-portal-config.json at the root of the your generated ng-doc-portal application. This file allows you to set all the top-level configuration in one spot.

Page Globbing

In the ng-doc-portal-config.json file you can set either the globPattern or globPatterns property. Both properties take either a string pattern or a GlobPattern object. In the case of globPatterns you can add an array of string or GlobPattern object.

By default we set the globPattern property to look anywhere in your Nx Workspace for the .doc-page.ts files with the below example:

{
  "globPattern": "**/*.doc-page.ts"
}

More examples below:

{
  "globPatterns": ["apps/component-doc-portal/src/app/doc-pages/*.doc-page.ts", "apps/component-doc-portal/src/app/starting-example.doc-page.ts"]
}
{
  "globPatterns": [
    {
      "pattern": "apps/component-doc-portal/src/app/doc-pages/*.doc-page.ts"
    },
    {
      "pattern": "apps/component-doc-portal/src/app/starting-example.doc-page.ts"
    }
  ]
}

Adding Prefixed Groups to Globs

You can add a prefixed group to any glob pattern object by adding the titlePrefix property. This will automatically prefix the globbed pages with the group in the side navigation system.

This will not overwrite any groups you explicitly defined in the page's title property. It will only prefix the title.

{
  "globPatterns": [
    {
      "pattern": "apps/component-doc-portal/src/app/doc-pages/*.doc-page.ts",
      "titlePrefix": "General"
    },
    {
      "pattern": "apps/component-doc-portal/src/app/starting-example.doc-page.ts",
      "titlePrefix": "Example"
    }
  ]
}

Adding Your Own Doc Page

In principle you can add your own doc pages anywhere inside the Nx Workspace. Although you will possibly need to update your globbing configuration.

To create a new doc page you can either make use of this plugins generator with the following command nx g @oasisdigital/ng-doc-portal-plugin:doc-page or manually create your own angular component file with the correct file extension.

Configuring Your Doc Page

By default this package makes use of Angular's standalone component system. When you create your own doc page component make sure to set the standalone property to true in your Component decorator.

Example:

import { Component } from '@angular/core';

@Component({
  standalone: true,
  template: `<h1>Example Doc Page</h1>`,
})
export default class ExamplePageComponent {}

The title of the doc page will also be auto-generated based on the glob prefix and the name of the file by default. This will be used for the side nav and the navigation url.

Adding Custom Title

In order to add a custom title to a doc page. You will need to export a config object instead of exporting your component by default.

Example below:

import { Component } from '@angular/core';
import { DocPageConfig } from '@oasisdigital/ng-doc-portal';

@Component({
  standalone: true,
  template: `<h1>Example Doc Page</h1>`,
})
export class ExamplePageComponent {}

const docPageConfig: DocPageConfig = {
  title: 'My Custom Example Page Title',
  component: ExamplePageComponent,
};

export default docPageConfig;

Adding Grouping to Titles

In order to add grouping to a doc page's title you can simply add one or more / characters in the title.

Example below:

import { Component } from '@angular/core';
import { DocPageConfig } from '@oasisdigital/ng-doc-portal';

@Component({
  standalone: true,
  template: `<h1>Example Doc Page</h1>`,
})
export class ExamplePageComponent {}

const docPageConfig: DocPageConfig = {
  title: 'My Custom Group/My Custom Example Page Title',
  component: ExamplePageComponent,
};

export default docPageConfig;

Adding ng-doc-portal or Other Custom Components

In order to add any component systems to your doc page you will need to add an imports property to your Component decorator.

You can also access this package's component system from the following import: import { NgDocPortalComponentsModule } from '@oasisdigital/ng-doc-portal';

Full Example Below:

import { Component } from '@angular/core';
import {
  NgDocPortalComponentsModule, // <---- Added import for the ng-doc-portal components module
  DocPageConfig,
} from '@oasisdigital/ng-doc-portal';

@Component({
  standalone: true,
  imports: [NgDocPortalComponentsModule], // <---- Added imports property here
  template: `
    <ngdp-tab-menu>
      <ngdp-tab-item title="Overview">
        <h1>Button Component Document Page</h1>
        <button>Example Button</button>

        <p>The button is used to get actions from the user by click</p>
      </ngdp-tab-item>
      <ngdp-tab-item title="Examples">
        <button>Example Button</button>
        <ngdp-code-snippet lang="html">
          <button>Example Buttons</button>
        </ngdp-code-snippet>
      </ngdp-tab-item>
    </ngdp-tab-menu>
  `,
})
export class ButtonDocumentPageComponent {}

const docPageConfig: DocPageConfig = {
  title: 'General/Button',
  component: ButtonDocumentPageComponent,
};

export default docPageConfig;

Styling your Ng Doc Portal Application

Milligram

The ng-doc-portal package makes use of the milligram minimalist css library for some basic look & feel improvements. If you do not want this, please remove the first line of the targets.ng-build.options.styles property in your application's project.json. This will remove the milligram cdn import and some override styles.

Ng Doc Portal Styles

The ng-doc-portal package has some global styles to set borders, paddings, margins, and css grid structures. This is all set via global styles imported in the targets.ng-build.options.styles property of the application's project.json and are overwritable.

Since the ng-doc-portal system piggy backs off of an angular application you can simply add your custom styles to the root styles.scss file or in the style property of the angular app's project.json build config to override or extend the base styles we include.

Application Bootstrapping

By default the application generated by the ng-doc-portal-plugin package will use the Standalone API for bootstrapping the application and for importing components. If you want to use the ng-doc-portal package's systems in a non Standalone application there are examples below:

Standalone

// main.ts

import { docPageLoaders } from '../app/doc-page-loaders.ts';

bootstrapApplication(AppComponent, {
  providers: [provideNgDocPortal(docPageLoaders)],
});

Pre-Standalone

// app.module.ts

import { docPageLoaders } from './doc-page-loaders.ts';

@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule, NgDocPortalModule.forRoot(docPageLoaders)],
  bootstrap: [AppComponent],
})
export class AppModule {}

Theming

Setup Theme Selection System

If you want to sync your theming system with your ng doc portal application you can make use of the ngDocPortalProvideThemeOptions in the app.module.ts of your ng doc portal application. You will need to give this method a list of theme options to display in a dropdown menu in our toolbar. Any theme selections will be stored in localstorage and should rehydrate upon refresh.

Example below:

Standalone

// main.ts

provideNgDocPortal(
  docPageLoaders,
  // Add the below method to your `provideNgDocPortal` arguments
  withThemeOptions([
    { value: 'light-theme', display: 'Light Theme' },
    { value: 'dark-theme', display: 'Dark Theme' },
  ])
);

Pre-Standalone

// app.module.ts
providers: [
  // Add the below method call to your `providers` list
  ngDocPortalProvideThemeOptions([
    { value: 'light-theme', display: 'Light Theme' },
    { value: 'dark-theme', display: 'Dark Theme' },
  ]),
],

The ThemeOption interface that you provide to the ngDocPortalProvideThemeOptions function is below:

interface ThemeOption {
  display: string;
  value: string;
  default?: boolean;
  hljsTheme?: string;
}

The display property is used for the text in the select dropdown option that is created.

The value is both used for the select dropdown option and is the class that will be applied to the <html> element for the application.

The default property will set the theme as the default selected theme (if there isn't already one). Otherwise the first theme in the list will be the default.

The hljsTheme property allows for custom css sheets to be applied to the HLJS syntax highlighting system for the code-snippet component. The value should be an href to a valid css HLJS theme css file. An example would be: assets/github.css. We recommend placing the css file in your Doc Portal's assets folder for easy linking. A list of available themes (or examples to make your own) can be found here: https://github.com/highlightjs/highlight.js/tree/main/src/styles

Syncing Ng Doc Portal Application With Your Theme Styles

The ng doc portal application uses the follow css variables for colors:

--ngdp-font-color
--ngdp-background-color
--ngdp-border-color
--ngdp-side-nav-active-color
--ngdp-side-nav-highlight-color
--ngdp-code-background-color

Feel free to override these with your own colors based on the selected theme like below:

html {
  &.dark-theme {
    --ngdp-font-color: white;
    --ngdp-background-color: #363636;
    --ngdp-border-color: white;
    --ngdp-side-nav-active-color: #6e6e6e;
    --ngdp-side-nav-highlight-color: #adadad;
    --ngdp-code-background-color: #4e4e4e;
  }

  &.light-theme {
    --ngdp-font-color: black;
    --ngdp-background-color: white;
    --ngdp-border-color: black;
    --ngdp-side-nav-active-color: #b9b9b9;
    --ngdp-side-nav-highlight-color: #868686;
    --ngdp-code-background-color: #eeeeee;
  }
}

Accessing and Setting Theme Value Manually

The theme system has an exposed ThemeService that you can access at any time via Dependency Injection to fetch the current theme value synchronously or asynchronously. You can also update the theme value at any time as well.

The API for the ThemeService is below:

theme: Observable<string>;

themeOptions: ThemeOption[] | undefined;

getTheme(): string | undefined;

setTheme(newTheme: string): void;

Custom Title

By default we setup a Title for the UI in the top left corner. This will have the default text of 'Doc Portal'.

If you want to set a custom title you may do so by providing the ngDocPortalProvideTitle function in the root module of the doc portal application.

This function takes in either a plain string value or a custom Component class. If you provide a custom component class you will need to make sure the content fits inside a height of 48px.

Example of custom plain string title:

Standalone

// main.ts

provideNgDocPortal(
  docPageLoaders,
  // Add the below method to your `provideNgDocPortal` arguments
  withTitle('My Custom Title')
);

Example of custom component title:

// main.ts

provideNgDocPortal(
  docPageLoaders,
  // Add the below method to your `provideNgDocPortal` arguments
  withTitle(MyCustomTitleComponent)
);

Pre-Standalone

// app.module.ts

providers: [
  // Add the below method call to your `providers` list
  ngDocPortalProvideTitle('My Custom Title'),
];

Example of custom component title:

// app.module.ts

providers: [
  // Add the below method call to your `providers` list
  ngDocpPortalProvideTitle(MyCustomTitleComponent),
];

Custom Toolbar Plugins

This system allows you to insert your own custom components into the doc portal's main toolbar/action bar. If you make use of the doc portal theming plugin this is the same toolbar it shows up in.

In order to provide your components you can setup the below code in your app.modules.ts providers:

Standalone

// main.ts

provideNgDocPortal(
  docPageLoaders,
  // Add the below method to your `provideNgDocPortal` arguments
  withToolbarPlugins([MyCustomPluginComponent])
);

Pre-Standalone

// app.module.ts

providers: [
  // Add the below method call to your `providers` list
  ngDocPortalProvideToolbarPlugins([MyCustomPluginComponent]),
];

The ngDocPortalProvideToolbarPlugins takes in an either a single component or an array of components as it's argument. These components will need to fit in a default height (can be overwritten) of 40-48px (depending on if there is horizontal overflow or not). The width of the component is not limited.

Custom Laning Page

By default we setup a landing page when there is no component doc page selected (default route of '/'). This will have the default text of 'Please select a component document page from the side navigation.'.

If you want to set a custom landing page you may do so by providing the ngDocPortalProvideLandingPage function in the root module of the doc portal application.

This function takes in a custom Component class.

Examples:

Standalone

// main.ts

provideNgDocPortal(
  docPageLoaders,
  // Add the below method to your `provideNgDocPortal` arguments
  withLandingPage(MyCustomLandingPageComponent)
);

Pre-Standalone

// app.module.ts

providers: [
  // Add the below method call to your `providers` list
  ngDocpPortalProvideLandingPage(MyCustomLandingPageComponent),
];

Ng Doc Portal's Component Library

The ng-doc-portal package ships with a small component-library that will help you document your component and display this information.

You can add this component module to your doc page via the imports property in your stand-alone Component decorator.

Example below:

import { Component } from '@angular/core';
import { NgDocPortalComponentsModule } from '@oasisdigital/ng-doc-portal';

@Component({
  standalone: true,
  imports: [NgDocPortalComponentsModule],
  template: `
    <!-- Your Content Here -->
  `
})

Tab Menu

The tab menu component system allows you to easily have tab-based navigation in your doc page. You will need to have a top level ngdp-tab-menu and subsequent ngdp-tab-item elements in your doc page template.

The navigation will use query-params for the title properties you have set on your ngdp-tab-item component instances.

Example below:

<ngdp-tab-menu>
  <ngdp-tab-item title="Overview">
    <h1>Button Component Document Page</h1>

    <p>The button is used to get actions from the user by click</p>
  </ngdp-tab-item>
  <ngdp-tab-item title="Examples">
    <button>Example Button</button>
  </ngdp-tab-item>
</ngdp-tab-menu>

A potential url for the above template could look like: /general-button?tab=overview

Code Snippet

The <ngdp-code-snippet> component allows you to display syntax highlighted code with an option to easily get the displayed code onto your clipboard.

There are three different approaches to displaying your code with syntax highlighting.

  1. <ngdp-code-snippet> with <textarea></textarea> inside it housing your code
<ngdp-code-snippet>
  <textarea>
    <!-- Your Code To Display Here -->
  </textarea>
</ngdp-code-snippet>
  1. <ngdp-code-snippet> with code input binding assigned to string housing your code
<ngdp-code-snippet [code]="yourCodeStringVariable"></ngdp-code-snippet>
  1. ngdpCodeSnippet directive on a <textarea></textarea> element housing your code
<textarea ngdpCodeSnippet>
  <!-- Your Code To Display Here -->
</textarea>

Setting the Code Language

By default the code "language" is set to HTML/Angular template. If you want to override this provide a value for the lang input attribute. The options we support are currently: 'html' | 'typescript' | 'css' | 'scss'. 'html' is treated the same as an angular template would be.

<ngdp-code-snippet lang="typescript">
  <textarea>
    function myFunction() {
      console.log('Hello World!');
    }
  </textarea>
</ngdp-code-snippet>

Angular Template Bindings Helper

If you are displaying Angular template code with any bindings (inputs, outputs, interpolation) then you will want to add the ngNonBindable attribute to your <ngdp-code-snippet> element or your <textarea> with the ngdpCodeSnippet directive on it.

Iframe Embed

The <ngdp-embed-iframe> component allows you to embed sites into your doc page. You will simply need to set the src property.

Example below:

<ngdp-embed-iframe src="https://www.youtube.com/embed/dQw4w9WgXcQ"></ngdp-embed-iframe>

Markdown

The <ngdp-markdown> component lets you to render some markdown code inside your doc page. This can either be done with static markdown text or a file located in your assets or hosted elsewhere.

Examples below:

Hosted/Asset Markdown File

<ngdp-markdown filePath="/assets/example-markdown.md"></ngdp-markdown>

Static Markdown Text

const exampleMarkdown = `
# Markdown from a string

Hello World!
`;
<ngdp-markdown [markdown]="markdownString"></ngdp-markdown>

Markdown Directive

<pre ngdpMarkdown>
  # Header
  
  Hello World!
</pre>

It should be noted that most markdown syntaxes should work within the html <pre> element. The only notable one that doesn't is the double space "line break" syntax. Please use a \ at the end of a paragraph line to denote a "line break".

It also generally helps to use a separate html file for your doc-page component's template when making use of the ngdpMarkdown directive. This is due to the angular language service having issues with syntax highlighting some parts of markdown code inside the inline template of your component's Typescript file. This is especially the case when using the "backtick" character for code blocks/in-line snippets.

Component Playground

The <ngdp-playground> component allows you to place your component in a playground form system. Here you can configure form fields that automatically hook into a component's input properties.

You will need to set the config property to a valid NgDocPortalPlaygroundConfig object variable on the doc page class.

export class ExamplePlaygroundPageComponent {
  playgroundComponentConfig: NgDocPortalPlaygroundConfig = {
    ...
  }
}
<ngdp-playground [config]="playgroundComponentConfig"></ngdp-playground>

The config object requires a component property to know which component to work with in the playground.

Input/Property Binding

By configuring the inputs property of your playground config object you can have form fields that hook into your component's input(s) or other class properties.

There is currently support for the following form controls:

  • TextControl
  • TextAreaControl
  • NumberControl
  • RangeControl
  • SelectControl
  • CheckboxControl
  • RadioGroupControl
  • DateControl
  • TimeControl
  • DateTimeControl
  • ColorPickerControl

Full Example Below:

<ngdp-playground [config]="playgroundConfig"></ngdp-playground>
export class ExamplePlaygroundPageComponent {
  playgroundConfig: NgDocPortalPlaygroundConfig = {
    component: TestComponent,
    inputs: [
      {
        label: 'Text Input',
        property: 'text',
        type: PlaygroundControlType.Text,
        value: 'blah',
      },
      {
        label: 'Select a Pet',
        property: 'pet',
        type: PlaygroundControlType.Select,
        value: 'dog',
        options: [
          {
            display: 'Dog',
            value: 'dog',
          },
          {
            display: 'Cat',
            value: 'cat',
          },
          {
            display: 'Hamster',
            value: 'hamster',
          },
        ],
      },
      {
        label: 'Color',
        property: 'color',
        type: PlaygroundControlType.ColorPicker,
        value: '#363636',
      },
    ],
  };
}

Text Content Binding

If you add the textContentBinding property to your playground config object you can allow for projecting strings or other native html elements into your component's ng-content.

Static Text

{
  ...
  textContentBinding: 'My Text Content!'
}

Dynamic Text Form Field

No default value:

{
  ...
  textContentBinding: true
}

Has default value:

{
  ...
  textContentBinding: { default: 'Hello World!' }
}

HTML Node Binding

const node = document.createElement('div');

{
  ...
  textContentBinding: [[node]]
}

Class Binding

If you add the classBinding property to your playground config object you can have static or dynamic classes added to your component element.

Static Class

You can either provide a string (with space separated classes) or an array of string classes.

Examples below:

{
  ...
  classBinding: 'my-class'
}
{
  ...
  classBinding: 'foo bar'
}
{
  ...
  classBinding: ['foo', 'bar']
}

Dynamic Class Field

You will have to provide the class list for the select field. You can optionally set a default value with a string or string[] and/or allow for multiple class selections with the multiple property.

Examples below:

{
  ...
  classBinding: {
    classes: ['foo', 'bar']
  }
}
{
  ...
  classBinding: {
    classes: ['foo', 'bar'],
    default: 'bar'
  }
}
{
  ...
  classBinding: {
    classes: ['foo', 'bar'],
    multiselect: true
  }
}

Package Sidebar

Install

npm i @oasisdigital/ng-doc-portal-plugin

Weekly Downloads

352

Version

1.8.0

License

MIT

Unpacked Size

94.5 kB

Total Files

51

Last publish

Collaborators

  • zjkipping
  • dpsthree