Open CITguy opened 2 years ago
What if we had a { "$type": "path" }
?
This could be used to reference any type of "file" (directory or otherwise), relative to the tokens.json
file.
$value
MUST begin with ./
(relative){
"assets": {
"$type": "path",
"icons": {
"alert": {
"$value": "./assets/images/icons/alert.svg"
},
"bookmark": {
"$value": "./assets/images/icons/bookmark.svg"
}
}
}
}
What if we had a { "$type": "asset" }
?
Opting for convention over configuration, assets always exist in a sibling assets/
directory to the tokens.json
file. Additionally, "asset" $value
will be relative to the assets/
directory.
{package}/
tokens.json
assets/
images/
icons/
alert.svg
bookmark.svg
...
...
$value
MUST NOT begin with assets/
(this is implied, by convention){
"assets": {
"$type": "asset",
"icons": {
"alert": {
"$value": "images/icons/alert.svg"
},
"bookmark": {
"$value": "images/icons/bookmark.svg"
}
}
}
}
assets/
is still free-form, to meet the needs of the token package authorYou're right, currently the draft spec doesn't have a type for things like assets. As you've noted, just falling back to a string type isn't helpful because there's no expectation for tools to do anything special with them (like guessing they could be file paths and trying to open them). In fact, the spec forbids tools from trying to infer a type from a basic value.
Adding a type for referencing files has been on our to-do list for a while though, so perhaps it's time to finally to do it! :-) In my head I had always imagined to be along the lines of your first idea: the path type. I wonder though if "file" or "asset" would be a more appropriate name for the type. I think the token represents a file, the path is just the technical means of locating that file. I don't have strong feelings about that though.
In terms of the specifics, I prefer your first idea of just specifying a relative path. In fact, why not allow any kind of relative path? For example:
{
"icons": {
"alert": {
"$type": "file",
"$value": "./path/to/file.svg"
},
"bookmark": {
"$type": "file",
"$value": "../a/different/file.svg"
}
}
}
The spec intentionally avoids requiring tokens or groups to have certain names, so in a similar vein, I don't think we should be mandating that people keep assets in directory with a specific name or location.
"$type": "file"
makes sense to me for a File token.
My biggest concern with the definition is that someone will eventually have a need to centralize assets on a public CDN or via an API.
In the CDN case, the File token would be a valid URL, given that most of the time you don't want to restrict access to files on a CDN.
{
"icons": {
"$type": "file",
"alert": {
"$value": "https://cdn.foobar.com/icons/alert.svg"
},
"bookmark": {
"$value": "https://cdn.foobar.com/icons/bookmark.svg"
}
}
}
A file path could be defined as an API path (e.g., /icons/alert.svg
), which isn't technically a valid file path or URL, but for many cases this can be mitigated by defining File tokens as URLs to an API endpoint (e.g., https://api.foobar.com/icons/alert.svg
).
It's possible that the API system may have access control strategies in place to restrict access to certain resources, but any access controls applied should be documented by the API itself (out of scope for the Design Tokens spec).
{
"icons": {
"$type": "file",
"alert": {
"$value": "https://api.foobar.com/icons/alert.svg"
},
"bookmark": {
"$value": "https://api.foobar.com/icons/bookmark.svg"
}
}
}
I'd recommend that File tokens be documented such that their value must satisfy one of the following conditions:
./
or ../
)
"./foo.svg"
, "../foo.svg"
, "../foo/bar.svg"
It might be best to avoid URL's for now. Downloading files always has security implications and it is easier to judge if this is harmful when the specification and the ecosystem has matured a bit.
In the mean time any design token file needs to be distributed between multiple persons. I don't think it will be likely that you can share a design token file but can not also share an asset file.
Only allowing file paths should be sufficient for now.
This is an old issue, but I’d love to see this revisited, as icons are an important part of every DS and I do think this is a core token type.
I’m strongly in favor of @CITguy’s most recent proposal (especially the URL Living Standard bit) and think it would work well.
Downloading files always has security implication
To reference how the web, a traditionally insecure platform, has handled it: the link tag marks a reference to a local or remote resource. It marks a relationship to the source to designate what’s done with it. And while a few built-in types are understood and executed (stylesheet
for CSS, shortcut icon
for favicons, etc.), many are simply ignored.
Perhaps there could be some hint as part of the schema, e.g:
{
"icons": {
"$type": "file",
"alert": {
"$value": {
"rel": "icon",
"url": "https://cdn.foobar.com/icons/alert.svg"
}
}
}
}
Note: rel
is a bad name; just using it as a placeholder
Perhaps there are a small number of rel
s that are recommended, such as:
icon
image
video
font
(as in the actual .ttf
or .woff2
itself)And the rest can be up to tooling to respect or ignore (similar to how $extensions
work).
This hopefully solves some of the security issues, because many systems can do basic checks on this (e.g. “I was expecting rel: "icon"
but the server returned a mimetype of application/zip
so I’ll throw an error). This could also be more extensible than having 1 token type for icons, images, etc.
I think this could actually be as simple as having a url
type which follows exactly the whatwg standard. Urls can be relative paths, which would be combined with a base path (which might be a file path for local files) by the parser. We can provide a standard (like RFC 3986 for resolving relative paths.
As for the security of URLs, I think we get into trouble when we start talking about a translator actually fetching something on the url. The original comment's author mentioned wanting a token translator to combine svgs into a sprite sheet or generate a font file; to me this seems like a job for another tool, not a token translator.
I'm building out a tiered design system, in which I'd like our core package to ship design tokens alongside universal (likely binary) assets (e.g., logos, icons, fonts, etc.).
For example, given the following abridged directory structure:
I'd like to define an "assets.*" group of tokens, all of which whose value is a relative path from
tokens.json
to a bundled SVG asset inassets/images/icons/
.($value strings are relative paths from
tokens.json
)The current design tokens format spec doesn't seem to be clear on how to define a
$value
that is a reference to a file external to the.tokens.json
file. My best guess would be to omit$type
altogether and set$value
to a string (implicit$type: string
), but there's no guarantee that a Translation Tool would know to treat the value as a file path.My Use Case
I ship SVG icons in my core package so that downstream dependencies can take those files and translate them into environment-specific assets.
For example...
<symbol>
<use href="..." />
to consume individual icons*.css
file to consume individual icons from the font*.dart
code to consume individual icons from the font