Skip to content

Latest commit

 

History

History
348 lines (264 loc) · 8.86 KB

README.md

File metadata and controls

348 lines (264 loc) · 8.86 KB

polymerts-doc-generator

This is a node module for parsing a TypeScript file (PolymerTS) and generating an empty documentation file (i.e. no code, only signatures) compatible with Polymer 1.0 to pass to iron-component-page for documentation. While we try to fill in anything that may be missing in the line of comments when we can, well documented code is both benefecial to new developers coming into the project as well as seasoned developers trying to remember why they may have done something the way they did when returning to a project.

Background Info

Since Red Pill Now changed our process to use TypeScript for components we lost the auto-generated documentation feature for our components. This node module attempts to restore that feature.

While we understand that the format generated here is for Polymer 1.0. Once we move to Polymer 2.0 we will need to revisit all the models to change how they are rendered. This should not be a big undertaking.

Setup

First, make sure you have Node.js installed, so we can use the Node Package Manger (NPM). Next install the other key tools:

Install

npm install polymerts-doc-generator

Usage

var polymerTsDoc = require('polymerts-doc-generator');
/**
 * @param {string} pathToTsFile - The path to the file we want to parse
 * @param {string} pathToDocFile - The directory where we want to put our documentation files
 */
var newDocFile = polymerTsDoc.start(pathToTsFile, pathToDocFile);

This will parse the pathToTsFile and generate the empty documentation file at the path of the pathToDocFile. The file name generated will be doc_original-file-name.html.

The generated file will be suitable for passing to an iron-component-page element.

Developing

Clone the project to your local environment and run:

npm install

This project is written in typescript. There is a compile script which just runs tsc on the src directory. This will generate .js files in the respective src directories which you can then test/debug.

Supported Patterns

In order for this tool to work, there are certain patterns you need to be aware of. Since this project uses the TypeScript compiler to determine all the information about a code block it is fairly accurate and lenient in it's pattern recognition. If it compiles then theoretically this tool should be able to parse it. Also, any comments for methods, properties, etc. will be included in the generated documentation in the appropriate place.

Component

This is the uppermost class. All other parts are stored inside the component. Once all the different parts are collected they are rendered.

@component('my-component')
export class MyComponent extends polymer.Base {...}

The above component definition will be converted to:

<!--
This is my cool component

@demo demo/index.html
@hero path/to/hero.png
-->
<dom-module id="my-component">
	<template>
		<style></style>
	</template>
	<script>
(function() {
	Polymer({
		is: 'my-component',
		behaviors: [...],
		properties: {...},
		observers: [...],
		listeners: {...},
		...
	});
})();
	</script>
</dom-module>

HTML Comments

The presence of an @demo or @hero tag encountered in a comment block of the HTML File will determine which comment block will be deemed the comment block to use. All other comment blocks will be ignored.

<link rel="import" href="../polymer/polymer.html">
<link rel="import" href="../polymer-ts/polymer-ts.html">
<!-- This comment will be ignored because it is missing the appropriate tag(s) -->
<!--
This is my element's style and example usage documentation

@demo demo/index.html
-->
<dom-module id="my-component">
	<template>
		<style>
			...
		</style>
		...
	</template>
</dom-module>

Properties

If no comment is defined, one will be created and it will include the @type tag.

@property({type: Boolean, reflectToAttribute: true})
propertyName: boolean;

// OR

@property({
	type: Boolean,
	reflectToAttribute: true
})
propertyName: boolean;

The above will be transformed to:

/**
 * propertyName
 * @type {boolean}
 */
propertyName: {
	type: Boolean,
	reflectToAttribute: true
}

Behaviors

Behaviors will be added to a behaviors array.

@component('my-component')
@behavior(Polymer['AppLocalizeBehavior']);
export class MyComponent extends polymer.Base {...}

// OR

@component('my-component')
@behavior(Polymer.AppLocalizeBehavior);
export class MyComponent extends polymer.Base {...}

The above would be transformed to an array and placed in the component structure:

