This commit is contained in:
nik
2025-10-03 22:27:28 +03:00
parent 829fad0e17
commit 871cf7e792
16520 changed files with 2967597 additions and 3 deletions

View File

@@ -0,0 +1,54 @@
== Audience
:icons: font
This document is written for the contributors. If you want to integrate ZenUML in your application,
you should read index.adoc; if you want to create themes, you should read create-my-own-theme.adoc.
== Build
This project is built with vue cli. It has two types of target: the web application and the library.
....
# to build the library
yarn build
# to build the web application
yarn build:site
....
== Demo pages
In the public folder, there are some demo pages for testing the library.
=== How do they work?
The demo pages^1^ are built with vue cli service. On the page, there needs to be a `pre`
element with class `zenuml` and the content being the ZenUML DSL code.
For example:
[source, html]
....
<pre class="zenuml">
A.method
</pre>
....
The entry point of the demo pages is `src/main.ts`. It will find all the `pre` elements with
class `zenuml` and render the ZenUML DSL code in it.
== Parser
We use antlr4 to parse the ZenUML DSL code. The grammar files are:
1. Parser: `./src/g4/sequenceParser.g4`
2. Lexer: `./src/g4/sequenceLexer.g4`
=== How to generate the parser and lexer
Run `yarn antlr4` to generate the parser and lexer.
=== Setup local development environment
Run `yarn antlr:setup` (`python3 -m pip install antlr4-tools`) to install the antlr4 command and the runtime.
To test the setup, go to `src/g4-unit/hello-world` folder, and run:
1.

View File

