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

typescript foundation #158

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from 2 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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@ node_modules
package-lock.json
yarn.lock
.vscode
.rpt2_cache
dist
5 changes: 5 additions & 0 deletions global.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
declare namespace jest {
interface Matchers<R> {
toMatchDOM(value: any): CustomMatcherResult
}
}
3 changes: 3 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = {
preset: "ts-jest"
}
52 changes: 27 additions & 25 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,39 +1,41 @@
{
"name": "superfine",
"description": "Minimal view layer for creating declarative web user interfaces.",
"version": "6.0.1",
"main": "dist/superfine.js",
"module": "src/index.js",
"license": "MIT",
"repository": "jorgebucaran/superfine",
"types": "superfine.d.ts",
"files": [
"src",
"dist",
"superfine.d.ts"
],
"author": "Jorge Bucaran",
"description": "Minimal view layer for creating declarative web user interfaces.",
"keywords": [
"superfine",
"frontend",
"virtual dom",
"vdom"
"superfine",
"vdom",
"virtual dom"
],
"repository": "jorgebucaran/superfine",
"license": "MIT",
"author": "Jorge Bucaran",
"files": [
"dist"
],
"main": "dist/superfine.js",
"module": "dist/superfine.mjs",
"types": "dist/superfine.d.ts",
"scripts": {
"test": "jest --coverage --no-cache",
"build": "npm run bundle && npm run minify",
"bundle": "rollup -i src/index.js -o dist/superfine.js -m -f umd -n superfine",
"minify": "terser dist/superfine.js -o dist/superfine.js -mc pure_funcs=['Object.defineProperty'] --source-map includeSources,url=superfine.js.map",
"build": "rollup -c",
"prepare": "npm run build",
"release": "npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish"
"release": "npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish",
"test": "jest --coverage --no-cache"
},
"babel": {
"presets": "env"
"prettier": {
"semi": false
},
"devDependencies": {
"@types/jest": "^23.3.10",
"@types/node": "^10.12.18",
"jest": "^23.6.0",
"rollup": "^0.62.0",
"terser": "^3.13.1",
"babel-preset-env": "^1.7.0"
"rollup": "^0.68.1",
"rollup-plugin-filesize": "^5.0.1",
"rollup-plugin-terser": "^3.0.0",
"rollup-plugin-typescript2": "^0.18.1",
"ts-jest": "^23.10.5",
"tslib": "^1.9.3",
"typescript": "^3.2.2"
}
}
30 changes: 30 additions & 0 deletions rollup.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import typescript from "rollup-plugin-typescript2"
import { terser } from "rollup-plugin-terser"
import filesize from "rollup-plugin-filesize"

export default [
{
input: "src/superfine.ts",
output: {
file: "dist/superfine.mjs",
format: "es"
},
plugins: [
typescript({ tsconfigOverride: { include: ["src"] } }),
filesize()
]
},
{
input: "src/superfine.ts",
output: {
file: "dist/superfine.js",
format: "umd",
name: "superfine"
},
plugins: [
typescript({ tsconfigOverride: { include: ["src"] } }),
terser(),
filesize()
]
}
]
58 changes: 48 additions & 10 deletions src/index.js → src/superfine.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,20 @@
/**
* The vdom representation of an element.
*/
export interface VNode<Props = {}> {
name: string
props?: Props
children?: Array<VNode>
element?: Element | null
key?: string | null
type?: number
}

/**
* Children of a vdom node
*/
export type Children = VNode | string | number | null

var DEFAULT = 0
var RECYCLED_NODE = 1
var TEXT_NODE = 2
Expand Down Expand Up @@ -86,8 +103,8 @@ var createElement = function(node, lifecycle, isSvg) {
node.type === TEXT_NODE
? document.createTextNode(node.name)
: (isSvg = isSvg || node.name === "svg")
? document.createElementNS(SVG_NS, node.name)
: document.createElement(node.name)
? document.createElementNS(SVG_NS, node.name)
: document.createElement(node.name)

var props = node.props
if (props.oncreate) {
Expand Down Expand Up @@ -183,7 +200,7 @@ var patchElement = function(
lastNode,
nextNode,
lifecycle,
isSvg
isSvg?
) {
if (nextNode === lastNode) {
} else if (
Expand Down Expand Up @@ -376,7 +393,7 @@ var createVNode = function(name, props, children, element, key, type) {
}
}

var createTextVNode = function(text, element) {
var createTextVNode = function(text, element?) {
return createVNode(text, EMPTY_OBJECT, EMPTY_ARRAY, element, null, TEXT_NODE)
}

Expand All @@ -397,11 +414,25 @@ var recycleElement = function(element) {
)
}

export var recycle = function(container) {
/**
* Superfine SSR: Create a virtual DOM from your container to patch it on client side
* @param container a DOM element
*/
export var recycle = function(container: Element): VNode {
return recycleElement(container.children[0])
}

export var patch = function(lastNode, nextNode, container) {
/**
* Render a vdom node in DOM element container
* @param lastNode the last vdom node
* @param nextNode the next vdom node
* @param container a DOM element where the new vdom will be rendered
*/
export var patch = function(
lastNode: VNode,
nextNode: VNode,
container: Element
): VNode {
var lifecycle = []

patchElement(container, container.children[0], lastNode, nextNode, lifecycle)
Expand All @@ -411,14 +442,21 @@ export var patch = function(lastNode, nextNode, container) {
return nextNode
}

export var h = function(name, props) {
/**
* create a new vdom node. vdom is a description of what DOM should look like using a tree of virtual nodes.
* @param name name of an element or function that returns vdom node
* @param props HTML props, SVG props, DOM events, lifecycle events and keys
* @param rest child nodes for an element
*/
export var h = function(
name: string | Function,
props?: any,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@mindplay-dk existing definition for h are open to Props being a type. This works ok when declaring TS definitions separately. Any pointers on how I can achieve that using TS definitions in file?

Copy link
Contributor

Choose a reason for hiding this comment

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

The only difference as far as I can figure, is the h function will have a body - other than that, you should be able to just copy and paste from the original .d.ts?

You'll want to exclude the .d.ts from the build (as you do already) and move to emitting a generated .d.ts instead - once you have all the type declarations moved over, the emitted .d.ts should be very close to the hand-written one we have now.

(I'm not sure if that's what you were asking?)

...rest: Array<Children | Children[]>
): VNode {
var node
var rest = []
var children = []
var length = arguments.length

while (length-- > 2) rest.push(arguments[length])

if ((props = props == null ? {} : props).children != null) {
if (rest.length <= 0) {
rest.push(props.children)
Expand Down
50 changes: 0 additions & 50 deletions superfine.d.ts

This file was deleted.

19 changes: 11 additions & 8 deletions test/test.js → test/superfine.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { h, patch, recycle } from "../src/index.js"
import { h, patch, recycle } from "../src/superfine"

beforeEach(() => {
document.body.innerHTML = ""
Expand All @@ -12,12 +12,12 @@ expect.extend({
return node
}, null)

return { pass: true }
return { pass: true, message: "DOM Nodes match" }
}
})

const expectDeepNS = (el, ns) =>
Array.from(el.childNodes).map(child => {
Array.from(el.childNodes).map((child: any) => {
expect(child.namespaceURI).toBe(ns)
expectDeepNS(child, ns)
})
Expand All @@ -29,7 +29,7 @@ const tag = name => (props, children) =>
Array.isArray(props) ? props : children
)

const { div, main, input, ul, li, svg, use } = [
const { div, main, input, ul, li, svg, use }: any = [
"div",
"main",
"input",
Expand Down Expand Up @@ -240,6 +240,7 @@ test("oncreate", () => {
})

test("onupdate", done => {
let node
const view = state =>
div(
{
Expand All @@ -253,7 +254,7 @@ test("onupdate", done => {
state
)

let node = patch(node, view("foo"), document.body)
node = patch(node, view("foo"), document.body)
patch(node, view("bar"), document.body)
})

Expand Down Expand Up @@ -303,6 +304,7 @@ test("ondestroy", done => {

test("onremove/ondestroy", done => {
let destroyed = false
let node

const view = state =>
state
Expand All @@ -322,14 +324,15 @@ test("onremove/ondestroy", done => {
])
: ul([li()])

let node = patch(node, view(true), document.body)
node = patch(node, view(true), document.body)
patch(node, view(false), document.body)
})

test("event bubbling", done => {
let count = 0
let node

const view = state =>
const view = (state?) =>
main(
{
oncreate: () => expect(count++).toBe(3),
Expand All @@ -354,7 +357,7 @@ test("event bubbling", done => {
]
)

let node = patch(node, view(), document.body)
node = patch(node, view(), document.body)
patch(node, view(), document.body)
})

Expand Down
12 changes: 12 additions & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"compilerOptions": {
"declaration": true,
"declarationDir": "dist",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"importHelpers": true,
"module": "es2015",
"moduleResolution": "node",
"target": "es2015"
}
}