is: 'my-component',
behaviors: [
	Polymer['AppLocalizeBehavior'],
	Polymer.AppLocalizeBehavior
],
...

Observers

If an observer has only 1 parameter defined, that property will need to be defined as a @property. We will add an observer definition to that @property definition

@observe('propertyName')
_onPropertyName(propertyName) {...}

// OR

@observe('propertyName,otherPropertyName')
_onPropertyName(propertyName, otherPropertyName) {...}

The above will be transformed to:

propertyName: {
	type: Boolean,
	reflectToAttribute: true,
	observer: '_onPropertyName'
}
_onPropertyName(propertyName) {...}

// OR

observers: [
	'_onPropertyName(propertyName,otherPropertyName)'
],
_onPropertyName(propertyName,otherPropertyName) {...}

Computed Property

A new property will be created pointing to the propertyName method.

@computed()
propertyName(someOtherProp) {...}

// OR

@computed({type: String})
propertyName(someOtherProp) {...}

The above computed property will be transformed to: (NOTE) Notice the type is Object. This will be the default if type is not defined in the decorator

propertyName: {
	type: Object,
	computed: 'propertyName(someOtherProp)'
}
propertyName(someOtherProp) {...}

// OR

propertyName: {
	type: String,
	computed: 'propertyName(someOtherProp)'
}
propertyName(someOtherProp) {...}

Listener

If an @listener is defined and there is not a comment, a comment will be created with an @listens tag. If there is a comment with no @listens tag, we add an @listens tag.

@listener('someElementId.some-event')
_onSomeEvent(evt: CustomEvent) {...}

// OR

@listener(SomeNameSpace.SOME_EVENT)
_onSomeEvent(evt: CustomEvent) {...}

The above Listener will be transformed to:

listeners: {
	'SomeNameSpace.SOME_EVENT': '_onSomeEvent',
	'someElementId.some-event': '_onSomeEvent'
}
/**
 *
 * @listens SomeNameSpace.SOME_EVENT
 * @listens #someElementId.some-event
 */
_onSomeEvent(evt: CustomEvent) {...}

Function

someFunction(arg1: any, arg2: any) {...}

// OR
/**
 * Some function
 * @param {any} arg1
 * @param {any} arg2
 * @returns {string}
 */
someFunction(arg1: any, arg2: any): string {...}

The above functions will be transformed to:

someFunction(arg1, arg2)

// OR

/**
 * Some function
 * @param {any} arg1
 * @param {any} arg2
 * @returns {string}
 */
someFunction(arg1, arg2) {...}

Project Structure

  • polymerts-doc-generator
    • dist/
      • lib/
        • utils.js
      • models/
        • behavior.js
        • comment.js
        • component.js
        • computed.js
        • function.js
        • html-comment.js
        • listener.js
        • observer.js
        • program-part.js
        • property.js
      • index.js
    • src/
      • data/ component files for development/testing purposes
      • docs/ development/testing generated doc files
      • lib/
        • utils.ts
      • models/
        • behavior.ts
        • comment.ts
        • component.ts
        • computed.ts
        • function.ts
        • html-comment.ts
        • listener.ts
        • observer.ts
        • program-part.ts
        • property.ts
      • index.ts
    • .gitignore
    • gulpfile.js
    • package-lock.json
    • package.json
    • README.md
    • tsconfig.json

Reporting Bugs

Please use the Issues link in this project. Be descriptive, provide any errors that may have been produced, a snippet of the code that caused the error and if possible how to reproduce the issue.

Contributing

Pull Requests are welcome, encouraged and greatly appreciated. When contributing, please follow the same coding style present in the project. Also, if relevant, please provide comments to your changes. If your Pull Request is addressing a feature request or issue, please include the issue # in the commit. For example "Fixes issue: #123".

Future Directions

After some conversations with the team this may be a good starting point for converting a PolymerTS/Polymer 1.x component to a PolmerTS/Polymer 2.x component. Also, converting to Polymer 2.0 should not be that big of a leap. We will just need to change the toMarkup of the models as long as the future PolymerTS 2.x maintains a similar structure.