bafolts / tplant Goto Github PK
View Code? Open in Web Editor NEWTypescript to plantuml
Home Page: https://segmentationfaults.com/tplant/default.html
License: GNU General Public License v3.0
Typescript to plantuml
Home Page: https://segmentationfaults.com/tplant/default.html
License: GNU General Public License v3.0
When running the npm test script the RayTracer parser test fails.
Parser
✓ generate plantuml for Classes/Greeter.ts (970ms)
✓ generate plantuml for Inheritance (568ms)
✓ generate plantuml for Abstract/AbstractClass.ts (410ms)
1) generate plantuml for RayTracer
3 passing (2s)
1 failing
1) Parser
generate plantuml for RayTracer:
AssertionError [ERR_ASSERTION]: '@startuml\n@enduml' == '@startuml\nclass Vector {\n +x: number\n +y: number\n +z: number\n +{static} times(k: number, v: Vector): Vector\n
+ expected - actual
It seems like nothing is being generated for RayTracer
.
Hey Brian,
I landed new from that other issue thread we were going back and forth in. I'm excited to try this out and get done actual uml diagrams for my Angular 2 projects. I'd also be willing to help add to the README once I get it working. thanks. :)
I suggest adding an option for generating UML diagrams without interfaces.
A way to specify the output format should be added. The current default of always writing to STDOUT wont work for all cases.
tplant fails when I use getter/setter such as
get Position()
vs getPosition()
Hi, I get errors. I am using Node 12 on Linux.
Should this file work? Thanks!:
$ npx tplant --input game-object.ts > app.puml
/home/david/sites/testuml/node_modules/.registry.npmjs.org/tplant/2.0.4/node_modules/tplant/dist/generateDocumentation.js:171
throw new Error('unable to determine member type');
^
Error: unable to determine member type
at getMemberType (/home/david/sites/testuml/node_modules/.registry.npmjs.org/tplant/2.0.4/node_modules/tplant/dist/generateDocumentation.js:171:23)
at getMemberReturnType (/home/david/sites/testuml/node_modules/.registry.npmjs.org/tplant/2.0.4/node_modules/tplant/dist/generateDocumentation.js:96:26)
at serializeMember (/home/david/sites/testuml/node_modules/.registry.npmjs.org/tplant/2.0.4/node_modules/tplant/dist/generateDocumentation.js:84:25)
at /home/david/sites/testuml/node_modules/.registry.npmjs.org/tplant/2.0.4/node_modules/tplant/dist/generateDocumentation.js:236:36
at Map.forEach (<anonymous>)
at serializeInterface (/home/david/sites/testuml/node_modules/.registry.npmjs.org/tplant/2.0.4/node_modules/tplant/dist/generateDocumentation.js:235:24)
at visit (/home/david/sites/testuml/node_modules/.registry.npmjs.org/tplant/2.0.4/node_modules/tplant/dist/generateDocumentation.js:56:25)
at visitNodes (/home/david/sites/testuml/node_modules/.registry.npmjs.org/typescript/3.4.5/node_modules/typescript/lib/typescript.js:16514:30)
at Object.forEachChild (/home/david/sites/testuml/node_modules/.registry.npmjs.org/typescript/3.4.5/node_modules/typescript/lib/typescript.js:16742:24)
at /home/david/sites/testuml/node_modules/.registry.npmjs.org/tplant/2.0.4/node_modules/tplant/dist/generateDocumentation.js:30:34
on game-object.ts:
export type Vector2 = [number, number];
export const vectors = {
add(a: Vector2, b: Vector2): Vector2 {
return [a[0] + b[0], a[1] + b[1]];
},
multiply(a: Vector2, b: Vector2): Vector2 {
return [a[0] * b[0], a[1] * b[1]];
},
get up(): Vector2 {
return [0, 1];
},
get down(): Vector2 {
return [0, -1];
},
get left(): Vector2 {
return [-1, 0];
},
get right(): Vector2 {
return [1, 0];
},
};
/**
* =============================================================================
* GameObject (modified https://docs.unity3d.com/Manual/class-Transform.html)
* =============================================================================
*/
interface GameObjectOptions {
position: Vector2;
rotation?: number;
scale?: Vector2;
}
export abstract class GameObject {
public position: Vector2;
public rotation?: number;
public scale: Vector2;
public constructor({
position,
rotation = 0,
scale = [1, 1],
}: GameObjectOptions) {
this.position = position;
this.rotation = rotation;
this.scale = scale;
}
public static createCharacters<T>({ ...options }: GameFactoryOptions): T[] {
let character: Character;
const characters = [];
for (let index = 0; index < options.numberOf; index += 1) {
switch (options.Character) {
case Hero:
character = new options.Character({
position: options.positionFn(),
widthHeight: [50, 25],
});
break;
case Zombie:
character = new options.Character({
position: options.positionFn(),
widthHeight: [50, 25],
image: options.image,
// velocity: [1, 1],
});
break;
case Bullet:
character = new options.Character({
position: options.positionFn(),
widthHeight: [5, 25],
rotation: [10, 10],
});
break;
default:
break;
}
characters.push(character);
}
return characters;
}
}
/**
* =============================================================================
* Character
* =============================================================================
*/
interface CharacterOptions extends GameObjectOptions {
alive?: boolean;
velocity?: Vector2;
widthHeight: Vector2;
}
abstract class Character extends GameObject {
public alive: boolean;
public velocity: Vector2;
public widthHeight: Vector2;
public abstract imageType: string; // 'bitmap' | 'rectangle';
public constructor({
alive = true,
velocity = [0, 0],
widthHeight,
...characterOptions
}: CharacterOptions) {
super(characterOptions);
this.alive = alive;
this.velocity = velocity;
this.widthHeight = vectors.multiply(widthHeight, this.scale);
}
}
/**
* =============================================================================
* Hero
* =============================================================================
*/
export class Hero extends Character {
private color = 'red';
public imageType = 'rectangle';
public constructor({ ...characterOptions }: CharacterOptions) {
super(characterOptions);
}
}
/**
* =============================================================================
* Zombie
* =============================================================================
*/
interface ZombieOptions extends CharacterOptions {
image: HTMLImageElement;
}
export class Zombie extends Character {
private image: HTMLImageElement;
public imageType = 'bitmap';
public constructor({ image, ...characterOptions }: ZombieOptions) {
super(characterOptions);
this.image = image;
}
}
/**
* =============================================================================
* Bullet
* =============================================================================
*/
export class Bullet extends Character {
private color = 'green';
public imageType = 'rectangle';
public constructor({ ...characterOptions }: CharacterOptions) {
super(characterOptions);
}
}
/**
* =============================================================================
* Game simple factory pattern
* =============================================================================
*/
export interface Newable<T> {
new (...args: any[]): T;
}
interface GameFactoryOptions {
Character: Newable<Character>; // https://stackoverflow.com/questions/41017287/cannot-use-new-with-expression-typescript
numberOf: number;
level: number;
positionFn: any;
image?: HTMLImageElement;
}
In:
npx tplant --input ./**/*.ts --output ./Playground.svg
Out:
npx: installed 15 in 3.177s
events.js:292
throw er; // Unhandled 'error' event
^
Error: socket hang up
at connResetException (internal/errors.js:607:14)
at Socket.socketOnEnd (_http_client.js:493:23)
at Socket.emit (events.js:327:22)
at endReadableNT (internal/streams/readable.js:1327:12)
at processTicksAndRejections (internal/process/task_queues.js:80:21)
Emitted 'error' event on ClientRequest instance at:
at Socket.socketOnEnd (_http_client.js:493:9)
at Socket.emit (events.js:327:22)
at endReadableNT (internal/streams/readable.js:1327:12)
at processTicksAndRejections (internal/process/task_queues.js:80:21) {
code: 'ECONNRESET'
It is clear that this is not a mistake on your part. However, it would be nice to write something meaningful in addition to the log.
Line 145 in f54c1de
I want to use this in a CI on Github to create PlantUML documentation of my API. But I don't want to see all the methods or attributes in the diagrams.
I'd like to insert a line hide members
. But maybe I also want to hide circle
or other customizations. I don't want to hack something with sed
(but I will probably end up doing that).
It would be cool if tplant had an option -config <includefile>
that would include the file just after the @startuml
that is generated.
https://github.com/bafolts/tplant/blob/master/package.json shows ISC as the license, but https://github.com/bafolts/tplant/blob/master/LICENSE is the GPL-3.0 license.
E.g.
tplant --input test/Playground/Inheritance/*.ts --output test/Playground/Inheritance.svg
results in a single box, that describes the Animal class.
tplant --input test/Playground/Inheritance/*.ts --output test/Playground/Inheritance.puml
results in:
@startuml
class Animal {
+name: string
+move(distanceInMeters?: number): void
}
@enduml
Presumably there should be other boxes, such as Horse.
Running on Win 10, via MINGW64 git-bash terminal window.
tplant version: 3.1.1
Problem
when the interface is in a different namespace, when using in a class or in an interface, the svg is not generated. Below, the svg "content":
Cause
I was able to replicate the problem with the code below:
namespace interfaces {
export interface IGreeter {
greet(): string;
}
}
export class Greeter implements interfaces.IGreeter {
greeting: string;
prefix: string = "Hello, ";
constructor(message: string) {
this.greeting = message;
}
set prefix(prefix: string) {
this.prefix = prefix;
}
greet(prefix: string = "Foo"): string;
greet(): string {
return this.prefix + this.greeting;
}
}
Code example:
interface ComplexTypesInterface {
type: Dict<{ stringType: string; numberType: number; }> | undefined;
}
Current transformation:
@startuml
interface ComplexTypesInterface {
type: Dict<{ stringType: string; numberType: number; }>
}
@enduml
Expected transformation:
@startuml
interface ComplexTypesInterface {
type: Dict<{ stringType: string; numberType: number; }> | undefined
}
@enduml
As a Dev I need a support for 'types'
e.g.
type ExampleType = string | Function;
Great work, I'm eager to use it!
I'm working on a large browser based project with namespaces. It looks like tplant outputs only the startuml and enduml tags when hitting the keyword namespace or module,..
I am trying to run your project on this repo
The command i am running is tplant --input **/*.ts --output Playground.svg --project /
Surely i should see many more relationships than this? Am i doing something wrong?
I am the maintainer of tplant ^ -1
or in other words plantuml-parser 😃 . I do think it would be very beneficial for users if we could somehow make our two projects compatible with each other. Meaning if code could be transpired to a diagram using tsplant
and then back to code using plantuml-parser
.
In this issue i would just like to check if you'd see value in a collaboration. And maybe discuss possible next steps.
The tplant
does not support type parameters. Therefore, when the following code was used:
class NodeDependenciesProvider implements vscode.TreeDataProvider<Dependency> {
...
The PlantUML output did not include the type information behind the implements
keyword:
@startuml
class NodeDependenciesProvider implements {
+getTreeItem(element: Dependency): vscode.TreeItem
+getChildren(element?: Dependency | undefined): Thenable<Dependency[]>
}
...
@enduml
When I run:
./bin/tplant.js -i ~/Git-Projects/t2-2/t2/CypherApp/src/app/app.component.ts
I now get this error:
/Users/jameslynch/Git-Projects/tplant/src/typescriptToMeta.js:154
throw new Error("unable to determine member modifier type");
^
Error: unable to determine member modifier type
at getMemberModifierType (/Users/jameslynch/Git-Projects/tplant/src/typescriptToMeta.js:154:15)
at serializeMember (/Users/jameslynch/Git-Projects/tplant/src/typescriptToMeta.js:72:27)
at serializeClass (/Users/jameslynch/Git-Projects/tplant/src/typescriptToMeta.js:209:34)
at visit (/Users/jameslynch/Git-Projects/tplant/src/typescriptToMeta.js:47:25)
at visitEachNode (/Users/jameslynch/Git-Projects/tplant/node_modules/typescript/lib/typescript.js:13907:30)
at Object.forEachChild (/Users/jameslynch/Git-Projects/tplant/node_modules/typescript/lib/typescript.js:14078:24)
at generateDocumentation (/Users/jameslynch/Git-Projects/tplant/src/typescriptToMeta.js:27:16)
at module.exports (/Users/jameslynch/Git-Projects/tplant/src/typescriptToMeta.js:230:12)
at Object.<anonymous> (/Users/jameslynch/Git-Projects/tplant/bin/tplant.js:19:5)
at Module._compile (module.js:570:32)
tplant (master) ♘
Hi,
At the moment tplant does not add {abstract}
fields when needed. For example:
abstract class BitmapCharacter extends BaseCharacter {
abstract image: HTMLImageElement;
abstract widthHeight: Vector2;
}
should generate:
abstract class BitmapCharacter extends BaseCharacter {
+{abstract} image: HTMLImageElement
+{abstract} widthHeight: [number, number]
}
Which makes them italic in the diagram, much easier to understand :) Cheers.
Hi! I have tried using project option, but cannot get it to work.
I always get "Missing input file"
Any clues?
I have tested with a simplified tsconfig (just files, one path).
No joy.
BR! /marcus
Wouldn't it be better to have class accessors together with it's methods? That would make diagram easier to read.
class Accessors {
_foo: string
_bar: string
get bar() {
return this._bar
}
set bar(value) {
this._bar = value
}
foo() {
this._foo = 'foo'
}
}
@startuml
class Accessors {
+_foo: string
+_bar: string
+bar: string
+bar: string
+foo(): void
}
@enduml
@startuml
class Accessors {
+_foo: string
+_bar: string
+{method} get bar: string
+{method} set bar: string
+foo(): void
}
@enduml
Add the feature to generate/download the platuml generated image. The url can be generated with plantuml-encoder
Suggestion:
Read the extension from the output file given like:
tplant -i sample/Classes/Greeter.ts -o Greeter.svg
tplant -i sample/Classes/Greeter.ts -o Greeter.png
For a better experience, we might need to accept multiple outputs for this case.
The recent commit 2 days ago (as of this writing) cb68f529491dabda19fe9e2ff3284ad80e8b2b30 has a bug which leads to the following error upon trying to use tplant
anything.
internal/modules/cjs/loader.js:605
throw err;
^
Error: Cannot find module './components/Class'
at Function.Module._resolveFilename (internal/modules/cjs/loader.js:603:15)
at Function.Module._load (internal/modules/cjs/loader.js:529:25)
at Module.require (internal/modules/cjs/loader.js:659:17)
at require (internal/modules/cjs/helpers.js:22:18)
at Object.<anonymous> (C:\Users\Administrator\AppData\Roaming\npm\node_modules\tplant\dist\convertToPlant.js:11:15)
at Module._compile (internal/modules/cjs/loader.js:723:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:734:10)
at Module.load (internal/modules/cjs/loader.js:620:32)
at tryModuleLoad (internal/modules/cjs/loader.js:560:12)
at Function.Module._load (internal/modules/cjs/loader.js:552:3)
Installing version 2.1.4 fixes the issue.
OS: Windows 10 64-bit Version: 1803. Build: 17134.81
NPM: 6.4.1
Node: 11.4.0
Opening this issue to request support for TSX files and to create class diagrams for React components.
export default (props: SomePropsType) => {
return <div />
}
For these, I think it would make sense to use the file name as the component's name, unless the filename is "index.tsx", in which case the containing folder's name should be used. This should cover 99.9% of use cases.
If a component is in the form const ComponentName = (props: SomePropsType) => <div />;
, then the const variable's name should be used as the component name.
With react hooks, it is not possible to determine a hooks-based component's state. We can just ignore the state in these cases. If better tooling arises in the future for this from the react team (or a 3rd party), this could be revisited
export default () => {
// Not easy at all to infer these types, especially with custom hooks
// that wrap multiple calls to useState
const [counter, setCounter] = useState(0);
return (
<div>
<h1>Count: {counter}</h1>
<button onClick={() => setCounter(counter + 1)}>+</button>
<button onClick={() => setCounter(counter - 1)}>-</button>
</div>
);
}
Input:
interface FCProps {
text: string
}
function FuncComp(props: FCProps) {
return <span>{props.text}</span>;
}
interface ArrowProps {
title: string;
value: number;
}
const ArrowComp = (props: ArrowProps) => {
return (
<div>
<FuncComp text={props.title} />
<span>Value: {props.value}</span>
</div>
);
}
const NoPropsComp = () => {
return (
<div>
<span>I don't have any props</span>
</div>
);
}
interface ClassProps {
title: string;
}
interface ClassState {
value: number;
}
// Props and state types can be left out here, but it has to be
// given if they're being used.
class ClassComp extends React.Component<ClassProps, ClassState> {
state = {
value: 0,
};
public render() {
return (
<div>
<ArrowComp
title={this.props.title}
value={this.state.value}
/>
<NoPropsComp />
<button onClick={this.onIncrement}>+</button>
<button onClick={this.onDecrement}>-</button>
</div>
);
}
private onIncrement = () => {
this.setState(prevState => ({ value: prevState.value + 1 }));
}
private onDecrement = () => {
this.setState(prevState => ({ value: prevState.value - 1 }));
}
}
Output:
@startuml
class FuncComp <function> {
..Props..
text: string
}
class ArrowComp <arrow> {
..Props..
title: string
value: number
}
class NoPropsComp <arrow> {
..Props..
}
class ClassComp <class> {
..Props..
title: string
..State..
value: number
}
ClassComp <-- ArrowComp
ClassComp <-- NoPropsComp
ArrowComp <-- FuncComp
@enduml
class MyComp extends React.Component {
contextType: React.ContextType<typeof MyContext>
}
but that seems out of scope for this initial issue, and becomes more complicated with hooks.
Component diagrams could become incredibly large. It is typical for React projects to have a lot of components defined in them. Maybe support a --max-component-depth
option or something to work around it?
This would ignore any components that are made using React.createElement
, but no one really does that anymore.
Doesn't address how to handle 3rd party components. I'd say ignore them. 3rd party components are often written in JS and shipped with .d.ts
files. This would be very difficult to support, and probably wouldn't be very useful anyway.
Version tplant: 3.1.1
Problem
when a class is in a different namespace, the relation to that class is not represented.
Cause
namespace classes {
export abstract class AbstractPrefix {
abstract prefix: string;
}
}
export class Greeter extends classes.AbstractPrefix {
greeting: string;
prefix: string = "Hello, ";
//... rest of the sample
}
Hi, is other relation like aggregation planned for the future release?
Implement Generic class or interface transformations.
Write a test case with sample/Generics/Greeter.ts.
Hi,
It could be great to add an option to exclude Typescript files.
Example :
tplant --input src/**/.ts --output uml/uml.svg --associations --exclude src/extensions/.ts
My use case is that I have created extensions for some class in the src/extensions/*
folder and plantuml does not support that. I would like to exclude all the files in this folder and keep all other files contains in src/**/*.ts to generate the uml.
First, thanks for making tplant! It is very useful!
The composition flag is good, but I'm suggesting the following improvements. Let me use this example from test/Raytracer/Scene.ts
:
export interface Scene {
things: Thing[];
lights: Light[];
camera: Camera;
}
The PlantUML produced using the composition flag should be
Scene --> "things" Thing
Scene --> "lights" Light
Scene --> "camera" Camera
Here are my reasons:
*--
), many of which are not truly the semantics of composition. It's pretty hard to figure that out from static analysis of source code, I think. Edit: Furthermore, aggregation (to many) isn't really any different than an association in UML, so a simpler link is just to use --
.Scene.things: Thing[];
implies one can navigate from the class Scene to one or more Thing. Edit: Hence, I suggest -->
."things" Thing
as above, and a cardinality such as "*" Thing
. Maybe combining them?Scene --> "things\n*" Thing
which doesn't always look so great, but is useful I think.
Edit: in cases of a single reference, e.g. myThing: Thing
the cardinality would be "1"
I'd be happy to try a PR to support some of these things (with tests, of course), if you think they're reasonable.
The supplied file doesn't generate correctly because of multiple inheritance when using Interfaces.
If I install globally or locally via NPM I just get:
/usr/bin/tplant: line 1: use strict: command not found
/usr/bin/tplant: line 2: syntax error near unexpected token `('
/usr/bin/tplant: line 2: `var __importDefault = (this && this.__importDefault) || function (mod) {'
If I just type tplant
or use tplant --input app.ts --output uml.puml
version 2.2, Fedora 29 Linux, Node 12.1.0
(an older version of tplant worked fine, I filed another issues a while ago)
Thanks for this :) !
I've an issue with enum when I use tplant the enum is empty.
cat MySuperEnum.ts
export enum MySuperEnum {
AWESOME,
SUPER,
COOL
}
npx tplant --version
2.0.3
npx tplant --input MySuperEnum.ts
@startuml
enum MySuperEnum {
}
@enduml
I know overloading is a rather rare (and kinda hacky) thing in Typescript, but still a thing that exists. At the moment, those functions will be exported incorrectly by tplant.
Example ts
export class Test {
move(dx: number, dy: number): string;
move(v: Vector2): string;
move(vordx: number | Vector2, dy?: number): string {
return "just a test";
}
}
export class Vector2{
public x: number;
public y: number;
}
What it currently looks like
@startuml
class Test {
+move(): dx: number, dy: number): string; (v: Vector2): string; }
}
class Vector2 {
+x: number
+y: number
}
@enduml
What it should look like
@startuml
class Test {
+move(dx: number, dy: number): string
+move(v: Vector2): string
}
class Vector2 {
+x: number
+y: number
}
@enduml
I started to create a small viewer: http://tplant.loopingz.com/
To avoid using a website to do the image generation we might me able to reuse the code from my viewer inside the tplant cli.
https://github.com/loopingz/tplantviewer/
Problem
When a namespace defines several namespaces, the output file is just the first namespace, and everything else is ignored.
Scenario
Imagine defining a namespace that contains other namespaces until it has the class:
namespace very.special {
export class Greeter {
greeting: string;
prefix: string = "Hello, ";
constructor(message: string) {
this.greeting = message;
}
set prefix(prefix: string) {
this.prefix = prefix;
}
greet(prefix: string = "Foo"): string;
greet(): string {
return this.prefix + this.greeting;
}
}
}
When running the command line:
tplant --input test/Playground/Classes/*.ts --output test/Playground/testmultinamespace.svg
All the code that is analyzed before this pattern gets added to the SVG, but after this pattern, nothing else is added.
Example:
interface GenericTypes {
genericType: GenericClass<string, number>;
genericType2: GenericClass2<string>;
genericReturnType(): GenericInterface<string>;
genericReturnType2(): GenericInterface3<string, number>;
genericParameter(parameter: GenericInterface2<string>): void;
}
Current behavior:
@startuml
interface GenericTypes {
+genericType: GenericClass<string, number>
+genericType2: GenericClass2<string>
+genericReturnType(): GenericInterface<string>
+genericReturnType2(): GenericInterface3<string, number>
+genericParameter(parameter: GenericInterface2<string>): void
}
@enduml
Expected behavior:
@startuml
interface GenericTypes {
+genericType: GenericClass<string, number>
+genericType2: GenericClass2<string>
+genericReturnType(): GenericInterface<string>
+genericReturnType2(): GenericInterface3<string, number>
+genericParameter(parameter: GenericInterface2<string>): void
}
GenericTypes *-- GenericClass
GenericTypes *-- GenericClass2
GenericTypes *-- GenericInterface
GenericTypes *-- GenericInterface3
GenericTypes *-- GenericInterface2
@enduml
Hi. This might be a big noob question, thanks for your help in advance.
I am creating a new ionic project which uses Typescript and am now trying to generate a UML diagram of all the pages and services I have in my project.
basically, I have 4 pages, each page have a .ts file which all imports one ts file called orgService.ts. When I use this orgService.ts as input, the uml generated only shows the orgService and files the orgService.ts imports, but not ones that import orgService.ts. How do I have all of them in a single uml diagram?
Thanks for the help again :)
TypeScript provides several utility types to facilitate common type transformations. These utilities are available globally.
interface Todo {
title: string;
description: string;
completed: boolean;
createdAt: number;
}
class MyTodo implements omit<Todo, "createdAt"> {
…
}
Utility Types should be considered in the presentation of the class diagrams. Currently, they are incorrectly listed as independent instances.
Hi! First of all I would like to express great admire to this idea.
It's so simple and implementation is perfect.
However I would like to have some feature which I wish to have in my diagram.
Sometimes we have classes which have instances of another classes. So it's not inheritance but another way of relationship.
How about the idea to invent pseudo comment (may be TSDoc) in ts file declaring that a specific attribute is a relationship in fact: aggregation or composition? Or at least by default all kinds of attributes with references to interfaces/classes include with aggregation by default?
Thank you!
Now, we always use an default configuration.
options: ts.CompilerOptions = {
module: ts.ModuleKind.CommonJS,
target: ts.ScriptTarget.ES2015
}
It can change from project to project, so we should be able to define an custom tsconfig.json file for the compiler.
Like:
tplant -i Foo/Bar.ts --tsconfig Foo/tsconfig.json
If a nested folder has a file with multiple named exports the output class name gets broken.
// /FooBar/types.ts
export interface Foo {
bar: number
foo: string
}
export interface Bar extends Foo {
foobar: boolean
}
run in root folder: npx tplant -A -f mermaid -i '**/*.ts' -o uml.mmd
Output:
classDiagram
class Foo {
+bar: number
+foo: string
}
<<Interface>> Foo
"FooBar/types".Foo <|.. Bar
class Bar {
+foobar: boolean
}
<<Interface>> Bar
Expected:
classDiagram
class Foo {
+bar: number
+foo: string
}
<<Interface>> Foo
Foo <|.. Bar
class Bar {
+foobar: boolean
}
<<Interface>> Bar
Both Mermaid and PlantUML break because of "FooBar/types".
Version: 3.1.2
Hi,
Thank you for this amazing tool.
When a property/parameter is of a type belonging to a namespace, is there a way to display this namespace in the generated PlantUML diagram?
Handle indexes. Example:
interface Dict<T> {
[index: string]: T;
}
@startuml
interface Dict<T> {
+[index: string]: T
}
@enduml
PS C:\victor-web\victor-next\apps\victor-next> tplant --input "./src/victor-next/controls/oneUp/*.ts" --output test.svg
events.js:291
throw er; // Unhandled 'error' event
^
Error: read ECONNRESET
at TCP.onStreamRead (internal/stream_base_commons.js:209:20)
Emitted 'error' event on ClientRequest instance at:
at Socket.socketErrorListener (_http_client.js:427:9)
at Socket.emit (events.js:314:20)
at emitErrorNT (internal/streams/destroy.js:92:8)
at emitErrorAndCloseNT (internal/streams/destroy.js:60:3)
at processTicksAndRejections (internal/process/task_queues.js:84:21) {
errno: 'ECONNRESET',
code: 'ECONNRESET',
syscall: 'read'
}
PS C:\victor-web\victor-next\apps\victor-next>
Hi,
Today I tried to create a .png file twice and both times they came back corrupted and unable to display. File length 111.2 kB. The .svg is still working fine.
"uml": "tplant --input src/app.ts --output uml-diagram.png"
( tplant --version 2.3.0 )
Hi, great library.
A small issue I ran into, is that tplant
will not throw an error/warning when the output directory does not exist. It simply says Done in x secs.
while nothing is generated.
In my case, I wanted to output to reports/uml/uml.svg
. reports/uml
did not exist, reports/xyz
did, though.
Suggested solution:
Cheers
Hi, I just cloned this repo and tried to run this command:
./tplant.js ../sample/Class.ts
but I'm getting this error:
module.js:471
throw err;
^
Error: Cannot find module 'commander'
at Function.Module._resolveFilename (module.js:469:15)
at Function.Module._load (module.js:417:25)
at Module.require (module.js:497:17)
at require (internal/module.js:20:19)
at Object.<anonymous> (/Users/jameslynch/Git-Projects/tplant/bin/tplant.js:3:15)
at Module._compile (module.js:570:32)
at Object.Module._extensions..js (module.js:579:10)
at Module.load (module.js:487:32)
at tryModuleLoad (module.js:446:12)
at Function.Module._load (module.js:438:3)
Hello! I encountered a problem when generating diagram.
Example content-object.model.ts
:
export interface ContentObject extends PageOption, BaseContentModel {
id: number;
type: string;
name: string;
label: string;
}
When I produce the UML file, there should have be two extend arrows (Pageoption and Basecontentmodel) but it only had one to PageOption interface.
Results in
ContentObject ⇒ PageOption
Using tplant CLI with Typescript 4.7 and moduleResolution="Node16" raises the following error:
Error: Argument for '--moduleResolution' option must be: 'node', 'classic', 'node12', 'nodenext'.
package.json
{
"name": "tplant-node16-bug",
"version": "1.0.0",
"type": "module",
"scripts": {
"uml": "tplant -i src/**/*.ts -o diagram.puml"
}
"devDependencies": {
"tplant": "^3.1.0",
"typescript": "^4.7.4"
}
}
tsconfig.json
{
"compilerOptions": {
"module": "Node16",
"moduleResolution": "Node16",
"target": "es6",
},
"exclude": [
"node_modules"
]
}
"moduleResolution": "Node16" is required for Typescript 4.7 support of the exports field in package.json
Just ran tplant on my project, got strange results. It doesn't seem to understand that default
is a keyword, and not the name of the class. Here are some examples:
class default extends Error {
class default {
class default extends Client
class default {
abstract class default {
class default extends Parser {
And so on.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.