@@ -0,0 +1,149 @@
= Creat my own theme
Since the elements on the rendered diagram is based on HTML Dom (and svg), it is simple
to create your own theme. There is a repository on GitHub that have some themes collected
by third party. You may be able to get some inspiration from there. https://github.com/abruzzi/zenuml-css-overrides
== The Information Architecture
image::./images/three-layer-info-arch.png[width=600]
The diagram is rendered in two layers. The back layer is the lifeline layer. The front layer
is the message layer.
Key information on the diagram can be grouped in the following structure:
Text messages are internally styled at four levels:
1. text-skin-base: used for all messages
2. text-skin-muted: used for comments
3. text-skin-link: used for links
4. text-skin-secondary: used for everything else, such as title, participant, divider notes, etc.
When it comes to branding, the following elements are the most important:
1. Canvas background, however, it can easily be overwhelming if you use high contrast color to the
overall page background.
2. Title background, participant background and fragment header background are the most attractive
elements to brand. These are where your brand color should be used.
3. The background of the occurrence (message bar) is also a good place to use your brand color, but
less attractive than the above three.
4. The borders of the frame, participant, fragment, occurrence and lifeline can add a bit
of color to the diagram.
5. The color of the message and the arrow are the most important information on
the diagram. Choose a striking and comfortable color for them. You can use the brand color here, but
they should not be the only elements that reflect your brand color. Same principles apply to the
background and text color for hover state.
6. Then is the color of link and control. They should avoid attracting too much attention
[%autowidth]
|===
|Category | Diagram Frame |Lifeline Layer | Message Layer
h|Text Info
a|* Title
* Brand
a|* Participant name
* Stereotype
* Comment
a|* Message name
* Fragment type
* Fragment condition
* Comment
* Divider name
h|Shapes
a|* Security (icon)
* Tips (icon)
a|* Participant box (rectangle)
* Lifeline (vertical line)
a|* Message arrow (line and head)
* Fragment (rectangle)
* Divider line (left and right)
|===
Each of the elements has a semantic selector that can be used to customize the appearance.
The component has basic styling in itself mostly to support layout and positioning. Then
the core renderer comes with a default theme that defines the appearance of the elements.
[source,css]
----
----
A typical custom theme will be like below:
[source,css]
----
----
== What can a theme change?
A theme can change two aspects of the diagram:
1. colors
2. slightly change the layout (e.g. padding, margin, etc.). For example, you can make the
diagram more compact by reducing the padding.
== where can I apply themes
You can apply themes on the follow products:
. JetBrains plugins (Intellij IDEA, WebStore, PhpStore, etc.)
. https://app.zenuml.com
With https://chrome.google.com/webstore/detail/user-css/okpjlejfhacmgjkmknjhadmkdbcldfcb[User CSS]
browser extension, you can apply themes anywhere (e.g. https://zenuml.cn).
== Principles of creating themes
=== 1. Do not override tailwind classes
The tailwind classes directly applied on the elements are important for layout so
they are NOT meant be overridden.
For example,
[html]
....
// Participant.vue
<div class="participant relative flex flex-col justify-center z-10 h-10"
....
=== 2. Use provided class selectors
Important elements are provided with a semantic class selector. You can use them
to override the style.
For the above example, the class selector is `participant`. You can override the
style by using this selector.
[css]
....
// use `.zenuml .sequence-diagram` to increase specificity
.zenuml .sequence-diagram .participant {
background-color: #f00;
}
....
=== 3. Debug your theme
You can use the browser extension https://chrome.google.com/webstore/detail/user-css/okpjlejfhacmgjkmknjhadmkdbcldfcb[User CSS]
to debug your theme.
image::user-css.png[User CSS]
Alternatively, you can use our web app https://app.zenuml.com[app.zenuml.com]. Go to the CSS tab
and paste your theme there. You can see the result immediately.
image::theme-debug-web-app.png[]
=== JetBrains
=== app.zenuml.com
== Tips
=== Give occurrence a boarder

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 510 KiB

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 202.624 202.624" style="enable-background:new 0 0 202.624 202.624" xml:space="preserve"><path d="M202.621 97.416h-38.966V58.45a3.896 3.896 0 0 0-3.897-3.897h-38.966a3.896 3.896 0 0 0-3.897 3.897v38.966H85.724V35.07a3.896 3.896 0 0 0-3.897-3.897H42.862a3.896 3.896 0 0 0-3.897 3.897v62.345H0v7.793h38.966v62.345a3.896 3.896 0 0 0 3.897 3.897h38.966a3.896 3.896 0 0 0 3.897-3.897v-62.345h31.172v38.966a3.896 3.896 0 0 0 3.897 3.897h38.966a3.896 3.896 0 0 0 3.897-3.897v-38.966h38.966v-7.793h-.003zm-124.69 0v66.241H46.759V38.968h31.172v58.448zm77.931 0v42.862H124.69V62.346h31.172v35.07z"/></svg>

After

Width:  |  Height:  |  Size: 647 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

277
node_modules/@zenuml/core/docs/asciidoc/index.adoc generated vendored Normal file
View File

@@ -0,0 +1,277 @@
:icons: font
== Font
Font [.underline]#must# be *preloaded*. Font mainly have impact to Creation
rendering. The font will impact the width of the participant box which then
impacts the with of message container for creation.
The following code should help with preloading google fonts. But it is not super
reliable. Specifically, when you disable cache in Chrome. It is not preloaded
where you can see the impact.
....
<link rel='preconnect' href='https://fonts.gstatic.com' crossorigin>
<link rel='preload stylesheet' as='style' href='https://fonts.googleapis.com/css2?family=Roboto+Slab:wght@300;400;500;700&display=swap'>
....
We have to use `setTimeout` to delay the calculation of the width of the
message container.
== The two layer structure
At the highest level, the diagram is rendered in two layers:
the lifeline layer and the message layer.
....
<div class="sequence-diagram">
<div class="life-line-layer absolute h-full">
</div>
<div class="message-layer">
</div>
</div>
....
=== Key classes
==== .absolute
The `absolute` class is used to remove the lifeline layer from the normal
flow of the document.
==== .h-full
The `h-full` class is used to make the lifeline layer as tall as the parent
element. The parent element get the height from the `message-layer`.
== The message layer
=== Occurrence
_TODO_: explain misalignment of the occurrence concept and the spec.
image::images/occurrence.png[width=304,alt="occurrence"]
The occurrence is the bar (or invisible bar for async messages) that
represents the execution of a message.
It has a width of 15px and border of 2px. These two values #must not#
be overridden in themes.
It has a padding-left of 5px which pushes the children `interaction` to
the middle of the occurrence.
....
(occurrenceWidth - occurrenceBorderWidth x 2 - lifelineWidth) / 2
= (15 - 2 x 2 - 1) / 2
= 5
....
Because the lifeline has width of 1px, for normal (left to right) `interaction` s
we give it a margin left of 1px to avoid the overlap of the lifeline and the
interaction border. See `interaction` for more details.
=== Interaction
The `interaction` is one of the key conceptual elements. It works with
the `occurrence` to influence high-level layout. The `interaction` is the container
of the message, children interactions and the response.
The `interaction` has a border of 5px. This value #must not# be overridden in themes.
....
(occurrenceWidth - occurrenceBorderWidth x 2 - lifelineWidth) / 2
= (15 - 2 x 2 - 1) / 2
= 5
....
Within Interaction, the DOM structure is like below:
....
<div class="interaction">
<div class="occurrence source"></div>
<comment/>
<invocation/> <1>
<occurrence/>
<message type="return">
</div>
....
<1> SelfInvocation or Message
==== Do not add margin to interaction
It is on purpose that interaction box overlaps source lifeline but not the target
lifeline. Do not add #margin# to interaction components. This margin will cause
interaction's right board overlaps target lifeline and that is accumulative.
==== Debugging
Disable transparency of the interaction borders.
=== Common features among Interaction, Interaction and Creation
All the three work as a container for the message, children interactions and the
response. In the normal direction (left to right), they start with the middle
of the source lifeline and end with the middle of the target lifeline.
=== Return message
The return message is the message that is sent back to the sender of the original
message. It is rendered as a dashed line.
A return message is rendered from three syntax:
* `return x` which matches `RETURN expr? SCOL?`
* `@return A->B: ret` which matches `ANNOTATION_RET asyncMessage EVENT_END?`
* `x=A.m` or `x=new A()` which matches `assignment? ((from ARROW)? to DOT)? func` or `assignment? NEW construct(OPAR parameters? CPAR)?`
==== Statement `return x` or `@return A->B: ret`
`return x` or `@return A->B: ret` is implemented via the `Return` component.
In such cases, it has its own context and can have a comment. Then it
delegates to `SelfInvocation` or `Message`.
===== When do we need `@return A->B: ret`?
....
Browser->BookController.onPost() {
BookLibService.Borrow(id) {
receipt = process(id)
if (receipt != null) {
return receipt
@return BookController->Browser: receipt
} else {
return null
@return BookController->Browser: 404
}
}
}
....
If the statement is the last statement we set the height of the message to 0px,
so that it does not push the message down further. This is because a return message
does not have children and does not need an occurrence.
....
.statement-container:last-child>.return {
height: 0;
}
....
==== Return message from `x=A.m` or `x=new A`
This is implemented in Interaction and Creation components.
....
<message class="return transform -translate-y-full"/>
....
==== Conflicting return messages
We provide two ways in DSL to represent `return` messages:
....
// option 1
x = A.method
// option 2
A.method() {
return y
}
....
If you use both, we will render both with overlapping. This is on purpose to expose
the conflict to the user.
.Return message conflict
image::images/return-message-conflict.png[width=200,alt="return message conflict"]
=== Message arrow
.Message arrow (the dashed line and arrow head)
image::images/creation-component.png[width=224]
This time we focus on how to align the arrow line and the arrow head.
We use a similar approach as pattern #vertically aligning# with pattern
#shift half the height#. Instead of `items-center` we use `items-end`.
Then we use `translate-y-1/2` to shift the arrow head down half the
height of the arrow head. (See Message.vue)
....
<div class="message flex items-end"
<div class="name flex-grow" style="padding-left: 10px">{{content}}</div>
<point class="flex-shrink-0 transform translate-y-1/2 -my-px" :fill="fill" :rtl="rtl"/>
</div>
....
==== Key classes
===== .flex .items-end
The `flex` and `items-end` classes are used to align the arrow line
and the arrow head at the bottom of the message.
===== .flex-grow
The `flex-grow` class is used to make the message name grow to fill
the available space.
===== .flex-shrink-0
The `flex-shrink-0` class is used to make the arrow head not shrink
when the message name is too long.
===== .transform .translate-y-1/2
The `transform` and `translate-y-1/2` classes are used to shift the
arrow head down half the height of the arrow head.
=== Message arrow right to left
image::images/message-arrow-rtl.png[width=200,alt="message arrow right to left"]
....
<div class="message flex items-end" :class="{'flex-row-reverse': rtl}">
<div class="name flex-grow"
>{{content}}</div>
<point class="flex-shrink-0 transform translate-y-1/2 -my-px"/>
</div>
....
==== Key classes
===== .flex-row-reverse
The `flex-row-reverse` class is used to reverse the order of the name and
the arrow head.
=== Creation
image::images/creation-component.png[width=240]
==== Pattern 1: Vertically aligning
image::images/vertical-alignment.svg[width=40]
....
<div class="flex items-center">
<div class="w-10 h-8 bg-blue-200"></div>
<div class="w-10 h-20 bg-green-200"></div>
</div>
....
==== Pattern 2: Shift half the height
image::images/shift-up-half-the-height.png[width=50]
The message arrow is supposed to point to the middle of the participant
box. It is not he whole message that is aligned with the participant
box. So we have to shift the message up half the height of the message.
....
<div class="flex items-center m-10">
<div class="w-10 h-8 bg-blue-200 transform -translate-y-1/2"></div>
<div class="w-10 h-20 bg-green-200"></div>
</div>
....
This pattern is also used at the arrows. See the image for creation.
=== Creation participant top
While all normal participants have their name boxes at the top of the
diagram, creation participant boxes need to be pushed down to align
with the message arrow.
To implement this, we add a `padding-top` to the containing lifeline
of the corresponding participant.
The padding top is calculated by subtracting the top of message from
the top of participant's original value.
==== Challenge
When the message container is mounted, it does not have the correct
participant box offsetWidth.
=== Creation right to left
image::images/creation-rtl.png[width=240,alt="creation right to left"]
On top of normal Creation, we need to flip the participant placeholder
and the message container. We use the `flex-row-reverse` class to flip.
See "Message right to left" for example using `flex-row-reverse`.

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

22
node_modules/@zenuml/core/docs/asciidoc/tutorial.adoc generated vendored Normal file
View File

@@ -0,0 +1,22 @@
= User's guide
== Audience
This document is written for end users of the software. If you want to integrate
ZenUML into your own application, please refer to the integration guide. If you
want to contribute to the development of ZenUML, please refer to the contributor's
guide.
== Introduction
> A Sequence diagram is an interaction diagram that shows how processes operate with one another and in what order.
ZenUML is a tool for creating sequence diagrams from text. It runs completely
in the browser, so you don't need to worry about data privacy or security. See
https://link[data privacy and security] for more information.
++++
<iframe src="https://embed.zenuml.com/smoke-creation.html"></iframe>
++++
== Syntax
=== Participants

BIN
node_modules/@zenuml/core/docs/asciidoc/user-css.png generated vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB