npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@creadigme/aurelia-docgen

v2.1.0

Published

Aurelia + Storybook (can be) ❤. Aurelia documentation generator.

Downloads

19

Readme

npm version Build Status CodeQL codecov License Badge

Aurelia Docgen | @creadigme/aurelia-docgen

Aurelia + Storybook (can be) ❤

Aurelia Docgen brings the ability to generate component1 documentations, stories, from any2 Aurelia3 TypeScript project. Component's stories are written in class comments @story or in YAML files.

This tool is intended to be used with projects based on Aurelia framework3 + Storybook. It could also work with projects using only Aurelia without Storybook.

aurelia logo

storybook logo

1. customElement, valueConverter, customAttribute, bindingBehavior and services. 2. Without any warranty. 3. ⚠️ Aurelia 1 support is not implemented yet.

📝 License

Copyright © 2022-2023 Creadigme.

Disclaimer

This project has a dual license:

  • The AGPLv3 License - see the LICENSE file for details.
  • A private license agreement for private or/and commercial use.

See the FAQ on licensing.

Do not hesitate to contact us.

💾 Installation

Aurelia Docgen

npm i @creadigme/aurelia-docgen@^2 -D
# or
yarn add @creadigme/aurelia-docgen@^2 -D
# or for global use
yarn add @creadigme/aurelia-docgen@^2 -g

Storybook (version 6)

Storybook for HTML (if needed)

Storybook for HTML

# Aurelia 2 project with webpack
npx sb init --type html --builder webpack5

Webpack configuration

./webpack.config.js

Storybook and Aurelia use HMR (Hot Module Replacement), we have to disable Aurelia HMR if Storybook is used.

In your project, edit this file: ./webpack.config.js.

Example: webpack.config.js

/** Your content */

