DEV Community

Murahashi [Matt] Kenichi
Murahashi [Matt] Kenichi

Posted on

Let's build browser engine! in typescript vol6 CSS Shortcut

Create CSS rules manually.

// $ node_modules/.bin/ts-node example/css-shortcut.ts

import {
  Color,
  CssValue,
  Declaration,
  Rule,
  Selector,
  SimpleSelector,
  Stylesheet,
  Unit
} from "../src/css";

// h1, h2, h3 { margin: auto; color: #cc0000; }
// div.note { margin-bottom: 20px; padding: 10px; }
// #answer { display: none; }

const stylesheet = new Stylesheet([]);
stylesheet.rules.push(
  new Rule(
    [
      new Selector.Simple(new SimpleSelector("h1", null, [])),
      new Selector.Simple(new SimpleSelector("h2", null, [])),
      new Selector.Simple(new SimpleSelector("h3", null, []))
    ],
    [
      new Declaration("margin", new CssValue.Keyword("auto")),
      new Declaration("color", new CssValue.ColorValue(new Color(204, 0, 0, 255)))
    ]
  )
);
stylesheet.rules.push(
  new Rule(
    [new Selector.Simple(new SimpleSelector("div", null, ["note"]))],
    [
      new Declaration("margin-bottom", new CssValue.Length(20, Unit.Px)),
      new Declaration("padding", new CssValue.Length(10, Unit.Px))
    ]
  )
);
stylesheet.rules.push(
  new Rule(
    [new Selector.Simple(new SimpleSelector(null, "answer", []))],
    [new Declaration("display", new CssValue.Keyword("none"))]
  )
);
console.dir(stylesheet, { depth: null });

// Stylesheet {
//   rules: [
//     Rule {
//       selectors: [
//         Simple {
//           format: 0,
//           selector: SimpleSelector { tagName: 'h1', id: null, classValue: [] }
//         },
//         Simple {
//           format: 0,
//           selector: SimpleSelector { tagName: 'h2', id: null, classValue: [] }
//         },
//         Simple {
//           format: 0,
//           selector: SimpleSelector { tagName: 'h3', id: null, classValue: [] }
//         }
//       ],
//       declarations: [
//         Declaration {
//           name: 'margin',
//           value: Keyword { format: 0, keyword: 'auto' }
//         },
//         Declaration {
//           name: 'color',
//           value: ColorValue {
//             format: 2,
//             colorValue: Color { r: 204, g: 0, b: 0, a: 255 }
//           }
//         }
//       ]
//     },
//     Rule {
//       selectors: [
//         Simple {
//           format: 0,
//           selector: SimpleSelector {
//             tagName: 'div',
//             id: null,
//             classValue: [ 'note' ]
//           }
//         }
//       ],
//       declarations: [
//         Declaration {
//           name: 'margin-bottom',
//           value: Length { format: 1, length: 20, unit: 0 }
//         },
//         Declaration {
//           name: 'padding',
//           value: Length { format: 1, length: 10, unit: 0 }
//         }
//       ]
//     },
//     Rule {
//       selectors: [
//         Simple {
//           format: 0,
//           selector: SimpleSelector {
//             tagName: null,
//             id: 'answer',
//             classValue: []
//           }
//         }
//       ],
//       declarations: [
//         Declaration {
//           name: 'display',
//           value: Keyword { format: 0, keyword: 'none' }
//         }
//       ]
//     }
//   ]
// }
Enter fullscreen mode Exit fullscreen mode
test("declaration", () => {
  expect(() => new Declaration("name", new CssValue.Keyword("keyword"))).not.toThrow();
});
Enter fullscreen mode Exit fullscreen mode
export class Declaration {
  name: string;
  value: CssValue;

  constructor(name: string, value: CssValue) {
    this.name = name;
    this.value = value;
  }
}
Enter fullscreen mode Exit fullscreen mode
test("simple selector", () => {
  expect(() => new SimpleSelector(null, null, [])).not.toThrow();
});
Enter fullscreen mode Exit fullscreen mode
export class SimpleSelector {
  tagName: string | null;
  id: string | null;
  classValue: string[];

  constructor(tagName: string | null, id: string | null, classValue: string[]) {
    this.tagName = tagName;
    this.id = id;
    this.classValue = classValue;
  }
}
Enter fullscreen mode Exit fullscreen mode
test("selector simple", () => {
  expect(() => new Selector.Simple(new SimpleSelector(null, null, []))).not.toThrow();
});
Enter fullscreen mode Exit fullscreen mode
export namespace Selector {
  export enum Format {
    Simple
  }

  export class Simple {
    readonly format = Format.Simple;
    selector: SimpleSelector;

    constructor(selector: SimpleSelector) {
      this.selector = selector;
    }
  }
}

export type Selector = Selector.Simple;
Enter fullscreen mode Exit fullscreen mode
test("rule", () => {
  expect(() => new Rule([], [])).not.toThrow();
});
Enter fullscreen mode Exit fullscreen mode
export class Rule {
  selectors: Selector[];
  declarations: Declaration[];

  constructor(selectors: Selector[], declarations: Declaration[]) {
    this.selectors = selectors;
    this.declarations = declarations;
  }
}
Enter fullscreen mode Exit fullscreen mode
test("stylesheet", () => {
  expect(() => new Stylesheet([])).not.toThrow();
});
Enter fullscreen mode Exit fullscreen mode
export class Stylesheet {
  rules: Rule[];

  constructor(rules: Rule[]) {
    this.rules = rules;
  }
}
Enter fullscreen mode Exit fullscreen mode

references

series

AWS Security LIVE!

Join us for AWS Security LIVE!

Discover the future of cloud security. Tune in live for trends, tips, and solutions from AWS and AWS Partners.

Learn More

Top comments (0)

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay