diff --git a/.prettierignore b/.prettierignore index c98aab7..001739a 100644 --- a/.prettierignore +++ b/.prettierignore @@ -9,3 +9,6 @@ dist/ # Test files test-data/NoUnnecessarySemicolonsTestInput.ts + +# Files from package for backward compatibility +build-tasks/back-compat diff --git a/build-tasks/back-compat/recommended_ruleset.js b/build-tasks/back-compat/recommended_ruleset.js new file mode 100644 index 0000000..07f7bf6 --- /dev/null +++ b/build-tasks/back-compat/recommended_ruleset.js @@ -0,0 +1,275 @@ +/** + * These rule settings are a broad, general recommendation for a good default configuration. + * This file is exported in the npm/nuget package as ./tslint.json. + */ +module.exports = { + 'rules': { + /** + * Security Rules. The following rules should be turned on because they find security issues + * or are recommended in the Microsoft Secure Development Lifecycle (SDL) + */ + 'insecure-random': true, + 'no-banned-terms': true, + 'no-cookies': true, + 'no-delete-expression': true, + 'no-disable-auto-sanitization': true, + 'no-document-domain': true, + 'no-document-write': true, + 'no-eval': true, + 'no-exec-script': true, + 'no-function-constructor-with-string-args': true, + 'no-http-string': [true, 'http://www.example.com/?.*', 'http://localhost:?.*'], + 'no-inner-html': true, + 'no-octal-literal': true, + 'no-reserved-keywords': true, + 'no-string-based-set-immediate': true, + 'no-string-based-set-interval': true, + 'no-string-based-set-timeout': true, + 'non-literal-fs-path': true, + 'non-literal-require': true, + 'possible-timing-attack': true, + 'react-anchor-blank-noopener': true, + 'react-iframe-missing-sandbox': true, + 'react-no-dangerous-html': true, + + /** + * Common Bugs and Correctness. The following rules should be turned on because they find + * common bug patterns in the code or enforce type safety. + */ + 'await-promise': true, + 'forin': true, + 'jquery-deferred-must-complete': true, + 'label-position': true, + 'match-default-export-name': true, + 'mocha-avoid-only': true, + 'mocha-no-side-effect-code': true, + 'no-any': true, + 'no-arg': true, + 'no-backbone-get-set-outside-model': true, + 'no-bitwise': true, + 'no-conditional-assignment': true, + 'no-console': [true, 'debug', 'info', 'error', 'log', 'time', 'timeEnd', 'trace'], + 'no-constant-condition': true, + 'no-control-regex': true, + 'no-debugger': true, + 'no-duplicate-super': true, + 'no-duplicate-switch-case': true, + 'no-duplicate-variable': true, + 'no-empty': true, + 'no-floating-promises': true, + 'no-for-in-array': true, + 'no-implicit-dependencies': true, + 'no-import-side-effect': true, + 'no-increment-decrement': true, + 'no-invalid-regexp': true, + 'no-invalid-template-strings': true, + 'no-invalid-this': true, + 'no-jquery-raw-elements': true, + 'no-misused-new': true, + 'no-non-null-assertion': true, + 'no-object-literal-type-assertion': true, + 'no-parameter-reassignment': true, + 'no-reference-import': true, + 'no-regex-spaces': true, + 'no-sparse-arrays': true, + 'no-string-literal': true, + 'no-string-throw': true, + 'no-submodule-imports': true, + 'no-unnecessary-bind': true, + 'no-unnecessary-callback-wrapper': true, + 'no-unnecessary-initializer': true, + 'no-unnecessary-override': true, + 'no-unsafe-any': true, + 'no-unsafe-finally': true, + 'no-unused-expression': true, + 'no-use-before-declare': true, + 'no-with-statement': true, + 'promise-function-async': true, + 'promise-must-complete': true, + 'radix': true, + 'react-this-binding-issue': true, + 'react-unused-props-and-state': true, + 'restrict-plus-operands': true, // the plus operand should really only be used for strings and numbers + 'strict-boolean-expressions': true, + 'switch-default': true, + 'switch-final-break': true, + 'triple-equals': [true, 'allow-null-check'], + 'use-isnan': true, + 'use-named-parameter': true, + 'use-simple-attributes': true, + + /** + * Code Clarity. The following rules should be turned on because they make the code + * generally more clear to the reader. + */ + 'adjacent-overload-signatures': true, + 'array-type': [true, 'array'], + 'arrow-parens': false, // for simple functions the parens on arrow functions are not needed + 'ban-comma-operator': true, // possibly controversial + 'binary-expression-operand-order': true, + 'callable-types': true, + 'chai-prefer-contains-to-index-of': true, + 'chai-vague-errors': true, + 'class-name': true, + 'comment-format': true, + 'completed-docs': [true, 'classes'], + 'export-name': true, + 'file-name-casing': true, + 'function-name': true, + 'import-name': true, + 'informative-docs': true, + 'interface-name': true, + 'jsdoc-format': true, + 'max-classes-per-file': [true, 3], // we generally recommend making one public class per file + 'max-file-line-count': true, + 'max-func-body-length': [true, 100, { 'ignore-parameters-to-function-regex': '^describe$' }], + 'max-line-length': [true, 140], + 'member-access': true, + 'member-ordering': [true, { 'order': 'fields-first' }], + 'mocha-unneeded-done': true, + 'new-parens': true, + 'newline-per-chained-call': true, + 'no-construct': true, + 'no-default-export': true, + 'no-duplicate-imports': true, + 'no-dynamic-delete': true, + 'no-empty-interface': true, + 'no-for-in': true, + 'no-function-expression': true, + 'no-inferrable-types': false, // turn no-inferrable-types off in order to make the code consistent in its use of type decorations + 'no-multiline-string': false, + 'no-null-keyword': true, + 'no-parameter-properties': true, + 'no-redundant-jsdoc': true, + 'no-relative-imports': true, + 'no-require-imports': true, + 'no-return-await': true, + 'no-shadowed-variable': true, + 'no-suspicious-comment': true, + 'no-this-assignment': true, + 'no-typeof-undefined': true, + 'no-unnecessary-field-initialization': true, + 'no-unnecessary-local-variable': true, + 'no-unnecessary-qualifier': true, + 'no-unnecessary-type-assertion': true, + 'no-unsupported-browser-code': true, + 'no-useless-files': true, + 'no-var-keyword': true, + 'no-var-requires': true, + 'no-void-expression': true, + 'number-literal-format': true, + 'object-literal-sort-keys': false, // turn object-literal-sort-keys off and sort keys in a meaningful manner + 'one-variable-per-declaration': true, + 'only-arrow-functions': false, // there are many valid reasons to declare a function + 'ordered-imports': true, + 'prefer-array-literal': true, + 'prefer-const': true, + 'prefer-for-of': true, + 'prefer-method-signature': true, + 'prefer-object-spread': true, + 'prefer-readonly': true, + 'prefer-template': true, + 'prefer-while': true, + 'type-literal-delimiter': true, + 'typedef': [true, 'call-signature', 'arrow-call-signature', 'parameter', 'arrow-parameter', 'property-declaration', 'variable-declaration', 'member-variable-declaration'], + 'underscore-consistent-invocation': true, + 'unified-signatures': true, + 'use-default-type-parameter': true, + 'variable-name': true, + + /** + * Accessibility. The following rules should be turned on to guarantee the best user + * experience for keyboard and screen reader users. + */ + 'react-a11y-anchors': true, + 'react-a11y-aria-unsupported-elements': true, + 'react-a11y-event-has-role': true, + 'react-a11y-image-button-has-alt': true, + 'react-a11y-img-has-alt': true, + 'react-a11y-input-elements': true, + 'react-a11y-lang': true, + 'react-a11y-meta': true, + 'react-a11y-no-onchange': true, + 'react-a11y-props': true, + 'react-a11y-proptypes': true, + 'react-a11y-required': true, + 'react-a11y-role': true, + 'react-a11y-role-has-required-aria-props': true, + 'react-a11y-role-supports-aria-props': true, + 'react-a11y-tabindex-no-positive': true, + 'react-a11y-titles': true, + + /** + * Whitespace related rules. The only recommended whitespace strategy is to pick a single format and + * be consistent. + */ + 'align': [true, 'parameters', 'arguments', 'statements'], + 'curly': true, + 'encoding': true, + 'eofline': true, + 'import-spacing': true, + 'indent': [true, 'spaces'], + 'linebreak-style': true, + 'newline-before-return': true, + 'no-consecutive-blank-lines': true, + 'no-empty-line-after-opening-brace': false, + 'no-irregular-whitespace': true, + 'no-single-line-block-comment': true, + 'no-trailing-whitespace': true, + 'no-unnecessary-semicolons': true, + 'object-literal-key-quotes': [true, 'as-needed'], + 'one-line': [true, 'check-open-brace', 'check-catch', 'check-else', 'check-whitespace'], + 'quotemark': [true, 'single'], + 'semicolon': [true, 'always'], + 'space-within-parens': true, + 'trailing-comma': [true, { 'singleline': 'never', 'multiline': 'never' }], // forcing trailing commas for multi-line + // lists results in lists that are easier to reorder and version control diffs that are more clear. + // Many teams like to have multiline be 'always'. There is no clear consensus on this rule but the + // internal MS JavaScript coding standard does discourage it. + 'typedef-whitespace': false, + 'whitespace': [true, 'check-branch', 'check-decl', 'check-operator', 'check-separator', 'check-type'], + + /** + * Controversial/Configurable rules. + */ + 'ban': false, // only enable this if you have some code pattern that you want to ban + 'ban-types': true, + 'cyclomatic-complexity': true, + 'deprecation': false, // deprecated APIs are sometimes unavoidable + 'file-header': false, // enable this rule only if you are legally required to add a file header + 'import-blacklist': false, // enable and configure this as you desire + 'interface-over-type-literal': false, // there are plenty of reasons to prefer interfaces + 'no-angle-bracket-type-assertion': false, // pick either type-cast format and use it consistently + 'no-inferred-empty-object-type': false, // if the compiler is satisfied then this is probably not an issue + 'no-internal-module': false, // only enable this if you are not using internal modules + 'no-magic-numbers': false, // by default it will find too many false positives + 'no-mergeable-namespace': false, // your project may require mergeable namespaces + 'no-namespace': false, // only enable this if you are not using modules/namespaces + 'no-reference': true, // in general you should use a module system and not /// reference imports + 'no-unexternalized-strings': false, // the VS Code team has a specific localization process that this rule enforces + 'object-literal-shorthand': false, // object-literal-shorthand offers an abbreviation not an abstraction + 'prefer-conditional-expression': false, // unnecessarily strict + 'prefer-switch': false, // more of a style preference + 'prefer-type-cast': true, // pick either type-cast format and use it consistently + 'return-undefined': false, // this actually affects the readability of the code + 'space-before-function-paren': false, // turn this on if this is really your coding standard + + /** + * Deprecated rules. The following rules are deprecated for various reasons. + */ + 'missing-jsdoc': false, + 'missing-optional-annotation': false, // now supported by TypeScript compiler + 'no-duplicate-case': false, + 'no-duplicate-parameter-names': false, // now supported by TypeScript compiler + 'no-empty-interfaces': false, // use tslint no-empty-interface rule instead + 'no-missing-visibility-modifiers': false, // use tslint member-access rule instead + 'no-multiple-var-decl': false, // use tslint one-variable-per-declaration rule instead + 'no-stateless-class': false, + 'no-switch-case-fall-through': false, // now supported by TypeScript compiler + 'no-unnecessary-class': true, + 'no-var-self': false, + 'react-tsx-curly-spacing': false, + 'typeof-compare': false, // the valid-typeof rule is currently superior to this version + 'valid-typeof': false, + } +}; diff --git a/build-tasks/back-compat/utils/NoStringParameterToFunctionCallWalker.js b/build-tasks/back-compat/utils/NoStringParameterToFunctionCallWalker.js new file mode 100644 index 0000000..2f43913 --- /dev/null +++ b/build-tasks/back-compat/utils/NoStringParameterToFunctionCallWalker.js @@ -0,0 +1,61 @@ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = function (d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); + } + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var ScopedSymbolTrackingWalker_1 = require("./ScopedSymbolTrackingWalker"); +var AstUtils_1 = require("./AstUtils"); +var NoStringParameterToFunctionCallWalker = (function (_super) { + __extends(NoStringParameterToFunctionCallWalker, _super); + function NoStringParameterToFunctionCallWalker(sourceFile, targetFunctionName, options, program) { + var _this = _super.call(this, sourceFile, options, program) || this; + _this.targetFunctionName = targetFunctionName; + _this.failureString = 'Forbidden ' + targetFunctionName + ' string parameter: '; + return _this; + } + NoStringParameterToFunctionCallWalker.prototype.visitCallExpression = function (node) { + this.validateExpression(node); + _super.prototype.visitCallExpression.call(this, node); + }; + NoStringParameterToFunctionCallWalker.prototype.validateExpression = function (node) { + var functionName = AstUtils_1.AstUtils.getFunctionName(node); + var functionTarget = AstUtils_1.AstUtils.getFunctionTarget(node); + var functionTargetType = this.getFunctionTargetType(node); + var firstArg = node.arguments[0]; + if (functionName === this.targetFunctionName && firstArg !== undefined) { + if (functionTarget) { + if (functionTargetType) { + if (!functionTargetType.match(/^(any|Window|Worker)$/)) { + return; + } + } + else { + if (!functionTarget.match(/^(this|window)$/)) { + return; + } + } + } + if (!this.isExpressionEvaluatingToFunction(firstArg)) { + var msg = this.failureString + + firstArg + .getFullText() + .trim() + .substring(0, 40); + this.addFailureAt(node.getStart(), node.getWidth(), msg); + } + } + }; + return NoStringParameterToFunctionCallWalker; +}(ScopedSymbolTrackingWalker_1.ScopedSymbolTrackingWalker)); +exports.NoStringParameterToFunctionCallWalker = NoStringParameterToFunctionCallWalker; +//# sourceMappingURL=NoStringParameterToFunctionCallWalker.js.map \ No newline at end of file diff --git a/build-tasks/back-compat/utils/ScopedSymbolTrackingWalker.js b/build-tasks/back-compat/utils/ScopedSymbolTrackingWalker.js new file mode 100644 index 0000000..7c4c5ec --- /dev/null +++ b/build-tasks/back-compat/utils/ScopedSymbolTrackingWalker.js @@ -0,0 +1,172 @@ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = function (d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); + } + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var ts = require("typescript"); +var Lint = require("tslint"); +var AstUtils_1 = require("./AstUtils"); +var Scope_1 = require("./Scope"); +var TypeGuard_1 = require("./TypeGuard"); +var ScopedSymbolTrackingWalker = (function (_super) { + __extends(ScopedSymbolTrackingWalker, _super); + function ScopedSymbolTrackingWalker(sourceFile, options, program) { + var _this = _super.call(this, sourceFile, options) || this; + if (program) { + _this.typeChecker = program.getTypeChecker(); + } + return _this; + } + ScopedSymbolTrackingWalker.prototype.getFunctionTargetType = function (expression) { + if (expression.expression.kind === ts.SyntaxKind.PropertyAccessExpression && this.typeChecker) { + var propExp = expression.expression; + var targetType = this.typeChecker.getTypeAtLocation(propExp.expression); + return this.typeChecker.typeToString(targetType); + } + return undefined; + }; + ScopedSymbolTrackingWalker.prototype.isExpressionEvaluatingToFunction = function (expression) { + if (expression.kind === ts.SyntaxKind.ArrowFunction || expression.kind === ts.SyntaxKind.FunctionExpression) { + return true; + } + if (expression.kind === ts.SyntaxKind.StringLiteral || + expression.kind === ts.SyntaxKind.NoSubstitutionTemplateLiteral || + expression.kind === ts.SyntaxKind.TemplateExpression || + expression.kind === ts.SyntaxKind.TaggedTemplateExpression || + expression.kind === ts.SyntaxKind.BinaryExpression) { + return false; + } + if (this.scope !== undefined && this.scope.isFunctionSymbol(expression.getText())) { + return true; + } + if (expression.kind === ts.SyntaxKind.Identifier && this.typeChecker) { + var tsSymbol = this.typeChecker.getSymbolAtLocation(expression); + if (tsSymbol && tsSymbol.flags === ts.SymbolFlags.Function) { + return true; + } + return false; + } + if (ts.isCallExpression(expression)) { + if (TypeGuard_1.isNamed(expression.expression) && expression.expression.name.getText() === 'bind') { + return true; + } + try { + if (!this.typeChecker) { + return true; + } + var signature = this.typeChecker.getResolvedSignature(expression); + if (signature !== undefined) { + var expressionType = this.typeChecker.getReturnTypeOfSignature(signature); + return this.isFunctionType(expressionType, this.typeChecker); + } + } + catch (e) { + return false; + } + } + if (!this.typeChecker) { + return true; + } + return this.isFunctionType(this.typeChecker.getTypeAtLocation(expression), this.typeChecker); + }; + ScopedSymbolTrackingWalker.prototype.isFunctionType = function (expressionType, typeChecker) { + var signatures = typeChecker.getSignaturesOfType(expressionType, ts.SignatureKind.Call); + if (signatures !== undefined && signatures.length > 0) { + var signatureDeclaration = signatures[0].declaration; + if (signatureDeclaration !== undefined && signatureDeclaration.kind === ts.SyntaxKind.FunctionType) { + return true; + } + } + return false; + }; + ScopedSymbolTrackingWalker.prototype.visitSourceFile = function (node) { + this.scope = new Scope_1.Scope(undefined); + this.scope.addGlobalScope(node, node, this.getOptions()); + _super.prototype.visitSourceFile.call(this, node); + this.scope = undefined; + }; + ScopedSymbolTrackingWalker.prototype.visitModuleDeclaration = function (node) { + this.scope = new Scope_1.Scope(this.scope); + this.scope.addGlobalScope(node.body, this.getSourceFile(), this.getOptions()); + _super.prototype.visitModuleDeclaration.call(this, node); + this.scope = this.scope.parent; + }; + ScopedSymbolTrackingWalker.prototype.visitClassDeclaration = function (node) { + var scope = (this.scope = new Scope_1.Scope(this.scope)); + node.members.forEach(function (element) { + var prefix = AstUtils_1.AstUtils.isStatic(element) && node.name !== undefined ? node.name.getText() + '.' : 'this.'; + if (element.kind === ts.SyntaxKind.MethodDeclaration) { + scope.addFunctionSymbol(prefix + element.name.getText()); + } + else if (element.kind === ts.SyntaxKind.PropertyDeclaration) { + var prop = element; + if (AstUtils_1.AstUtils.isDeclarationFunctionType(prop)) { + scope.addFunctionSymbol(prefix + element.name.getText()); + } + else { + scope.addNonFunctionSymbol(prefix + element.name.getText()); + } + } + }); + _super.prototype.visitClassDeclaration.call(this, node); + this.scope = this.scope.parent; + }; + ScopedSymbolTrackingWalker.prototype.visitFunctionDeclaration = function (node) { + this.scope = new Scope_1.Scope(this.scope); + this.scope.addParameters(node.parameters); + _super.prototype.visitFunctionDeclaration.call(this, node); + this.scope = this.scope.parent; + }; + ScopedSymbolTrackingWalker.prototype.visitConstructorDeclaration = function (node) { + this.scope = new Scope_1.Scope(this.scope); + this.scope.addParameters(node.parameters); + _super.prototype.visitConstructorDeclaration.call(this, node); + this.scope = this.scope.parent; + }; + ScopedSymbolTrackingWalker.prototype.visitMethodDeclaration = function (node) { + this.scope = new Scope_1.Scope(this.scope); + this.scope.addParameters(node.parameters); + _super.prototype.visitMethodDeclaration.call(this, node); + this.scope = this.scope.parent; + }; + ScopedSymbolTrackingWalker.prototype.visitArrowFunction = function (node) { + this.scope = new Scope_1.Scope(this.scope); + this.scope.addParameters(node.parameters); + _super.prototype.visitArrowFunction.call(this, node); + this.scope = this.scope.parent; + }; + ScopedSymbolTrackingWalker.prototype.visitFunctionExpression = function (node) { + this.scope = new Scope_1.Scope(this.scope); + this.scope.addParameters(node.parameters); + _super.prototype.visitFunctionExpression.call(this, node); + this.scope = this.scope.parent; + }; + ScopedSymbolTrackingWalker.prototype.visitSetAccessor = function (node) { + this.scope = new Scope_1.Scope(this.scope); + this.scope.addParameters(node.parameters); + _super.prototype.visitSetAccessor.call(this, node); + this.scope = this.scope.parent; + }; + ScopedSymbolTrackingWalker.prototype.visitVariableDeclaration = function (node) { + if (AstUtils_1.AstUtils.isDeclarationFunctionType(node)) { + this.scope.addFunctionSymbol(node.name.getText()); + } + else { + this.scope.addNonFunctionSymbol(node.name.getText()); + } + _super.prototype.visitVariableDeclaration.call(this, node); + }; + return ScopedSymbolTrackingWalker; +}(Lint.RuleWalker)); +exports.ScopedSymbolTrackingWalker = ScopedSymbolTrackingWalker; +//# sourceMappingURL=ScopedSymbolTrackingWalker.js.map \ No newline at end of file diff --git a/build-tasks/copy-config-json.js b/build-tasks/copy-config-json.js index c476f56..823d954 100644 --- a/build-tasks/copy-config-json.js +++ b/build-tasks/copy-config-json.js @@ -19,3 +19,5 @@ mkdirp.sync('./dist/build'); for (const configFileName of readDirectory('./configs')) { copyConfigFile(`./configs/${configFileName}`, `./dist/build/${configFileName}`); } + +copyConfigFile('./configs/legacy.json', './dist/build/tslint.json'); diff --git a/build-tasks/generate-package-json-for-npm.js b/build-tasks/generate-package-json-for-npm.js index 2130649..f185171 100644 --- a/build-tasks/generate-package-json-for-npm.js +++ b/build-tasks/generate-package-json-for-npm.js @@ -6,5 +6,6 @@ const { readJSON, writeFile } = require('./common/files'); const basePackageJson = readJSON('package.json'); delete basePackageJson.devDependencies; +delete basePackageJson.scripts; writeFile('dist/build/package.json', JSON.stringify(basePackageJson, undefined, 4)); diff --git a/configs/legacy.json b/configs/legacy.json index 2cc6175..7665c97 100644 --- a/configs/legacy.json +++ b/configs/legacy.json @@ -184,13 +184,11 @@ "unified-signatures": true, "use-default-type-parameter": true, "variable-name": true, - "void-zero": true, /** * Accessibility. The following rules should be turned on to guarantee the best user * experience for keyboard and screen reader users. */ - "react-a11y-accessible-headings": true, "react-a11y-anchors": true, "react-a11y-aria-unsupported-elements": true, "react-a11y-event-has-role": true, diff --git a/docs/Releases.md b/docs/Releases.md index e5a24a0..8b781c5 100644 --- a/docs/Releases.md +++ b/docs/Releases.md @@ -29,31 +29,12 @@ git push --tags - Create [release](https://github.com/Microsoft/tslint-microsoft-contrib/releases) for newly pushed tag - Increase the version number in package.json and README.md to the next minor version and push -## Prepare the tslint-microsoft-contrib releases branch +## Publish the npm package -- Clone the repo again to a new folder: +Package should be published only from `dist/build` folder. -```shell -git clone https://github.com/Microsoft/tslint-microsoft-contrib tslint-microsoft-contrib-releases -``` +- For beta release run `npm publish --tag beta` -- Checkout branch `releases` +- For stable release run `npm publish` -```shell -git checkout releases -``` - -- Replace all files with the contents of `/dist/build` directory created from `master` -- Commit and push to remote -- tag the releases branch with the format `npm-[version]` - -```shell -git tag npm-2.0.10 -git push --tags -``` - -## Publish the Package with the Microsoft npmjs Account - -- Follow the steps at https://docs.opensource.microsoft.com/releasing/build-your-project.html#npm - - Basically just send the email they want and wait a little while - - Include the npmjs.org user ids of all contributors: brndkfr, hamletdrc, dmanesku, joshuakgoldberg +If you need to promote package from beta to stable use `npm dist-tag add tslint-microsoft-contrib@ latest` diff --git a/package.json b/package.json index 2de1ee6..f81e5ae 100644 --- a/package.json +++ b/package.json @@ -49,6 +49,7 @@ }, "scripts": { "clean": "rimraf dist", + "copy:back-compat": "cpy \"**/*.js\" ../../dist/build --cwd=\"build-tasks/back-compat\" --parents", "copy:config-json": "node build-tasks/copy-config-json.js", "copy:json": "cpy \"src/**/*.json\" dist --parents", "copy:meta": "cpy README.md dist/build --parents", @@ -60,11 +61,12 @@ "generate:package-json-for-npm": "node build-tasks/generate-package-json-for-npm.js", "lint:rules": "tslint -p tsconfig.json -t stylish -c tslint.json -e \"src/tests/**\" \"src/**/*.ts\"", "lint:tests": "tslint -p tsconfig.json -t stylish -c src/tests/tslint.json -e src/tests/references.ts \"src/tests/**/*.ts\"", + "prepublishOnly": "node -e \"throw 'You should not publish package from root directory. Publish from `dist/build` instead'\"", "prettier": "prettier --write \"**/*.{js,ts,tsx,json,md}\"", "start": "npm-run-all clean copy:json watch:src", "test:mocha": "mocha \"dist/src/tests/**/*.js\" --timeout 5000", "test:rules": "tslint -r dist/src --test \"tests/**\"", - "test": "npm-run-all clean copy:json tsc:src test:* tslint:check lint:* validate:* copy:package generate:* copy:meta copy:config-json", + "test": "npm-run-all clean copy:json tsc:src test:* tslint:check lint:* validate:* copy:package generate:* copy:meta copy:config-json copy:back-compat", "tsc:src": "tsc", "tslint:check": "tslint-config-prettier-check ./tslint.json", "validate:documentation": "node build-tasks/validate-documentation.js",