Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generic typescript #4177

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/lazy-cougars-doubt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
slate: minor
---

**The `Node.extractProps` utility is now `Node.props`.** This is just to stay consistent with the rest of the API that uses terse names for getters since they're used so frequently when writing transforms/normalizations.
5 changes: 5 additions & 0 deletions .changeset/light-horses-wink.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
slate: minor
---

**Remove `Element.isElementProps` and `Text.isTextProps`.** These didn't actually do what they promised to do, since they were really check if something was a base `Element` or base `Text` node, and not just a valid props object. So this removes them to not cause confusion. If you need to check if something is a valid props object you will need to implement it in userland because Slate doesn't have awareness of what is valid for you.
5 changes: 5 additions & 0 deletions .changeset/perfect-candles-judge.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
slate: minor
---

**The `Element.isAncestor` method is now `Node.isAncestor`.** This is done to stay consistent, where any node-related helpers that aren't specifically scoped to `Editor`, `Element`, or `Text` nodes are stored in the more general `Node` namespace instead.
47 changes: 9 additions & 38 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,7 @@
"prettier/@typescript-eslint",
"prettier/react"
],
"plugins": [
"@typescript-eslint",
"import",
"react",
"prettier"
],
"plugins": ["@typescript-eslint", "import", "react", "prettier"],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"sourceType": "module",
Expand All @@ -21,12 +16,7 @@
},
"ignorePatterns": ["**/next-env.d.ts"],
"settings": {
"import/extensions": [
".js",
".ts",
".jsx",
".tsx"
],
"import/extensions": [".js", ".ts", ".jsx", ".tsx"],
"react": {
"version": "detect"
}
Expand All @@ -45,10 +35,7 @@
"allowKeywords": true
}
],
"eqeqeq": [
"error",
"smart"
],
"eqeqeq": ["error", "smart"],
"import/default": "error",
"import/export": "error",
"import/first": "error",
Expand All @@ -65,7 +52,6 @@
"import/no-mutable-exports": "error",
"import/no-named-as-default": "error",
"import/no-named-as-default-member": "error",
"import/no-unresolved": "error",
"linebreak-style": "error",
"no-array-constructor": "error",
"no-class-assign": "error",
Expand All @@ -89,7 +75,6 @@
"no-new-object": "error",
"no-new-symbol": "error",
"no-path-concat": "error",
"no-redeclare": "error",
"no-regex-spaces": "error",
"no-sequences": "error",
"no-tabs": "error",
Expand All @@ -106,10 +91,7 @@
"no-var": "error",
"no-void": "error",
"no-with": "error",
"object-shorthand": [
"error",
"always"
],
"object-shorthand": ["error", "always"],
"prefer-arrow-callback": "error",
"prefer-const": [
"error",
Expand All @@ -123,10 +105,7 @@
"prefer-template": "error",
"prettier/prettier": "error",
"radix": "error",
"react/jsx-boolean-value": [
"error",
"never"
],
"react/jsx-boolean-value": ["error", "never"],
"react/jsx-no-duplicate-props": "error",
"react/jsx-no-target-blank": "error",
"react/jsx-no-undef": "error",
Expand All @@ -145,9 +124,7 @@
"error",
"always",
{
"exceptions": [
"-"
]
"exceptions": ["-"]
}
],
"use-isnan": "error",
Expand All @@ -161,14 +138,8 @@
}
],
"valid-typeof": "error",
"yield-star-spacing": [
"error",
"after"
],
"yoda": [
"error",
"never"
]
"yield-star-spacing": ["error", "after"],
"yoda": ["error", "never"]
},
"overrides": [
{
Expand All @@ -179,4 +150,4 @@
}
}
]
}
}
14 changes: 7 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,24 +53,24 @@
"@types/node": "^12.12.14",
"@types/react": "^16.9.13",
"@types/react-dom": "^16.9.4",
"@typescript-eslint/eslint-plugin": "^2.9.0",
"@typescript-eslint/parser": "^2.9.0",
"@typescript-eslint/eslint-plugin": "^4.21.0",
"@typescript-eslint/parser": "^4.21.0",
"babel-eslint": "^10.0.3",
"babel-plugin-dev-expression": "^0.2.2",
"babel-plugin-module-resolver": "^3.1.1",
"cross-env": "6.0.3",
"emotion": "^10.0.9",
"eslint": "^6.7.1",
"eslint-config-prettier": "^6.7.0",
"eslint-plugin-import": "^2.18.2",
"eslint-plugin-prettier": "^3.1.1",
"eslint-plugin-react": "^7.16.0",
"eslint-plugin-import": "^2.22.1",
"eslint-plugin-prettier": "^3.3.1",
"eslint-plugin-react": "^7.23.1",
"faker": "^4.1.0",
"image-extensions": "^1.1.0",
"is-hotkey": "^0.1.6",
"is-url": "^1.2.2",
"lerna": "^3.19.0",
"lint-staged": ">=10",
"lint-staged": "^10.5.4",
"lodash": "^4.17.4",
"mocha": "^6.2.0",
"next": "^9.4.0",
Expand Down Expand Up @@ -99,7 +99,7 @@
"slate-hyperscript": "*",
"slate-react": "*",
"source-map-loader": "^0.2.4",
"typescript": "3.9.7"
"typescript": "^4.2.3"
},
"simple-git-hooks": {
"pre-commit": "yarn lint-staged"
Expand Down
30 changes: 18 additions & 12 deletions packages/slate-history/src/history-editor.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
import { BaseEditor, Editor } from 'slate'
import { Editor, Value } from 'slate'
import { History } from './history'

/**
* Weakmaps for attaching state to the editor.
*/

export const HISTORY = new WeakMap<Editor, History>()
export const SAVING = new WeakMap<Editor, boolean | undefined>()
export const MERGING = new WeakMap<Editor, boolean | undefined>()
export const HISTORY = new WeakMap<HistoryEditor<any>, History>()
export const SAVING = new WeakMap<HistoryEditor<any>, boolean | undefined>()
export const MERGING = new WeakMap<HistoryEditor<any>, boolean | undefined>()

/**
* `HistoryEditor` contains helpers for history-enabled editors.
*/

export interface HistoryEditor extends BaseEditor {
export type HistoryEditor<V extends Value> = Editor<V> & {
history: History
undo: () => void
redo: () => void
Expand All @@ -24,39 +24,39 @@ export const HistoryEditor = {
* Check if a value is a `HistoryEditor` object.
*/

isHistoryEditor(value: any): value is HistoryEditor {
isHistoryEditor(value: any): value is HistoryEditor<Value> {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missed a V extends Value type parameter?

Suggested change
isHistoryEditor(value: any): value is HistoryEditor<Value> {
isHistoryEditor<V extends Value>(value: any): value is HistoryEditor<V> {

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good question. I'm not really sure how to handle the checking functions in general (like Element.isElement, or this one). I'm not sure there's a way to accurately infer V in that case without the user passing it in? And even if they pass it in, the function itself isn't verifying that it objects any sort of value?

return History.isHistory(value.history) && Editor.isEditor(value)
},

/**
* Get the merge flag's current value.
*/

isMerging(editor: HistoryEditor): boolean | undefined {
isMerging<V extends Value>(editor: HistoryEditor<V>): boolean | undefined {
return MERGING.get(editor)
},

/**
* Get the saving flag's current value.
*/

isSaving(editor: HistoryEditor): boolean | undefined {
isSaving<V extends Value>(editor: HistoryEditor<V>): boolean | undefined {
return SAVING.get(editor)
},

/**
* Redo to the previous saved state.
*/

redo(editor: HistoryEditor): void {
redo<V extends Value>(editor: HistoryEditor<V>): void {
editor.redo()
},

/**
* Undo to the previous saved state.
*/

undo(editor: HistoryEditor): void {
undo<V extends Value>(editor: HistoryEditor<V>): void {
editor.undo()
},

Expand All @@ -65,7 +65,10 @@ export const HistoryEditor = {
* the new operations into previous save point in the history.
*/

withoutMerging(editor: HistoryEditor, fn: () => void): void {
withoutMerging<V extends Value>(
editor: HistoryEditor<V>,
fn: () => void
): void {
const prev = HistoryEditor.isMerging(editor)
MERGING.set(editor, false)
fn()
Expand All @@ -77,7 +80,10 @@ export const HistoryEditor = {
* their operations into the history.
*/

withoutSaving(editor: HistoryEditor, fn: () => void): void {
withoutSaving<V extends Value>(
editor: HistoryEditor<V>,
fn: () => void
): void {
const prev = HistoryEditor.isSaving(editor)
SAVING.set(editor, false)
fn()
Expand Down
8 changes: 5 additions & 3 deletions packages/slate-history/src/with-history.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Editor, Operation, Path } from 'slate'
import { Editor, Operation, Path, Value } from 'slate'

import { HistoryEditor } from './history-editor'

Expand All @@ -12,8 +12,10 @@ import { HistoryEditor } from './history-editor'
* See https://docs.slatejs.org/concepts/11-typescript to learn how.
*/

export const withHistory = <T extends Editor>(editor: T) => {
const e = editor as T & HistoryEditor
export const withHistory = <V extends Value, E extends Editor<V>>(
editor: E
): E & HistoryEditor<V> => {
const e = (editor as unknown) as E & HistoryEditor<V>
const { apply } = e
e.history = { undos: [], redos: [] }

Expand Down
3 changes: 2 additions & 1 deletion packages/slate-hyperscript/src/creators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
Text,
Editor,
createEditor as makeEditor,
Value,
} from 'slate'
import {
AnchorToken,
Expand Down Expand Up @@ -221,7 +222,7 @@ export function createEditor(
tagName: string,
attributes: { [key: string]: any },
children: any[]
): Editor {
): Editor<Value> {
const otherChildren: any[] = []
let selectionChild: Range | undefined

Expand Down
3 changes: 2 additions & 1 deletion packages/slate-react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@
"is-plain-object": "^3.0.0",
"lodash": "^4.17.4",
"scroll-into-view-if-needed": "^2.2.20",
"tiny-invariant": "1.0.6"
"tiny-invariant": "^1.0.6",
"tiny-warning": "^1.0.3"
},
"devDependencies": {
"slate": "^0.62.0",
Expand Down
Loading