diff --git a/Cargo.lock b/Cargo.lock index 1452075c6..088989e2d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1711,6 +1711,16 @@ dependencies = [ "tonic-build", ] +[[package]] +name = "paperclip_tidy" +version = "0.1.1" +dependencies = [ + "paperclip_core", + "paperclip_project", + "paperclip_proto", + "paperclip_validate", +] + [[package]] name = "paperclip_validate" version = "0.1.1" diff --git a/Cargo.toml b/Cargo.toml index e748e0108..4efaae811 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,7 @@ members = [ "libs/validate", "libs/project", "libs/evaluator", + "libs/tidy", "libs/paperclip-loader", "libs/workspace", "libs/infer", diff --git a/TODO.md b/TODO.md index 0cee4a78a..ddc63b09c 100644 --- a/TODO.md +++ b/TODO.md @@ -1,40 +1,49 @@ #### FOCUS -- focus on editing - - - ensure that paths are absolute - - can move components to to other files - - references are updated - - update refs OF expression moved - -- everything should be editable in the UI - - should be able to edit variant triggers - - should be able to add scripts - - prohibit things from being deleted if references to them +- layers + - select slots + - ensure that all inserts are created + - proper UI for inserts #### Immediate -- designer stops working after lint error +- post edit clean up + + - prune unused imports + - add inserts of elements -- editing +- layers panel - - circular dependencies - - ability to move tokens to other files - - ability to move mixins to other files - - ability to move components to other files - - ability to move triggers to other files - - ensure that - - all instances of each expression is updated + - ability to drop assets to the canvas -- linting +- canvas + - topbar should not move when panels hide / show +- AI - - ensure that no magic colors are present - - ensure that no magic measurements are present + - CLI tool for interacting with code + - compare before committing -- layers panel +- Online editor - - ability to drop files into file navigator + - WASM bridge - file navigator -- styles + - ability to drop files to file navigator + - display assets + +- resource panel + + - display components + - display assets (svg, png) + - ability to drop assets to canvas + +- styles panel + +- properties panel + + - text input should be text area + +- compiler + - compile style mixins as css selectors + - compile style vars diff --git a/gpt-instructions.md b/gpts/archive/syntax.md similarity index 100% rename from gpt-instructions.md rename to gpts/archive/syntax.md diff --git a/gpts/current/bridge.md b/gpts/current/bridge.md new file mode 100644 index 000000000..479363ee9 --- /dev/null +++ b/gpts/current/bridge.md @@ -0,0 +1,8 @@ +/\* + +Instructions + behavior to bridge GPT with a library +that can interact with it. + +\*/ + +You will also be interacting with another system that can only take JSON. It will give you instructions, and you should only diff --git a/gpts/current/examples.md b/gpts/current/examples.md new file mode 100644 index 000000000..da06cbc84 --- /dev/null +++ b/gpts/current/examples.md @@ -0,0 +1,74 @@ +I'm going to give you some example instructions and what you might produce as a result of these instructions + +User: "build a card component with a title slot. Give the card a grey background and some padding" + +System: + +``` +component Card { + render div { + style { + background: grey + padding: 14px + } + + render h1 { + slot title + } + + slot content + } +} +``` + +User: "Create a card element with a class attribute called "card" + +System: + +``` +div (class: "card") { + +} +``` + +User: "Create a button component with an onClick handler" + +System: + +``` +component Button { + render button(onClick: onClick) { + slot children + } +} +``` + +User: "Create a header with a text node 'hello world'!" + +System: + +``` +h1 { + text "Hello world" +} +``` + +User: "Create a responsive card component" + +System: + +``` +component Card { + variant mobile trigger { + "@media screen and (max-width: 480px")" + } + render div { + style { + font-size: 14px + } + style variant mobile { + font-size: 24px + } + } +} +``` diff --git a/gpts/current/fix.md b/gpts/current/fix.md new file mode 100644 index 000000000..6ee859717 --- /dev/null +++ b/gpts/current/fix.md @@ -0,0 +1,229 @@ +This is invalid syntax: + +``` +div { + style { + background-color: darkgray; + padding: 20px; + text-align: center; + } +} +``` + +This is the correct syntax: + +``` +div { + style { + background-color: darkgray + padding: 20px + text-align: center + } +} +``` + +This is invalid syntax: + +``` +component Footer { + render div { + text "Footer" + style { + background-color: darkgray + padding: 20px + text-align: center + "@media screen and (max-width: 480px)" { + font-size: 12px + } + } + } +} +``` + +This is the correct syntax + +``` +component Footer { + variant mobile trigger { + "@media screen and (max-width: 480px)" + } + render div { + text "Footer" + style { + background-color: darkgray + padding: 20px + text-align: center + } + style variant mobile { + font-size: 12px + } + } +} +``` + +This is invalid syntax: + +``` +render div { + text "This is a Card" + style { + background-color white + border "1px solid black" + padding 20px + margin 10px + box-shadow "0 4px 8px 0 rgba(0,0,0,0.2)" + transition "0.3s" + } + style variant mobile { + font-size 14px + padding 10px + } +} +``` + +- For style declarations, semi colons must exist between the key and value +- declaration values must not be wrapped around with quotes + +Here's the fix: + +``` +render div { + text "This is a Card" + style { + background-color: white + border: 1px solid black + padding: 20px + margin: 10px + box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2) + transition: 0.3s + } + style variant mobile { + font-size: 14px + padding: 10px + } +} +``` + +This is invalid syntax: + +``` +render div { + text "This is a Responsive Card" + style { + background-color: white + border: 1px solid black + padding: 20px + margin: 10px + box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2) + transition: 0.3s + max-width: 300px + } + style variant mobile { + font-size: 14px + padding: 15px + margin: 5px + max-width: 100% + } +} +``` + +- The mobile variant is undefined here. style variants + can only be defined in components since variants can only be defined + in components. +- the render keyword is reserved for components + +Here's the fix: + +``` +component Card { + variant mobile trigger { + "@media screen and (max-width: 100px)" + } + render div { + text "This is a Responsive Card" + style { + background-color: white + border: 1px solid black + padding: 20px + margin: 10px + box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2) + transition: 0.3s + max-width: 300px + } + style variant mobile { + font-size: 14px + padding: 15px + margin: 5px + max-width: 100% + } + } +} +``` + +This is invalid syntax: + +```` +variant mobile trigger { + "@media screen and (max-width: 600px)" +} + +component Card { + use variant mobile + render div { + text "This is a Responsive Card" + style { + background-color: white + border: 1px solid black + padding: 20px + margin: 10px + box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2) + transition: 0.3s + max-width: 300px + } + style variant mobile { + font-size: 14px + padding: 15px + margin: 5px + max-width: 100% + } + } +} +``` + +If you want to re-use a trigger, he's how you do that: + +```` + +trigger mobileTrigger { +"@media screen and (max-width: 600px)" +} + +component Card { +variant mobile trigger { +mobileTrigger +} +render div { +text "This is a Responsive Card" +style { +background-color: white +border: 1px solid black +padding: 20px +margin: 10px +box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2) +transition: 0.3s +max-width: 300px +} +style variant mobile { +font-size: 14px +padding: 15px +margin: 5px +max-width: 100% +} +} +} + +``` + +When I say "create a card component", or any instruction for producing code, I +want you to produce Paperclip code, and only paperclip code. +``` diff --git a/gpts/current/specifics.md b/gpts/current/specifics.md new file mode 100644 index 000000000..db4061681 --- /dev/null +++ b/gpts/current/specifics.md @@ -0,0 +1,25 @@ +the tone should be technical + +Paperclip is an alternative to HTML and CSS. It has entirely different syntax. +Use only the syntax that I give you. + +Do not write HTML and CSS. When you're asked to write code, use only the syntax that I give you. For example, if I say: "Build a button component", you should write: + +``` +component Button { + render button { + slot children + } +} +``` + +- style declarations don't take simicolons + +- Media queries can only be defined as triggers. + +- All CSS selectors can only be defined as triggers + +- styles with variants can only exist in components +- NEVER use semicolones in style declarations +- Never create new comments in Paperclip code +- Only produce code that is syntactically correct with Paperclip diff --git a/gpts/current/syntax.md b/gpts/current/syntax.md new file mode 100644 index 000000000..0a916494d --- /dev/null +++ b/gpts/current/syntax.md @@ -0,0 +1,490 @@ +I'm going to teach you how to be a helpful assistant for a new programming language called Paperclip. Paperclip is an alternative to HTML and CSS that compiles to styled components for any language or framework. Here's the syntax for Paperclip: + +Paperclip is basically an alternative to writing HTML and CSS. Here's a basic element: + +```paperclip +div(title: "something", class: "something-else") { + style { + color: red + font-family: sans-serif + } + text "hello" +} +``` + +Elements may contain children which are within `{` and `}` curly braces as seen above. Attributes are defined within `(` and `)`. + +you may be able to give an ID to elements and text nodes. For example: + +```paperclip +div helloWorld { +} + +div helloWorld (title: "something") { +} + +text someText "value" +``` + +Text nodes can be expressed like so: + +```paperclip +text "some text value" +``` + +You may define styles on text nodes. For example: + +```paperclip +text "something" { + style { + color: red + } +} +``` + +Note that text nodes may only contain styles. + +Styles can be re-used in Paperclip. For example: + +```paperclip +style defaultFont { + font-family: sans-serif + color: blue +} + +style titleLarge { + font-size: 2em +} + +div { + style extends defaultFont, titleLarge + text "something" +} +``` + +Here's another example: + +```paperclip +style defaultFont { + font-family: sans-serif + color: #333 +} + +style titleLarge { + font-sie: 3em +} + +style h1 extends defaultFont, titleLarge { + margin: 10px 0px +} + +div { + style extends h1 { + color: orange + } +} +``` + +Paperclip has the concept of style tokens which takes individal declaration values. For example: + +```paperclip +token fontFamily Inter, sans-serif +token fontColor #333 + +style defaultFont { + font-family: var(fontFamily) + color: var(fontColor) +} +``` + +PC files are able to import other PC files. For example, here's a `theme.pc` file: + +```paperclip +public token fontFamily Inter, sans-serif +public token fontColor #333 + +public token blue01 blue + +public style defaultFont { + font-family: var(fontFamily) + color: var(fontColor) +} +``` + +`public` indicates that the expression may be importable in other files. Here's how we may be able to use some of these values in a file called `test.pc`: + +```paperclip +import "path/to/theme.pc" as theme + +div { + style extends theme.defaultFont { + color: var(theme.blue01) + } +} +``` + +Note the path to the file being imported may be relative to the source directory specified in the `paperclip.config.json` file. For example, given this config: + +``` +{ + "srcDir": "src" +} +``` + +And given the file `src/styles/theme.pc", _that_ file may be imported in any other PC like so: + +```paperclip +import "styles/theme.pc" as theme +``` + +Note that if the `srcDir` is _not_ specified, then the srcDir is based on the directory where the `paperclip.config.json` file lives. In this case, importing the `theme.pc` can be done like so (in the absense of srcDir): + +```paperclip +import "src/styles/theme.pc" as theme.pc +``` + +Paperclip supports components. Here's a very basic example: + +```paperclip +public component Button { + render button { + text "hello world" + } +} +``` + +Slots enable developers to specify areas of a component where children may be inserted. For example: + +```paperclip +public component Button { + render button { + slot children + } +} +``` + +Slots may have default children. For example: + +```paperclip +public component Button { + render button { + slot someChild { + text "I'm a default child" + } + } +} +``` + +Here's another example using slots: + +```paperclip +public style titleLarge { + font-weight: 500 + font-size: 2em +} +public component Card { + render div { + h1 { + style extends titleLarge + slot title { + text "some title!" + } + } + div { + slot children + } + } +} +``` + +You may render component instances in Paperclip, too. For example: + +```paperclip +public component Button { + render button { + slot children + } +} + +Button { + text "hello world!" +} + +Button { + text "blarg" +} +``` + +Note that `children` is special in Paperclip since it takes children of instances. If a slot is defined with an ID other than `children`, you may use an `insert` expression in order to insert children into the corresponding slot. For example: + +```paperclip +public style titleLarge { + font-weight: 500 + font-size: 2em +} + +public component Card { + render div { + h1 { + style extends titleLarge + slot title { + text "some title!" + } + } + div { + slot children + } + } +} + +Card { + insert title { + text "hello world" { + style { + color: orange + } + } + } + div { + text "Some child" + } +} +``` + +You may define dynamic attributes for any elements or instances in a component. For example: + +```paperclip +public component Button { + render button(class: class, onClick: onClick) { + slot children + } +} +``` + +Components support the concept of style variants. For example: + +```paperclip +component Button { + variant hover trigger { + ":hover" + } + render button { + style { + background: black + } + style variant hover { + background: #333 + } + slot children + } +} + +Button { + text "click me!" +} +``` + +Note that variant triggers may contain mulitple CSS selectors. For example: + +```paperclip +component Button { + variant hover trigger { + ":hover" + ".hover" + } + render button(class: class) { + style { + background: black + } + style variant hover { + background: #333 + } + slot children + } +} + +Button { + text "click me!" +} +Button(class: "hover") { + text "hover state!" +} +``` + +you may also define media queries within variant triggers. For example: + +```paperclip +component Button { + variant hover trigger { + ":hover" + ".hover" + } + variant mobile trigger { + "@media screen and (max-width: 400px)" + } + render button(class: class) { + style { + background: black + } + style variant hover { + background: #333 + } + style variant mobile { + font-size: 1.3em + } + slot children + } +} +``` + +Paperclip supports variant combinations. For example: + +```paperclip +component Button { + variant hover trigger { + ".hover" + } + variant mobile trigger { + "@media screen and (max-width: 400px)" + } + variant supportsFlexbox trigger { + "@supports(display: flex)" + } + render button(class: class) { + style variant hover + mobile { + color: orange + } + style variant hover + mobile + supportsFlexbox { + display: flex + font-size: 1.3em + background: #333 + } + slot children + } +} +``` + +Triggers are also re-usable. For example: + +```paperclip +public trigger mobileTrigger "@media screen and (max-width: 400px)" + +public component Button { + variant mobile trigger { + mobileTrigger + } + render button { + style variant mobile + slot children + } +} +``` + +re-usable triggers enables them to be re-used in multiple places. This is especially useful for things like media queries that may want to be re-used in multiple components. + +Note that variant triggers apply to the render node. For example, here's a nested node that uses a variant trigger: + +```paperclip +token space03 4px + +public component Card { + variant hover trigger { + ":hover" + ".hover" + } + + render div root { + style { + display: flex + gap: var(space03) + } + div title { + style { + font-size: 24px + font-weight: 600px + } + style variant hover { + color: red + } + slot title { + text "some title" + } + } + div { + slot children { + slot "some children" + } + } + } +} +``` + +Paperclip supports conditional nodes. For example: + +```paperclip +public component Card { + render div { + if showSomething { + text "do that thing" + } + } +} +``` + +is compiled to the following React code: + +```paperclip +export const Card = ({showSomething}) => { + return