Ref https://github.com/webstudio-is/webstudio/issues/2532
We decided to treat expressions as props bindings
so it makes sense to move expression data to props as well. This will
make expression and action simetrical and simplify data sources
management.
As you can see all expressions have same "expression" name now. In
another PR will change to prop name.
## Description
- Added support of "image/x-icon", "image/ico", for upload
- changed local dev resize path
- fixed zod meta types
- added favicon, site_name og tags in route template
- added cache headers for html content
## Steps for reproduction
1. click button
2. expect xyz
## Code Review
- [ ] hi @kof, I need you to do
- conceptual review (architecture, feature-correctness)
- detailed review (read every line)
- test it on preview
## Before requesting a review
- [ ] made a self-review
- [ ] added inline comments where things may be not obvious (the "why",
not "what")
## Before merging
- [ ] tested locally and on preview environment (preview dev login:
5de6)
- [ ] updated [test
cases](https://github.com/webstudio-is/webstudio/blob/main/apps/builder/docs/test-cases.md)
document
- [ ] added tests
- [ ] if any new env variables are added, added them to `.env.example`
and the `builder/env-check.js` if mandatory
Ref https://github.com/blakeembrey/change-case/releases
Change case in last major merged many packages into one to simplify
maintaining and usage. A few packages like title-case are still separate
as more rare case.
- replaced no-case with change-case (merged into change-case)
- replaced param-case with change-case (merged into change-case and
renamed to kebab (finally))
- replaced camelcase with change-case (has own camelcase utility)
- bumped title-case
Implements an operation-based system to accomplish a number of edit
tasks on a JSX+CSS representation of a selected Webstudio tree.
Every JSX element has the instance id as data-ws-id and therefore the
LLM knows what to edit.
The idea is to create a number of operations (aiOperations)
specs/schemas with Zod describing unique edit tasks, make a
discriminated union, convert them to JSON Schema. We then inject this
information and the current JSX+CSS in the LLM prompt asking the model
to generate an array of operations.
The LLM responds with an array of operations (aiOperations) to fulfill
the user request. We then process these doing the necessary
transformations to convert these to a Webstudio-friendly format
(wsOperations) and send them to the client where we apply them (see
applyOperations).
Some of these operations are going to be "intermediate" operations for
now.
Generating quality user interfaces might be challenging with LLMs.
Having to do so within a generic operations framework like the one
described above makes it even more challenging.
For this reason when it comes to generating user interfaces, the
Operation chain instead offers an operation called
generateTemplatePrompt that provides information about insertion point
in the existing UI and a prompt, possibly enhanced.
Another chain can use these information and a more sophisticated prompt
and model to then generate the user interface and return a
generateInsertTemplate wsOperation. Webstudio does exactly this in a
rest endpoint, using the template-generator chain with gpt4 instead of
gpt-3.5-turbo.
Adds utils to work with JSX and transform it to Webstudio Embed Template
as well as converting Tailwind styles to Webstudio Embed Template style
declarations and a fake `<HeroIcon>` component to `HtmlEmbed` with
inline SVG taken from heroicons (we will need this for ai).
Internal data structures like instances, props, data sources, assets and
pages no longer necessary in generated sites. Nanostores not longer used
to store them.
Now we have less dependencies and smaller runtime.
Here generated a list of pages paths. It is used in link component to
switch to remix link internally when the link is app route.
Providing whole pages list can bloat runtime when there are many pages
or when there are many seo data so having single page per route should
be enough.
The list is always empty in builder because links are managed with
global interceptor. Ideally frameworks should uses navigation api and
distinct routes from other paths so we would not need to generate
anything.
Moved links resolve into props normalizing which is called for whole
project before rendering converting page prop into string.
Remix links now check only if provided path matches any page. Ideally it
should be handled with navigation api to remove all complexity from
links components.
This will let us stop rendering props and assets data in generated
pages.
Also fixed links with hashes.
Before links and images required logic to traverse raw props data and
assets to resolve href and src. This can potentially affect rendering
performance and requires additional data to be stored in runtime.
Here pregenerated props with "asset" type as a first step. Images still
have to be aware of asset base url to trim it from resolved src but no
longer access to assets store. Links now interpret it as string url.
See fixtures for examples.
Here added "sdk-cli" package with "generate-stories" command which looks
for metas and generate stories from each one with template. This give us
more insight how component would look like on published sites.
Also removed old stories and added custom id support into embed template
to make stories ids stable.
Can be tested in local storybook
Scope utility give us a way to generate more readable data sources and
actions. Here variables, expressions and actions are output into the
same map.
In the future same utility can be used to produce framework specific
stores like React.useState.
See fixtures for example.
Here added jsx component generator. It allows us to have less tree
traversing and more clear output for debugging.
For now data sources are managed the old way with stores. In the future
we can switch to react `useState`.
In the future will be integrated into stories generator and cli
Internal data sources updates complicate code generation Here changed
forms too expose onStateChange action instead of implicit data source
update.
Added migration to add the action to every existing form. Tested locally
both new and migrated forms.
## Description
CLI support of vercel image optimisation
## Steps for reproduction
1. click button
2. expect xyz
## Code Review
- [ ] hi @kof, I need you to do
- conceptual review (architecture, feature-correctness)
- detailed review (read every line)
- test it on preview
## Before requesting a review
- [ ] made a self-review
- [ ] added inline comments where things may be not obvious (the "why",
not "what")
## Before merging
- [ ] tested locally and on preview environment (preview dev login:
5de6)
- [ ] updated [test
cases](https://github.com/webstudio-is/webstudio/blob/main/apps/builder/docs/test-cases.md)
document
- [ ] added tests
- [ ] if any new env variables are added, added them to `.env.example`
and the `builder/env-check.js` if mandatory
Pubsub is only used for builder/canvas communication while sdk is
responsible for rendering sites.
Here moved pubsub to builder. Now we can drop nanoevents from cli
dependencies.
Css-data now responsible for generated data and parsers which requires
heavy dependencies like csstree and openai.
Here moved style schema into css-engine which makes is responsible for
own input representation. So now schema and serialization are co-located
in single package.
Cli install size
```diff
du -ck node_modules
- 42680
+ 35516
```
We had db data validation enabled before but it made api requests very
slow. We disabled this validation and seems like there is no need to
enable again.
Also dropped all zod list types of our data because validation was the
only use case.
We are planning to move all types necessary to represent generated site
into separate package. This way we will be able to make CLI as small as
possible.
Here moved only assets schema. Now we get rid of aws, sharp and one
prisma usage (project-build still use it)
```diff
- 99MB
+ 75MB
```
Here moved PropMeta to react-sdk package. It was the only reason to
install generate-arg-types cli as direct dependency in all component
libraries.
This is the resulting install size of webstudio CLI. TypeScript and
react-docgen-typescript no longer installed.
```diff
- 141MB
+ 99MB
```
We used to set undefined in assets map value to preserve the order
between uploading and uploaded states. Now we started sorting uploaded
assets by create time and stubbing no longer do anything useful.
## Description
On onmount outdated onSave were used. What cause creation of additional
href property on instance.
- [x] - Fix duplication on unmount (1st commit)
- [x] - Fix save, to validate if multiple properties with same name
exists. (2nd commit)
- [x] - Use latest prop in resolveUrlProp (3rd commit)
Use hide whitespaces.
<img width="303" alt="image"
src="https://github.com/webstudio-is/webstudio-builder/assets/5077042/156fc5a4-c697-4b05-8caf-7a3b7fa29264">
## Steps for reproduction
1. click button
2. expect xyz
## Code Review
- [ ] hi @kof, I need you to do
- conceptual review (architecture, feature-correctness)
- detailed review (read every line)
- test it on preview
## Before requesting a review
- [ ] made a self-review
- [ ] added inline comments where things may be not obvious (the "why",
not "what")
## Before merging
- [ ] tested locally and on preview environment (preview dev login:
5de6)
- [ ] updated [test
cases](https://github.com/webstudio-is/webstudio-builder/blob/main/apps/builder/docs/test-cases.md)
document
- [ ] added tests
- [ ] if any new env variables are added, added them to `.env.example`
and the `builder/env-check.js` if mandatory
Here made meta.label optional to simplify adding new stuff. Most of the
time label is just a "humanized" version of component name. With radix
there is an additional action to strip namespace. But still would be
less repetition if the name is just inferred.
Here moved code generation of utilities from saas into sdk.
Now InstanceRoot accepts utils object with these 3 fields
- indexesWithinAncestors,
- executeComputingExpressions,
- executeEffectfulExpression,
Generation utility can be shared between cli and saas to simplify
maintenance.
## Description
Add radix button.
<img width="555" alt="image"
src="https://github.com/webstudio-is/webstudio-builder/assets/5077042/afd07b25-2592-4ed6-9788-dd880be2f22e">
## Steps for reproduction
1. click button
2. expect xyz
## Code Review
- [ ] hi @kof, I need you to do
- conceptual review (architecture, feature-correctness)
- detailed review (read every line)
- test it on preview
## Before requesting a review
- [ ] made a self-review
- [ ] added inline comments where things may be not obvious (the "why",
not "what")
## Before merging
- [ ] tested locally and on preview environment (preview dev login:
5de6)
- [ ] updated [test
cases](https://github.com/webstudio-is/webstudio-builder/blob/main/apps/builder/docs/test-cases.md)
document
- [ ] added tests
- [ ] if any new env variables are added, added them to `.env.example`
and the `builder/env-check.js` if mandatory
We want to control some builder behavior specific to some components.
For example set open state on dialog, collapsible etc when select in
navigator.
Here I added hooks to be called from builder and executed in canvas. For
now added 2 hooks onNavigatorSelect and onNavigatorDeselect.
## Description
Fix presets in case of namespaeces added `"` to selector
<img width="605" alt="image"
src="https://github.com/webstudio-is/webstudio-builder/assets/5077042/9b367c73-466e-4592-b45f-0b84660e423f">
Added presets to radix components
## Steps for reproduction
1. click button
2. expect xyz
## Code Review
- [ ] hi @kof, I need you to do
- conceptual review (architecture, feature-correctness)
- detailed review (read every line)
- test it on preview
## Before requesting a review
- [ ] made a self-review
- [ ] added inline comments where things may be not obvious (the "why",
not "what")
## Before merging
- [ ] tested locally and on preview environment (preview dev login:
5de6)
- [ ] updated [test
cases](https://github.com/webstudio-is/webstudio-builder/blob/main/apps/builder/docs/test-cases.md)
document
- [ ] added tests
- [ ] if any new env variables are added, added them to `.env.example`
and the `builder/env-check.js` if mandatory
Here added dedicated field to meta to simplify computing and using
indexes.
```
{
type: 'container',
label: 'Tab Trigger',
// this one
indexWithinAncestor: 'Tabs'
}
```
Since it's single value, we no longer need to provide ancestor name in
runtime and no longer have bug with namespaces. Index now provided with
props.
```
getIndexWithinAncestorFromComponentProps(props): string | undefined
```
Here changed the way we define data sources in embed templates. Now they
have separate section on instance. This way we will be able to use data
sources on styles or instances without binding them to props.
Also it's not more clear where data source is created vs where it is
only referenced.
```js
{
type: 'instance',
component: 'Form',
dataSources: {
state: { type: 'variable', initialValue: 'initial' },
stateInitial: { type: 'expression', code: `state === 'initial'` }
},
props: [
{
type: 'dataSource',
name: 'data-state',
dataSourceName: 'state'
}
],
children: []
}
```
Here added support for namespacing external libraries. Need this for
radix components to not prefix manually and have isolation in names in
case a few client libs are added an have collission in names or we add
native components with same names.