Jump to content
clsource

Solidwire Language

Recommended Posts

Hello friends,

I participated in a project that needed lots of relationships between fields and pages.

and I struggled on how to arquitech such complex scenario. So I figure out and documented this little idea.

A CSS like language for data relationships.

https://github.com/joyofpw/solidwire

Hope you find it useful and all ideas and contributions are welcome 😄

 

Thanks.

  • Like 6

Share this post


Link to post
Share on other sites

This looks really interesting!

But I don't quite understand. The intro says:

Quote

Inspiration was taken from different tools and languages like C, UML, Markdown, Javascript, Python and PHP.

Solid Wire means to be like cascading style language. CSS for data relationships.

So does this language convert to some other format (like Markdown > HTML)? Does the language translate to some visual form like CSS does? Or is it executable like Javascript, PHP, etc? Putting it another way, is the end result something other than the document itself?

Sorry if these are dumb questions - just struggling to get my head around it.

Share this post


Link to post
Share on other sites

Hello Robin,

Is not meant to be a programming language. Is more like a prototyping language.

maybe in the future tools can be written to generate files or similar.

 

The objective is to create a document that can show pages, templates and fields relationships
in a eagle view fashion.

Before you start creating the templates in PW you can prototype in this document
like a scratch pad to clear ideas and see different options before investing time in programming.

  • Like 4

Share this post


Link to post
Share on other sites
30 minutes ago, clsource said:

maybe in the future tools can be written to generate files or similar.

It would be great to have a tool that takes the document as input and spits out an HTML flow diagram as output, where explanatory details could be shown in tooltips, modals, etc. Because to make sense of the language you'd have to spend a fair bit of time memorising the syntax and I can see that being a problem for non-devs (i.e. clients).

  • Like 3

Share this post


Link to post
Share on other sites

Well is true that non technical clients could have some trouble understanding this language. But I believe they often have a technical counter part that could understand this.

Though tools that generate documentation pages and maybe even migrations scripts?. would be cool to have 😛

  • Like 1

Share this post


Link to post
Share on other sites

Hey I updated the spec. Now it's more like Pseudocode than a whole language in itself.

The idea is just to communicate better and make plans before building or thinkering with the fields.

Example for this small project that I'm building https://github.com/NinjasCL/chileanbirds-api



@document {

    @wire {
        @templates {
            home: template().options({@once, @strong, @root}),
            notfound: template().options({@once, @childless}).description("Used in 404 errors"),
            birds: template().options({@strong}).family({
                    parents: ["home"],
                    children: ["birds-item"]
            }),
            birds-item: template().options({@childless}).family({
                parents: ["birds"]
            })
        },

        @fields {

            title: text().options({@i18n, @global}),

            body: textarea().options({@i18n}),

            uid: text(),

            href: url(),

            file: files().max(1),

            migration: checkbox(),

            dimorfism: checkbox(),

            size: text(),

            order: text(),

            species: text(),

            image: images().max(1).mediatypes([@jpg, @png, @svg]),

            images: images().mediatypes([@jpg, @png, @svg]),

            value: text().options({@i18n}),

            habitat: textarea()
                    .description("Stores the habitat property")
                    .options({@i18n}),

            didyouknow: textarea()
                    .description("Stores the did you know property")
                    .options({@i18n}),

            iucn: pagetable()
                    .max(1)
                    .fields({
                        body: body().description("Stores the iucn description"),
                        value: value().description("Stores the iucn value")
                    }),

            audio: pagetable()
                    .max(1)
                    .fields({
                        file,
                        title.label("Author")
                    }),

            map: pagetable()
                .max(1)
                .fields({
                    image,
                    value
                }),


        },

        @pages {
            + "Home" (template:home) @many -> {
                + "Birds" (template:birds) @many -> {
                    + "Bird 1" (template:birds-item, fields: {
                        title: title().label("Names"),
                        body: body().label("Description").description("Stores the bird description"),
                        images,
                        habitat,
                        didyouknow,
                        iucn,
                        audio,
                        map,
                        species,
                        migration,
                        dimorfism
                    })
                } // /birds
            } // /home
        } // /pages
    } // /wire
} // /document

 

  • Like 3

Share this post


Link to post
Share on other sites

This doesn't look too different to how everything can be defined in RockMigrations...

  /**
   * Migrate issues related things
   * @return void
   */
  public function migrate() {
    $this->log('Migrate Issues');
    $this->rm()->migrate([
      'fields' => [
        self::field_sections => [
          'type' => 'FieldtypeRockMatrix',
          'icon' => 'files-o',
          'tags' => self::tags,
        ],
      ],
      'templates' => [
        self::tpl_issues => [
          'childTemplates' => [
            self::tpl_issue,
          ],
          'tags' => self::tags,
          'icon' => 'stack-overflow',
          'parentTemplates' => ['home'],
          'childNameFormat' => "title",
          'fields' => [
            'title',
          ],
          'noSettings' => 1,
          'useRoles' => true,
          'roles' => [self::role_admin],
          'addRoles' => [self::role_admin],
          'pageClass' => '\RockMag\Issues',
        ],
        self::tpl_issue => [
          // no children allowed
          // children will only be added via rockmatrix field
          'noChildren' => 1,
          'parentTemplates' => [self::tpl_issues],
          'tags' => self::tags,
          'fields' => [
            'title',
            self::field_sections,
            self::field_pdf,
          ],
          'pageClass' => '\RockMag\Issue',
          'noSettings' => 1,
          'noLang' => 1, // single language
          'icon' => 'book',
          'useRoles' => true,
          'roles' => [self::role_admin],
          'createRoles' => [self::role_admin], // may create pages
          'editRoles' => [self::role_admin], // may edit pages
          'addRoles' => [self::role_admin], // may add children (MagPage)
        ],
      ],
    ]);

    // create issues page
    if(!$this->getIssuesPage()->id) {
      $this->rm()->createPage("RockMag", null, self::tpl_issues, 1, ['hidden', 'locked']);
    }
  }