- module.exports = function(env, { analyze }) {
+ module.exports = function(env, { analyze, hmr }) {

/** Your content */

{ test: /\.ts$/i, use: ['ts-loader', 
- '@aurelia/webpack-loader'
+ {
+   loader: '@aurelia/webpack-loader',
+   options: {
+     hmr: hmr === false ? false : undefined,
+   },
+ }
], exclude: /node_modules/ },
{
  test: /[/\\]src[/\\].+\.html$/i,
- use: '@aurelia/webpack-loader',
+ use: {
+   loader: '@aurelia/webpack-loader',
+   options: {
+     hmr: hmr === false ? false : undefined,
+   },
+ },

/** Your content */

./.storybook/main.js

Storybook must use Aurelia configuration. In your project, edit this file: ./.storybook/main.js.

Example: main.js

+ const customWP = require('../webpack.config.js');

module.exports = {
+ webpackFinal: async (config) => {
+   const customConfigs = customWP(config.mode, {
+     hmr: false
+   });
+   return {
+     ...config,
+     module: {
+       ...config.module,
+       rules: (Array.isArray(customConfigs) ? customConfigs[0] : customConfigs).module.rules
+     }
+   };
+ },
+ core: {
+   builder: 'webpack5',
+ },
  "stories": [
-   "../src/**/*.stories.mdx",
    "../src/**/*.stories.@(js|jsx|ts|tsx)"
  ],
  "addons": [
    "@storybook/addon-links",
    "@storybook/addon-essentials"
  ],
  "framework": "@storybook/html",
  "core": {
    "builder": "@storybook/builder-webpack5"
  }
}

⚠️ Currently we do not support .mdx stories.

📝 Write stories

TLDR; comment your class with @story or/and via YAML files.

Comment your class @story

Just like that:

customElement

/**
 * My component
 *
 * @story My story
 * ```html
 * <au-component value.bind="1"></<au-component>
 * ```
 *
 * @story My another story
 * ```html
 * <au-component value.bind="200"></<au-component>
 * ```
 */
@customElement('au-component')
export class AuComponent implements ICustomElementViewModel {
  /** ... */
  @bindable()
  public value = 1;
}

valueConverter

/**
 * My converter
 *
 * @example
 * ```html
 * <!-- it's the default usage for valueConverter ! -->
 * <span>${ '1' | doSomething}</span>
 * ```
 *
 * @story My story
 * ```html
 * <let my-value.bind="{ a: 1 }">
 * <span>${ myValue | doSomething}</span>
 * ```
 *
 * @story My another story
 * ```html
 * <let my-value.bind="{ a: 1, b: 2 }">
 * <span>${ myValue | doSomething}</span>
 * ```
 */
@valueConverter('doSomething')
export class DoSomethingValueConverter {
  public toView(value: string | Record<string, number>): string {
    return /* ?? */ 'ok';
  }
}

customAttribute

import { customAttribute, INode } from 'aurelia';

/**
 * Red Square
 * From https://docs.aurelia.io/getting-to-know-aurelia/custom-attributes#attribute-aliases
 *
 * @group attributes/red-square
 */
@customAttribute({ name: 'red-square', aliases: ['redify', 'redbox'] }) 
export class RedSquareCustomAttribute {
  constructor(@INode private element: HTMLElement){
      this.element.style.width = this.element.style.height = '100px';
      this.element.style.backgroundColor = 'red';
  }
}

bindingBehavior

import { ILogger, bindingBehavior } from 'aurelia';

/**
 * Log behavior
 *
 * @group binding-behavior/log
 */
@bindingBehavior('log')
export class Log {
  constructor(
    @ILogger readonly logger: ILogger,
  ) {}
  bind(...args) {
    this.logger.debug('bind', ...args);
  }
  unbind(...args) {
    this.logger.debug('unbind', ...args);
  }
}

service

The tag comment @service is the key.

/**
 * My Service
 *
 * @service
 */
export class MyService implements IMyService {
  /**
   * @inheritDoc
   */
  public running: boolean = false;

  /**
   * @inheritDoc
   */
  public start(): void {
    this.running = true;
  }

  /**
   * @inheritDoc
   */
   public stop(): void {
    this.running = false;
  }
}

YAML Way

Stories are written in YAML next to components like these:

 components
 ├── something
 │   ├── au2-button.html
 │   ├── au2-button.ts
+│   ├── au2-button.stories.yml
 │   ├── au2-switch.html
 │   ├── au2-switch.ts
+│   ├── au2-switch.stories.yml
 └── else
 │   ├── supra-ultra-component.html
 │   ├── supra-ultra-component.ts
+│   ├── supra-ultra-component.stories.yml

With this format:

# au2-button stories
- title: Toggle
  help: |
    A button toggle
  tags:
    - button
    - simple
  code: |
    <let state.bind="false"></let>
    <au2-button action.bind="() => state = !state" content="${state ? 'Turn me off' : 'Turn me on'}"></au2-button>
    <div>${state ? '✅' : '☐' }</div>
- title: Another story
  help: |
    Another story. Look at this sample...
  tags:
    - button
    - simple
    - supra
  code: |
    <let state.bind="false"></let>
    <au2-button action.bind="() => state = !state" content="${state ? '✅' : '☐'}"></au2-button>
    <div>${state ? '✅' : '☐' }</div>

🔨 How to use

(optional) Add script in your package.json

{
  "name": "something",
  "scripts": {
+   "build:stories": "aurelia-docgen --out ./src/stories"
!   "build:stories": "aurelia-docgen"
!   "build:stories": "aurelia-docgen --out ./src/stories --auConfigure ./src/configure"
  }
}

Default way - All component stories in one directory

# Go to your project
cd ./my-supra-project

# add a new script in package.json, like `build:stories` with command
# aurelia-docgen --out ./src/stories
npm run build:stories

# all detect components and stories will be written in ./src/stories directory.

DRY way - Component stories next to components

# add a new script in package.json, like `build:stories` with command
# aurelia-docgen
npm run build:stories

# all detected components and the stories will be written next to the detected components.

Real world installation

  • Install @creadigme/aurelia-docgen in devDependencies.
  • Script on package.json as below.
  • All component stories in one directory.
  • Storybook stories can use any register elements.
  • ./.storybook/main.js is edited with webpack configuration.

./package.json

{
  "name": "something",
  "scripts": {
+   "build:stories": "aurelia-docgen --out ./src/stories --auConfigure ./src/configure"
+   "watch:stories": "npm run build:stories -- --watch"
  },
  "devDependencies": {
+   "@creadigme/aurelia-docgen": "^1"
  }
}

./src/configure.ts

import { Aurelia, Registration, type IEnhancementConfig, type IHydratedParentController } from "aurelia";

/** It's just an example */
let au: Aurelia;

/**
 * If specified, this function is called to retrieve the instance of Aurelia
 * @return Aurelia
 */
export async function getOrCreateAurelia(): Promise<Aurelia> {
  if (!au) {
    au = new Aurelia().register(/** Your configuration */);
    // Do your specific stuff here
  }
  return au;
}

let lastController: ICustomElementController<unknown>;

/** Cleanup previous story and enhance current */
export async function enhance(aureliaInst: Aurelia, config: IEnhancementConfig<unknown>, parentController?: IHydratedParentController | null): Promise<ICustomElementController<unknown>> {
  if (lastController) {
    // detaching, unbinding
    await lastController.deactivate(lastController, null);
    // dispose
    await lastController.dispose();
  }

  lastController = await aureliaInst.enhance(config, parentController);
  return lastController;
}
npm run build:stories
# all detect components and stories will be written in ./src/stories directory.
# launch storybook
npm run storybook

CLI parameters

| Parameter | Description | Sample | |---|---|---| | --projectDir | Project directory. Current working directory is used by default. | ./ | | --out | Output directory for generated stories. If not specified, stories are written next to the components. | ./src/stories/ | | --mergeOut | If out is specified, merges the component stories into a single file | ./src/stories/components.stories.ts | | --auConfigure | Specify the TS file for Aurelia configuration (without extension).Example ./src/configure file:export async function getOrCreateAurelia(): Promise<Aurelia> { return Aurelia.register(/** */); }. If null or empty, only the current component will be register. | | | --etaTemplate | Path of Eta template (https://eta.js.org/). If null, the default template is used | | | --verbose | More logs | | | --watch | Monitor changes | |

API Parameters

CLI Parameters + below:

| Parameter | Description | Sample | |---|---|---| | logger | (msg: string, level: LevelLog) => void | console.log(``${level} - ${msg}``) |

import { AureliaDocgen } from '@creadigme/aurelia-docgen';

const au2Docgen = new AureliaDocgen({
  projectDir: './path-of-your-supra-ultra-project',
  out: './src/stories',
});

for (const ceStories of au2Docgen.getStories()) {
  console.dir(ceStories);
}

Coverage

codecov

Coverage sunburst