npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@lynx-js/css-defines

v0.0.7

Published

Property definitions of Lynx Styling module

Readme

CSS Generator

This package serves as the source of truth for all CSS APIs defined in the Lynx platform. It's used to generate C++ code in the engine for Lynx contributors, as well as Types consumed by the Lynx frontend developers.

Table of Contents

CSS Property Definition

Property vs Attribute

Properties are features of an element that you can change the value of, to make it styled differently (e.g. color, font-size). If the feature is not related to element's style, or it is strongly coupled with a specific element type (e.g. initial-scroll-offset on <scroll-view>), it is recommended to add it as an attribute. Most times, the style property should have a prototype in the W3C CSS specification.

If the implementation of the property is non-standardized, or it is under experimental, it should be a prefixed property.

Vendor Prefix

-x- is the vendor prefix used by Lynx to distinguish CSS properties that are specific to Lynx and not part of the Web standard. They provide Web developers with some layout and styling capabilities specific to Lynx, such as:

.linear {
    /* similar to when Grid layout was -ms-grid, -webkit-grid: */
    display: -x-linear;
    display: linear; /* should also work */
    -x-linear-orientation: horizontal;
}

Adding a New Property

Once you have decided to add a new property, you can follow the steps below:

  1. Add a definition file under the css_defines directory. The file name should begin with an incremental number indicating the ID of the property. We use the ID at runtime to map the property's parser, getter and setter functions to avoid string comparison. So the ID should be unique, and should not be modified after it is added. The consistency of the ID will be checked according to property_index.json. The new ID and property name will be automatically added to the index file by css_parser_generator.py.

  2. Execute python tools/css_generator/css_parser_generator.py

  3. Implement the code in generated files.
    There are a couple of functions that cannot be automatically implemented by the script. According to the complexity of the property's value, you may need to implement the following functions:

    1. Parser: The parser function is used to parse the value of the property.
    2. ComputedCSSStyle: The setter and getter functions should be manually implemented according to the output of parser. If the property will be consumed by the platform UI layer, you have to add it to the macro FOREACH_PLATFORM_PROPERTY in the header file.

TypeScript Type Generation

Type Generation Rules

The type definitions in js_libraries/types/types/common/csstype.d.ts are automatically generated from CSS define files in the css_defines directory. The generation process follows these rules:

  1. For enum types (properties with "type": "enum"):

    • Uses the values array to generate a union type of string literals
    • Example: display?: 'none' | 'flex' | 'grid' | 'linear' | 'relative' | 'block' | 'auto';
  2. For properties with keywords:

    • Uses the keywords array to generate a union type of string literals
    • Adds (string & {}) for open-ended string types
    • Example: animationTimingFunction?: 'linear' | 'ease-in' | 'ease-out' | ... | (string & {});
  3. For other types:

    • Uses string type
    • Example: color?: string;

Build Process

The build process generates TypeScript type definitions and copies them to the types package:

  1. npm run gen:types - Generates types in the dist/ directory (gitignored)
  2. npm run copy:types - Copies generated types to js_libraries/types/types/common/
  3. npm run build - Runs both steps in sequence

Note: The dist/ directory is gitignored because it's an intermediate build artifact. The final types are always in js_libraries/types/types/common/csstype.d.ts.

Usage

# Validate all CSS defines
npm run validate

# Test validation with invalid CSS defines
npm run test

# Generate types and copy to types package
npm run build

# Generate types in dist/ for testing (without copying)
npm run gen:types

Schema

The schema in css_define_json_schema/css_define_with_doc.schema.json defines the structure of CSS define files and is used for both validation and type generation.

Tutorial: Implementing a CSS Property

The following example demonstrates how to add a new CSS property to the system:

{
    "name": "test",
    "id": 213,
    "type": "complex",
    "default_value": "auto",
    "version": "1.0",
    "author": "wangerpao",
    "consumption_status": "layout-only",
    "desc": "left offset",
    "keywords": ["foo", "bar", "foobar"],
    "values": [
        {
            "value": "test-value",
            "version": "1.0"
        }
    ],
    "links": [
        {
            "url": "<reference docs>",
            "desc": "description of the reference"
        },
        {
            "url": "123"
        }
    ],
    "note": [
        {
            "literal": "this is a note",
            "level": "tip"
        },
        {
            "literal": "This is a warning for user of this property.",
            "level": "warning"
        }
    ],
    "__compat": {
        "description": "<Description of this compat data entry>",
        "lynx_path": "<path to api reference in lynx website> docs/zh/api/css/properties/left)",
        "mdn_url": "<path to mdn definition> https://developer.mozilla.org/zh-CN/docs/Web/CSS/left",
        "spec_url": ["<path to w3c specification file>"],
        "status": {
            "deprecated": false,
            "experimental": false
        },
        "support": {
            "android": {
                "version_added": "1.0"
            },
            "ios": {
                "version_added": "1.0"
            }
        }
    }
}
  1. Create a new file named 999-test.json and copy the above JSON into it.

  2. Run css_parser_generator.py to generate the necessary files.

    The css_property_id.h file will be autogenerated under core/renderer/css. You will find your newly added property test appended to the end of the macro FOREACH_ALL_PROPERTY, as well as the property enum class CSSPropertyID.

  3. Implement the parser for the property value:

    • If the type is one of color, length, time, enum, border-width, border-style, bool, timing-function or animation-property, the parser will be auto-generated
    • Otherwise, manually add it to core/renderer/css/parser directory

    Create two new files, test_handler.h and test_handler.cc under the directory:

    #include "core/renderer/css/parser/handler_defines.h"
    
    namespace lynx {
    namespace tasm {
    namespace TestHandler {
    
    HANDLER_REGISTER_DECLARE();
    
    }  // namespace TestHandler
    }  // namespace tasm
    }  // namespace lynx

    Register your parsing functions into the 'array' to your property id, and implement the parser functions, which converts the input string value into a CSSValue object and put it into the 'output' map. It is recommended that you implement the parser based on CSSStringParser, as it already has some basic tokenizers and lexical checks.

    #include "core/renderer/css/parser/test_handler.h"
    
    #include <string>
    #include <utility>
    
    #include "base/include/debug/lynx_assert.h"
    #include "core/renderer/css/parser/css_string_parser.h"
    #include "core/renderer/css/unit_handler.h"
    #include "core/renderer/tasm/config.h"
    
    namespace lynx {
    namespace tasm {
    namespace TestHandler {
    
    HANDLER_IMPL() {
      CSS_HANDLER_FAIL_IF_NOT(input.IsString(), configs.enable_css_strict_mode,
                             TYPE_MUST_BE, CSSProperty::GetPropertyNameCStr(key),
                             STRING_TYPE)
    
      CSSStringParser parser = CSSStringParser::FromLepusString(input, configs);
      parser.SetIsLegacyParser(configs.enable_legacy_parser);
      output[kPropertyIDTest] = parser.ParseTest();
      return true;
    }
    
    HANDLER_REGISTER_IMPL() {
      array[kPropertyIDTest] = &Handle;
    }
    
    }  // namespace TestHandler
    }  // namespace tasm
    }  // namespace lynx
  4. Register the parser by adding your customized handler to core/renderer/css/parser/unit_handler.cc:

    UnitHandler::UnitHandler() {
      TestHandler::Register(interceptors_);
    }
  5. Implement setter & getter for ComputedCSSStyle:

    After converting the raw string into a CSSValue, in a ComputedCSSValue, it should be a data struct based on primitive types. Implement the value conversion from CSSValue, and calculate it if your value is context related (e.g. length value with sp unit is related to root element's font-size).

    If your property will be consumed by platform layer, add it to macro FOREACH_PLATFORM_PROPERTY. Then implement your function in prop_bundle_style_writer, to enable the runtime to put your computed value into prop bundle, and send it to platform layer.

    #define FOREACH_PLATFORM_PROPERTY(V) \
      V(Test)
    
    bool ComputedCSSValue::SetTest(const tasm::CSSValue& value, bool reset);
    
    // In prop_bundle_style_writer
    static void TestWriterFunc(PropBundle* bundle, CSSPropertyID id,
                             starlight::ComputedCSSStyle* style);
    
    static constexpr std::array<WriterFunc, kPropertyEnd> kWriter = [] {
      std::array<WriterFunc, kPropertyEnd> writer = {nullptr};
      for (CSSPropertyID id : kPlatformIDs) {
        writer[id] = &DefaultWriterFunc;
      }
      writer[kPropertyIDTest] = &TestWriterFunc;
      return writer;
    }();