But you get all your defined fields and templates with a single ->migrate() call 🙂 

  • Like 1

Share this post


Link to post
Share on other sites

Ok I have been toying around with this lib https://mudgen.github.io/webscript/docs/

And make a somewhat implementation of SolidWire using Javascript.

import builder from "webscript/src/webscript.js";
import createElement from "webscript/src/createObjectElement.js";

const { wire, templates, template, fields, field, pages, page } = builder(
  createElement
);

const core = {
  fields: {
    textarea: field.class("FieldtypeTextarea"),
  },
};

const site = {};

site.fields = {
  body: core.fields.textarea.name("body"),
  about: core.fields.textarea.name("about").max(100),
};

site.templates = {
  home: template
    .name("home")
    .root(true)
    .fields(site.fields.body.label("Content")(), site.fields.about()),
};

site.pages = {
  home: page.title("Home").template(site.templates.home()),
};

const render = (data) => Object.values(data).map((item) => item());

const solid = wire(
  templates(render(site.templates)),
  fields(render(site.fields)),
  pages(render(site.pages))
);

console.log(JSON.stringify(solid, null, 2));

executing that code brings this result in json

{
  "tagName": "wire",
  "children": [
    {
      "tagName": "templates",
      "children": [
        {
          "tagName": "template",
          "children": [],
          "value": "",
          "__isElement": true,
          "name": "home",
          "root": true,
          "fields": [
            {
              "tagName": "field",
              "children": [],
              "value": "",
              "__isElement": true,
              "class": "FieldtypeTextarea",
              "name": "body",
              "label": "Content"
            },
            {
              "tagName": "field",
              "children": [],
              "value": "",
              "__isElement": true,
              "class": "FieldtypeTextarea",
              "name": "about",
              "max": 100
            }
          ]
        }
      ],
      "value": "",
      "__isElement": true
    },
    {
      "tagName": "fields",
      "children": [
        {
          "tagName": "field",
          "children": [],
          "value": "",
          "__isElement": true,
          "class": "FieldtypeTextarea",
          "name": "body"
        },
        {
          "tagName": "field",
          "children": [],
          "value": "",
          "__isElement": true,
          "class": "FieldtypeTextarea",
          "name": "about",
          "max": 100
        }
      ],
      "value": "",
      "__isElement": true
    },
    {
      "tagName": "pages",
      "children": [
        {
          "tagName": "page",
          "children": [],
          "value": "",
          "__isElement": true,
          "title": "Home",
          "template": {
            "tagName": "template",
            "children": [],
            "value": "",
            "__isElement": true,
            "name": "home",
            "root": true,
            "fields": [
              {
                "tagName": "field",
                "children": [],
                "value": "",
                "__isElement": true,
                "class": "FieldtypeTextarea",
                "name": "body",
                "label": "Content"
              },
              {
                "tagName": "field",
                "children": [],
                "value": "",
                "__isElement": true,
                "class": "FieldtypeTextarea",
                "name": "about",
                "max": 100
              }
            ]
          }
        }
      ],
      "value": "",
      "__isElement": true
    }
  ],
  "value": "",
  "__isElement": true
}

@bernhard maybe some JSON like that could be used in RockMigrations. So you have the best of both worlds. A simpler syntax and an output that could be used to define migrations using JSON 🙂

Share this post


Link to post
Share on other sites
11 hours ago, clsource said:

So you have the best of both worlds. A simpler syntax and an output that could be used to define migrations using JSON

To be honest I don't see anything better in "your" world compared to "mine". My world is basically the PW API, so I don't see why it would be better to learn another language/syntax that does the same but works a little different. PW API can be used everywhere, works out of the box, is documented, tested, maintained etc...

But I'm open to suggestions for improving the RockMigrations API further 🙂 

Share this post


Link to post
Share on other sites
10 hours ago, bernhard said:

To be honest I don't see anything better in "your" world compared to "mine". My world is basically the PW API, so I don't see why it would be better to learn another language/syntax that does the same but works a little different. PW API can be used everywhere, works out of the box, is documented, tested, maintained etc...

But I'm open to suggestions for improving the RockMigrations API further 🙂 

I didn´t mean to say which approach is better. I think RockMigrations is a good tool. SolidWire is not a replacement of any migration strategy or tool.
It's just an idea to ease the communication and prototyping between developers and other people.
It's in the same area of https://plantuml.com/

Just a tool to improving an eagle view of the system. The JSON output is just an idea similar to https://doc.mapeditor.org/en/stable/manual/introduction/

Any other proper migration tool could use it to generate a proper output. But is not mandatory :).

  • Like 1

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...