Skip to content

Commit

Permalink
Typescriptify Phase III ๐Ÿฉ ๐Ÿ• (#741)
Browse files Browse the repository at this point in the history
* RENDERER! 0.2.0 ๐Ÿฉ

* RENDERER! 0.3.0โ€ฆ0.3.2 ๐Ÿ•โ€๐Ÿฆบ

* RENDERER! Index + fix what I broke ๐Ÿฆฎ

* Migrate DOM renderer to TypeScript ๐ŸงŸโ€โ™‚๏ธ
  • Loading branch information
ZeeJab committed Aug 6, 2020
1 parent 9bb0b49 commit ed3dcc2
Show file tree
Hide file tree
Showing 29 changed files with 661 additions and 386 deletions.
12 changes: 0 additions & 12 deletions src/js/cards/image.js

This file was deleted.

17 changes: 17 additions & 0 deletions src/js/cards/image.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import placeholderImageSrc from '../utils/placeholder-image-src'
import { CardData } from '../models/card-node'

interface ImagePayload {
src?: string
}

export default {
name: 'image',
type: 'dom',

render({ payload }: { payload: ImagePayload }) {
let img = document.createElement('img')
img.src = payload.src || placeholderImageSrc
return img
},
} as CardData
10 changes: 10 additions & 0 deletions src/js/models/_has-child-sections.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import LinkedList from '../utils/linked-list'
import Section from './_section'

export default interface HasChildSections<T extends Section = Section> {
sections: LinkedList<T>
}

export function hasChildSections(section: {}): section is HasChildSections {
return 'sections' in section
}
2 changes: 1 addition & 1 deletion src/js/models/_markerable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export default abstract class Markerable extends tagNameable(Section) {

clone(): this {
const newMarkers = this.markers.map(m => m.clone())
return this.builder.createMarkerableSection(this.type, this.tagName, newMarkers) as any as this
return (this.builder.createMarkerableSection(this.type, this.tagName, newMarkers) as any) as this
}

get isBlank() {
Expand Down
5 changes: 4 additions & 1 deletion src/js/models/atom-node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,12 @@ export interface AtomRenderOptions {
payload: {}
}

export type AtomRenderHook = (options: AtomRenderOptions) => Element

export type AtomData = {
name: string
render(options: AtomRenderOptions): Element
type: 'dom'
render: AtomRenderHook
}

export default class AtomNode {
Expand Down
6 changes: 3 additions & 3 deletions src/js/models/atom.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ATOM_TYPE } from './types'
import { Type } from './types'
import Markuperable from '../utils/markuperable'
import assert from '../utils/assert'
import Marker from './marker'
Expand All @@ -7,7 +7,7 @@ import Markup from './markup'
const ATOM_LENGTH = 1

export default class Atom extends Markuperable {
type = ATOM_TYPE
type: Type = Type.ATOM
isAtom = true

name: string
Expand All @@ -25,7 +25,7 @@ export default class Atom extends Markuperable {
this.text = '' // An atom never has text, but it does have a value
assert('Atom must have value', value !== undefined && value !== null)
this.payload = payload
this.type = ATOM_TYPE
this.type = Type.ATOM
this.isMarker = false
this.isAtom = true

Expand Down
10 changes: 7 additions & 3 deletions src/js/models/card-node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,19 @@ import Card, { CardMode } from './card'

export interface CardNodeOptions {}

export type CardRenderHook = (...args: any[]) => Element

type DidRenderCallback = null | (() => void)
type TeardownCallback = null | (() => void)

type RenderMethod = (...args: any[]) => Element
type CardDataType = 'dom'

export interface CardData {
name: string
render: RenderMethod
edit: RenderMethod
type?: CardDataType

render: CardRenderHook
edit?: CardRenderHook
}

type CardRenderMethodName = 'render' | 'edit'
Expand Down
4 changes: 2 additions & 2 deletions src/js/models/image.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { Type } from './types'
import Section from './_section'
import { Option } from '../utils/types'

export default class Image extends Section {
src: string | null = null
src: Option<string> = null

constructor() {
super(Type.IMAGE_SECTION)
this.src = null
}

canJoin() {
Expand Down
2 changes: 1 addition & 1 deletion src/js/models/is-list-section.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import ListSection from "./list-section"
import ListSection from './list-section'

export function isListSection(item: any): item is ListSection {
return 'items' in item && item.items
Expand Down
3 changes: 2 additions & 1 deletion src/js/models/list-section.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@ import assert from '../utils/assert'
import { entries } from '../utils/object-utils'
import ListItem from './list-item'
import { tagNameable } from './_tag-nameable'
import HasChildSections from './_has-child-sections'

export const VALID_LIST_SECTION_TAGNAMES = ['ul', 'ol'].map(normalizeTagName)

export const DEFAULT_TAG_NAME = VALID_LIST_SECTION_TAGNAMES[0]

export default class ListSection extends attributable(tagNameable(Section)) {
export default class ListSection extends attributable(tagNameable(Section)) implements HasChildSections<ListItem> {
isListSection = true
isLeafSection = false

Expand Down
4 changes: 2 additions & 2 deletions src/js/models/marker.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { isArrayEqual } from '../utils/array-utils'
import Markuperable from '../utils/markuperable'
import assert from '../utils/assert'
import { MARKER_TYPE } from './types'
import { Type } from './types'
import Markup from './markup'
import Markerable from './_markerable'
import RenderNode from './render-node'
Expand All @@ -17,7 +17,7 @@ export const HIGH_SURROGATE_RANGE = [0xd800, 0xdbff]
export const LOW_SURROGATE_RANGE = [0xdc00, 0xdfff]

export default class Marker extends Markuperable {
type = MARKER_TYPE
type: Type = Type.MARKER
isMarker = true

value: string
Expand Down
2 changes: 1 addition & 1 deletion src/js/models/markup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export const VALID_ATTRIBUTES = ['href', 'rel']
*/
export default class Markup {
tagName: string
attributes: { [key: string]: unknown }
attributes: { [key: string]: string }

type = MARKUP_TYPE

Expand Down
10 changes: 7 additions & 3 deletions src/js/models/post-node-builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,13 @@ export default class PostNodeBuilder {
return post
}

createMarkerableSection(type: Type.LIST_ITEM, tagName: string, markers: Marker[]): ListItem;
createMarkerableSection(type: Type.MARKUP_SECTION, tagName: string, markers: Marker[]): MarkupSection;
createMarkerableSection(type: Exclude<Type, Type.LIST_ITEM & Type.MARKUP_SECTION>, tagName: string, markers: Marker[]): never;
createMarkerableSection(type: Type.LIST_ITEM, tagName: string, markers: Marker[]): ListItem
createMarkerableSection(type: Type.MARKUP_SECTION, tagName: string, markers: Marker[]): MarkupSection
createMarkerableSection(
type: Exclude<Type, Type.LIST_ITEM & Type.MARKUP_SECTION>,
tagName: string,
markers: Marker[]
): never
createMarkerableSection(type: Type, tagName: string, markers: Marker[] = []) {
switch (type) {
case LIST_ITEM_TYPE:
Expand Down
16 changes: 10 additions & 6 deletions src/js/models/post.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import ListSection, { isListSection } from './list-section'
import ListItem, { isListItem } from './list-item'
import MarkupSection from './markup-section'
import RenderNode from './render-node'
import HasChildSections from './_has-child-sections'

type SectionCallback = (section: Section, index: number) => void

Expand All @@ -24,10 +25,10 @@ type SectionCallback = (section: Section, index: number) => void
* When persisting a post, it must first be serialized (loss-lessly) into
* mobiledoc using {@link Editor#serialize}.
*/
export default class Post {
export default class Post implements HasChildSections {
type = Type.POST
builder!: PostNodeBuilder
sections: LinkedList<any>
sections: LinkedList<Section>
renderNode!: RenderNode

constructor() {
Expand All @@ -45,7 +46,7 @@ export default class Post {
if (this.isBlank) {
return Position.blankPosition()
} else {
return this.sections.head.headPosition()
return this.sections.head!.headPosition()
}
}

Expand All @@ -58,7 +59,7 @@ export default class Post {
if (this.isBlank) {
return Position.blankPosition()
} else {
return this.sections.tail.tailPosition()
return this.sections.tail!.tailPosition()
}
}

Expand All @@ -81,7 +82,7 @@ export default class Post {
* @public
*/
get hasContent(): boolean {
if (this.sections.length > 1 || (this.sections.length === 1 && !this.sections.head.isBlank)) {
if (this.sections.length > 1 || (this.sections.length === 1 && !this.sections.head!.isBlank)) {
return true
} else {
return false
Expand Down Expand Up @@ -235,7 +236,10 @@ export default class Post {
(newSection as MarkupSection | ListItem).markers.append(m)
)
} else {
newSection = tailNotSelected && tail.section === section ? builder.createMarkupSection('p') : expectCloneable(section).clone()
newSection =
tailNotSelected && tail.section === section
? builder.createMarkupSection('p')
: expectCloneable(section).clone()

sectionParent = post
}
Expand Down
14 changes: 7 additions & 7 deletions src/js/models/render-node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import AtomNode from './atom-node'
import Section from './_section'
import Markuperable from '../utils/markuperable'

type PostNode = Section | Markuperable
export type PostNode = Section | Markuperable

export default class RenderNode extends LinkedItem {
export default class RenderNode<T extends Node = Node> extends LinkedItem {
parent: Option<RenderNode> = null
isDirty = true
isRemoved = false
Expand All @@ -20,21 +20,21 @@ export default class RenderNode extends LinkedItem {
renderTree: Option<RenderTree>

// RenderNodes for Markers keep track of their markupElement
markupElement = null
markupElement: Option<Node> = null

// RenderNodes for Atoms use these properties
headTextNode = null
tailTextNode = null
headTextNode: Option<Text> = null
tailTextNode: Option<Text> = null
atomNode: Option<AtomNode> = null

// RenderNodes for cards use this property
cardNode: Option<CardNode> = null

_childNodes: Option<LinkedList<RenderNode>> = null
_element: Option<Node> = null
_element: Option<T> = null
_cursorElement: Option<Node> = null // blank render nodes need a cursor element

constructor(postNode: Section, renderTree: RenderTree) {
constructor(postNode: PostNode, renderTree: RenderTree) {
super()
this.postNode = postNode
this.renderTree = renderTree
Expand Down
4 changes: 2 additions & 2 deletions src/js/models/render-tree.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import RenderNode from '../models/render-node'
import RenderNode, { PostNode } from '../models/render-node'
import ElementMap from '../utils/element-map'
import Section from './_section'

Expand Down Expand Up @@ -69,7 +69,7 @@ export default class RenderTree {
}
}

buildRenderNode(postNode: Section) {
buildRenderNode(postNode: PostNode) {
const renderNode = new RenderNode(postNode, this)
postNode.renderNode = renderNode
return renderNode
Expand Down
2 changes: 1 addition & 1 deletion src/js/models/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,5 @@ export const enum Type {
LIST_ITEM = 'list-item',
CARD = 'card-section',
IMAGE_SECTION = 'image-section',
ATOM = 'atom'
ATOM = 'atom',
}
Loading

0 comments on commit ed3dcc2

Please sign in to comment.