зеркало из https://github.com/github/remote-form.git
Merge pull request #18 from github/typescript
Convert project to Typescript
This commit is contained in:
Коммит
75043852f4
18
.babelrc
18
.babelrc
|
@ -1,18 +0,0 @@
|
||||||
{
|
|
||||||
"env": {
|
|
||||||
"esm": {
|
|
||||||
"presets": ["github"]
|
|
||||||
},
|
|
||||||
"umd": {
|
|
||||||
"plugins": [
|
|
||||||
["@babel/plugin-transform-modules-umd", {
|
|
||||||
"globals": {
|
|
||||||
"selector-set": "SelectorSet"
|
|
||||||
}
|
|
||||||
}]
|
|
||||||
],
|
|
||||||
"moduleId": "remoteForm",
|
|
||||||
"presets": ["github"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,12 +1,20 @@
|
||||||
{
|
{
|
||||||
|
"parser": "@typescript-eslint/parser",
|
||||||
"extends": [
|
"extends": [
|
||||||
"plugin:github/es6",
|
"plugin:github/es6",
|
||||||
"plugin:github/browser",
|
"plugin:github/browser",
|
||||||
"plugin:github/flow"
|
"plugin:github/typescript"
|
||||||
],
|
],
|
||||||
|
"rules": {
|
||||||
|
"@typescript-eslint/no-non-null-assertion": "off"
|
||||||
|
},
|
||||||
"overrides": [
|
"overrides": [
|
||||||
{
|
{
|
||||||
"files": "test/**/*.js",
|
"files": "test/**/*.js",
|
||||||
|
"parser": "espree",
|
||||||
|
"parserOptions": {
|
||||||
|
"ecmaVersion": 2020
|
||||||
|
},
|
||||||
"rules": {
|
"rules": {
|
||||||
"flowtype/require-valid-file-annotation": "off",
|
"flowtype/require-valid-file-annotation": "off",
|
||||||
"github/unescaped-html-literal": "off",
|
"github/unescaped-html-literal": "off",
|
||||||
|
|
11
.flowconfig
11
.flowconfig
|
@ -1,11 +0,0 @@
|
||||||
[ignore]
|
|
||||||
|
|
||||||
[include]
|
|
||||||
|
|
||||||
[libs]
|
|
||||||
|
|
||||||
[lints]
|
|
||||||
|
|
||||||
[options]
|
|
||||||
|
|
||||||
[strict]
|
|
|
@ -0,0 +1 @@
|
||||||
|
* @github/web-systems-reviewers
|
|
@ -1,32 +0,0 @@
|
||||||
type Kicker = {
|
|
||||||
text: () => Promise<SimpleResponse>,
|
|
||||||
json: () => Promise<SimpleResponse>,
|
|
||||||
html: () => Promise<SimpleResponse>
|
|
||||||
}
|
|
||||||
|
|
||||||
type SimpleRequest = {
|
|
||||||
method: string,
|
|
||||||
url: string,
|
|
||||||
body: FormData | null,
|
|
||||||
headers: Headers
|
|
||||||
}
|
|
||||||
|
|
||||||
export type SimpleResponse = {
|
|
||||||
url: string,
|
|
||||||
status: number,
|
|
||||||
statusText: string,
|
|
||||||
headers: Headers,
|
|
||||||
text: string,
|
|
||||||
json: {[key: string]: any},
|
|
||||||
html: DocumentFragment
|
|
||||||
}
|
|
||||||
|
|
||||||
export type ErrorWithResponse = {
|
|
||||||
response: SimpleResponse
|
|
||||||
}
|
|
||||||
|
|
||||||
export type RemoteFormHandler = (form: HTMLFormElement, kicker: Kicker, req: SimpleRequest) => void | Promise<void>;
|
|
||||||
export function afterRemote(fn: (form: HTMLFormElement) => void | Promise<void>): void;
|
|
||||||
export function beforeRemote(fn: (form: HTMLFormElement) => void | Promise<void>): void;
|
|
||||||
export function remoteForm(selector: string, fn: RemoteFormHandler): void;
|
|
||||||
export function remoteUninstall(selector: string, fn: RemoteFormHandler): void;
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
32
package.json
32
package.json
|
@ -4,24 +4,22 @@
|
||||||
"description": "Decorator that will submit a form over AJAX",
|
"description": "Decorator that will submit a form over AJAX",
|
||||||
"repository": "github/remote-form",
|
"repository": "github/remote-form",
|
||||||
"files": [
|
"files": [
|
||||||
"dist",
|
"dist"
|
||||||
"index.d.ts"
|
|
||||||
],
|
],
|
||||||
"main": "dist/index.umd.js",
|
"main": "dist/index.js",
|
||||||
"module": "dist/index.esm.js",
|
"module": "dist/index.js",
|
||||||
"types:": "index.d.ts",
|
"types:": "dist/index.d.ts",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"clean": "rm -rf dist",
|
"clean": "rm -rf dist",
|
||||||
"lint": "github-lint",
|
"lint": "github-lint",
|
||||||
"prebuild": "npm run clean && npm run lint && mkdir dist",
|
"prebuild": "npm run clean && npm run lint && mkdir dist",
|
||||||
"build-umd": "BABEL_ENV=umd babel src/index.js -o dist/index.umd.js",
|
"build": "tsc",
|
||||||
"build-esm": "BABEL_ENV=esm babel src/index.js -o dist/index.esm.js",
|
|
||||||
"build": "npm run build-umd && npm run build-esm && cp src/index.js.flow dist/index.umd.js.flow && cp src/index.js.flow dist/index.esm.js.flow",
|
|
||||||
"pretest": "npm run build",
|
"pretest": "npm run build",
|
||||||
"test": "karma start test/karma.config.js",
|
"test": "karma start test/karma.config.js",
|
||||||
"prepublishOnly": "npm run build",
|
"prepublishOnly": "npm run build",
|
||||||
"postpublish": "npm publish --ignore-scripts --@github:registry='https://npm.pkg.github.com'"
|
"postpublish": "npm publish --ignore-scripts --@github:registry='https://npm.pkg.github.com'"
|
||||||
},
|
},
|
||||||
|
"prettier": "@github/prettier-config",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"decorator",
|
"decorator",
|
||||||
"remote-form",
|
"remote-form",
|
||||||
|
@ -32,21 +30,17 @@
|
||||||
],
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/cli": "^7.7.0",
|
"@github/prettier-config": "0.0.4",
|
||||||
"@babel/core": "^7.7.0",
|
|
||||||
"@babel/plugin-transform-modules-commonjs": "^7.7.0",
|
|
||||||
"@babel/plugin-transform-modules-umd": "^7.7.0",
|
|
||||||
"babel-preset-github": "^3.2.1",
|
|
||||||
"chai": "^4.2.0",
|
"chai": "^4.2.0",
|
||||||
"eslint": "^6.6.0",
|
"eslint": "^6.8.0",
|
||||||
"eslint-plugin-github": "^3.2.1",
|
"eslint-plugin-github": "^3.4.1",
|
||||||
"flow-bin": "^0.102.0",
|
"karma": "^5.0.2",
|
||||||
"karma": "^4.4.1",
|
|
||||||
"karma-chai": "^0.1.0",
|
"karma-chai": "^0.1.0",
|
||||||
"karma-chrome-launcher": "^3.1.0",
|
"karma-chrome-launcher": "^3.1.0",
|
||||||
"karma-mocha": "^1.3.0",
|
"karma-mocha": "^2.0.0",
|
||||||
"karma-mocha-reporter": "^2.2.5",
|
"karma-mocha-reporter": "^2.2.5",
|
||||||
"mocha": "^6.2.2"
|
"mocha": "^7.1.1",
|
||||||
|
"typescript": "^3.8.3"
|
||||||
},
|
},
|
||||||
"dependencies": {}
|
"dependencies": {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
/* @flow strict */
|
|
||||||
module.exports = require('eslint-plugin-github/prettier.config')
|
|
|
@ -1,30 +0,0 @@
|
||||||
/* @flow strict */
|
|
||||||
|
|
||||||
type Kicker = {
|
|
||||||
text: () => Promise<SimpleResponse>,
|
|
||||||
json: () => Promise<SimpleResponse>,
|
|
||||||
html: () => Promise<SimpleResponse>
|
|
||||||
}
|
|
||||||
|
|
||||||
type SimpleRequest = {
|
|
||||||
method: string,
|
|
||||||
url: string,
|
|
||||||
body: ?FormData,
|
|
||||||
headers: Headers
|
|
||||||
}
|
|
||||||
|
|
||||||
export type SimpleResponse = {
|
|
||||||
url: string,
|
|
||||||
status: number,
|
|
||||||
statusText: string,
|
|
||||||
headers: Headers,
|
|
||||||
text: string,
|
|
||||||
json: {[string]: any},
|
|
||||||
html: DocumentFragment
|
|
||||||
}
|
|
||||||
export type RemoteFormHandler = (form: HTMLFormElement, kicker: Kicker, req: SimpleRequest) => void | Promise<void>;
|
|
||||||
|
|
||||||
declare export function afterRemote(fn: (form: HTMLFormElement) => void | Promise<void>): void;
|
|
||||||
declare export function beforeRemote(fn: (form: HTMLFormElement) => void | Promise<void>): void;
|
|
||||||
declare export function remoteForm(selector: string, fn: RemoteFormHandler): void;
|
|
||||||
declare export function remoteUninstall(selector: string, fn: RemoteFormHandler): void;
|
|
|
@ -1,5 +1,3 @@
|
||||||
/* @flow strict */
|
|
||||||
|
|
||||||
// Parse HTML text into document fragment.
|
// Parse HTML text into document fragment.
|
||||||
function parseHTML(document: Document, html: string): DocumentFragment {
|
function parseHTML(document: Document, html: string): DocumentFragment {
|
||||||
const template = document.createElement('template')
|
const template = document.createElement('template')
|
||||||
|
@ -19,61 +17,59 @@ function serialize(form: HTMLFormElement): string {
|
||||||
class ErrorWithResponse extends Error {
|
class ErrorWithResponse extends Error {
|
||||||
response: SimpleResponse
|
response: SimpleResponse
|
||||||
|
|
||||||
constructor(message, response) {
|
constructor(message: string, response: SimpleResponse) {
|
||||||
super(message)
|
super(message)
|
||||||
this.response = response
|
this.response = response
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function makeDeferred<T>(): [Promise<T>, () => T, () => T] {
|
function makeDeferred<T>(): [Promise<T>, () => void, () => void] {
|
||||||
let resolve
|
let resolve: () => void
|
||||||
let reject
|
let reject: () => void
|
||||||
const promise = new Promise(function (_resolve, _reject) {
|
const promise = new Promise(function (_resolve, _reject) {
|
||||||
resolve = _resolve
|
resolve = _resolve
|
||||||
reject = _reject
|
reject = _reject
|
||||||
})
|
})
|
||||||
|
|
||||||
// eslint-disable-next-line flowtype/no-flow-fix-me-comments
|
return [promise as Promise<T>, resolve!, reject!]
|
||||||
// $FlowFixMe
|
|
||||||
return [promise, resolve, reject]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type SimpleRequest = {
|
interface SimpleRequest {
|
||||||
method: string,
|
method: string
|
||||||
url: string,
|
url: string
|
||||||
body: ?FormData,
|
body: FormData | null
|
||||||
headers: Headers
|
headers: Headers
|
||||||
}
|
}
|
||||||
|
|
||||||
export type SimpleResponse = {
|
export interface SimpleResponse {
|
||||||
url: string,
|
url: string
|
||||||
status: number,
|
status: number
|
||||||
statusText: string,
|
statusText: string
|
||||||
headers: Headers,
|
headers: Headers
|
||||||
text: string,
|
text: string
|
||||||
// eslint-disable-next-line flowtype/no-weak-types
|
json: {[key: string]: unknown}
|
||||||
json: {[string]: any},
|
|
||||||
html: DocumentFragment
|
html: DocumentFragment
|
||||||
}
|
}
|
||||||
|
|
||||||
type Kicker = {
|
interface Kicker {
|
||||||
text: () => Promise<SimpleResponse>,
|
text: () => Promise<SimpleResponse>
|
||||||
json: () => Promise<SimpleResponse>,
|
json: () => Promise<SimpleResponse>
|
||||||
html: () => Promise<SimpleResponse>
|
html: () => Promise<SimpleResponse>
|
||||||
}
|
}
|
||||||
|
|
||||||
export type RemoteFormHandler = (form: HTMLFormElement, kicker: Kicker, req: SimpleRequest) => void
|
export type RemoteFormHandler = (form: HTMLFormElement, kicker: Kicker, req: SimpleRequest) => void
|
||||||
|
|
||||||
let formHandlers: Map<string, RemoteFormHandler[]>
|
let formHandlers: Map<string, RemoteFormHandler[]>
|
||||||
|
type Handler = (form: HTMLFormElement) => void
|
||||||
|
|
||||||
const afterHandlers = []
|
const afterHandlers: Handler[] = []
|
||||||
const beforeHandlers = []
|
const beforeHandlers: Handler[] = []
|
||||||
|
|
||||||
export function afterRemote(fn: (form: HTMLFormElement) => mixed) {
|
export function afterRemote(fn: Handler) {
|
||||||
afterHandlers.push(fn)
|
afterHandlers.push(fn)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function beforeRemote(fn: (form: HTMLFormElement) => mixed) {
|
export function beforeRemote(fn: Handler) {
|
||||||
beforeHandlers.push(fn)
|
beforeHandlers.push(fn)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,7 +85,10 @@ export function remoteForm(selector: string, fn: RemoteFormHandler) {
|
||||||
export function remoteUninstall(selector: string, fn: RemoteFormHandler) {
|
export function remoteUninstall(selector: string, fn: RemoteFormHandler) {
|
||||||
if (formHandlers) {
|
if (formHandlers) {
|
||||||
const handlers = formHandlers.get(selector) || []
|
const handlers = formHandlers.get(selector) || []
|
||||||
formHandlers.set(selector, handlers.filter(x => x !== fn))
|
formHandlers.set(
|
||||||
|
selector,
|
||||||
|
handlers.filter(x => x !== fn)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,11 +114,11 @@ function handleSubmit(event: Event) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const req = buildRequest(form)
|
const req = buildRequest(form)
|
||||||
const [kickerPromise, ultimateResolve, ultimateReject] = makeDeferred()
|
const [kickerPromise, ultimateResolve, ultimateReject] = makeDeferred<SimpleResponse>()
|
||||||
|
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
processHandlers(matches, form, req, kickerPromise).then(
|
processHandlers(matches, form, req, kickerPromise).then(
|
||||||
async performAsyncSubmit => {
|
async (performAsyncSubmit: unknown) => {
|
||||||
if (performAsyncSubmit) {
|
if (performAsyncSubmit) {
|
||||||
for (const handler of beforeHandlers) {
|
for (const handler of beforeHandlers) {
|
||||||
await handler(form)
|
await handler(form)
|
||||||
|
@ -128,6 +127,7 @@ function handleSubmit(event: Event) {
|
||||||
// TODO: ensure that these exceptions are processed by our global error handler
|
// TODO: ensure that these exceptions are processed by our global error handler
|
||||||
remoteSubmit(req)
|
remoteSubmit(req)
|
||||||
.then(ultimateResolve, ultimateReject)
|
.then(ultimateResolve, ultimateReject)
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||||
.catch(() => {})
|
.catch(() => {})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
for (const handler of afterHandlers) {
|
for (const handler of afterHandlers) {
|
||||||
|
@ -139,7 +139,7 @@ function handleSubmit(event: Event) {
|
||||||
form.submit()
|
form.submit()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
err => {
|
(err: Error) => {
|
||||||
// TODO: special "cancel" error object to halt processing and avoid
|
// TODO: special "cancel" error object to halt processing and avoid
|
||||||
// submitting the form
|
// submitting the form
|
||||||
form.submit()
|
form.submit()
|
||||||
|
@ -202,7 +202,7 @@ function buildRequest(form: HTMLFormElement): SimpleRequest {
|
||||||
return req
|
return req
|
||||||
}
|
}
|
||||||
|
|
||||||
async function remoteSubmit(req): Promise<SimpleResponse> {
|
async function remoteSubmit(req: SimpleRequest): Promise<SimpleResponse> {
|
||||||
const response = await window.fetch(req.url, {
|
const response = await window.fetch(req.url, {
|
||||||
method: req.method,
|
method: req.method,
|
||||||
body: req.body !== null ? req.body : undefined,
|
body: req.body !== null ? req.body : undefined,
|
||||||
|
@ -217,7 +217,7 @@ async function remoteSubmit(req): Promise<SimpleResponse> {
|
||||||
headers: response.headers,
|
headers: response.headers,
|
||||||
text: '',
|
text: '',
|
||||||
get json() {
|
get json() {
|
||||||
// eslint-disable-next-line no-shadow
|
// eslint-disable-next-line no-shadow, @typescript-eslint/no-this-alias
|
||||||
const response: SimpleResponse = this
|
const response: SimpleResponse = this
|
||||||
const data = JSON.parse(response.text)
|
const data = JSON.parse(response.text)
|
||||||
delete response.json
|
delete response.json
|
||||||
|
@ -225,7 +225,7 @@ async function remoteSubmit(req): Promise<SimpleResponse> {
|
||||||
return response.json
|
return response.json
|
||||||
},
|
},
|
||||||
get html() {
|
get html() {
|
||||||
// eslint-disable-next-line no-shadow
|
// eslint-disable-next-line no-shadow, @typescript-eslint/no-this-alias
|
||||||
const response: SimpleResponse = this
|
const response: SimpleResponse = this
|
||||||
delete response.html
|
delete response.html
|
||||||
|
|
|
@ -24,7 +24,10 @@ module.exports = function(config) {
|
||||||
config.set({
|
config.set({
|
||||||
basePath: '..',
|
basePath: '..',
|
||||||
frameworks: ['mocha', 'chai'],
|
frameworks: ['mocha', 'chai'],
|
||||||
files: [{pattern: 'dist/index.esm.js', type: 'module'}, {pattern: 'test/test.js', type: 'module'}],
|
files: [
|
||||||
|
{pattern: 'dist/index.js', type: 'module'},
|
||||||
|
{pattern: 'test/test.js', type: 'module'}
|
||||||
|
],
|
||||||
reporters: ['mocha'],
|
reporters: ['mocha'],
|
||||||
port: 9876,
|
port: 9876,
|
||||||
colors: true,
|
colors: true,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import {remoteForm as _remoteForm, remoteUninstall} from '../dist/index.esm.js'
|
import {remoteForm as _remoteForm, remoteUninstall} from '../dist/index.js'
|
||||||
|
|
||||||
describe('remoteForm', function () {
|
describe('remoteForm', function () {
|
||||||
let htmlForm
|
let htmlForm
|
||||||
|
@ -102,6 +102,7 @@ describe('remoteForm', function() {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
}
|
}
|
||||||
const originalMochaError = window.onerror
|
const originalMochaError = window.onerror
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||||
window.onerror = function () {}
|
window.onerror = function () {}
|
||||||
window.addEventListener('error', errorHandler)
|
window.addEventListener('error', errorHandler)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"include": ["src"],
|
||||||
|
"compilerOptions": {
|
||||||
|
"strict": true,
|
||||||
|
"module": "ESNext",
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"lib": ["es6", "dom", "dom.iterable"],
|
||||||
|
"target": "ES2020",
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"declaration": true,
|
||||||
|
"declarationMap": true,
|
||||||
|
"sourceMap": true,
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"rootDir": "src",
|
||||||
|
"outDir": "dist"
|
||||||
|
}
|
||||||
|
}
|
Загрузка…
Ссылка в новой задаче