SKY MODULE
<!-- this is part of sky:core -->
<script>
 // "internals" is an object only made visible to this module that exports stuff implemented in C++
 module.exports.registerProperty = internals.registerProperty;
 internals.registerLayoutManager('none', null);
 module.exports.LayoutManager = internals.LayoutManager;
 module.exports.InlineLayoutManager = internals.InlineLayoutManager;
 internals.registerLayoutManager('inline', internals.InlineLayoutManager);
 module.exports.ParagraphLayoutManager = internals.ParagraphLayoutManager;
 internals.registerLayoutManager('paragraph', internals.ParagraphLayoutManager);
 module.exports.BlockLayoutManager = internals.BlockLayoutManager;
 internals.registerLayoutManager('block', internals.BlockLayoutManager);

 let displayTypes = new Map();
 module.exports.registerLayoutManager = function registerLayoutManager(displayValue, layoutManagerConstructor) {
   // TODO(ianh): apply rules for type-checking displayValue is a String
   // TODO(ianh): apply rules for type-checking layoutManagerConstructor implements the LayoutManagerConstructor interface (or is null)
   if (displayTypes.has(displayValue))
     throw new Error();
   displayTypes.set(displayValue, layoutManagerConstructor);
 };

 module.exports.DisplayStyleGrammar = new StyleGrammar(); // value is null or a LayoutManagerConstructor
 module.exports.DisplayStyleGrammar.addParser((tokens) => {
   let token = tokens.next();
   if (token.done)
     throw new Error();
   if (token.value.kind != 'identifier')
     throw new Error();
   if (!displayTypes.has(token.value.value))
     throw new Error();
   return {
     value: displayTypes.get(token.value.value),
   }
 });

 internals.registerProperty({
   name: 'display',
   type: module.exports.DisplayStyleGrammar,
   inherits: false,
   initialValue: internals.BlockLayoutManager,
   needsLayout: true,
 });

 module.exports.PositiveLengthStyleGrammar = new StyleGrammar(); // value is a ParsedValue whose value (once resolved) is a number in 96dpi pixels, >=0
 module.exports.PositiveLengthStyleGrammar.addParser((tokens) => {
   // just handle "<number>px"
   let token = tokens.next();
   if (token.done)
     throw new Error();
   if (token.value.kind != 'dimension')
     throw new Error();
   if (token.value.unit != 'px')
     throw new Error();
   if (token.value.value < 0)
     throw new Error();
   return {
     value: token.value.value;
   };
 });

 internals.registerProperty({
   name: 'min-width',
   type: module.exports.PositiveLengthStyleGrammar,
   inherits: false,
   initialValue: 0,
   needsLayout: true,
 });
 internals.registerProperty({
   name: 'min-height',
   type: module.exports.PositiveLengthStyleGrammar,
   inherits: false,
   initialValue: 0,
   needsLayout: true,
 });

 module.exports.PositiveLengthOrAutoStyleGrammar = new StyleGrammar(); // value is a ParsedValue whose value (once resolved) is either a number in 96dpi pixels (>=0) or null (meaning 'auto')
 module.exports.PositiveLengthOrAutoStyleGrammar.addParser((tokens) => {
   // handle 'auto'
   let token = tokens.next();
   if (token.done)
     throw new Error();
   if (token.value.kind != 'identifier')
     throw new Error();
   if (token.value.value != 'auto')
     throw new Error();
   return {
     value: null,
   };
 });
 module.exports.PositiveLengthOrAutoStyleGrammar.addParser((tokens) => {
   return module.exports.PositiveLengthStyleGrammar.parse(tokens);
 });

 internals.registerProperty({
   name: 'width',
   type: module.exports.PositiveLengthOrAutoStyleGrammar,
   inherits: false,
   initialValue: null,
   needsLayout: true,
 });
 internals.registerProperty({
   name: 'height',
   type: module.exporets.PositiveLengthOrAutoStyleGrammar,
   inherits: false,
   initialValue: null,
   needsLayout: true,
 });

 module.exports.PositiveLengthOrInfinityStyleGrammar = new StyleGrammar(); // value is a ParsedValue whose value (once resolved) is either a number in 96dpi pixels (>=0) or Infinity
 module.exports.PositiveLengthOrInfinityStyleGrammar.addParser((tokens) => {
   // handle 'infinity'
   let token = tokens.next();
   if (token.done)
     throw new Error();
   if (token.value.kind != 'identifier')
     throw new Error();
   if (token.value.value != 'infinity')
     throw new Error();
   return {
     value: Infinity,
   };
 });
 module.exports.PositiveLengthOrInfinityStyleGrammar.addParser((tokens) => {
   return module.exports.PositiveLengthStyleGrammar.parse(tokens);
 });

 internals.registerProperty({
   name: 'width',
   type: module.exports.PositiveLengthOrInfinityStyleGrammar,
   inherits: false,
   initialValue: Infinity,
   needsLayout: true,
 });
 internals.registerProperty({
   name: 'height',
   type: module.exporets.PositiveLengthOrInfinityStyleGrammar,
   inherits: false,
   initialValue: Infinity,
   needsLayout: true,
 });
</script>
