Skip to content

[RFC] Properly defining the public API of the library #201

@stof

Description

@stof

Defining such API is important regarding semver.

We have 2 kind of public APIs: the API meant at projects using scssphp and the API relevant for projects extending Scssphp

Usage API

  • Compiler::__construct
  • Compiler constants
  • formatter class names (as that's how the formatter is configured)
  • Compiler::compile
  • Compiler::addImportPath
  • Compiler::setImportPaths
  • Compiler::getParsedFiles
  • Compiler::setEncoding
  • Compiler::setFormatter
  • Compiler::setSourceMap
  • Compiler::setSourceMapOptions
  • Compiler::setErrorOuput ? (maybe not, as it says `for testing purpose only)

Note that we have a few deprecated APIs in this category, which I'm not listing there.

This clearly belongs to the public API of the package and BC layers should be provided for any change here.

Extension API

These APIs are weird. These APIs are about extending the Sass implementation from the PHP side. But the way they are implemented makes them depending on all the internal implementation details of scssphp.

The API for variables does not document the expected format. In practice, it seems to support 2 different formats:

  • a string in the Sass syntax that will be parsed by the parser. The drawback here is that there is nothing restricting it to contain only Sass values for now (related to the fact that there is no proper distinction between values and AST nodes) which allows creating weird thing where full expressions could be stored in the variable (no idea whether this would work)
  • if the parsing fails, it will try to coerce the PHP values into Sass values:
    • array or ArrayAccess are assumed to be in the internal representation already, but this cannot be passed to injectVariables anyway as it would break the parsing done for the first format
    • scalars and null are turned into the corresponding Sass values. But this is attempted only if it could not be parsed before as a Sass syntax when casting it as string, making this almost unusable

The function API expects to pass a callable and a prototype, without documenting what they are. And the callable will have to work with the way scssphp represents values internally, which is totally undocumented.

Looking at dart-sass, it does not support injecting global variables from the outside but it supports providing functions.

My suggestion is to exclude these from the public API for now. Otherwise, we need to freeze the library or release major versions at every release for now: our work on spec compliance makes us break the internal representation of things all the time, and this representation is currently part of the API of custom functions.
Once the work on object-oriented values is done, the custom functions can become stable as the signature for the callable will be list<Value> -> Value (we also need to figure out the proper way to provide the prototype, but that's something for which we could have a BC layer if it changes, and the current way might be fine, provided we document it).
For the variable API, I think we should first clarify the expected signature (with no guessing-based logic between 2 format but rather 2 methods if necessary). We might change it to expect a Value as argument but it might not be the best way. Another alternative is to deprecate it given that official sass does not support such use case. But that requires more discussion.

Additional extension points

Almost everything in the library is public or protected with no final keyword, meaning that projects could actually go crazy and extend the Compiler class to override almost anything.
I strongly suggest that no BC guarantee is provided at all here, and that we actively work on restricting this in the future. Making inheritance of the Compiler a supported extension point would force to freeze the library, as any refactoring we do towards spec compliance is actually breaking BC here.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions