TheLarkInn / unity-component-specification

This is a WIP draft of the Unity (Single File Web Component) Specification
Apache License 2.0
217 stars 2 forks source link

Glimmer thoughts #1

Open tomdale opened 6 years ago

tomdale commented 6 years ago

Thanks for putting this together @TheLarkInn it's very exciting.

Couple of first impressions/questions from a Glimmer perspective.

  1. Need support for specifying alternate langs for each section. E.g. we would want <template> to contain Handlebars templates, whose syntax is not parseable as vanilla HTML.
  2. Require single-element root is probably a no-go for us and I would assume React as well.

Another question is what value is this providing by building into the platform? E.g. what is it providing that can't be provided by tools like webpack today. For me there is more value in standardizing on a file format for Single-File Component for ecosystem reasons. E.g. if I want to do SFCs in Glimmer it would be nice to share infrastructure with vue-loader for transpiling TypeScript or whatever. That way if someone comes out with a new precompiler for CSS and implements it for Glimmer, Vue users get it for free, or whatever.

I think one nice way to start would be to create a small utility library for reading/writing SFCs and their constituent parts. This would allow people to build transforms, tooling, editor integrations, etc. Something like:

<template type="glimmer">
  <Greeting @message="hi Sean" />
</template>

<module type="typescript" is-awesome>
  import Component from "@glimmer/component";

  export default class extends Component {
  }
</module>

<x-glimmer>
  something here
</x-glimmer>
import SFCParser from "sfc-parser";

let component = new SFCParser('src/components/my-component');

// Querying Standard Elements
component.hasScript(); // true
component.hasTemplate(); // true
component.hasStyle(); // false

// Retrieving Standard Elements
// getScript() returns either `<module>` or `<script>`, file can only have one.
component.getScript();
// {
//   tagName: 'module',
//   attributes: {
//     type: "typescript",
//   },
//   content: '  <Greeting @message="hi Sean" />'
// }

// Mutating Standard Elements
component.setScript({
  content: '  <Greeting @message="sayonara" />'
});
component.deleteTemplate();
await component.save();

// Custom Elements
component.has('x-glimmer'); // true

component.get('x-glimmer');
// {
//   tagName: 'x-glimmer',
//   attributes: {},
//   content: '  something here'
// }

component.set('x-glimmer' {
  attributes: {
    'data-foo': 'bar'
  }
});

// Might be nice to have some utilities for language servers and other editor
// integrations?

// Start and end position of contents inside `<module>` or `<script>`
component.rangeForScript();
// { start: 47, end: 92 }

// Given a range relative to the SFC file contents, shifts the range to be
// relative to the contents of the script content.
component.relativeRangeForScript({ start: 49, end: 88 });
// { start: 3, end: 47 }

component.elementAtPosition({ line: 3, character: 72 });
// returns whatever SFC element is at the provided position
// returns null if position is whitespace between elements
yyx990803 commented 6 years ago

A standard utility would be great. Currently in vue-template-compiler there is a parseComponent method which returns an SFC descriptor object with the following type (in flow declarations):

// SFC-parser related declarations

// an object format describing a single-file component.
declare type SFCDescriptor = {
  template: ?SFCBlock;
  script: ?SFCBlock;
  styles: Array<SFCBlock>;
  customBlocks: Array<SFCCustomBlock>;
}

declare type SFCCustomBlock = {
  type: string;
  content: string;
  start?: number;
  end?: number;
  src?: string;
  attrs: {[attribute:string]: string};
};

declare type SFCBlock = {
  type: string;
  content: string;
  start?: number;
  end?: number;
  lang?: string;
  src?: string;
  scoped?: boolean;
  module?: string | boolean;
};

It's simply a data structure, but adding some utility methods would be helpful and straightforward.

TheLarkInn commented 6 years ago

I'll leave this thread focused on the single utility and open a separate issue for the platform goals.

tomdale commented 6 years ago

@yyx990803 Ah yeah, that looks exactly like what I was thinking would be helpful!

EisenbergEffect commented 6 years ago

Just sounding off in agreement with @tomdale's thoughts above. Aurelia would also want to specify a template lang and not require a single element root.

In all honesty, I'm extremely skeptical of the platform side of this conversation. When I see an attempt to dictate a binding syntax, for example, I get turned off very quick.

I am interested in having a shared set of utilities and tools. We've been talking a lot about single file components for Aurelia recently, so timing is good for us. We'd love to adopt a standard format for these files and leverage the broader community's work around tooling. This is where the greatest value for us lies.

Regarding component interop, it's not so much of an issue for Aurelia. Aurelia has a view resource pipeline that enables us to generate interop code on the fly for any 3rd party component library.

developit commented 6 years ago

I'll add my agreement to the pile-on here. Tom's API describes where I hope to take the SFC parser I showed on Twitter this week. It lets the analysis and codegen remain output-specific but keeps the parsing and early passes generalized.

Couple questions for you @tomdale:

  1. Would handlebars templates within <template lang="glimmer"> (or similar) be converted to annotated HTML as a preprocessing step? Or would you want to bypass the HTML parser entirely in that case?

  2. Can you expand on the single element root issue?

TheLarkInn commented 6 years ago

Would handlebars templates within <template lang="glimmer"> (or similar) be converted to annotated HTML as a preprocessing step? Or would you want to bypass the HTML parser entirely in that case?

I very much so would like to know this. I think if we implement Unity SFC as a common interop layer and target for all of the following FW's, there is nothing that says that "preprocessed" transpilations couldn't translate to the unity format. The goal is as much interop as possible in my opinion.

TheLarkInn commented 6 years ago

Alright @tomdale @developit @yyx990803 I've begun the creation of a few loaders that will hopefully help support Single File Components.