diff --git a/gulp/tasks/dist.js b/gulp/tasks/dist.js index f80d2367..3d323b99 100644 --- a/gulp/tasks/dist.js +++ b/gulp/tasks/dist.js @@ -22,6 +22,7 @@ gulp.task('zip', ['clean:zip', 'dist'], function() { gulp.src([ 'dist/paper-full*.js', 'dist/paper-core*.js', + 'dist/index.d.ts', 'dist/node/**/*', 'LICENSE.txt', 'examples/**/*', diff --git a/gulp/tasks/docs.js b/gulp/tasks/docs.js index 96728ea4..9459f5d0 100644 --- a/gulp/tasks/docs.js +++ b/gulp/tasks/docs.js @@ -14,14 +14,15 @@ var gulp = require('gulp'), del = require('del'), rename = require('gulp-rename'), shell = require('gulp-shell'), - options = require('../utils/options.js'); + options = require('../utils/options.js'), + run = require('run-sequence'); var docOptions = { local: 'docs', // Generates the offline docs server: 'serverdocs' // Generates the website templates for the online docs }; -gulp.task('docs', ['docs:local', 'build:full'], function() { +gulp.task('docs', ['docs:local', 'docs:typescript', 'build:full'], function() { return gulp.src('dist/paper-full.js') .pipe(rename({ basename: 'paper' })) .pipe(gulp.dest('dist/docs/assets/js/')); @@ -32,15 +33,57 @@ Object.keys(docOptions).forEach(function(name) { var mode = docOptions[name]; return gulp.src('src') .pipe(shell( - ['java -cp jsrun.jar:lib/* JsRun app/run.js', - ' -c=conf/', name, '.conf ', - ' -D="renderMode:', mode, '" ', - ' -D="version:', options.version, '"'].join(''), + [ + 'java -cp jsrun.jar:lib/* JsRun app/run.js', + ' -c=conf/', name, '.conf ', + ' -D="renderMode:', mode, '" ', + ' -D="version:', options.version, '"' + ].join(''), { cwd: 'gulp/jsdoc' }) - ) + ); }); gulp.task('clean:docs:' + name, function() { - return del([ 'dist/' + docOptions[name] + '/**' ]); + return del(['dist/' + docOptions[name] + '/**']); }); }); + +// The goal of the typescript task is to automatically generate a type +// definition for the library. +gulp.task('docs:typescript', function() { + return run( + 'docs:typescript:clean:before', + 'docs:typescript:build', + 'docs:typescript:clean:after' + ); +}); +// First clean eventually existing type definition... +gulp.task('docs:typescript:clean:before', function() { + return del('dist/index.d.ts'); +}); +// ...then build the definition... +gulp.task('docs:typescript:build', function() { + // First parse JSDoc comments and store parsed data in a temporary file... + return gulp.src('src') + .pipe(shell( + [ + 'java -cp jsrun.jar:lib/* JsRun app/run.js', + ' -c=conf/typescript.conf ', + ' -D="file:../../gulp/typescript/typescript-definition-data.json"', + ' -D="version:', options.version, '"', + ' -D="date:', options.date, '"' + ].join(''), + { cwd: 'gulp/jsdoc' }) + ) + // ...then generate definition from parsed data... + .pipe(shell('node gulp/typescript/typescript-definition-generator.js')) + // ...finally test the definition by compiling a typescript file. + .pipe(shell('node node_modules/typescript/bin/tsc gulp/typescript/typescript-definition-test.ts')); +}); +// ...finally remove all unneeded temporary files that were used for building. +gulp.task('docs:typescript:clean:after', function() { + return del([ + 'gulp/typescript/typescript-definition-data.json', + 'gulp/typescript/typescript-definition-test.js' + ]); +}); diff --git a/gulp/typescript/typescript-definition-generator.js b/gulp/typescript/typescript-definition-generator.js new file mode 100644 index 00000000..e4dfda30 --- /dev/null +++ b/gulp/typescript/typescript-definition-generator.js @@ -0,0 +1,317 @@ +/** + * This script generates a type definition by taking JSDoc roughly parsed data, + * formatting it and passing it to a mustache template. + */ + +const fs = require('fs'); +const mustache = require('mustache'); + +// Retrieve JSDoc data. +const data = JSON.parse(fs.readFileSync(__dirname + '/typescript-definition-data.json', 'utf8')); +const classes = data.classes; +let globals = data.global.properties; + +// Format classes. +classes.forEach(cls => { + // Format class. + // Store name as `className` and not simply `name`, to avoid name conflict + // in static constructors block. + cls.className = cls._name; + // Store closest parent if there is one. + cls.extends = cls.inheritsFrom && cls.inheritsFrom.length > 0 + ? cls.inheritsFrom[0] + : null; + // Store comment using class tag as description. + cls.comment = formatComment(cls.comment, 'class'); + + // Build a filter for deprecated or inherited methods or properties. + const filter = _ => !_.deprecated && _.memberOf == cls.alias && !_.isNamespace; + + // Format properties. + cls.properties = cls.properties + .filter(filter) + .map(_ => ({ + name: _._name, + type: formatType(_.type), + static: formatStatic(_.isStatic), + readOnly: formatReadOnly(_.readOnly), + comment: formatComment(_.comment) + })); + + // Format methods. + const methods = cls.methods + .filter(filter) + .map(_ => { + const name = formatMethodName(_._name); + const isStaticConstructor = _.isStatic && _.isConstructor; + return { + name: name, + // Constructors don't need return type. + type: !_.isConstructor + ? formatType(getMethodReturnType(_), true) + : '', + static: formatStatic(_.isStatic), + // This flag is only used below to filter methods. + isStaticConstructor: isStaticConstructor, + comment: formatComment(_.comment, 'desc', _.isConstructor), + params: _._params + ? _._params + // Filter internal parameters (starting with underscore). + .filter(_ => !/^_/.test(_.name)) + .map(_ => formatParameter(_, isStaticConstructor && cls)) + .join(', ') + : '' + }; + }) + .sort(sortMethods); + + // Divide methods in 2 parts: static constructors and other. Because static + // constructors need a special syntax in type definition. + cls.methods = []; + cls.staticConstructors = []; + methods.forEach(method => { + if (method.isStaticConstructor) { + // Group static constructors by method name. + let staticConstructors = cls.staticConstructors.find(_ => _.name === method.name); + if (!staticConstructors) { + staticConstructors = { + name: method.name, + constructors: [] + }; + cls.staticConstructors.push(staticConstructors); + } + staticConstructors.constructors.push(method); + } else { + cls.methods.push(method); + } + }); + // Store a conveniance flag to check whether class has static constructors. + cls.hasStaticConstructors = cls.staticConstructors.length > 0; +}); + +// Format global vriables. +globals = globals +// Filter global variables that make no sense in type definition. + .filter(_ => !/^on/.test(_._name) && _._name !== 'paper') + .map(_ => ({ + name: _._name, + type: formatType(_.type), + comment: formatComment(_.comment) + })); + +// Format data trough a mustache template. +// Prepare data for the template. +const context = { + classes: classes, + globals: globals, + version: data.version, + date: data.date, + // {{#doc}} blocks are used in template to automatically generate a JSDoc + // comment with a custom indent. + doc: () => formatJSDoc +}; +// Retrieve template content. +const template = fs.readFileSync(__dirname + '/typescript-definition-template.mustache', 'utf8'); +// Render template. +const output = mustache.render(template, context); +// Write output in a file. +fs.writeFileSync(__dirname + '/../../dist/index.d.ts', output, 'utf8'); + + +// +// METHODS +// + +function formatReadOnly(isReadOnly) { + return isReadOnly ? 'readonly ' : null; +} + +function formatStatic(isStatic) { + return isStatic ? 'static ' : null; +} + +function formatType(type, isMethodReturnType, staticConstructorClass) { + return ': ' + parseType(type, isMethodReturnType, staticConstructorClass); +} + +function parseType(type, isMethodReturnType, staticConstructorClass) { + // Always return a type even if input type is empty. In that case, return + // `void` for method return type and `any` for the rest. + if (!type) { + return isMethodReturnType ? 'void' : 'any'; + } + if (type === '*') { + return 'any'; + } + // Prefer `any[]` over `Array` to be more consistent with other types. + if (type === 'Array') { + return 'any[]'; + } + // Handle multiple types possibility by splitting on `|` then re-joining + // back parsed types. + return type.split('|').map(type => { + // Handle rest parameter pattern: `...Type` => `Type[]` + const matches = type.match(/^\.\.\.(.+)$/); + if (matches) { + return parseType(matches[1]) + '[]'; + } + // Get type without array suffix `[]` for easier matching. + const singleType = type.replace(/(\[\])+$/, ''); + // Handle eventual type conflict in static constructors block. For + // example, in `Path.Rectangle(rectangle: Rectangle)` method, + // `rectangle` parameter type must be mapped to `paper.Rectangle` as it + // is declared inside a `Path` namespace and would otherwise be wrongly + // assumed as being the type of `Path.Rectangle` class. + if (staticConstructorClass && staticConstructorClass.methods.find(_ => _.isStatic && _.isConstructor && formatMethodName(_._name) === singleType) + ) { + return 'paper.' + type; + } + // Convert primitive types to their lowercase equivalent to suit + // typescript best practices. + return ['Number', 'String', 'Boolean', 'Object'].indexOf(singleType) >= 0 + ? type.toLowerCase() + : type; + }).join(' | '); +} + +function formatMethodName(methodName) { + // Overloaded methods were parsed as `method^0`, `method^1`... here, we + // turn them back to `method` as typescript allow overloading. + methodName = methodName.replace(/\^[0-9]+$/, ''); + // Real contructors are called `initialize` in the library. + methodName = methodName.replace(/^initialize$/, 'constructor'); + return methodName; +} + +function formatParameter(_, staticConstructorClass) { + let content = ''; + // Handle rest parameter pattern `...Type`. Parameter name needs to be + // prefixed with `...` as in ES6. E.g. `...parameter: type[]`. + if (_.type.match(/^\.\.\.(.+)$/)) { + content += '...'; + } + content += formatParameterName(_.name); + // Optional parameters are formatted as: `parameter?: type`. + if (_.isOptional) { + content += '?'; + } + content += formatType(_.type, false, staticConstructorClass); + return content; +} + +function formatParameterName(parameterName) { + // Avoid usage of reserved keyword as parameter name. + // E.g. `function` => `callback`. + if (parameterName === 'function') { + return 'callback'; + } + return parameterName; +} + +function formatComment(comment, descriptionTagName = 'desc', skipReturn = false) { + const tags = comment.tags; + let content = ''; + + // Retrieve description tag. + const descriptionTag = tags.find(_ => _.title === descriptionTagName); + if (descriptionTag) { + // Don't display group titles. + content += descriptionTag.desc.replace(/\{@grouptitle .+?\}/g, '').trim(); + } + + // Preserve some of the JSDoc tags that can be usefull even in type + // definition. Format their values to make sure that only informations + // that make sense are kept. E.g. method parameters types are already + // provided in the signature... + content += formatCommentTags(tags, 'see'); + content += formatCommentTags(tags, 'option'); + content += formatCommentTags(tags, 'param', _ => _.name + ' - ' + _.desc); + + if (!skipReturn) { + content += formatCommentTags(tags, 'return', _ => _.desc.trim().replace(/^\{|\}$/g, '').replace(/@([a-zA-Z]+)/, '$1')); + } + + // Make sure links are followable (e.g. by IDEs) by removing parameters. + // {@link Class#method(param)} => {@link Class#method} + content = content.replace(/(\{@link [^\}]+?)\(.*?\)(\})/g, '$1$2'); + + content = content.trim(); + return content; +} + +function formatCommentTags(tags, tagName, formatter) { + let content = ''; + // Default formatter simply outputs description. + formatter = formatter || (_ => _.desc); + // Only keep tags that have a description. + tags = tags.filter(_ => _.desc && _.title === tagName); + if (tags.length > 0) { + content += '\n'; + // Display tag as it was in original JSDoc, followed by formatted value. + tags.forEach(_ => content += '\n@' + tagName + ' ' + formatter(_)); + } + return content; +} + +/** + * This outputs a JSDoc comment indented at the given offset and including the + * parsed comment for current mustache block. + * @param {Number} offset the number of spaces to use for indentation + * @param {Function} render the mustache render method + * @return {string} the formatted JSDoc comment + */ +function formatJSDoc(offset, render) { + // First render current block comment. Use `{{&}}` syntax to make sure + // special characters are not escaped. + let content = render('{{&comment}}'); + if (!content) { + return ''; + } + + // Build indentation. + offset = parseInt(offset); + if (offset > 0) { + offset++; + } + const indentation = new Array(offset).join(' '); + + // Prefix each line with the indentation. + content = content.split('\n') + .map(_ => indentation + ' * ' + _) + .join('\n'); + + // Wrap content in JSDoc delimiters: `/**` and `*/`. + return '/** \n' + content + '\n' + indentation + ' */'; +} + +function getMethodReturnType(_) { + return _.returnType || _.returns.length > 0 && _.returns[0].type; +} + +function sortMethods(methodA, methodB) { + // This places constructors before other methods as it is a best practice. + // This also place constructors with only one object parameter after other + // constructors to avoid type inference errors due to constructors + // overloading order. E.g. if `constructor(object: object)` is defined + // before `constructor(instance: Class)`, calling `constructor(instance)` + // will always be mapped to `contructor(object: object)`, since everything + // is an object in JavaScript. This is problematic because most of Paper.js + // classes have a constructor accepting an object. + const aIsContructor = methodA.name === 'constructor'; + const bIsContructor = methodB.name === 'constructor'; + if (aIsContructor && bIsContructor) { + if (methodA.params === 'object: object') { + return 1; + } + if (methodB.params === 'object: object') { + return -1; + } + } + else if (aIsContructor) { + return -1; + } + else if (bIsContructor) { + return 1; + } + return 0; +} diff --git a/gulp/typescript/typescript-definition-template.mustache b/gulp/typescript/typescript-definition-template.mustache new file mode 100644 index 00000000..a7856e17 --- /dev/null +++ b/gulp/typescript/typescript-definition-template.mustache @@ -0,0 +1,59 @@ +/*! + * Paper.js v{{version}} - The Swiss Army Knife of Vector Graphics Scripting. + * http://paperjs.org/ + * + * Copyright (c) 2011 - 2016, Juerg Lehni & Jonathan Puckey + * http://scratchdisk.com/ & https://puckey.studio/ + * + * Distributed under the MIT license. See LICENSE file for details. + * + * All rights reserved. + * + * Date: {{date}} + * + * This is an auto-generated type definition. + */ + +declare module paper { + {{#globals}} + {{#doc}}4{{/doc}} + let {{name}}{{type}} + + {{/globals}} + + {{#classes}} + + {{#doc}}4{{/doc}} + class {{className}} {{#extends}}extends {{extends}}{{/extends}} { + {{#properties}} + {{#doc}}8{{/doc}} + {{static}}{{readOnly}}{{name}}{{type}} + + {{/properties}} + + {{#methods}} + {{#doc}}8{{/doc}} + {{static}}{{name}}({{params}}){{type}} + + {{/methods}} + } + {{#hasStaticConstructors}} + namespace {{className}} { + {{#staticConstructors}} + + class {{name}} extends {{className}} { + {{#constructors}} + {{#doc}}12{{/doc}} + constructor({{params}}) + + {{/constructors}} + } + {{/staticConstructors}} + } + {{/hasStaticConstructors}} + {{/classes}} +} + +declare module 'paper' { + export = paper +} diff --git a/gulp/typescript/typescript-definition-test.ts b/gulp/typescript/typescript-definition-test.ts new file mode 100644 index 00000000..22431122 --- /dev/null +++ b/gulp/typescript/typescript-definition-test.ts @@ -0,0 +1,1155 @@ +/// + +/** + * This file is used as a way to test auto-generated typescript definition + * validity. For now, this only check that calling methods as they are defined + * in online documentation does not throw error in typescript compilation. + * + * Todo: add more advanced type checking by using either: + * - typescript compiler check: `let result:type = methodCall()` + * - dedicated testing library like: https://github.com/Microsoft/dtslint + */ + +import * as paper from 'paper'; + + +// +// Global +// + +paper.project; +paper.projects; +paper.view; +paper.tool; +paper.tools; + + +// +// Utility variables +// + +let point = {} as paper.Point; +let size = {} as paper.Size; +let rectangle = {} as paper.Rectangle; +let matrix = {} as paper.Matrix; +let project = {} as paper.Project; +let item = {} as paper.Item; +let layer = {} as paper.Layer; +let group = {} as paper.Group; +let shape = {} as paper.Shape; +let raster = {} as paper.Raster; +let pathItem = {} as paper.PathItem; +let path = {} as paper.Path; +let compoundPath = {} as paper.CompoundPath; +let segment = {} as paper.Segment; +let curve = {} as paper.Curve; +let curveLocation = {} as paper.CurveLocation; +let symbolDefinition = {} as paper.SymbolDefinition; +let symbolItem = {} as paper.SymbolItem; +let style = {} as paper.Style; +let color = {} as paper.Color; +let gradient = {} as paper.Gradient; +let gradientStop = {} as paper.GradientStop; +let textItem = {} as paper.TextItem; +let pointText = {} as paper.PointText; +let view = {} as paper.View; +let event = {} as paper.Event; +let mouseEvent = {} as paper.MouseEvent; +let tool = {} as paper.Tool; +let toolEvent = {} as paper.ToolEvent; +let keyEvent = {} as paper.KeyEvent; +let paperScope = {} as paper.PaperScope; +let callback = {} as () => {}; +let hitResult = {} as paper.HitResult; +let object = {} as object; + + +// +// Classes +// + +// +// Point +// + +new paper.Point(0, 0); +new paper.Point([ 0, 0 ]); +new paper.Point({ x: 0, y: 0 }); +new paper.Point(size); +new paper.Point(point); +point.x; +point.y; +point.length; +point.angle; +point.angleInRadians; +point.quadrant; +point.selected; +point.set(0, 0); +point.set([ 0, 0 ]); +point.set({ x: 0, y: 0 }); +point.set(size); +point.set(point); +point.equals(point); +point.clone(); +point.toString(); +point.getAngle(point); +point.getAngleInRadians(point); +point.getDirectedAngle(point); +point.getDistance(point, true); +point.normalize(); +point.normalize(0); +point.rotate(0, point); +point.transform(matrix); +point.isInside(rectangle); +point.isClose(point, 0); +point.isCollinear(point); +point.isOrthogonal(point); +point.isZero(); +point.isNaN(); +point.isInQuadrant(0); +point.dot(point); +point.cross(point); +point.project(point); +point.round(); +point.ceil(); +point.floor(); +point.abs(); +point.add(0); +point.add(point); +point.subtract(0); +point.subtract(point); +point.multiply(0); +point.multiply(point); +point.divide(0); +point.divide(point); +point.modulo(0); +point.modulo(point); +paper.Point.min(point, point); +paper.Point.max(point, point); +paper.Point.random(); + + +// +// Size +// + + +new paper.Size(0, 0); +new paper.Size([ 0, 0 ]); +new paper.Size({ width: 0, height: 0 }); +new paper.Size(size); +new paper.Size(point); +size.width; +size.height; +size.set(0, 0); +size.set([ 0, 0 ]); +size.set({ x: 0, y: 0 }); +size.set(size); +size.set(point); +size.equals(size); +size.clone(); +size.toString(); +size.isZero(); +size.isNaN(); +size.round(); +size.ceil(); +size.floor(); +size.abs(); +size.add(0); +size.add(size); +size.subtract(0); +size.subtract(size); +size.multiply(0); +size.multiply(size); +size.divide(0); +size.divide(size); +size.modulo(0); +size.modulo(size); +paper.Size.min(size, size); +paper.Size.max(size, size); +paper.Size.random(); + + +// +// Rectangle +// + + +new paper.Rectangle(point, size); +new paper.Rectangle({ point: point, size: size }); +new paper.Rectangle(0, 0, 0, 0); +new paper.Rectangle(point, point); +new paper.Rectangle(rectangle); +rectangle.x; +rectangle.y; +rectangle.width; +rectangle.height; +rectangle.point; +rectangle.size; +rectangle.left; +rectangle.top; +rectangle.right; +rectangle.bottom; +rectangle.center; +rectangle.topLeft; +rectangle.topRight; +rectangle.bottomLeft; +rectangle.bottomRight; +rectangle.leftCenter; +rectangle.topCenter; +rectangle.rightCenter; +rectangle.bottomCenter; +rectangle.area; +rectangle.selected; +rectangle.set(point, size); +rectangle.set({ point: point, size: size }); +rectangle.set(0, 0, 0, 0); +rectangle.set(point, point); +rectangle.set(rectangle); +rectangle.clone(); +rectangle.equals(rectangle); +rectangle.toString(); +rectangle.isEmpty(); +rectangle.contains(point); +rectangle.contains(rectangle); +rectangle.intersects(rectangle); +rectangle.intersects(rectangle, 0); +rectangle.intersect(rectangle); +rectangle.unite(rectangle); +rectangle.include(point); +rectangle.expand(0); +rectangle.expand(0, 0); +rectangle.scale(0); +rectangle.scale(0, 0); + + +// +// Matrix +// + +new paper.Matrix(); +new paper.Matrix(0, 0, 0, 0, 0, 0); +new paper.Matrix([ 0, 0, 0, 0, 0, 0 ]); +new paper.Matrix(matrix); +matrix.a; +matrix.b; +matrix.c; +matrix.d; +matrix.tx; +matrix.ty; +matrix.values; +matrix.translation; +matrix.scaling; +matrix.rotation; +matrix.set(0, 0, 0, 0, 0, 0); +matrix.set([ 0, 0, 0, 0, 0, 0 ]); +matrix.set(matrix); +matrix.clone(); +matrix.equals(matrix); +matrix.toString(); +matrix.reset(); +matrix.apply(); +matrix.apply(true); +matrix.translate(point); +matrix.translate(0, 0); +matrix.scale(0); +matrix.scale(0, point); +matrix.scale(0, 0); +matrix.scale(0, 0, point); +matrix.rotate(0, point); +matrix.rotate(0, 0, 0); +matrix.shear(point); +matrix.shear(point, point); +matrix.shear(0, 0); +matrix.shear(0, 0, point); +matrix.skew(point); +matrix.skew(point, point); +matrix.skew(0, 0); +matrix.skew(0, 0, point); +matrix.append(matrix); +matrix.prepend(matrix); +matrix.appended(matrix); +matrix.prepended(matrix); +matrix.invert(); +matrix.inverted(); +matrix.isIdentity(); +matrix.isInvertible(); +matrix.isSingular(); +matrix.transform(point); +matrix.transform([ 0, 0 ], [ 0, 0 ], 0); +matrix.inverseTransform(point); +matrix.decompose(); +matrix.applyToContext({} as CanvasRenderingContext2D); + + +// +// Project +// + +new paper.Project({} as HTMLCanvasElement); +new paper.Project(''); +new paper.Project(size); +project.view; +project.currentStyle; +project.index; +project.layers; +project.activeLayer; +project.symbolDefinitions; +project.selectedItems; +project.activate(); +project.clear(); +project.isEmpty(); +project.remove(); +project.selectAll(); +project.deselectAll(); +project.addLayer(layer); +project.insertLayer(0, layer); +project.hitTest(point); +project.hitTest(point, {}); +project.hitTestAll(point); +project.hitTestAll(point, {}); +project.getItems({}); +project.getItems(callback); +project.getItem({}); +project.getItem(callback); +project.exportJSON(); +project.exportJSON({}); +project.importJSON(''); +project.exportSVG(); +project.exportSVG({}); +project.importSVG(''); +project.importSVG({} as SVGElement); +project.importSVG('', {}); +project.importSVG('', callback); + + +// +// Item +// + +item.id; +item.className; +item.name; +item.style; +item.locked; +item.visible; +item.blendMode; +item.opacity; +item.selected; +item.clipMask; +item.data; +item.position; +item.pivot; +item.bounds; +item.strokeBounds; +item.handleBounds; +item.rotation; +item.scaling; +item.matrix; +item.globalMatrix; +item.viewMatrix; +item.applyMatrix; +item.project; +item.view; +item.layer; +item.parent; +item.children; +item.firstChild; +item.lastChild; +item.nextSibling; +item.previousSibling; +item.index; +item.strokeColor; +item.strokeWidth; +item.strokeCap; +item.strokeJoin; +item.dashOffset; +item.strokeScaling; +item.dashArray; +item.miterLimit; +item.fillColor; +item.fillRule; +item.shadowColor; +item.shadowBlur; +item.shadowOffset; +item.selectedColor; +item.onFrame; +item.onMouseDown; +item.onMouseDrag; +item.onMouseUp; +item.onClick; +item.onDoubleClick; +item.onMouseMove; +item.onMouseEnter; +item.onMouseLeave; +item.set({}); +item.clone(); +item.clone({}); +item.copyContent(item); +item.copyAttributes(item, true); +item.rasterize(); +item.rasterize(0); +item.rasterize(0, true); +item.contains(point); +item.isInside(rectangle); +item.intersects(item); +item.hitTest(point); +item.hitTest(point, {}); +item.hitTestAll(point); +item.hitTestAll(point, {}); +item.matches({}); +item.matches(callback); +item.matches(name, {}); +item.getItems({}); +item.getItems(callback); +item.getItem({}); +item.getItem(callback); +item.exportJSON(); +item.exportJSON({}); +item.importJSON(''); +item.exportSVG(); +item.exportSVG({}); +item.importSVG(''); +item.importSVG({} as SVGElement); +item.importSVG('', {}); +item.importSVG('', callback); +item.addChild(item); +item.insertChild(0, item); +item.addChildren([ item ]); +item.insertChildren(0, [ item ]); +item.insertAbove(item); +item.insertBelow(item); +item.sendToBack(); +item.bringToFront(); +item.addTo(group); +item.copyTo(group); +item.reduce({}); +item.remove(); +item.replaceWith(item); +item.removeChildren(); +item.removeChildren(0); +item.removeChildren(0, 0); +item.reverseChildren(); +item.isEmpty(); +item.hasFill(); +item.hasStroke(); +item.hasShadow(); +item.hasChildren(); +item.isInserted(); +item.isAbove(item); +item.isBelow(item); +item.isParent(item); +item.isChild(item); +item.isDescendant(item); +item.isAncestor(item); +item.isSibling(item); +item.isGroupedWith(item); +item.translate(point); +item.rotate(0); +item.rotate(0, point); +item.scale(0); +item.scale(0, point); +item.scale(0, 0); +item.scale(0, 0, point); +item.shear(point); +item.shear(point, point); +item.shear(0, 0); +item.shear(0, 0, point); +item.skew(point); +item.skew(point, point); +item.skew(0, 0); +item.skew(0, 0, point); +item.transform(matrix); +item.globalToLocal(point); +item.localToGlobal(point); +item.parentToLocal(point); +item.localToParent(point); +item.fitBounds(rectangle); +item.fitBounds(rectangle, true); +item.on('', callback); +item.on({}); +item.off('', callback); +item.off({}); +item.emit('', event); +item.responds(''); +item.removeOn({}); +item.removeOnMove(); +item.removeOnDown(); +item.removeOnDrag(); +item.removeOnUp(); + + +// +// Layer +// + +new paper.Layer([ item ]); +new paper.Layer({}); +layer.activate(); + + +// +// Group +// + +new paper.Group([ item ]); +new paper.Group({}); +group.clipped; + + +// +// Shape +// + +new paper.Shape.Circle(point, 0); +new paper.Shape.Circle({}); +new paper.Shape.Rectangle(rectangle); +new paper.Shape.Rectangle(rectangle, size); +new paper.Shape.Rectangle(point, size); +new paper.Shape.Rectangle(point, point); +new paper.Shape.Rectangle({}); +new paper.Shape.Ellipse(rectangle); +new paper.Shape.Ellipse({}); +shape.type; +shape.size; +shape.radius; +shape.toPath(); +shape.toPath(true); + + +// +// Raster +// + +new paper.Raster(); +new paper.Raster({} as HTMLImageElement); +new paper.Raster({} as HTMLCanvasElement); +new paper.Raster(''); +new paper.Raster('', point); +raster.size; +raster.width; +raster.height; +raster.loaded; +raster.resolution; +raster.image; +raster.canvas; +raster.context; +raster.source; +raster.crossOrigin; +raster.smoothing; +raster.onLoad; +raster.onError; +raster.getSubCanvas(rectangle); +raster.getSubRaster(rectangle); +raster.toDataURL(); +raster.drawImage({} as HTMLImageElement, point); +raster.getAverageColor(path); +raster.getAverageColor(rectangle); +raster.getAverageColor(point); +raster.getPixel(0, 0); +raster.getPixel(point); +raster.setPixel(0, 0, color); +raster.setPixel(point, color); +raster.createImageData(size); +raster.getImageData(rectangle); +raster.setImageData({} as ImageData, point); + + +// +// HitResult +// + +hitResult.type; +hitResult.name; +hitResult.item; +hitResult.location; +hitResult.color; +hitResult.segment; +hitResult.point; + + +// +// PathItem +// + +pathItem.interiorPoint; +pathItem.clockwise; +pathItem.pathData; +pathItem.unite(path); +pathItem.unite(path, {}); +pathItem.intersect(path); +pathItem.intersect(path, {}); +pathItem.subtract(path); +pathItem.subtract(path, {}); +pathItem.exclude(path); +pathItem.exclude(path, {}); +pathItem.divide(path); +pathItem.divide(path, {}); +pathItem.reorient(); +pathItem.reorient(true); +pathItem.reorient(true, true); +pathItem.getIntersections(path); +pathItem.getIntersections(path, callback); +pathItem.getCrossings(path); +pathItem.getNearestLocation(point); +pathItem.getNearestPoint(point); +pathItem.reverse(); +pathItem.flatten(); +pathItem.flatten(0); +pathItem.smooth(); +pathItem.smooth({}); +pathItem.simplify(); +pathItem.simplify(0); +pathItem.interpolate(path, path, 0); +pathItem.compare(path); +pathItem.moveTo(point); +pathItem.lineTo(point); +pathItem.arcTo(point, point); +pathItem.arcTo(point); +pathItem.arcTo(point, true); +pathItem.curveTo(point, point); +pathItem.curveTo(point, point, 0); +pathItem.cubicCurveTo(point, point, point); +pathItem.quadraticCurveTo(point, point); +pathItem.closePath(); +pathItem.moveBy(point); +pathItem.lineBy(point); +pathItem.arcBy(point, point); +pathItem.arcBy(point); +pathItem.arcBy(point, true); +pathItem.curveBy(point, point); +pathItem.curveBy(point, point, 0); +pathItem.cubicCurveBy(point, point, point); +pathItem.quadraticCurveBy(point, point); +paper.PathItem.create(''); +paper.PathItem.create([ [ 0 ] ]); +paper.PathItem.create({}); + + +// +// Path +// + +new paper.Path(); +new paper.Path([ segment ]); +new paper.Path(object); +new paper.Path(''); +new paper.Path.Line(point, point); +new paper.Path.Line(object); +new paper.Path.Circle(point, 0); +new paper.Path.Circle(object); +new paper.Path.Rectangle(rectangle); +new paper.Path.Rectangle(rectangle, size); +new paper.Path.Rectangle(point, size); +new paper.Path.Rectangle(point, point); +new paper.Path.Rectangle(object); +new paper.Path.Ellipse(rectangle); +new paper.Path.Ellipse(object); +new paper.Path.Arc(point, point, point); +new paper.Path.Arc(object); +new paper.Path.RegularPolygon(point, 0, 0); +new paper.Path.RegularPolygon(object); +new paper.Path.Star(point, 0, 0, 0); +new paper.Path.Star(object); +path.segments; +path.firstSegment; +path.lastSegment; +path.curves; +path.firstCurve; +path.lastCurve; +path.closed; +path.length; +path.area; +path.fullySelected; +path.add(segment); +path.insert(0, segment); +path.addSegments([ segment ]); +path.insertSegments(0, [ segment ]); +path.removeSegment(0); +path.removeSegments(); +path.removeSegments(0); +path.removeSegments(0, 0); +path.hasHandles(); +path.clearHandles(); +path.divideAt(curveLocation); +path.splitAt(curveLocation); +path.join(path); +path.join(path, 0); +path.reduce(object); +path.toShape(); +path.toShape(true); +path.getLocationOf(point); +path.getOffsetOf(point); +path.getLocationAt(0); +path.getPointAt(0); +path.getTangentAt(0); +path.getNormalAt(0); +path.getWeightedTangentAt(0); +path.getWeightedNormalAt(0); +path.getCurvatureAt(0); +path.getOffsetsWithTangent(point); + + +// +// CompoundPath +// + +new paper.CompoundPath(object); +new paper.CompoundPath(''); +compoundPath.closed; +compoundPath.firstSegment; +compoundPath.lastSegment; +compoundPath.curves; +compoundPath.firstCurve; +compoundPath.lastCurve; +compoundPath.area; +compoundPath.length; + + +// +// Segment +// + +new paper.Segment(); +new paper.Segment(point); +new paper.Segment(point, point); +new paper.Segment(point, point, point); +new paper.Segment(object); +segment.point; +segment.handleIn; +segment.handleOut; +segment.selected; +segment.index; +segment.path; +segment.curve; +segment.location; +segment.next; +segment.previous; +segment.hasHandles(); +segment.isSmooth(); +segment.clearHandles(); +segment.smooth(); +segment.smooth(object); +segment.isFirst(); +segment.isLast(); +segment.reverse(); +segment.reversed(); +segment.remove(); +segment.toString(); +segment.transform(matrix); +segment.interpolate(segment, segment, 0); + + +// +// Curve +// + +new paper.Curve(segment, segment); +new paper.Curve(point, point, point, point); +curve.point1; +curve.point2; +curve.handle1; +curve.handle2; +curve.segment1; +curve.segment2; +curve.path; +curve.index; +curve.next; +curve.previous; +curve.selected; +curve.values; +curve.points; +curve.length; +curve.area; +curve.bounds; +curve.strokeBounds; +curve.handleBounds; +curve.clone(); +curve.toString(); +curve.classify(); +curve.remove(); +curve.isFirst(); +curve.isLast(); +curve.getPart(0, 0); +curve.divideAt(curveLocation); +curve.divideAtTime(0); +curve.splitAt(curveLocation); +curve.splitAtTime(0); +curve.reversed(); +curve.clearHandles(); +curve.hasHandles(); +curve.hasLength(); +curve.hasLength(0); +curve.isStraight(); +curve.isLinear(); +curve.isCollinear(curve); +curve.isHorizontal(); +curve.isVertical(); +curve.getLocationAt(0); +curve.getLocationAtTime(0); +curve.getTimeAt(0); +curve.getTimeAt(0, 0); +curve.getTimesWithTangent(point); +curve.getOffsetAtTime(0); +curve.getLocationOf(point); +curve.getOffsetOf(point); +curve.getTimeOf(point); +curve.getNearestLocation(point); +curve.getNearestPoint(point); +curve.getPointAt(curveLocation); +curve.getTangentAt(curveLocation); +curve.getNormalAt(curveLocation); +curve.getWeightedTangentAt(curveLocation); +curve.getWeightedNormalAt(curveLocation); +curve.getCurvatureAt(curveLocation); +curve.getPointAtTime(0); +curve.getTangentAtTime(0); +curve.getNormalAtTime(0); +curve.getWeightedTangentAtTime(0); +curve.getWeightedNormalAtTime(0); +curve.getCurvatureAtTime(0); +curve.getIntersections(curve); + + +// +// CurveLocation +// + +new paper.CurveLocation(curve, 0); +new paper.CurveLocation(curve, 0, point); +curveLocation.segment; +curveLocation.curve; +curveLocation.path; +curveLocation.index; +curveLocation.time; +curveLocation.point; +curveLocation.offset; +curveLocation.curveOffset; +curveLocation.intersection; +curveLocation.tangent; +curveLocation.normal; +curveLocation.curvature; +curveLocation.distance; +curveLocation.equals(curveLocation); +curveLocation.toString(); +curveLocation.isTouching(); +curveLocation.isCrossing(); +curveLocation.hasOverlap(); + + +// +// SymbolDefinition +// + +new paper.SymbolDefinition(item); +new paper.SymbolDefinition(item, true); +symbolDefinition.project; +symbolDefinition.item; +symbolDefinition.place(); +symbolDefinition.place(point); +symbolDefinition.clone(); +symbolDefinition.equals(symbolDefinition); + + +// +// SymbolItem +// + +new paper.SymbolItem(symbolDefinition); +new paper.SymbolItem(item); +new paper.SymbolItem(symbolDefinition, point); +symbolItem.definition; + + +// +// Style +// + +new paper.Style(object); +style.view; +style.strokeColor; +style.strokeWidth; +style.strokeCap; +style.strokeJoin; +style.strokeScaling; +style.dashOffset; +style.dashArray; +style.miterLimit; +style.fillColor; +style.fillRule; +style.shadowColor; +style.shadowBlur; +style.shadowOffset; +style.selectedColor; +style.fontFamily; +style.fontWeight; +style.fontSize; +style.leading; +style.justification; + + +// +// Color +// + +new paper.Color(0, 0, 0); +new paper.Color(0, 0, 0, 0); +new paper.Color(0); +new paper.Color(0, 0); +new paper.Color(object); +new paper.Color(''); +new paper.Color(gradient, point, point); +new paper.Color(gradient, point, point, point); +color.type; +color.components; +color.alpha; +color.red; +color.green; +color.blue; +color.gray; +color.hue; +color.saturation; +color.brightness; +color.lightness; +color.gradient; +color.highlight; +color.set(0, 0, 0); +color.set(0, 0, 0, 0); +color.set(0); +color.set(0, 0); +color.set(object); +color.set(color); +color.set(gradient, point, point); +color.set(gradient, point, point, point); +color.convert(''); +color.hasAlpha(); +color.equals(color); +color.clone(); +color.toString(); +color.toCSS(true); +color.transform(matrix); +color.add(0); +color.add(color); +color.subtract(0); +color.subtract(color); +color.multiply(0); +color.multiply(color); +color.divide(0); +color.divide(color); +paper.Color.random(); + + +// +// Gradient +// + +gradient.stops; +gradient.radial; +gradient.clone(); +gradient.equals(gradient); + + +// +// GradientStop +// + +new paper.GradientStop(); +new paper.GradientStop(color); +new paper.GradientStop(color, 0); +gradientStop.offset; +gradientStop.color; +gradientStop.clone(); + + +// +// TextItem +// + +textItem.content; +textItem.fontFamily; +textItem.fontWeight; +textItem.fontSize; +textItem.leading; +textItem.justification; + + +// +// PointText +// + +new paper.PointText(point); +new paper.PointText(object); +pointText.point; + + +// +// View +// + +view.autoUpdate; +view.element; +view.pixelRatio; +view.resolution; +view.viewSize; +view.bounds; +view.size; +view.center; +view.zoom; +view.rotation; +view.scaling; +view.matrix; +view.onFrame; +view.onResize; +view.onMouseDown; +view.onMouseDrag; +view.onMouseUp; +view.onClick; +view.onDoubleClick; +view.onMouseMove; +view.onMouseEnter; +view.onMouseLeave; +view.remove(); +view.update(); +view.requestUpdate(); +view.play(); +view.pause(); +view.isVisible(); +view.isInserted(); +view.translate(point); +view.rotate(0); +view.rotate(0, point); +view.scale(0); +view.scale(0, point); +view.scale(0, 0); +view.scale(0, 0, point); +view.shear(point); +view.shear(point, point); +view.shear(0, 0); +view.shear(0, 0, point); +view.skew(point); +view.skew(point, point); +view.skew(0, 0); +view.skew(0, 0, point); +view.transform(matrix); +view.projectToView(point); +view.viewToProject(point); +view.getEventPoint(event); +view.on('', callback); +view.on(object); +view.off('', callback); +view.off(object); +view.emit('', event); +view.responds(''); + + +// +// Event +// + +event.timeStamp; +event.modifiers; +event.preventDefault(); +event.stopPropagation(); +event.stop(); + + +// +// MouseEvent +// + +mouseEvent.type; +mouseEvent.point; +mouseEvent.target; +mouseEvent.currentTarget; +mouseEvent.delta; +mouseEvent.toString(); + + +// +// Tool +// + +tool.minDistance; +tool.maxDistance; +tool.fixedDistance; +tool.onMouseDown; +tool.onMouseDrag; +tool.onMouseMove; +tool.onMouseUp; +tool.onKeyDown; +tool.onKeyUp; +tool.activate(); +tool.remove(); +tool.on('', callback); +tool.on(object); +tool.off('', callback); +tool.off(object); +tool.emit('', event); +tool.responds(''); + + +// +// ToolEvent +// + +toolEvent.type; +toolEvent.point; +toolEvent.lastPoint; +toolEvent.downPoint; +toolEvent.middlePoint; +toolEvent.delta; +toolEvent.count; +toolEvent.item; +toolEvent.toString(); + + +// +// Key +// + +paper.Key.modifiers; +paper.Key.isDown(''); + + +// +// KeyEvent +// + +keyEvent.type; +keyEvent.character; +keyEvent.key; +keyEvent.toString(); + + +// +// PaperScope +// + +new paper.PaperScope(); +paperScope.version; +paperScope.settings; +paperScope.project; +paperScope.projects; +paperScope.view; +paperScope.tool; +paperScope.tools; +paperScope.execute(''); +paperScope.execute('', object); +paperScope.install(object); +paperScope.setup(''); +paperScope.setup({} as HTMLCanvasElement); +paperScope.setup(size); +paperScope.activate(); +paper.PaperScope.get(0); + + +// +// PaperScript +// + +paper.PaperScript.compile(''); +paper.PaperScript.compile('', object); +paper.PaperScript.execute('', paperScope); +paper.PaperScript.execute('', paperScope, object); +paper.PaperScript.load(); +paper.PaperScript.load({} as HTMLScriptElement); diff --git a/package.json b/package.json index 95756b2b..5471766d 100644 --- a/package.json +++ b/package.json @@ -52,6 +52,7 @@ "jshint-summary": "^0.4.0", "merge-stream": "^1.0.0", "minimist": "^1.2.0", + "mustache": "^3.0.1", "prepro": "^2.4.0", "qunitjs": "^1.23.0", "require-dir": "^0.3.0", @@ -59,7 +60,8 @@ "run-sequence": "^1.2.2", "source-map-support": "^0.4.0", "stats.js": "0.16.0", - "straps": "^3.0.1" + "straps": "^3.0.1", + "typescript": "^3.1.6" }, "browser": { "canvas": false, diff --git a/src/basic/Matrix.js b/src/basic/Matrix.js index 6d695445..070578c5 100644 --- a/src/basic/Matrix.js +++ b/src/basic/Matrix.js @@ -104,6 +104,7 @@ var Matrix = Base.extend(/** @lends Matrix# */{ * also work for calls of `set()`. * * @function + * @param {...*} value * @return {Point} */ set: '#initialize', diff --git a/src/basic/Point.js b/src/basic/Point.js index 066be97a..9cc4dfb8 100644 --- a/src/basic/Point.js +++ b/src/basic/Point.js @@ -170,6 +170,7 @@ var Point = Base.extend(/** @lends Point# */{ * for calls of `set()`. * * @function + * @param {...*} value * @return {Point} */ set: '#initialize', diff --git a/src/basic/Rectangle.js b/src/basic/Rectangle.js index 72f93dff..4be507aa 100644 --- a/src/basic/Rectangle.js +++ b/src/basic/Rectangle.js @@ -159,6 +159,7 @@ var Rectangle = Base.extend(/** @lends Rectangle# */{ * constructors also work for calls of `set()`. * * @function + * @param {...*} value * @return {Rectangle} */ set: '#initialize', diff --git a/src/basic/Size.js b/src/basic/Size.js index 219528ab..502276f6 100644 --- a/src/basic/Size.js +++ b/src/basic/Size.js @@ -130,6 +130,7 @@ var Size = Base.extend(/** @lends Size# */{ * for calls of `set()`. * * @function + * @param {...*} value * @return {Size} */ set: '#initialize', diff --git a/src/style/Color.js b/src/style/Color.js index 86c0765c..dfb62a58 100644 --- a/src/style/Color.js +++ b/src/style/Color.js @@ -691,6 +691,7 @@ var Color = Base.extend(new function() { * constructors also work for calls of `set()`. * * @function + * @param {...*} value * @return {Color} */ set: '#initialize',