adobexd / typings Goto Github PK
View Code? Open in Web Editor NEWTypings for Adobe XD API Surfaces
License: MIT License
Typings for Adobe XD API Surfaces
License: MIT License
If you convert the jsconfig.json
file to a tsconfig.json
file, set strict: true
, and then open the assets.d.ts
file (in VSCode, at least), you are presented with the following errors:
ts(2535) [9, 15]
ts(2535) [52, 15]
These refer to the fact that you have the following in a type
declaration:
type PrototypeArtifact = {
type: ArtifactType.PROTOTYPE, // <-- Can't do this with ambient enums!
The problem here is that you are assigning a value to the type PrototypeArtifact.type
but that you have not explicitly said what ArtifactType.PROTOTYPE
is actually equivalent to. When you declare an ambient enum, you provide information on the names of each valid type but not the value. While this works for usage of that enum entry, you cannot use it in another ambient type declaration as you do above.
That said, enums in JavaScript are simple objects and we can easily see what their values are with a quick test (though it would be nice if Adobe simply documented them...):
// Outputs:
// { PROTOTYPE: 'prototype', SPECS: 'specs' }
console.log(require('cloud').ArtifactType);
// Outputs:
// { WEB: 'Web', IOS: 'iOS', ANDROID: 'Android' }
console.log(require('cloud').TargetPlatform);
// Outputs:
// { LINKABLE: 'linkable',
// PASSWORD_PROTECTED: 'passwordProtected',
// INVITE_ONLY: 'inviteOnly' }
console.log(require('cloud').AccessLevel);
Cool. With that information in hand, we can write the enums as follows:
export enum ArtifactType {
PROTOTYPE = 'prototype',
SPECS = 'specs'
}
export enum TargetPlatform {
WEB = 'Web',
IOS = 'iOS',
ANDROID = 'Android'
}
export enum AccessLevel {
LINKABLE = 'linkable',
PASSWORD_PROTECTED = 'passwordProtected',
INVITE_ONLY = 'inviteOnly'
}
Once those definitions are added the errors go away!
It should also be noted that the declarations in cloud.d.ts
appear to be out-of-sync with those in the current documentation.
In the current version, the PrototypeArtifact
and SpecsArtifact
types are effectively "extensions" of a new BaseSharedArtifact
. It also appears that there's a documentation bug for the description of the BaseSharedArtifact.type
member in that it appears to suggest that it is constantly ArtifactType.PROTOTYPE
. I'd be willing to bet my hat that that is a copy-pasta error.
While it is possible to "extend" a type
declaration, I would highly recommend converting these types
into interface
s. Adobe's use of "typedef" in the documentation simply suggests that "this is the shape of an object". You can use a TypeScript interface
to match that purpose (especially when typedef 'inheritance' is suggested).
Note that if you do adjust the declarations and unify the two Artifact
types with the BaseSharedArtifact
, you could get away without adding the enum values as explained above. It might be better, however, to do something like:
interface BaseSharedArtifact {
type: ArtifactType;
// Other common declarations...
}
interface PrototypeArtifact extends BaseSharedArtifact {
type: ArtifactType.PROTOTYPE;
// Prototype-specific declarations...
}
interface SpecsArtifact extends BaseSharedArtifact {
type: ArtifactType.SPECS;
// Specs-specific declarations...
}
At which point you would still need those enum values.
When importing individual classes like this:
import { Ellipse as Ellipse,
Rectangle as Rectangle,
Color as Color } from "../node_modules/@adobexd/typings/types/scenegraph";
and compiling using tsc
, the compiler throws the following errors:
306 public constructor(fileOrDataURI: string | uxp.storage.File);
~~~
node_modules/@adobexd/typings/types/scenegraph.d.ts:341:74 - error TS2371: A parameter initializer is only allowed in a function or constructor implementation.
341 public constructor(x: number, y: number, blur: number, color: Color, visible: boolean = true)
~~~~~~~~~~~~~~~~~~~~~~~
node_modules/@adobexd/typings/types/scenegraph.d.ts:413:31 - error TS2304: Cannot find name 'SceneNodeList'.
413 public readonly children: SceneNodeList;
importing using require
works, but doing so means you can't use the types as intended in your code:
const {Rectangle, Ellipse, Color} = require('scenegraph');
Here is an example project: https://github.com/mattThousand/typings
please let me know if I can provide additional information or help out in any way
If you convert the jsconfig.json
file to a tsconfig.json
file, set strict: true
, and then open the assets.d.ts
file (in VSCode, at least), you are presented with the following errors:
ts(1038) [119, 5]
ts(1038) [155, 5]
These refer to the fact that the colors
and characterStyles
classes are declared inside an already declared module.
Removing those declare
statements results in further errors related to the definition of the static class
. As both the colors
and characterStyles
"classes" are actually interfaces that allow you to access information (you never have an "instance" of those "classes"), they should simply be converted to interface
s and the static
keyword removed from all function definitions. Then a constant should be added that implements that interface so that it is accessible as a name and not just a type. Taken together, the two "class"es should look something like this:
interface colors {
get(): Array<ColorAsset | GradientAsset>;
add(...): number;
delete(...): number;
}
const colors: colors;
Since the class Matrix
is now documented in the API Reference (https://adobe-xd.gitbook.io/plugin-api-reference/xd-api-reference/scenegraph/matrix), we can implement it in the type definitions.
I know that it doesn't have official documentation but we still need to work with it. Please add currently existing properties to unblock current development:
"isCentered": true,
"flipScale": { "sx": 1, "sy": 1 },
"rotationHandle": { "x": 1, "y": 0.5 },
"degreeRotation": 0,
"scaleFactors": { "scaleX": 1, "scaleY": 1 },
"linkId": "",
"endR": 0.5,
"endY": 0.5,
"endX": 0.5,
"startR": 0,
"startY": 0.5,
"startX": 0.5,
"transformHeight": 0,
"transformWidth": 0,
"gradientTransform": { "a": 1, "b": 0, "c": 0, "d": 1, "e": 0, "f": 0 },
"colorStops": [
{
"color": { "a": 255, "r": 255, "g": 255, "b": 255, "linkId": "", "value": 4294967295 },
"stop": 0
},
{
"color": { "a": 255, "r": 88, "g": 58, "b": 168, "linkId": "", "value": 4283972264 },
"stop": 1
}
],
"rotationHandleX": 1,
"rotationHandleY": 0.5,
"rotation": 0,
"scaleX": 1,
"scaleY": 1
}```
As proposed by @ericdrobinson in #54 (comment):
Repo Structure - New Issue?
I would like to suggest that the jsconfig.json and sample.js file get moved into a sample or
example folder that's separate from the top level. A tsconfig.json file at the top level then makes > the most sense. This will allow a clear separation of TypeScript and JavaScript files while allowing > you to have a tsconfig.json file that's designed specifically for writing the declaration files.Thoughts?
Since the class LinearGradientFill
is now documented in the API Reference (https://adobe-xd.gitbook.io/plugin-api-reference/xd-api-reference/scenegraph/lineargradientfill), we can implement it in the type definitions.
part of updating the typings to match XD 14
From the looks of it, SceneNode
and RootNode
aren't actually exported classes in the scenegraph
module. This is wrongly declared in the typings (scenegraph.d.ts
).
A space for discussions about
Since the class Color
is now documented in the API Reference (https://adobe-xd.gitbook.io/plugin-api-reference/xd-api-reference/scenegraph/color), we can implement it in the type definitions.
Currently, the open source editor "Brackets" is not supported. Instructions on how to use the typings with this editor (if possible) should be added to the wiki.
I downloaded this repository, unzipped it, opened the folder in Visual Studio Code (v1.33.0), opened the sample.js
file, and was greeted to the following two errors:
These are pretty simple to fix.
RootNode
Type ErrorThis problem occurs because the sample.js
scope doesn't have the RootNode
type imported yet, even though it's used in a JSDoc parameter
declaration:
/**
* @param {Selection} selection
* @param {RootNode} documentRoot
*/
There are two ways to fix this:
RootNode
type (class).import
types".If you chose the second route, the code excerpt above would become:
/**
* @param {Selection} selection
* @param {import('scenegraph').RootNode} documentRoot
*/
Note that this does not actually import the type into the sample.js
"module"'s scope, but enables it and consumers to get proper type handling.
File | Folder
Type ErrorThis problem refers to this code from line 23:
newFile.write("Hello, world!");
This is actually a bit more complicated than the previous error as there are three things going on:
Folder
type defined in the current scope.File
type specified refers to the global Web DOM File
type.Folder.createEntry
method returns either a UXP File
or a UXP Folder
(and the code assumes it returns a UXP File
instance).To handle all of these issues and provide a safer usage example, do the following:
File
type.write()
.Put together the above looks like this:
// At the top of sample.js
const UXPFile = require("uxp").storage.File;
// ...
// Replace Line 23 with this:
if (newFile instanceof UXPFile) {
newFile.write("Hello, world!");
}
With these changes you will find that your JavaScript sample is now error-free! Hurray!
I decided to explain these here in the hopes that it will be more instructive than a simple PR. Hope this helps!
part of updating the typings for XD 14, see https://adobexdplatform.com/plugin-docs/reference/scenegraph.html#text
Please adjust names of these classes as it doesn't work now.
https://forums.adobexdplatform.com/t/what-namespace-is-lineargradientfill/942/2
AdobeXD/plugin-docs#179
According to https://adobexdplatform.com/plugin-docs/reference/uxp/module/storage.html#module-storage-filesystemprovider-getfileforsaving, types
(an array of file extensions) is the only valid option. However, initialDomain
is set in the typings (https://github.com/AdobeXD/typings/blob/master/types/uxp.d.ts#L200).
Part of updating the typings for XD 14
Documentation:
https://adobe-xd.gitbook.io/plugin-api-reference/uxp-api-reference/network-apis/shell
(includes global class Shell
)
I'm getting this message after importing the new type defs directory (today Sept 28).
'SceneNode' refers to a value, but is being used as a type here.ts(2749)
And this error:
Property 'SceneNode' does not exist on type 'typeof import("/Users/user/Library/Application Support/Adobe/Adobe XD/develop/myplugin/types/scenegraph")'.ts(2339)
It happens on the const
line and the @param
line:
// there's a red underline under scene node
const {SceneNode} = require("scenegraph");
/**
* Adds interaction
* @param {SceneNode} item
**/
function addInteractions(item, model) {
}
The SceneNodeList
class should not be in the global context. Actual attempts to access the SceneNodeList
directly in a command script results in undefined
(it's not actually a global).
Further, this should probably be an interface rather than a class as there does not appear to be a way to create new instances yourself.
Therefore I would recommend moving the SceneNodeList
declaration into scenegraph.d.ts
, (the only location the type is actually referenced) and simultaneously convert it to an interface.
While TypeScript theoretically supports declaring one-off types with the JSDoc format, it doesn't work terribly well for ambient type declarations (*.d.ts
). It appears to mainly provide context for type checking the usage of that type in the body of a function's definition.
Let's look at an example with the Entry.copyTo
function. Here is how it's currently defined:
/**
* Copies this entry to the specified `folder`.
* @param folder the folder to which to copy this entry
* @param {object} options additional options
* @param {boolean=false} options.overwrite if `true`, allows overwriting existing entries
*
* @throws errors.EntryExistsError if the attempt would overwrite an entry and `overwrite` is `false`
* @throws errors.PermissionDeniedError if the underlying file system rejects the attempt
* @throws errors.OutOfSpaceError if the file system is out of storage space
*/
copyTo(folder: Folder, options?): Promise<void>;
As written, the TypeScript language service is already confused about the use of the @param
directive. See:
Whoops! It didn't identify the options.overwrite
parameter correctly. To do this in a way that satisfies TypeScript, we would write the following:
/**
* @param {boolean} [options.overwrite=false] if `true`, allows overwriting existing entries
*/
Oddly, once you write it "correctly" for TypeScript, the option
object's parameters disappear from the IntelliSense entirely:
Unfortunately, constructing the parameters in this way also doesn't help the language service with type checking. If you look at the type of the options
parameter in that declaration it is considered any
.
Oh no!
A much better and safer way to handle this is to implement the options parameters inline inside the declaration. Here's an example that uses the copyTo
function:
/**
* Copies this entry to the specified `folder`.
*
* The Entry object passed to this function will continue to reference the original item - it is _not_ updated to reference the copy.
*
* @param folder the folder to which to copy this entry
* @param options
*
* @throws errors.EntryExistsError if the attempt would overwrite an entry and `overwrite` is `false`
* @throws errors.PermissionDeniedError if the underlying file system rejects the attempt
* @throws errors.OutOfSpaceError if the file system is out of storage space
*/
copyTo(folder: Folder, options?: {
/**
* if `true`, allows overwriting existing entries
*/
overwrite?: boolean = false;
}): Promise<void>;
[Note: The above version includes an updated body based on the current docs.]
With this approach we get the following three benefits:
If inline parameter documentation is unappealing, there is one other method that could be used. It's more flexible, but less "precise" when it comes to Adobe's documentation. Specifically, you could define your own interface:
interface CopyToOptions {
/**
* if `true`, allows overwriting existing entries
*/
overwrite?: boolean = false;
}
With the above, you would change the declaration of copyTo
to the following:
copyTo(folder: Folder, options?: CopyToOptions): Promise<void>;
This provides the same exact benefits as the inline approach with one additional benefit: you can reuse that type!
/** @type {import("uxp").storage.CopyToOptions} */
let copyOptions = {
overwrite: true
};
anEntry.copyTo(null, copyOptions);
That said, it is unlikely that many people would use such a feature...
Maybe I got it wrong but RenditionSettings.outputFile must point to the same type as uxp.storage.Folder.createFile return type (uxp.storage.File) not generic File (which is Blob).
part of updating the typings to match XD v14
Since the class BitmapFill
is now documented in the API Reference (https://adobe-xd.gitbook.io/plugin-api-reference/xd-api-reference/scenegraph/bitmapfill), we can implement it in the type definitions.
UXP supports a specific subset of browser DOM APIs. TypeScript's DOM lib, on the other hand, is extremely comprehensive. Configuring an environment with TypeScript's built-in DOM library leads to confusing bugs and causes tools to incorrectly suggest types.
Recommendation:
dom
entry from the tsconfig.json
lib
array.Attr
and friends)HTMLAnchorElement
and friends)BaseUIEvent
and friends)As Adobe incorporates more HTML and standard browser DOM APIs into UXP, the type declaration files can be updated to reflect the enhancements. This will help resolve an entire class of typo/error/etc.
Update definitions to match the XD 13 version (replace BitmapFill with new ImageFill)
part of updating the typings for XD 14
I think setSTartEnd
is a typo in setStartEnd
.
https://github.com/AdobeXD/typings/blob/master/types/scenegraph.d.ts#L885
Part of updating typings for XD 14, see https://adobexdplatform.com/plugin-docs/reference/cloud.html
Since the class Shadow
is now documented in the API Reference (https://adobe-xd.gitbook.io/plugin-api-reference/xd-api-reference/scenegraph/shadow), we can implement it in the type definitions.
Currently format specific properties like quality
(for jpg only) are required. Please make them optional:
quality?: number;
or use different types, e.g. JPEGRenditionSettings | SVGRenditionSettings | PNGRenditionSettings
Since the class Blur
is now documented in the API Reference (https://adobe-xd.gitbook.io/plugin-api-reference/xd-api-reference/scenegraph/blur), we can implement it in the type definitions.
The symbol declarations for storage.formats
, storage.modes
, and storage.types
are defined too "loosely".
First of all, the type Symbol
refers to the constructor for symbol
instances. At the very least, all symbols defined in the uxp.d.ts
file should use the lowercase version.
Second, as each symbol being referenced here is a unique symbol, the unique
keyword should be applied. As an example, this is how formats
should be defined:
/**
* This namespace describes the file content formats supported in FS methods like read and write.
*/
namespace formats {
/**
* UTF8 File encoding
*/
const utf8: unique symbol;
/**
* Binary file encoding
*/
const binary: unique symbol;
}
This allows us to do something extremely cool. We can now use those symbols to restrict options for other fields. Let's say we had an options
object with a format
field. By default you might define that format
field as type symbol
so that it would be restricted to symbols in general. That's decent as you can no longer say something like options.format = 5
. But options.format = Symbol("5")
is no better, right?
These unique symbol
types allow us to do this:
interface Options
{
format: typeof formats.utf8 | typeof formats.binary;
}
Now the only symbols allowed are specifically formats.utf8
or formats.binary
. That's much better!
With this in mind, the type declarations for some options
object fields in uxp.d.ts
(example) can be updated to be more strict (and helpful!).
RenditionSettings.type can have only specific value so I suppose it must be strongly typed, like:
/**
* File type: RenditionType.PNG, JPG, PDF, or SVG
*/
type: "PNG" | "JPG" | "PDF" | "SVG";
Really documentation is unclear if RenditionType stands for specific type or just a way to describe values.
Implement definitions for new repeat grid APIs
@ericdrobinson Any ideas? Since the type gets defined in the interactions
module, it doesn't get recognized inside scenegraph.d.ts
. Should this then be defined in the index.d.ts
as global?
Thank you very much in advance.
Property definitions are all public
by default in TypeScript. Adding the public
keyword in front of every declaration is distracting and makes it more difficult to identify the standout private
or protected
parameters.
Removing the public
keyword from the type declarations would make them far more readable and help them better match most other type declaration files.
[I understand that this is a style thing, but it does have an impact on readability and maintainability...]
For projects that utilize typescript and npm, types can be associated to a project by downloading the library via npm and exposeing a typings key. The request is to create the necessary values and expose the library on npm as a published package
"typings": "./types/index.d.ts"
key/valueA declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.