Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ideas #23

Open
zdenko opened this issue Jun 28, 2018 · 14 comments
Open

Ideas #23

zdenko opened this issue Jun 28, 2018 · 14 comments

Comments

@zdenko
Copy link
Contributor

zdenko commented Jun 28, 2018

I have few proposals related to the great news 😄
Jadelet, because of its simplicity and aesthetics, is also my favorite choice whenever possible.
So, I would like to see it moving forward and am ready to help.
I already made some "improvements" (not published yet), i.e., upgrade to CoffeeScript 2, replaced deprecated packages (wrench => through2). And, last but not least, #21 and #6.
I also started playing with adding support for template compiling (similar to #18) to different bundlers. I began with Parcel, which is my preferred choice.

Example:

  • main.coffee
import jadelet from "jadelet"
import Tmpl from "./templates/intro.jadelet"

main = 
  name: "Joe"

document.getElementById("app").appendChild Tmpl main
  • template (templates/intro.jadelet)
h1 Hello #{@name}

Plugins for other bundlers (Webpack, Rollup) could be prepared as well.
I think this would make an easier start for new users.

Let me know.

@STRd6
Copy link
Owner

STRd6 commented Jul 3, 2019

Hi zdenko,

Sorry I haven't been very responsive on this. I've taking some time to update Jadelet again and welcome any contributions along these lines.

I've also got some ideas for an even simpler version that could remove the dependence on CoffeeScript completely by removing code in the templates. In my more recent work I've noticed that I generally avoid logic and iteration in the templates themselves. As the most active member of the Jadelet community I'd love to hear your feedback sometime.

Thanks!

@zdenko
Copy link
Contributor Author

zdenko commented Jul 13, 2019

Nice having you back 😄
Lately, I hadn't had much chance to use Jadelet as much as I would like to. Due to the current hype around existing frameworks and libraries, and for the sake of the rest of the team, I have to give in and try not to react in the wrong way (pun intended). But, whenever I can, I come back to the lightness of Jadelet.

By removing the code from the templates you mean remove logic completely, or get rid of Coffeescript?
Avoiding logic and iterations in templates is also my preference in any templating/rendering solution.
The outcome of this is short and light template files. More often then not you end with just a line or two of the template code.
A while ago I was playing with the idea of having the code in a single file, e.g. like this:

<template>
div
  button(click=@increment) Increment
  label= @count
</template>

self =
  count: Observable(0)
  increment: -> @count.increment()

This is similar approach as in Vue.js, Riot.js, or Svelte

But, I feel that such simplicity can increase organizational efforts. By breaking the code into "reusable components," you need to think ahead what to put where, and how to efficiently nest components.
I guess there's no clear winner, as in the end, it all depends on the task one tries to solve.

Can you share details of some of your ideas if possible? Is observable still in your path?

@STRd6
Copy link
Owner

STRd6 commented Sep 2, 2021

I know this is old... but better late than never :P

What I've been doing recently is using template strings in JS or multiline strings in CoffeeScript like this:

Template = Jadelet.exec """
app
  .toolbar
    button(click=@save) Save
  @content
"""

document.body.appendChild Template
  save: -> alert "pretend this saved"
  content: contentElement

It works pretty well for my use cases and is nice and simple and doesn't require any additional build processes or tools.

Good luck!

@zdenko
Copy link
Contributor Author

zdenko commented Sep 4, 2021

This looks cool, but I can't figure out where Jadelet.exec, and contentElement come from.
Could you elaborate on this example?

@STRd6
Copy link
Owner

STRd6 commented Sep 4, 2021

I think in this version it's actually Jadelet.compile. contentElement is just a placeholder for any arbitrary element to insert into the template demonstrating adding more than just a button to the template.

I may have Jadelet v2 ready sometime soon. It's quite a bit smaller and faster.

@zdenko
Copy link
Contributor Author

zdenko commented Sep 4, 2021

it's actually Jadelet.compile

Ah, that makes sense. But in that case, you have to set the compiler property, which is Coffeescript, if I'm not mistaken.
That's quite heavy for browser use. Or, is there some other alternative to CS?

I may have Jadelet v2 ready sometime soon

😮 Who do I have to bribe to get access to it? 🙏

@zdenko
Copy link
Contributor Author

zdenko commented Sep 4, 2021

which is Coffeescript, if I'm not mistaken. That's quite heavy for browser use. Or, is there some other alternative to CS?

I think I got this. 😄
CS is required to compile the source in the compile. If I convert a few lines in the compiler.coffee from CS source to JS, then CS is not needed anymore.
And, in jadelet template strings, I just use JS. For example:

h1= this.title

@STRd6
Copy link
Owner

STRd6 commented Sep 4, 2021

@zdenko that's pretty much it 🎊 I'll see if I can update this repo with a copy of Jadelet v2. I've been doing most of my development in whimsy.space so I don't use GitHub much anymore.

@STRd6
Copy link
Owner

STRd6 commented Sep 4, 2021

Just pushed a preview of Jadelet2 to dist/jadelet2.js and updated the changelog. It's usable in the browser but I'll need to make a legitimate branch and actually set up the project to use it as a npm package.

1st third of the file is Observable dependency.
2nd third is the parser built with hera https://danielx.net/hera/docs/README.html
last third is Jadelet runtime, very similar to previous version.

It's definitely not "ready" as a package, lots of chores and setup to do but I'm out of time for today. If there's excitement I'll get it finalized sometime soon.

@zdenko
Copy link
Contributor Author

zdenko commented Sep 5, 2021

If there's excitement

Oh, there is excitement for sure :)
Hera looks pretty amazing. I noticed you also creted a repo here. I hope you'll be also able to share the source soon. And, if not, maybe some private repo for a start?

I tried to wrap my head around the new Jadelet grammar and parser. But, if I'm not mistaken, only simple rules work for now (i.e., p(title=@attr) @value).
So far, I couldn't embed any logic in the template (e.g., iteration, condition).
To render the following example,

ul @list.map( @item )

I tried this object

{
  list: [1, 2, 3, 4],
  itemTpl: Jadelet2.exec("li @item"),
  item: function (item) { return this.itemTpl({item}) }
}

but, I couldn't get it to work.

In the end, I came up with this solution
ul @lineItems

{
  items: [1, 2, 3, 4],
  itemTpl: Jadelet2.exec("li @item"),
  get lineItems() { return this.items.map( item => this.itemTpl({item}) ) } 
}

Is there a better way?

@STRd6
Copy link
Owner

STRd6 commented Sep 5, 2021

@zdenko your ul @lineItems solution is how I've been doing things since removing the logic from templates in v2.

I just published the hera repo https://github.com/STRd6/hera and tried to get the readme somewhat more informative. I'll get a v2 branch going on Jadelet while I'm on a roll.

@zdenko
Copy link
Contributor Author

zdenko commented Sep 8, 2021

@STRd6 I've been playing with the v2, and I love it.
I'm trying to convert some existing code from React for a test drive, and it's working great.
The only part I encountered obstacles was the indention of the templates. If I use CS, the transpiler will take care of tagged templates, and the content will be correctly aligned.
For example, all CS examples below

Template = Jadelet2.exec """
div
  .toolbar
    button(click=@save) Save
  @content
"""
Template = Jadelet2.exec """div
                              .toolbar
                                button(click=@save) Save
                              @content"""```
Template = Jadelet2.exec """
                         div
                           .toolbar
                             button(click=@save) Save
                           @content
                         """

will be transpiled into

Template = Jadelet2.exec(`div
  .toolbar
    button(click=@save) Save 
  @content`);

But, when I'm working in JS, I have to be very careful about the indent.
This is especially annoying when the function where I'm creating the template is already indented.

(function(self) {
  ...
  function foo() {
    ...
    myTemplate = (props) => {
      if (props.value === 42) {
        return `div
  .toolbar
    button(click=@save) Save
  @content`;
      } else {
        return `div
  .toolbar
    button(click=@cancel) Cancel
  @content`;
      }
      ...
    };
   ... 
  };
  ...
})(global);

To solve this and have nicer formatting of the templates, I came up with the idea to store the first indent level in the parser and then deduct this value from the indentions.
So, I've added a few lines to the reduceLines function in the grammar:

  function reduceLines(lines) {
    var depth = 0;
    var stack = [[]];
+   var firstIndent = 0;
    lines.forEach( ([indent, line]) => {
+     if (firstIndent === 0 && indent > depth + 1) {
+       firstIndent = indent - 1;
+     }
+     indent = indent > firstIndent ? indent - firstIndent : indent;

This change enables me to write more "freely":

(function(self) {
  ...
  function foo() {
    ...
    myTemplate = (props) => {
      if (props.value === 42) {
        return `div
                  .toolbar
                    button(click=@save) Save
                  @content`;
      } else {
        return `div
                  .toolbar
                    button(click=@cancel) Cancel
                  @content`;
      }
      ...
    };
   ... 
  };
  ...
})(global);

Of course, I didn't run any proper tests, so I'm not sure if this is bulletproof.

And I think I've probably found a minor issue in the Òbservable module.
This code gives an error.

o = Jadelet2.observable
foo = o 42
foo()

# Uncaught TypeError: array is undefined

I think that in lines

self.OBSERVABLE_ROOT_HACK = [];
and
observerSet = last(self.OBSERVABLE_ROOT_HACK);
,
self should be replaced with global.

After the change, the example above works.

@STRd6
Copy link
Owner

STRd6 commented Sep 9, 2021

Thanks @zdenko!

I've updated the v2 branch with this fix as well as some more dependency cleanup and updates to CHANGELOG.md and README.md as well. It's published to npm as 2.0.0-pre.0. Just about ready for the official 2.0.0 release.

Let me know if there are any other issues that you encounter.

@zdenko
Copy link
Contributor Author

zdenko commented Sep 10, 2021

@STRd6 I just found a bug in my solution for indent. I'll prepare a fix and make a pull request.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants