From 35d70443bedf842151bf00666006cc07856b38af Mon Sep 17 00:00:00 2001 From: Gregorio Chiko Putra Date: Tue, 26 Sep 2017 16:28:18 +0700 Subject: [PATCH 1/5] Added mithril.js on new branch mithril --- App/Controllers/Home.php | 5 + App/Views/Data/mithril.html | 38 ++ App/Views/base.html | 1 + public/js/mithril.js | 1242 +++++++++++++++++++++++++++++++++++ 4 files changed, 1286 insertions(+) create mode 100644 App/Views/Data/mithril.html create mode 100644 public/js/mithril.js diff --git a/App/Controllers/Home.php b/App/Controllers/Home.php index 0040cd4..76a60e6 100644 --- a/App/Controllers/Home.php +++ b/App/Controllers/Home.php @@ -175,4 +175,9 @@ class Home } return true; } + + // Branch mithril test + public function mithril() { + View::render('Data/mithril.html'); + } } diff --git a/App/Views/Data/mithril.html b/App/Views/Data/mithril.html new file mode 100644 index 0000000..3848421 --- /dev/null +++ b/App/Views/Data/mithril.html @@ -0,0 +1,38 @@ +{% extends "base.html" %} + +{% block title %}Mithril{% endblock %} + +{% block body %} +
+
+
+
+ +{% endblock %} diff --git a/App/Views/base.html b/App/Views/base.html index 1983ab9..0481b1e 100644 --- a/App/Views/base.html +++ b/App/Views/base.html @@ -210,6 +210,7 @@ + {% block body %} {% endblock %} diff --git a/public/js/mithril.js b/public/js/mithril.js new file mode 100644 index 0000000..3b0d05b --- /dev/null +++ b/public/js/mithril.js @@ -0,0 +1,1242 @@ +;(function() { +"use strict" +function Vnode(tag, key, attrs0, children, text, dom) { + return {tag: tag, key: key, attrs: attrs0, children: children, text: text, dom: dom, domSize: undefined, state: undefined, _state: undefined, events: undefined, instance: undefined, skip: false} +} +Vnode.normalize = function(node) { + if (Array.isArray(node)) return Vnode("[", undefined, undefined, Vnode.normalizeChildren(node), undefined, undefined) + if (node != null && typeof node !== "object") return Vnode("#", undefined, undefined, node === false ? "" : node, undefined, undefined) + return node +} +Vnode.normalizeChildren = function normalizeChildren(children) { + for (var i = 0; i < children.length; i++) { + children[i] = Vnode.normalize(children[i]) + } + return children +} +var selectorParser = /(?:(^|#|\.)([^#\.\[\]]+))|(\[(.+?)(?:\s*=\s*("|'|)((?:\\["'\]]|.)*?)\5)?\])/g +var selectorCache = {} +var hasOwn = {}.hasOwnProperty +function compileSelector(selector) { + var match, tag = "div", classes = [], attrs = {} + while (match = selectorParser.exec(selector)) { + var type = match[1], value = match[2] + if (type === "" && value !== "") tag = value + else if (type === "#") attrs.id = value + else if (type === ".") classes.push(value) + else if (match[3][0] === "[") { + var attrValue = match[6] + if (attrValue) attrValue = attrValue.replace(/\\(["'])/g, "$1").replace(/\\\\/g, "\\") + if (match[4] === "class") classes.push(attrValue) + else attrs[match[4]] = attrValue === "" ? attrValue : attrValue || true + } + } + if (classes.length > 0) attrs.className = classes.join(" ") + return selectorCache[selector] = {tag: tag, attrs: attrs} +} +function execSelector(state, attrs, children) { + var hasAttrs = false, childList, text + var className = attrs.className || attrs.class + for (var key in state.attrs) { + if (hasOwn.call(state.attrs, key)) { + attrs[key] = state.attrs[key] + } + } + if (className !== undefined) { + if (attrs.class !== undefined) { + attrs.class = undefined + attrs.className = className + } + if (state.attrs.className != null) { + attrs.className = state.attrs.className + " " + className + } + } + for (var key in attrs) { + if (hasOwn.call(attrs, key) && key !== "key") { + hasAttrs = true + break + } + } + if (Array.isArray(children) && children.length === 1 && children[0] != null && children[0].tag === "#") { + text = children[0].children + } else { + childList = children + } + return Vnode(state.tag, attrs.key, hasAttrs ? attrs : undefined, childList, text) +} +function hyperscript(selector) { + // Because sloppy mode sucks + var attrs = arguments[1], start = 2, children + if (selector == null || typeof selector !== "string" && typeof selector !== "function" && typeof selector.view !== "function") { + throw Error("The selector must be either a string or a component."); + } + if (typeof selector === "string") { + var cached = selectorCache[selector] || compileSelector(selector) + } + if (attrs == null) { + attrs = {} + } else if (typeof attrs !== "object" || attrs.tag != null || Array.isArray(attrs)) { + attrs = {} + start = 1 + } + if (arguments.length === start + 1) { + children = arguments[start] + if (!Array.isArray(children)) children = [children] + } else { + children = [] + while (start < arguments.length) children.push(arguments[start++]) + } + var normalized = Vnode.normalizeChildren(children) + if (typeof selector === "string") { + return execSelector(cached, attrs, normalized) + } else { + return Vnode(selector, attrs.key, attrs, normalized) + } +} +hyperscript.trust = function(html) { + if (html == null) html = "" + return Vnode("<", undefined, undefined, html, undefined, undefined) +} +hyperscript.fragment = function(attrs1, children) { + return Vnode("[", attrs1.key, attrs1, Vnode.normalizeChildren(children), undefined, undefined) +} +var m = hyperscript +/** @constructor */ +var PromisePolyfill = function(executor) { + if (!(this instanceof PromisePolyfill)) throw new Error("Promise must be called with `new`") + if (typeof executor !== "function") throw new TypeError("executor must be a function") + var self = this, resolvers = [], rejectors = [], resolveCurrent = handler(resolvers, true), rejectCurrent = handler(rejectors, false) + var instance = self._instance = {resolvers: resolvers, rejectors: rejectors} + var callAsync = typeof setImmediate === "function" ? setImmediate : setTimeout + function handler(list, shouldAbsorb) { + return function execute(value) { + var then + try { + if (shouldAbsorb && value != null && (typeof value === "object" || typeof value === "function") && typeof (then = value.then) === "function") { + if (value === self) throw new TypeError("Promise can't be resolved w/ itself") + executeOnce(then.bind(value)) + } + else { + callAsync(function() { + if (!shouldAbsorb && list.length === 0) console.error("Possible unhandled promise rejection:", value) + for (var i = 0; i < list.length; i++) list[i](value) + resolvers.length = 0, rejectors.length = 0 + instance.state = shouldAbsorb + instance.retry = function() {execute(value)} + }) + } + } + catch (e) { + rejectCurrent(e) + } + } + } + function executeOnce(then) { + var runs = 0 + function run(fn) { + return function(value) { + if (runs++ > 0) return + fn(value) + } + } + var onerror = run(rejectCurrent) + try {then(run(resolveCurrent), onerror)} catch (e) {onerror(e)} + } + executeOnce(executor) +} +PromisePolyfill.prototype.then = function(onFulfilled, onRejection) { + var self = this, instance = self._instance + function handle(callback, list, next, state) { + list.push(function(value) { + if (typeof callback !== "function") next(value) + else try {resolveNext(callback(value))} catch (e) {if (rejectNext) rejectNext(e)} + }) + if (typeof instance.retry === "function" && state === instance.state) instance.retry() + } + var resolveNext, rejectNext + var promise = new PromisePolyfill(function(resolve, reject) {resolveNext = resolve, rejectNext = reject}) + handle(onFulfilled, instance.resolvers, resolveNext, true), handle(onRejection, instance.rejectors, rejectNext, false) + return promise +} +PromisePolyfill.prototype.catch = function(onRejection) { + return this.then(null, onRejection) +} +PromisePolyfill.resolve = function(value) { + if (value instanceof PromisePolyfill) return value + return new PromisePolyfill(function(resolve) {resolve(value)}) +} +PromisePolyfill.reject = function(value) { + return new PromisePolyfill(function(resolve, reject) {reject(value)}) +} +PromisePolyfill.all = function(list) { + return new PromisePolyfill(function(resolve, reject) { + var total = list.length, count = 0, values = [] + if (list.length === 0) resolve([]) + else for (var i = 0; i < list.length; i++) { + (function(i) { + function consume(value) { + count++ + values[i] = value + if (count === total) resolve(values) + } + if (list[i] != null && (typeof list[i] === "object" || typeof list[i] === "function") && typeof list[i].then === "function") { + list[i].then(consume, reject) + } + else consume(list[i]) + })(i) + } + }) +} +PromisePolyfill.race = function(list) { + return new PromisePolyfill(function(resolve, reject) { + for (var i = 0; i < list.length; i++) { + list[i].then(resolve, reject) + } + }) +} +if (typeof window !== "undefined") { + if (typeof window.Promise === "undefined") window.Promise = PromisePolyfill + var PromisePolyfill = window.Promise +} else if (typeof global !== "undefined") { + if (typeof global.Promise === "undefined") global.Promise = PromisePolyfill + var PromisePolyfill = global.Promise +} else { +} +var buildQueryString = function(object) { + if (Object.prototype.toString.call(object) !== "[object Object]") return "" + var args = [] + for (var key0 in object) { + destructure(key0, object[key0]) + } + return args.join("&") + function destructure(key0, value) { + if (Array.isArray(value)) { + for (var i = 0; i < value.length; i++) { + destructure(key0 + "[" + i + "]", value[i]) + } + } + else if (Object.prototype.toString.call(value) === "[object Object]") { + for (var i in value) { + destructure(key0 + "[" + i + "]", value[i]) + } + } + else args.push(encodeURIComponent(key0) + (value != null && value !== "" ? "=" + encodeURIComponent(value) : "")) + } +} +var FILE_PROTOCOL_REGEX = new RegExp("^file://", "i") +var _8 = function($window, Promise) { + var callbackCount = 0 + var oncompletion + function setCompletionCallback(callback) {oncompletion = callback} + function finalizer() { + var count = 0 + function complete() {if (--count === 0 && typeof oncompletion === "function") oncompletion()} + return function finalize(promise0) { + var then0 = promise0.then + promise0.then = function() { + count++ + var next = then0.apply(promise0, arguments) + next.then(complete, function(e) { + complete() + if (count === 0) throw e + }) + return finalize(next) + } + return promise0 + } + } + function normalize(args, extra) { + if (typeof args === "string") { + var url = args + args = extra || {} + if (args.url == null) args.url = url + } + return args + } + function request(args, extra) { + var finalize = finalizer() + args = normalize(args, extra) + var promise0 = new Promise(function(resolve, reject) { + if (args.method == null) args.method = "GET" + args.method = args.method.toUpperCase() + var useBody = (args.method === "GET" || args.method === "TRACE") ? false : (typeof args.useBody === "boolean" ? args.useBody : true) + if (typeof args.serialize !== "function") args.serialize = typeof FormData !== "undefined" && args.data instanceof FormData ? function(value) {return value} : JSON.stringify + if (typeof args.deserialize !== "function") args.deserialize = deserialize + if (typeof args.extract !== "function") args.extract = extract + args.url = interpolate(args.url, args.data) + if (useBody) args.data = args.serialize(args.data) + else args.url = assemble(args.url, args.data) + var xhr = new $window.XMLHttpRequest(), + aborted = false, + _abort = xhr.abort + xhr.abort = function abort() { + aborted = true + _abort.call(xhr) + } + xhr.open(args.method, args.url, typeof args.async === "boolean" ? args.async : true, typeof args.user === "string" ? args.user : undefined, typeof args.password === "string" ? args.password : undefined) + if (args.serialize === JSON.stringify && useBody) { + xhr.setRequestHeader("Content-Type", "application/json; charset=utf-8") + } + if (args.deserialize === deserialize) { + xhr.setRequestHeader("Accept", "application/json, text/*") + } + if (args.withCredentials) xhr.withCredentials = args.withCredentials + for (var key in args.headers) if ({}.hasOwnProperty.call(args.headers, key)) { + xhr.setRequestHeader(key, args.headers[key]) + } + if (typeof args.config === "function") xhr = args.config(xhr, args) || xhr + xhr.onreadystatechange = function() { + // Don't throw errors on xhr.abort(). + if(aborted) return + if (xhr.readyState === 4) { + try { + var response = (args.extract !== extract) ? args.extract(xhr, args) : args.deserialize(args.extract(xhr, args)) + if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304 || FILE_PROTOCOL_REGEX.test(args.url)) { + resolve(cast(args.type, response)) + } + else { + var error = new Error(xhr.responseText) + for (var key in response) error[key] = response[key] + reject(error) + } + } + catch (e) { + reject(e) + } + } + } + if (useBody && (args.data != null)) xhr.send(args.data) + else xhr.send() + }) + return args.background === true ? promise0 : finalize(promise0) + } + function jsonp(args, extra) { + var finalize = finalizer() + args = normalize(args, extra) + var promise0 = new Promise(function(resolve, reject) { + var callbackName = args.callbackName || "_mithril_" + Math.round(Math.random() * 1e16) + "_" + callbackCount++ + var script = $window.document.createElement("script") + $window[callbackName] = function(data) { + script.parentNode.removeChild(script) + resolve(cast(args.type, data)) + delete $window[callbackName] + } + script.onerror = function() { + script.parentNode.removeChild(script) + reject(new Error("JSONP request failed")) + delete $window[callbackName] + } + if (args.data == null) args.data = {} + args.url = interpolate(args.url, args.data) + args.data[args.callbackKey || "callback"] = callbackName + script.src = assemble(args.url, args.data) + $window.document.documentElement.appendChild(script) + }) + return args.background === true? promise0 : finalize(promise0) + } + function interpolate(url, data) { + if (data == null) return url + var tokens = url.match(/:[^\/]+/gi) || [] + for (var i = 0; i < tokens.length; i++) { + var key = tokens[i].slice(1) + if (data[key] != null) { + url = url.replace(tokens[i], data[key]) + } + } + return url + } + function assemble(url, data) { + var querystring = buildQueryString(data) + if (querystring !== "") { + var prefix = url.indexOf("?") < 0 ? "?" : "&" + url += prefix + querystring + } + return url + } + function deserialize(data) { + try {return data !== "" ? JSON.parse(data) : null} + catch (e) {throw new Error(data)} + } + function extract(xhr) {return xhr.responseText} + function cast(type0, data) { + if (typeof type0 === "function") { + if (Array.isArray(data)) { + for (var i = 0; i < data.length; i++) { + data[i] = new type0(data[i]) + } + } + else return new type0(data) + } + return data + } + return {request: request, jsonp: jsonp, setCompletionCallback: setCompletionCallback} +} +var requestService = _8(window, PromisePolyfill) +var coreRenderer = function($window) { + var $doc = $window.document + var $emptyFragment = $doc.createDocumentFragment() + var nameSpace = { + svg: "http://www.w3.org/2000/svg", + math: "http://www.w3.org/1998/Math/MathML" + } + var onevent + function setEventCallback(callback) {return onevent = callback} + function getNameSpace(vnode) { + return vnode.attrs && vnode.attrs.xmlns || nameSpace[vnode.tag] + } + //create + function createNodes(parent, vnodes, start, end, hooks, nextSibling, ns) { + for (var i = start; i < end; i++) { + var vnode = vnodes[i] + if (vnode != null) { + createNode(parent, vnode, hooks, ns, nextSibling) + } + } + } + function createNode(parent, vnode, hooks, ns, nextSibling) { + var tag = vnode.tag + if (typeof tag === "string") { + vnode.state = {} + if (vnode.attrs != null) initLifecycle(vnode.attrs, vnode, hooks) + switch (tag) { + case "#": return createText(parent, vnode, nextSibling) + case "<": return createHTML(parent, vnode, nextSibling) + case "[": return createFragment(parent, vnode, hooks, ns, nextSibling) + default: return createElement(parent, vnode, hooks, ns, nextSibling) + } + } + else return createComponent(parent, vnode, hooks, ns, nextSibling) + } + function createText(parent, vnode, nextSibling) { + vnode.dom = $doc.createTextNode(vnode.children) + insertNode(parent, vnode.dom, nextSibling) + return vnode.dom + } + function createHTML(parent, vnode, nextSibling) { + var match1 = vnode.children.match(/^\s*?<(\w+)/im) || [] + var parent1 = {caption: "table", thead: "table", tbody: "table", tfoot: "table", tr: "tbody", th: "tr", td: "tr", colgroup: "table", col: "colgroup"}[match1[1]] || "div" + var temp = $doc.createElement(parent1) + temp.innerHTML = vnode.children + vnode.dom = temp.firstChild + vnode.domSize = temp.childNodes.length + var fragment = $doc.createDocumentFragment() + var child + while (child = temp.firstChild) { + fragment.appendChild(child) + } + insertNode(parent, fragment, nextSibling) + return fragment + } + function createFragment(parent, vnode, hooks, ns, nextSibling) { + var fragment = $doc.createDocumentFragment() + if (vnode.children != null) { + var children = vnode.children + createNodes(fragment, children, 0, children.length, hooks, null, ns) + } + vnode.dom = fragment.firstChild + vnode.domSize = fragment.childNodes.length + insertNode(parent, fragment, nextSibling) + return fragment + } + function createElement(parent, vnode, hooks, ns, nextSibling) { + var tag = vnode.tag + var attrs2 = vnode.attrs + var is = attrs2 && attrs2.is + ns = getNameSpace(vnode) || ns + var element = ns ? + is ? $doc.createElementNS(ns, tag, {is: is}) : $doc.createElementNS(ns, tag) : + is ? $doc.createElement(tag, {is: is}) : $doc.createElement(tag) + vnode.dom = element + if (attrs2 != null) { + setAttrs(vnode, attrs2, ns) + } + insertNode(parent, element, nextSibling) + if (vnode.attrs != null && vnode.attrs.contenteditable != null) { + setContentEditable(vnode) + } + else { + if (vnode.text != null) { + if (vnode.text !== "") element.textContent = vnode.text + else vnode.children = [Vnode("#", undefined, undefined, vnode.text, undefined, undefined)] + } + if (vnode.children != null) { + var children = vnode.children + createNodes(element, children, 0, children.length, hooks, null, ns) + setLateAttrs(vnode) + } + } + return element + } + function initComponent(vnode, hooks) { + var sentinel + if (typeof vnode.tag.view === "function") { + vnode.state = Object.create(vnode.tag) + sentinel = vnode.state.view + if (sentinel.$$reentrantLock$$ != null) return $emptyFragment + sentinel.$$reentrantLock$$ = true + } else { + vnode.state = void 0 + sentinel = vnode.tag + if (sentinel.$$reentrantLock$$ != null) return $emptyFragment + sentinel.$$reentrantLock$$ = true + vnode.state = (vnode.tag.prototype != null && typeof vnode.tag.prototype.view === "function") ? new vnode.tag(vnode) : vnode.tag(vnode) + } + vnode._state = vnode.state + if (vnode.attrs != null) initLifecycle(vnode.attrs, vnode, hooks) + initLifecycle(vnode._state, vnode, hooks) + vnode.instance = Vnode.normalize(vnode._state.view.call(vnode.state, vnode)) + if (vnode.instance === vnode) throw Error("A view cannot return the vnode it received as argument") + sentinel.$$reentrantLock$$ = null + } + function createComponent(parent, vnode, hooks, ns, nextSibling) { + initComponent(vnode, hooks) + if (vnode.instance != null) { + var element = createNode(parent, vnode.instance, hooks, ns, nextSibling) + vnode.dom = vnode.instance.dom + vnode.domSize = vnode.dom != null ? vnode.instance.domSize : 0 + insertNode(parent, element, nextSibling) + return element + } + else { + vnode.domSize = 0 + return $emptyFragment + } + } + //update + function updateNodes(parent, old, vnodes, recycling, hooks, nextSibling, ns) { + if (old === vnodes || old == null && vnodes == null) return + else if (old == null) createNodes(parent, vnodes, 0, vnodes.length, hooks, nextSibling, ns) + else if (vnodes == null) removeNodes(old, 0, old.length, vnodes) + else { + if (old.length === vnodes.length) { + var isUnkeyed = false + for (var i = 0; i < vnodes.length; i++) { + if (vnodes[i] != null && old[i] != null) { + isUnkeyed = vnodes[i].key == null && old[i].key == null + break + } + } + if (isUnkeyed) { + for (var i = 0; i < old.length; i++) { + if (old[i] === vnodes[i]) continue + else if (old[i] == null && vnodes[i] != null) createNode(parent, vnodes[i], hooks, ns, getNextSibling(old, i + 1, nextSibling)) + else if (vnodes[i] == null) removeNodes(old, i, i + 1, vnodes) + else updateNode(parent, old[i], vnodes[i], hooks, getNextSibling(old, i + 1, nextSibling), recycling, ns) + } + return + } + } + recycling = recycling || isRecyclable(old, vnodes) + if (recycling) { + var pool = old.pool + old = old.concat(old.pool) + } + var oldStart = 0, start = 0, oldEnd = old.length - 1, end = vnodes.length - 1, map + while (oldEnd >= oldStart && end >= start) { + var o = old[oldStart], v = vnodes[start] + if (o === v && !recycling) oldStart++, start++ + else if (o == null) oldStart++ + else if (v == null) start++ + else if (o.key === v.key) { + var shouldRecycle = (pool != null && oldStart >= old.length - pool.length) || ((pool == null) && recycling) + oldStart++, start++ + updateNode(parent, o, v, hooks, getNextSibling(old, oldStart, nextSibling), shouldRecycle, ns) + if (recycling && o.tag === v.tag) insertNode(parent, toFragment(o), nextSibling) + } + else { + var o = old[oldEnd] + if (o === v && !recycling) oldEnd--, start++ + else if (o == null) oldEnd-- + else if (v == null) start++ + else if (o.key === v.key) { + var shouldRecycle = (pool != null && oldEnd >= old.length - pool.length) || ((pool == null) && recycling) + updateNode(parent, o, v, hooks, getNextSibling(old, oldEnd + 1, nextSibling), shouldRecycle, ns) + if (recycling || start < end) insertNode(parent, toFragment(o), getNextSibling(old, oldStart, nextSibling)) + oldEnd--, start++ + } + else break + } + } + while (oldEnd >= oldStart && end >= start) { + var o = old[oldEnd], v = vnodes[end] + if (o === v && !recycling) oldEnd--, end-- + else if (o == null) oldEnd-- + else if (v == null) end-- + else if (o.key === v.key) { + var shouldRecycle = (pool != null && oldEnd >= old.length - pool.length) || ((pool == null) && recycling) + updateNode(parent, o, v, hooks, getNextSibling(old, oldEnd + 1, nextSibling), shouldRecycle, ns) + if (recycling && o.tag === v.tag) insertNode(parent, toFragment(o), nextSibling) + if (o.dom != null) nextSibling = o.dom + oldEnd--, end-- + } + else { + if (!map) map = getKeyMap(old, oldEnd) + if (v != null) { + var oldIndex = map[v.key] + if (oldIndex != null) { + var movable = old[oldIndex] + var shouldRecycle = (pool != null && oldIndex >= old.length - pool.length) || ((pool == null) && recycling) + updateNode(parent, movable, v, hooks, getNextSibling(old, oldEnd + 1, nextSibling), recycling, ns) + insertNode(parent, toFragment(movable), nextSibling) + old[oldIndex].skip = true + if (movable.dom != null) nextSibling = movable.dom + } + else { + var dom = createNode(parent, v, hooks, ns, nextSibling) + nextSibling = dom + } + } + end-- + } + if (end < start) break + } + createNodes(parent, vnodes, start, end + 1, hooks, nextSibling, ns) + removeNodes(old, oldStart, oldEnd + 1, vnodes) + } + } + function updateNode(parent, old, vnode, hooks, nextSibling, recycling, ns) { + var oldTag = old.tag, tag = vnode.tag + if (oldTag === tag) { + vnode.state = old.state + vnode._state = old._state + vnode.events = old.events + if (!recycling && shouldNotUpdate(vnode, old)) return + if (typeof oldTag === "string") { + if (vnode.attrs != null) { + if (recycling) { + vnode.state = {} + initLifecycle(vnode.attrs, vnode, hooks) + } + else updateLifecycle(vnode.attrs, vnode, hooks) + } + switch (oldTag) { + case "#": updateText(old, vnode); break + case "<": updateHTML(parent, old, vnode, nextSibling); break + case "[": updateFragment(parent, old, vnode, recycling, hooks, nextSibling, ns); break + default: updateElement(old, vnode, recycling, hooks, ns) + } + } + else updateComponent(parent, old, vnode, hooks, nextSibling, recycling, ns) + } + else { + removeNode(old, null) + createNode(parent, vnode, hooks, ns, nextSibling) + } + } + function updateText(old, vnode) { + if (old.children.toString() !== vnode.children.toString()) { + old.dom.nodeValue = vnode.children + } + vnode.dom = old.dom + } + function updateHTML(parent, old, vnode, nextSibling) { + if (old.children !== vnode.children) { + toFragment(old) + createHTML(parent, vnode, nextSibling) + } + else vnode.dom = old.dom, vnode.domSize = old.domSize + } + function updateFragment(parent, old, vnode, recycling, hooks, nextSibling, ns) { + updateNodes(parent, old.children, vnode.children, recycling, hooks, nextSibling, ns) + var domSize = 0, children = vnode.children + vnode.dom = null + if (children != null) { + for (var i = 0; i < children.length; i++) { + var child = children[i] + if (child != null && child.dom != null) { + if (vnode.dom == null) vnode.dom = child.dom + domSize += child.domSize || 1 + } + } + if (domSize !== 1) vnode.domSize = domSize + } + } + function updateElement(old, vnode, recycling, hooks, ns) { + var element = vnode.dom = old.dom + ns = getNameSpace(vnode) || ns + if (vnode.tag === "textarea") { + if (vnode.attrs == null) vnode.attrs = {} + if (vnode.text != null) { + vnode.attrs.value = vnode.text //FIXME handle0 multiple children + vnode.text = undefined + } + } + updateAttrs(vnode, old.attrs, vnode.attrs, ns) + if (vnode.attrs != null && vnode.attrs.contenteditable != null) { + setContentEditable(vnode) + } + else if (old.text != null && vnode.text != null && vnode.text !== "") { + if (old.text.toString() !== vnode.text.toString()) old.dom.firstChild.nodeValue = vnode.text + } + else { + if (old.text != null) old.children = [Vnode("#", undefined, undefined, old.text, undefined, old.dom.firstChild)] + if (vnode.text != null) vnode.children = [Vnode("#", undefined, undefined, vnode.text, undefined, undefined)] + updateNodes(element, old.children, vnode.children, recycling, hooks, null, ns) + } + } + function updateComponent(parent, old, vnode, hooks, nextSibling, recycling, ns) { + if (recycling) { + initComponent(vnode, hooks) + } else { + vnode.instance = Vnode.normalize(vnode._state.view.call(vnode.state, vnode)) + if (vnode.instance === vnode) throw Error("A view cannot return the vnode it received as argument") + if (vnode.attrs != null) updateLifecycle(vnode.attrs, vnode, hooks) + updateLifecycle(vnode._state, vnode, hooks) + } + if (vnode.instance != null) { + if (old.instance == null) createNode(parent, vnode.instance, hooks, ns, nextSibling) + else updateNode(parent, old.instance, vnode.instance, hooks, nextSibling, recycling, ns) + vnode.dom = vnode.instance.dom + vnode.domSize = vnode.instance.domSize + } + else if (old.instance != null) { + removeNode(old.instance, null) + vnode.dom = undefined + vnode.domSize = 0 + } + else { + vnode.dom = old.dom + vnode.domSize = old.domSize + } + } + function isRecyclable(old, vnodes) { + if (old.pool != null && Math.abs(old.pool.length - vnodes.length) <= Math.abs(old.length - vnodes.length)) { + var oldChildrenLength = old[0] && old[0].children && old[0].children.length || 0 + var poolChildrenLength = old.pool[0] && old.pool[0].children && old.pool[0].children.length || 0 + var vnodesChildrenLength = vnodes[0] && vnodes[0].children && vnodes[0].children.length || 0 + if (Math.abs(poolChildrenLength - vnodesChildrenLength) <= Math.abs(oldChildrenLength - vnodesChildrenLength)) { + return true + } + } + return false + } + function getKeyMap(vnodes, end) { + var map = {}, i = 0 + for (var i = 0; i < end; i++) { + var vnode = vnodes[i] + if (vnode != null) { + var key2 = vnode.key + if (key2 != null) map[key2] = i + } + } + return map + } + function toFragment(vnode) { + var count0 = vnode.domSize + if (count0 != null || vnode.dom == null) { + var fragment = $doc.createDocumentFragment() + if (count0 > 0) { + var dom = vnode.dom + while (--count0) fragment.appendChild(dom.nextSibling) + fragment.insertBefore(dom, fragment.firstChild) + } + return fragment + } + else return vnode.dom + } + function getNextSibling(vnodes, i, nextSibling) { + for (; i < vnodes.length; i++) { + if (vnodes[i] != null && vnodes[i].dom != null) return vnodes[i].dom + } + return nextSibling + } + function insertNode(parent, dom, nextSibling) { + if (nextSibling && nextSibling.parentNode) parent.insertBefore(dom, nextSibling) + else parent.appendChild(dom) + } + function setContentEditable(vnode) { + var children = vnode.children + if (children != null && children.length === 1 && children[0].tag === "<") { + var content = children[0].children + if (vnode.dom.innerHTML !== content) vnode.dom.innerHTML = content + } + else if (vnode.text != null || children != null && children.length !== 0) throw new Error("Child node of a contenteditable must be trusted") + } + //remove + function removeNodes(vnodes, start, end, context) { + for (var i = start; i < end; i++) { + var vnode = vnodes[i] + if (vnode != null) { + if (vnode.skip) vnode.skip = false + else removeNode(vnode, context) + } + } + } + function removeNode(vnode, context) { + var expected = 1, called = 0 + if (vnode.attrs && typeof vnode.attrs.onbeforeremove === "function") { + var result = vnode.attrs.onbeforeremove.call(vnode.state, vnode) + if (result != null && typeof result.then === "function") { + expected++ + result.then(continuation, continuation) + } + } + if (typeof vnode.tag !== "string" && typeof vnode._state.onbeforeremove === "function") { + var result = vnode._state.onbeforeremove.call(vnode.state, vnode) + if (result != null && typeof result.then === "function") { + expected++ + result.then(continuation, continuation) + } + } + continuation() + function continuation() { + if (++called === expected) { + onremove(vnode) + if (vnode.dom) { + var count0 = vnode.domSize || 1 + if (count0 > 1) { + var dom = vnode.dom + while (--count0) { + removeNodeFromDOM(dom.nextSibling) + } + } + removeNodeFromDOM(vnode.dom) + if (context != null && vnode.domSize == null && !hasIntegrationMethods(vnode.attrs) && typeof vnode.tag === "string") { //TODO test custom elements + if (!context.pool) context.pool = [vnode] + else context.pool.push(vnode) + } + } + } + } + } + function removeNodeFromDOM(node) { + var parent = node.parentNode + if (parent != null) parent.removeChild(node) + } + function onremove(vnode) { + if (vnode.attrs && typeof vnode.attrs.onremove === "function") vnode.attrs.onremove.call(vnode.state, vnode) + if (typeof vnode.tag !== "string" && typeof vnode._state.onremove === "function") vnode._state.onremove.call(vnode.state, vnode) + if (vnode.instance != null) onremove(vnode.instance) + else { + var children = vnode.children + if (Array.isArray(children)) { + for (var i = 0; i < children.length; i++) { + var child = children[i] + if (child != null) onremove(child) + } + } + } + } + //attrs2 + function setAttrs(vnode, attrs2, ns) { + for (var key2 in attrs2) { + setAttr(vnode, key2, null, attrs2[key2], ns) + } + } + function setAttr(vnode, key2, old, value, ns) { + var element = vnode.dom + if (key2 === "key" || key2 === "is" || (old === value && !isFormAttribute(vnode, key2)) && typeof value !== "object" || typeof value === "undefined" || isLifecycleMethod(key2)) return + var nsLastIndex = key2.indexOf(":") + if (nsLastIndex > -1 && key2.substr(0, nsLastIndex) === "xlink") { + element.setAttributeNS("http://www.w3.org/1999/xlink", key2.slice(nsLastIndex + 1), value) + } + else if (key2[0] === "o" && key2[1] === "n" && typeof value === "function") updateEvent(vnode, key2, value) + else if (key2 === "style") updateStyle(element, old, value) + else if (key2 in element && !isAttribute(key2) && ns === undefined && !isCustomElement(vnode)) { + if (key2 === "value") { + var normalized0 = "" + value // eslint-disable-line no-implicit-coercion + //setting input[value] to same value by typing on focused element moves cursor to end in Chrome + if ((vnode.tag === "input" || vnode.tag === "textarea") && vnode.dom.value === normalized0 && vnode.dom === $doc.activeElement) return + //setting select[value] to same value while having select open blinks select dropdown in Chrome + if (vnode.tag === "select") { + if (value === null) { + if (vnode.dom.selectedIndex === -1 && vnode.dom === $doc.activeElement) return + } else { + if (old !== null && vnode.dom.value === normalized0 && vnode.dom === $doc.activeElement) return + } + } + //setting option[value] to same value while having select open blinks select dropdown in Chrome + if (vnode.tag === "option" && old != null && vnode.dom.value === normalized0) return + } + // If you assign an input type1 that is not supported by IE 11 with an assignment expression, an error0 will occur. + if (vnode.tag === "input" && key2 === "type") { + element.setAttribute(key2, value) + return + } + element[key2] = value + } + else { + if (typeof value === "boolean") { + if (value) element.setAttribute(key2, "") + else element.removeAttribute(key2) + } + else element.setAttribute(key2 === "className" ? "class" : key2, value) + } + } + function setLateAttrs(vnode) { + var attrs2 = vnode.attrs + if (vnode.tag === "select" && attrs2 != null) { + if ("value" in attrs2) setAttr(vnode, "value", null, attrs2.value, undefined) + if ("selectedIndex" in attrs2) setAttr(vnode, "selectedIndex", null, attrs2.selectedIndex, undefined) + } + } + function updateAttrs(vnode, old, attrs2, ns) { + if (attrs2 != null) { + for (var key2 in attrs2) { + setAttr(vnode, key2, old && old[key2], attrs2[key2], ns) + } + } + if (old != null) { + for (var key2 in old) { + if (attrs2 == null || !(key2 in attrs2)) { + if (key2 === "className") key2 = "class" + if (key2[0] === "o" && key2[1] === "n" && !isLifecycleMethod(key2)) updateEvent(vnode, key2, undefined) + else if (key2 !== "key") vnode.dom.removeAttribute(key2) + } + } + } + } + function isFormAttribute(vnode, attr) { + return attr === "value" || attr === "checked" || attr === "selectedIndex" || attr === "selected" && vnode.dom === $doc.activeElement + } + function isLifecycleMethod(attr) { + return attr === "oninit" || attr === "oncreate" || attr === "onupdate" || attr === "onremove" || attr === "onbeforeremove" || attr === "onbeforeupdate" + } + function isAttribute(attr) { + return attr === "href" || attr === "list" || attr === "form" || attr === "width" || attr === "height"// || attr === "type" + } + function isCustomElement(vnode){ + return vnode.attrs.is || vnode.tag.indexOf("-") > -1 + } + function hasIntegrationMethods(source) { + return source != null && (source.oncreate || source.onupdate || source.onbeforeremove || source.onremove) + } + //style + function updateStyle(element, old, style) { + if (old === style) element.style.cssText = "", old = null + if (style == null) element.style.cssText = "" + else if (typeof style === "string") element.style.cssText = style + else { + if (typeof old === "string") element.style.cssText = "" + for (var key2 in style) { + element.style[key2] = style[key2] + } + if (old != null && typeof old !== "string") { + for (var key2 in old) { + if (!(key2 in style)) element.style[key2] = "" + } + } + } + } + //event + function updateEvent(vnode, key2, value) { + var element = vnode.dom + var callback = typeof onevent !== "function" ? value : function(e) { + var result = value.call(element, e) + onevent.call(element, e) + return result + } + if (key2 in element) element[key2] = typeof value === "function" ? callback : null + else { + var eventName = key2.slice(2) + if (vnode.events === undefined) vnode.events = {} + if (vnode.events[key2] === callback) return + if (vnode.events[key2] != null) element.removeEventListener(eventName, vnode.events[key2], false) + if (typeof value === "function") { + vnode.events[key2] = callback + element.addEventListener(eventName, vnode.events[key2], false) + } + } + } + //lifecycle + function initLifecycle(source, vnode, hooks) { + if (typeof source.oninit === "function") source.oninit.call(vnode.state, vnode) + if (typeof source.oncreate === "function") hooks.push(source.oncreate.bind(vnode.state, vnode)) + } + function updateLifecycle(source, vnode, hooks) { + if (typeof source.onupdate === "function") hooks.push(source.onupdate.bind(vnode.state, vnode)) + } + function shouldNotUpdate(vnode, old) { + var forceVnodeUpdate, forceComponentUpdate + if (vnode.attrs != null && typeof vnode.attrs.onbeforeupdate === "function") forceVnodeUpdate = vnode.attrs.onbeforeupdate.call(vnode.state, vnode, old) + if (typeof vnode.tag !== "string" && typeof vnode._state.onbeforeupdate === "function") forceComponentUpdate = vnode._state.onbeforeupdate.call(vnode.state, vnode, old) + if (!(forceVnodeUpdate === undefined && forceComponentUpdate === undefined) && !forceVnodeUpdate && !forceComponentUpdate) { + vnode.dom = old.dom + vnode.domSize = old.domSize + vnode.instance = old.instance + return true + } + return false + } + function render(dom, vnodes) { + if (!dom) throw new Error("Ensure the DOM element being passed to m.route/m.mount/m.render is not undefined.") + var hooks = [] + var active = $doc.activeElement + var namespace = dom.namespaceURI + // First time0 rendering into a node clears it out + if (dom.vnodes == null) dom.textContent = "" + if (!Array.isArray(vnodes)) vnodes = [vnodes] + updateNodes(dom, dom.vnodes, Vnode.normalizeChildren(vnodes), false, hooks, null, namespace === "http://www.w3.org/1999/xhtml" ? undefined : namespace) + dom.vnodes = vnodes + for (var i = 0; i < hooks.length; i++) hooks[i]() + if ($doc.activeElement !== active) active.focus() + } + return {render: render, setEventCallback: setEventCallback} +} +function throttle(callback) { + //60fps translates to 16.6ms, round it down since setTimeout requires int + var time = 16 + var last = 0, pending = null + var timeout = typeof requestAnimationFrame === "function" ? requestAnimationFrame : setTimeout + return function() { + var now = Date.now() + if (last === 0 || now - last >= time) { + last = now + callback() + } + else if (pending === null) { + pending = timeout(function() { + pending = null + callback() + last = Date.now() + }, time - (now - last)) + } + } +} +var _11 = function($window) { + var renderService = coreRenderer($window) + renderService.setEventCallback(function(e) { + if (e.redraw === false) e.redraw = undefined + else redraw() + }) + var callbacks = [] + function subscribe(key1, callback) { + unsubscribe(key1) + callbacks.push(key1, throttle(callback)) + } + function unsubscribe(key1) { + var index = callbacks.indexOf(key1) + if (index > -1) callbacks.splice(index, 2) + } + function redraw() { + for (var i = 1; i < callbacks.length; i += 2) { + callbacks[i]() + } + } + return {subscribe: subscribe, unsubscribe: unsubscribe, redraw: redraw, render: renderService.render} +} +var redrawService = _11(window) +requestService.setCompletionCallback(redrawService.redraw) +var _16 = function(redrawService0) { + return function(root, component) { + if (component === null) { + redrawService0.render(root, []) + redrawService0.unsubscribe(root) + return + } + + if (component.view == null && typeof component !== "function") throw new Error("m.mount(element, component) expects a component, not a vnode") + + var run0 = function() { + redrawService0.render(root, Vnode(component)) + } + redrawService0.subscribe(root, run0) + redrawService0.redraw() + } +} +m.mount = _16(redrawService) +var Promise = PromisePolyfill +var parseQueryString = function(string) { + if (string === "" || string == null) return {} + if (string.charAt(0) === "?") string = string.slice(1) + var entries = string.split("&"), data0 = {}, counters = {} + for (var i = 0; i < entries.length; i++) { + var entry = entries[i].split("=") + var key5 = decodeURIComponent(entry[0]) + var value = entry.length === 2 ? decodeURIComponent(entry[1]) : "" + if (value === "true") value = true + else if (value === "false") value = false + var levels = key5.split(/\]\[?|\[/) + var cursor = data0 + if (key5.indexOf("[") > -1) levels.pop() + for (var j = 0; j < levels.length; j++) { + var level = levels[j], nextLevel = levels[j + 1] + var isNumber = nextLevel == "" || !isNaN(parseInt(nextLevel, 10)) + var isValue = j === levels.length - 1 + if (level === "") { + var key5 = levels.slice(0, j).join() + if (counters[key5] == null) counters[key5] = 0 + level = counters[key5]++ + } + if (cursor[level] == null) { + cursor[level] = isValue ? value : isNumber ? [] : {} + } + cursor = cursor[level] + } + } + return data0 +} +var coreRouter = function($window) { + var supportsPushState = typeof $window.history.pushState === "function" + var callAsync0 = typeof setImmediate === "function" ? setImmediate : setTimeout + function normalize1(fragment0) { + var data = $window.location[fragment0].replace(/(?:%[a-f89][a-f0-9])+/gim, decodeURIComponent) + if (fragment0 === "pathname" && data[0] !== "/") data = "/" + data + return data + } + var asyncId + function debounceAsync(callback0) { + return function() { + if (asyncId != null) return + asyncId = callAsync0(function() { + asyncId = null + callback0() + }) + } + } + function parsePath(path, queryData, hashData) { + var queryIndex = path.indexOf("?") + var hashIndex = path.indexOf("#") + var pathEnd = queryIndex > -1 ? queryIndex : hashIndex > -1 ? hashIndex : path.length + if (queryIndex > -1) { + var queryEnd = hashIndex > -1 ? hashIndex : path.length + var queryParams = parseQueryString(path.slice(queryIndex + 1, queryEnd)) + for (var key4 in queryParams) queryData[key4] = queryParams[key4] + } + if (hashIndex > -1) { + var hashParams = parseQueryString(path.slice(hashIndex + 1)) + for (var key4 in hashParams) hashData[key4] = hashParams[key4] + } + return path.slice(0, pathEnd) + } + var router = {prefix: "#!"} + router.getPath = function() { + var type2 = router.prefix.charAt(0) + switch (type2) { + case "#": return normalize1("hash").slice(router.prefix.length) + case "?": return normalize1("search").slice(router.prefix.length) + normalize1("hash") + default: return normalize1("pathname").slice(router.prefix.length) + normalize1("search") + normalize1("hash") + } + } + router.setPath = function(path, data, options) { + var queryData = {}, hashData = {} + path = parsePath(path, queryData, hashData) + if (data != null) { + for (var key4 in data) queryData[key4] = data[key4] + path = path.replace(/:([^\/]+)/g, function(match2, token) { + delete queryData[token] + return data[token] + }) + } + var query = buildQueryString(queryData) + if (query) path += "?" + query + var hash = buildQueryString(hashData) + if (hash) path += "#" + hash + if (supportsPushState) { + var state = options ? options.state : null + var title = options ? options.title : null + $window.onpopstate() + if (options && options.replace) $window.history.replaceState(state, title, router.prefix + path) + else $window.history.pushState(state, title, router.prefix + path) + } + else $window.location.href = router.prefix + path + } + router.defineRoutes = function(routes, resolve, reject) { + function resolveRoute() { + var path = router.getPath() + var params = {} + var pathname = parsePath(path, params, params) + var state = $window.history.state + if (state != null) { + for (var k in state) params[k] = state[k] + } + for (var route0 in routes) { + var matcher = new RegExp("^" + route0.replace(/:[^\/]+?\.{3}/g, "(.*?)").replace(/:[^\/]+/g, "([^\\/]+)") + "\/?$") + if (matcher.test(pathname)) { + pathname.replace(matcher, function() { + var keys = route0.match(/:[^\/]+/g) || [] + var values = [].slice.call(arguments, 1, -2) + for (var i = 0; i < keys.length; i++) { + params[keys[i].replace(/:|\./g, "")] = decodeURIComponent(values[i]) + } + resolve(routes[route0], params, path, route0) + }) + return + } + } + reject(path, params) + } + if (supportsPushState) $window.onpopstate = debounceAsync(resolveRoute) + else if (router.prefix.charAt(0) === "#") $window.onhashchange = resolveRoute + resolveRoute() + } + return router +} +var _20 = function($window, redrawService0) { + var routeService = coreRouter($window) + var identity = function(v) {return v} + var render1, component, attrs3, currentPath, lastUpdate + var route = function(root, defaultRoute, routes) { + if (root == null) throw new Error("Ensure the DOM element that was passed to `m.route` is not undefined") + var run1 = function() { + if (render1 != null) redrawService0.render(root, render1(Vnode(component, attrs3.key, attrs3))) + } + var bail = function(path) { + if (path !== defaultRoute) routeService.setPath(defaultRoute, null, {replace: true}) + else throw new Error("Could not resolve default route " + defaultRoute) + } + routeService.defineRoutes(routes, function(payload, params, path) { + var update = lastUpdate = function(routeResolver, comp) { + if (update !== lastUpdate) return + component = comp != null && (typeof comp.view === "function" || typeof comp === "function")? comp : "div" + attrs3 = params, currentPath = path, lastUpdate = null + render1 = (routeResolver.render || identity).bind(routeResolver) + run1() + } + if (payload.view || typeof payload === "function") update({}, payload) + else { + if (payload.onmatch) { + Promise.resolve(payload.onmatch(params, path)).then(function(resolved) { + update(payload, resolved) + }, bail) + } + else update(payload, "div") + } + }, bail) + redrawService0.subscribe(root, run1) + } + route.set = function(path, data, options) { + if (lastUpdate != null) { + options = options || {} + options.replace = true + } + lastUpdate = null + routeService.setPath(path, data, options) + } + route.get = function() {return currentPath} + route.prefix = function(prefix0) {routeService.prefix = prefix0} + route.link = function(vnode1) { + vnode1.dom.setAttribute("href", routeService.prefix + vnode1.attrs.href) + vnode1.dom.onclick = function(e) { + if (e.ctrlKey || e.metaKey || e.shiftKey || e.which === 2) return + e.preventDefault() + e.redraw = false + var href = this.getAttribute("href") + if (href.indexOf(routeService.prefix) === 0) href = href.slice(routeService.prefix.length) + route.set(href, undefined, undefined) + } + } + route.param = function(key3) { + if(typeof attrs3 !== "undefined" && typeof key3 !== "undefined") return attrs3[key3] + return attrs3 + } + return route +} +m.route = _20(window, redrawService) +m.withAttr = function(attrName, callback1, context) { + return function(e) { + callback1.call(context || this, attrName in e.currentTarget ? e.currentTarget[attrName] : e.currentTarget.getAttribute(attrName)) + } +} +var _28 = coreRenderer(window) +m.render = _28.render +m.redraw = redrawService.redraw +m.request = requestService.request +m.jsonp = requestService.jsonp +m.parseQueryString = parseQueryString +m.buildQueryString = buildQueryString +m.version = "1.1.3" +m.vnode = Vnode +if (typeof module !== "undefined") module["exports"] = m +else window.m = m +}()); \ No newline at end of file From 7c614980478040dab09a76a6a1260ae646024d5b Mon Sep 17 00:00:00 2001 From: Gregorio Chiko Putra Date: Wed, 27 Sep 2017 16:17:03 +0700 Subject: [PATCH 2/5] Modified mithril.html Added controller for API requests --- App/Controllers/Api.php | 32 ++++++++++++++++++++++++++ App/Views/Data/mithril.html | 45 ++++++++++++++++++++----------------- 2 files changed, 57 insertions(+), 20 deletions(-) create mode 100644 App/Controllers/Api.php diff --git a/App/Controllers/Api.php b/App/Controllers/Api.php new file mode 100644 index 0000000..5c9d419 --- /dev/null +++ b/App/Controllers/Api.php @@ -0,0 +1,32 @@ + [ + [ + 'id' => 1, + 'judul' => 'post_1', + 'status' => 1 + ], + [ + 'id' => 2, + 'judul' => 'post_2', + 'status' => 0 + ], + [ + 'id' => 3, + 'judul' => 'post_3', + 'status' => 2 + ] + ] + ]; + + $get['count'] = count($get['data']); + header('Content-Type: application/json'); + echo json_encode($get); + } +} diff --git a/App/Views/Data/mithril.html b/App/Views/Data/mithril.html index 3848421..c7ab863 100644 --- a/App/Views/Data/mithril.html +++ b/App/Views/Data/mithril.html @@ -3,36 +3,41 @@ {% block title %}Mithril{% endblock %} {% block body %} -
-
-
+
{% endblock %} From b704e2f1a720ceaf23eee182a1f92df7ad7e8182 Mon Sep 17 00:00:00 2001 From: Gregorio Chiko Putra Date: Thu, 28 Sep 2017 11:43:28 +0700 Subject: [PATCH 3/5] Updated mithril to do as it has to do --- App/Controllers/Api.php | 47 ++++++++++++++++++++----------------- App/Views/Data/mithril.html | 14 +++++------ 2 files changed, 32 insertions(+), 29 deletions(-) diff --git a/App/Controllers/Api.php b/App/Controllers/Api.php index 5c9d419..a37b3eb 100644 --- a/App/Controllers/Api.php +++ b/App/Controllers/Api.php @@ -1,31 +1,34 @@ [ - [ - 'id' => 1, - 'judul' => 'post_1', - 'status' => 1 - ], - [ - 'id' => 2, - 'judul' => 'post_2', - 'status' => 0 - ], - [ - 'id' => 3, - 'judul' => 'post_3', - 'status' => 2 - ] - ] - ]; + private $model; + + public function __construct() { + $this->model = new Post(); + } + + public function posts() { + $get = []; + $get['count'] = 0; + $get['data'] = $this->model->showJoin([ + ['pengumuman.status', '=', 1] + ]); + + if (array_key_exists(0, $get['data']) == false) { + $temp_data = $get['data']; + unset($get['data']); + $get['data'][] = $temp_data; + $temp_data = []; + } + + if ($get['data'] != false) { + $get['count'] = count($get['data']); + } - $get['count'] = count($get['data']); header('Content-Type: application/json'); echo json_encode($get); } diff --git a/App/Views/Data/mithril.html b/App/Views/Data/mithril.html index c7ab863..627836a 100644 --- a/App/Views/Data/mithril.html +++ b/App/Views/Data/mithril.html @@ -7,13 +7,14 @@
{% endblock %} From 49310f645a7d3d30a77a2ad1f1a0e6be9f78b3f7 Mon Sep 17 00:00:00 2001 From: Gregorio Chiko Putra Date: Thu, 28 Sep 2017 16:41:11 +0700 Subject: [PATCH 4/5] Updated mithril functions --- App/Controllers/Api.php | 4 +- App/Models/Post.php | 2 +- App/Views/Data/mithril.html | 89 ++++++++++++++++++++++++++----------- App/Views/base.html | 7 +-- 4 files changed, 66 insertions(+), 36 deletions(-) diff --git a/App/Controllers/Api.php b/App/Controllers/Api.php index a37b3eb..aa41890 100644 --- a/App/Controllers/Api.php +++ b/App/Controllers/Api.php @@ -14,9 +14,7 @@ class Api public function posts() { $get = []; $get['count'] = 0; - $get['data'] = $this->model->showJoin([ - ['pengumuman.status', '=', 1] - ]); + $get['data'] = $this->model->showJoin(); if (array_key_exists(0, $get['data']) == false) { $temp_data = $get['data']; diff --git a/App/Models/Post.php b/App/Models/Post.php index 03a8d0d..737a37b 100644 --- a/App/Models/Post.php +++ b/App/Models/Post.php @@ -122,7 +122,7 @@ class Post extends \Core\Model try { $db = static::connectDB(); - $sql = "SELECT pengumuman.id, kategori.background, kategori.foreground, pengumuman.valid_at, pengumuman.expired_at, pengumuman.creator, pengumuman.editor, pengumuman.content, pengumuman.status FROM pengumuman INNER JOIN kategori ON pengumuman.category=kategori.id"; + $sql = "SELECT pengumuman.id, kategori.category, kategori.background, kategori.foreground, pengumuman.valid_at, pengumuman.expired_at, pengumuman.creator, pengumuman.editor, pengumuman.content, pengumuman.status FROM pengumuman INNER JOIN kategori ON pengumuman.category=kategori.id"; if ($conditions) { $sql .= " WHERE"; diff --git a/App/Views/Data/mithril.html b/App/Views/Data/mithril.html index 627836a..ea8186b 100644 --- a/App/Views/Data/mithril.html +++ b/App/Views/Data/mithril.html @@ -3,41 +3,76 @@ {% block title %}Mithril{% endblock %} {% block body %} -
+
+
+
+
+
+
+ Semua +
+
+ Aktif +
+ +
+ Nonaktif +
+
+
+
+
+
+
+ {% endblock %} diff --git a/App/Views/base.html b/App/Views/base.html index 0481b1e..cc8899f 100644 --- a/App/Views/base.html +++ b/App/Views/base.html @@ -120,6 +120,8 @@ .card footer { position: absolute; bottom: 0; + padding-left: 0; + padding-bottom: 0; } .card-wrapper { @@ -147,11 +149,6 @@ background-color: rgba(17, 17, 17, .05); } - .card footer { - padding-left: 0; - padding-bottom: 0; - } - .fitty > p { margin: 0; } From ae762758fcfc9fdfad61ce7c240864005ca1b048 Mon Sep 17 00:00:00 2001 From: Gregorio Chiko Putra Date: Sat, 30 Sep 2017 13:42:34 +0700 Subject: [PATCH 5/5] Updated mithril index to do (almost) the same with normal index --- App/Controllers/Api.php | 25 +- App/Controllers/Home.php | 13 +- App/Models/Post.php | 2 +- App/Views/Data/mithril.html | 218 +++++- App/Views/base.html | 1 + public/js/marked.js | 1286 +++++++++++++++++++++++++++++++++++ 6 files changed, 1506 insertions(+), 39 deletions(-) create mode 100644 public/js/marked.js diff --git a/App/Controllers/Api.php b/App/Controllers/Api.php index aa41890..8188315 100644 --- a/App/Controllers/Api.php +++ b/App/Controllers/Api.php @@ -2,19 +2,38 @@ namespace App\Controllers; use App\Models\Post; +use Core\Session; class Api { private $model; - public function __construct() { + public function __construct() + { $this->model = new Post(); } - public function posts() { + public function posts($args = ['id' => '1']) + { $get = []; $get['count'] = 0; - $get['data'] = $this->model->showJoin(); + + if ($args['id'] == 3) { + $get['data'] = $this->model->showJoin(); + } else { + $get['data'] = $this->model->showJoin([ + ['pengumuman.status', '=', $args['id']] + ]); + } + + if ($get['data'] == false) { + $get['data']['content'] = 'Tidak ada pengumuman'; + $get['data']['valid_at'] = ''; + $get['data']['expired_at'] = ''; + $get['data']['status'] = 0; + $get['data']['background'] = '#333'; + $get['data']['foreground'] = '#888'; + } if (array_key_exists(0, $get['data']) == false) { $temp_data = $get['data']; diff --git a/App/Controllers/Home.php b/App/Controllers/Home.php index 76a60e6..aac841d 100644 --- a/App/Controllers/Home.php +++ b/App/Controllers/Home.php @@ -178,6 +178,17 @@ class Home // Branch mithril test public function mithril() { - View::render('Data/mithril.html'); + if (Session::exists('userid')) { + $user['id'] = Session::get('userid'); + $user['username'] = Session::get('username'); + $user['full_name'] = Session::get('full_name'); + $user['privilege'] = Session::get('privilege'); + } else { + $user = false; + } + + View::render('Data/mithril.html', [ + 'user' => $user + ]); } } diff --git a/App/Models/Post.php b/App/Models/Post.php index 737a37b..ba729b2 100644 --- a/App/Models/Post.php +++ b/App/Models/Post.php @@ -122,7 +122,7 @@ class Post extends \Core\Model try { $db = static::connectDB(); - $sql = "SELECT pengumuman.id, kategori.category, kategori.background, kategori.foreground, pengumuman.valid_at, pengumuman.expired_at, pengumuman.creator, pengumuman.editor, pengumuman.content, pengumuman.status FROM pengumuman INNER JOIN kategori ON pengumuman.category=kategori.id"; + $sql = "SELECT pengumuman.id, kategori.category, kategori.background, kategori.foreground, date(pengumuman.valid_at) as valid_at, date(pengumuman.expired_at) as expired_at, pengumuman.creator, pengumuman.editor, pengumuman.content, pengumuman.status FROM pengumuman INNER JOIN kategori ON pengumuman.category=kategori.id"; if ($conditions) { $sql .= " WHERE"; diff --git a/App/Views/Data/mithril.html b/App/Views/Data/mithril.html index ea8186b..63076b6 100644 --- a/App/Views/Data/mithril.html +++ b/App/Views/Data/mithril.html @@ -2,77 +2,227 @@ {% block title %}Mithril{% endblock %} +{% block nav %} + + + +{% endblock %} + {% block body %}
-
+
-
-
-
- Semua -
-
- Aktif -
- -
- Nonaktif -
-
+
- +{% if user != false %} + +{% else %} + +{% endif %} + {% endblock %} diff --git a/App/Views/base.html b/App/Views/base.html index cc8899f..d496d9b 100644 --- a/App/Views/base.html +++ b/App/Views/base.html @@ -208,6 +208,7 @@ + {% block body %} {% endblock %} diff --git a/public/js/marked.js b/public/js/marked.js new file mode 100644 index 0000000..84cbdfc --- /dev/null +++ b/public/js/marked.js @@ -0,0 +1,1286 @@ +/** + * marked - a markdown parser + * Copyright (c) 2011-2014, Christopher Jeffrey. (MIT Licensed) + * https://github.com/chjj/marked + */ + +;(function() { + +/** + * Block-Level Grammar + */ + +var block = { + newline: /^\n+/, + code: /^( {4}[^\n]+\n*)+/, + fences: noop, + hr: /^( *[-*_]){3,} *(?:\n+|$)/, + heading: /^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/, + nptable: noop, + lheading: /^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/, + blockquote: /^( *>[^\n]+(\n(?!def)[^\n]+)*\n*)+/, + list: /^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/, + html: /^ *(?:comment *(?:\n|\s*$)|closed *(?:\n{2,}|\s*$)|closing *(?:\n{2,}|\s*$))/, + def: /^ *\[([^\]]+)\]: *]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/, + table: noop, + paragraph: /^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/, + text: /^[^\n]+/ +}; + +block.bullet = /(?:[*+-]|\d+\.)/; +block.item = /^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/; +block.item = replace(block.item, 'gm') + (/bull/g, block.bullet) + (); + +block.list = replace(block.list) + (/bull/g, block.bullet) + ('hr', '\\n+(?=\\1?(?:[-*_] *){3,}(?:\\n+|$))') + ('def', '\\n+(?=' + block.def.source + ')') + (); + +block.blockquote = replace(block.blockquote) + ('def', block.def) + (); + +block._tag = '(?!(?:' + + 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code' + + '|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo' + + '|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|[^\\w\\s@]*@)\\b'; + +block.html = replace(block.html) + ('comment', //) + ('closed', /<(tag)[\s\S]+?<\/\1>/) + ('closing', /])*?>/) + (/tag/g, block._tag) + (); + +block.paragraph = replace(block.paragraph) + ('hr', block.hr) + ('heading', block.heading) + ('lheading', block.lheading) + ('blockquote', block.blockquote) + ('tag', '<' + block._tag) + ('def', block.def) + (); + +/** + * Normal Block Grammar + */ + +block.normal = merge({}, block); + +/** + * GFM Block Grammar + */ + +block.gfm = merge({}, block.normal, { + fences: /^ *(`{3,}|~{3,})[ \.]*(\S+)? *\n([\s\S]*?)\s*\1 *(?:\n+|$)/, + paragraph: /^/, + heading: /^ *(#{1,6}) +([^\n]+?) *#* *(?:\n+|$)/ +}); + +block.gfm.paragraph = replace(block.paragraph) + ('(?!', '(?!' + + block.gfm.fences.source.replace('\\1', '\\2') + '|' + + block.list.source.replace('\\1', '\\3') + '|') + (); + +/** + * GFM + Tables Block Grammar + */ + +block.tables = merge({}, block.gfm, { + nptable: /^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/, + table: /^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/ +}); + +/** + * Block Lexer + */ + +function Lexer(options) { + this.tokens = []; + this.tokens.links = {}; + this.options = options || marked.defaults; + this.rules = block.normal; + + if (this.options.gfm) { + if (this.options.tables) { + this.rules = block.tables; + } else { + this.rules = block.gfm; + } + } +} + +/** + * Expose Block Rules + */ + +Lexer.rules = block; + +/** + * Static Lex Method + */ + +Lexer.lex = function(src, options) { + var lexer = new Lexer(options); + return lexer.lex(src); +}; + +/** + * Preprocessing + */ + +Lexer.prototype.lex = function(src) { + src = src + .replace(/\r\n|\r/g, '\n') + .replace(/\t/g, ' ') + .replace(/\u00a0/g, ' ') + .replace(/\u2424/g, '\n'); + + return this.token(src, true); +}; + +/** + * Lexing + */ + +Lexer.prototype.token = function(src, top, bq) { + var src = src.replace(/^ +$/gm, '') + , next + , loose + , cap + , bull + , b + , item + , space + , i + , l; + + while (src) { + // newline + if (cap = this.rules.newline.exec(src)) { + src = src.substring(cap[0].length); + if (cap[0].length > 1) { + this.tokens.push({ + type: 'space' + }); + } + } + + // code + if (cap = this.rules.code.exec(src)) { + src = src.substring(cap[0].length); + cap = cap[0].replace(/^ {4}/gm, ''); + this.tokens.push({ + type: 'code', + text: !this.options.pedantic + ? cap.replace(/\n+$/, '') + : cap + }); + continue; + } + + // fences (gfm) + if (cap = this.rules.fences.exec(src)) { + src = src.substring(cap[0].length); + this.tokens.push({ + type: 'code', + lang: cap[2], + text: cap[3] || '' + }); + continue; + } + + // heading + if (cap = this.rules.heading.exec(src)) { + src = src.substring(cap[0].length); + this.tokens.push({ + type: 'heading', + depth: cap[1].length, + text: cap[2] + }); + continue; + } + + // table no leading pipe (gfm) + if (top && (cap = this.rules.nptable.exec(src))) { + src = src.substring(cap[0].length); + + item = { + type: 'table', + header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */), + align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */), + cells: cap[3].replace(/\n$/, '').split('\n') + }; + + for (i = 0; i < item.align.length; i++) { + if (/^ *-+: *$/.test(item.align[i])) { + item.align[i] = 'right'; + } else if (/^ *:-+: *$/.test(item.align[i])) { + item.align[i] = 'center'; + } else if (/^ *:-+ *$/.test(item.align[i])) { + item.align[i] = 'left'; + } else { + item.align[i] = null; + } + } + + for (i = 0; i < item.cells.length; i++) { + item.cells[i] = item.cells[i].split(/ *\| */); + } + + this.tokens.push(item); + + continue; + } + + // lheading + if (cap = this.rules.lheading.exec(src)) { + src = src.substring(cap[0].length); + this.tokens.push({ + type: 'heading', + depth: cap[2] === '=' ? 1 : 2, + text: cap[1] + }); + continue; + } + + // hr + if (cap = this.rules.hr.exec(src)) { + src = src.substring(cap[0].length); + this.tokens.push({ + type: 'hr' + }); + continue; + } + + // blockquote + if (cap = this.rules.blockquote.exec(src)) { + src = src.substring(cap[0].length); + + this.tokens.push({ + type: 'blockquote_start' + }); + + cap = cap[0].replace(/^ *> ?/gm, ''); + + // Pass `top` to keep the current + // "toplevel" state. This is exactly + // how markdown.pl works. + this.token(cap, top, true); + + this.tokens.push({ + type: 'blockquote_end' + }); + + continue; + } + + // list + if (cap = this.rules.list.exec(src)) { + src = src.substring(cap[0].length); + bull = cap[2]; + + this.tokens.push({ + type: 'list_start', + ordered: bull.length > 1 + }); + + // Get each top-level item. + cap = cap[0].match(this.rules.item); + + next = false; + l = cap.length; + i = 0; + + for (; i < l; i++) { + item = cap[i]; + + // Remove the list item's bullet + // so it is seen as the next token. + space = item.length; + item = item.replace(/^ *([*+-]|\d+\.) +/, ''); + + // Outdent whatever the + // list item contains. Hacky. + if (~item.indexOf('\n ')) { + space -= item.length; + item = !this.options.pedantic + ? item.replace(new RegExp('^ {1,' + space + '}', 'gm'), '') + : item.replace(/^ {1,4}/gm, ''); + } + + // Determine whether the next list item belongs here. + // Backpedal if it does not belong in this list. + if (this.options.smartLists && i !== l - 1) { + b = block.bullet.exec(cap[i + 1])[0]; + if (bull !== b && !(bull.length > 1 && b.length > 1)) { + src = cap.slice(i + 1).join('\n') + src; + i = l - 1; + } + } + + // Determine whether item is loose or not. + // Use: /(^|\n)(?! )[^\n]+\n\n(?!\s*$)/ + // for discount behavior. + loose = next || /\n\n(?!\s*$)/.test(item); + if (i !== l - 1) { + next = item.charAt(item.length - 1) === '\n'; + if (!loose) loose = next; + } + + this.tokens.push({ + type: loose + ? 'loose_item_start' + : 'list_item_start' + }); + + // Recurse. + this.token(item, false, bq); + + this.tokens.push({ + type: 'list_item_end' + }); + } + + this.tokens.push({ + type: 'list_end' + }); + + continue; + } + + // html + if (cap = this.rules.html.exec(src)) { + src = src.substring(cap[0].length); + this.tokens.push({ + type: this.options.sanitize + ? 'paragraph' + : 'html', + pre: !this.options.sanitizer + && (cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style'), + text: cap[0] + }); + continue; + } + + // def + if ((!bq && top) && (cap = this.rules.def.exec(src))) { + src = src.substring(cap[0].length); + this.tokens.links[cap[1].toLowerCase()] = { + href: cap[2], + title: cap[3] + }; + continue; + } + + // table (gfm) + if (top && (cap = this.rules.table.exec(src))) { + src = src.substring(cap[0].length); + + item = { + type: 'table', + header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */), + align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */), + cells: cap[3].replace(/(?: *\| *)?\n$/, '').split('\n') + }; + + for (i = 0; i < item.align.length; i++) { + if (/^ *-+: *$/.test(item.align[i])) { + item.align[i] = 'right'; + } else if (/^ *:-+: *$/.test(item.align[i])) { + item.align[i] = 'center'; + } else if (/^ *:-+ *$/.test(item.align[i])) { + item.align[i] = 'left'; + } else { + item.align[i] = null; + } + } + + for (i = 0; i < item.cells.length; i++) { + item.cells[i] = item.cells[i] + .replace(/^ *\| *| *\| *$/g, '') + .split(/ *\| */); + } + + this.tokens.push(item); + + continue; + } + + // top-level paragraph + if (top && (cap = this.rules.paragraph.exec(src))) { + src = src.substring(cap[0].length); + this.tokens.push({ + type: 'paragraph', + text: cap[1].charAt(cap[1].length - 1) === '\n' + ? cap[1].slice(0, -1) + : cap[1] + }); + continue; + } + + // text + if (cap = this.rules.text.exec(src)) { + // Top-level should never reach here. + src = src.substring(cap[0].length); + this.tokens.push({ + type: 'text', + text: cap[0] + }); + continue; + } + + if (src) { + throw new + Error('Infinite loop on byte: ' + src.charCodeAt(0)); + } + } + + return this.tokens; +}; + +/** + * Inline-Level Grammar + */ + +var inline = { + escape: /^\\([\\`*{}\[\]()#+\-.!_>])/, + autolink: /^<([^ >]+(@|:\/)[^ >]+)>/, + url: noop, + tag: /^|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/, + link: /^!?\[(inside)\]\(href\)/, + reflink: /^!?\[(inside)\]\s*\[([^\]]*)\]/, + nolink: /^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/, + strong: /^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/, + em: /^\b_((?:[^_]|__)+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/, + code: /^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/, + br: /^ {2,}\n(?!\s*$)/, + del: noop, + text: /^[\s\S]+?(?=[\\?(?:\s+['"]([\s\S]*?)['"])?\s*/; + +inline.link = replace(inline.link) + ('inside', inline._inside) + ('href', inline._href) + (); + +inline.reflink = replace(inline.reflink) + ('inside', inline._inside) + (); + +/** + * Normal Inline Grammar + */ + +inline.normal = merge({}, inline); + +/** + * Pedantic Inline Grammar + */ + +inline.pedantic = merge({}, inline.normal, { + strong: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/, + em: /^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/ +}); + +/** + * GFM Inline Grammar + */ + +inline.gfm = merge({}, inline.normal, { + escape: replace(inline.escape)('])', '~|])')(), + url: /^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/, + del: /^~~(?=\S)([\s\S]*?\S)~~/, + text: replace(inline.text) + (']|', '~]|') + ('|', '|https?://|') + () +}); + +/** + * GFM + Line Breaks Inline Grammar + */ + +inline.breaks = merge({}, inline.gfm, { + br: replace(inline.br)('{2,}', '*')(), + text: replace(inline.gfm.text)('{2,}', '*')() +}); + +/** + * Inline Lexer & Compiler + */ + +function InlineLexer(links, options) { + this.options = options || marked.defaults; + this.links = links; + this.rules = inline.normal; + this.renderer = this.options.renderer || new Renderer; + this.renderer.options = this.options; + + if (!this.links) { + throw new + Error('Tokens array requires a `links` property.'); + } + + if (this.options.gfm) { + if (this.options.breaks) { + this.rules = inline.breaks; + } else { + this.rules = inline.gfm; + } + } else if (this.options.pedantic) { + this.rules = inline.pedantic; + } +} + +/** + * Expose Inline Rules + */ + +InlineLexer.rules = inline; + +/** + * Static Lexing/Compiling Method + */ + +InlineLexer.output = function(src, links, options) { + var inline = new InlineLexer(links, options); + return inline.output(src); +}; + +/** + * Lexing/Compiling + */ + +InlineLexer.prototype.output = function(src) { + var out = '' + , link + , text + , href + , cap; + + while (src) { + // escape + if (cap = this.rules.escape.exec(src)) { + src = src.substring(cap[0].length); + out += cap[1]; + continue; + } + + // autolink + if (cap = this.rules.autolink.exec(src)) { + src = src.substring(cap[0].length); + if (cap[2] === '@') { + text = cap[1].charAt(6) === ':' + ? this.mangle(cap[1].substring(7)) + : this.mangle(cap[1]); + href = this.mangle('mailto:') + text; + } else { + text = escape(cap[1]); + href = text; + } + out += this.renderer.link(href, null, text); + continue; + } + + // url (gfm) + if (!this.inLink && (cap = this.rules.url.exec(src))) { + src = src.substring(cap[0].length); + text = escape(cap[1]); + href = text; + out += this.renderer.link(href, null, text); + continue; + } + + // tag + if (cap = this.rules.tag.exec(src)) { + if (!this.inLink && /^/i.test(cap[0])) { + this.inLink = false; + } + src = src.substring(cap[0].length); + out += this.options.sanitize + ? this.options.sanitizer + ? this.options.sanitizer(cap[0]) + : escape(cap[0]) + : cap[0] + continue; + } + + // link + if (cap = this.rules.link.exec(src)) { + src = src.substring(cap[0].length); + this.inLink = true; + out += this.outputLink(cap, { + href: cap[2], + title: cap[3] + }); + this.inLink = false; + continue; + } + + // reflink, nolink + if ((cap = this.rules.reflink.exec(src)) + || (cap = this.rules.nolink.exec(src))) { + src = src.substring(cap[0].length); + link = (cap[2] || cap[1]).replace(/\s+/g, ' '); + link = this.links[link.toLowerCase()]; + if (!link || !link.href) { + out += cap[0].charAt(0); + src = cap[0].substring(1) + src; + continue; + } + this.inLink = true; + out += this.outputLink(cap, link); + this.inLink = false; + continue; + } + + // strong + if (cap = this.rules.strong.exec(src)) { + src = src.substring(cap[0].length); + out += this.renderer.strong(this.output(cap[2] || cap[1])); + continue; + } + + // em + if (cap = this.rules.em.exec(src)) { + src = src.substring(cap[0].length); + out += this.renderer.em(this.output(cap[2] || cap[1])); + continue; + } + + // code + if (cap = this.rules.code.exec(src)) { + src = src.substring(cap[0].length); + out += this.renderer.codespan(escape(cap[2], true)); + continue; + } + + // br + if (cap = this.rules.br.exec(src)) { + src = src.substring(cap[0].length); + out += this.renderer.br(); + continue; + } + + // del (gfm) + if (cap = this.rules.del.exec(src)) { + src = src.substring(cap[0].length); + out += this.renderer.del(this.output(cap[1])); + continue; + } + + // text + if (cap = this.rules.text.exec(src)) { + src = src.substring(cap[0].length); + out += this.renderer.text(escape(this.smartypants(cap[0]))); + continue; + } + + if (src) { + throw new + Error('Infinite loop on byte: ' + src.charCodeAt(0)); + } + } + + return out; +}; + +/** + * Compile Link + */ + +InlineLexer.prototype.outputLink = function(cap, link) { + var href = escape(link.href) + , title = link.title ? escape(link.title) : null; + + return cap[0].charAt(0) !== '!' + ? this.renderer.link(href, title, this.output(cap[1])) + : this.renderer.image(href, title, escape(cap[1])); +}; + +/** + * Smartypants Transformations + */ + +InlineLexer.prototype.smartypants = function(text) { + if (!this.options.smartypants) return text; + return text + // em-dashes + .replace(/---/g, '\u2014') + // en-dashes + .replace(/--/g, '\u2013') + // opening singles + .replace(/(^|[-\u2014/(\[{"\s])'/g, '$1\u2018') + // closing singles & apostrophes + .replace(/'/g, '\u2019') + // opening doubles + .replace(/(^|[-\u2014/(\[{\u2018\s])"/g, '$1\u201c') + // closing doubles + .replace(/"/g, '\u201d') + // ellipses + .replace(/\.{3}/g, '\u2026'); +}; + +/** + * Mangle Links + */ + +InlineLexer.prototype.mangle = function(text) { + if (!this.options.mangle) return text; + var out = '' + , l = text.length + , i = 0 + , ch; + + for (; i < l; i++) { + ch = text.charCodeAt(i); + if (Math.random() > 0.5) { + ch = 'x' + ch.toString(16); + } + out += '&#' + ch + ';'; + } + + return out; +}; + +/** + * Renderer + */ + +function Renderer(options) { + this.options = options || {}; +} + +Renderer.prototype.code = function(code, lang, escaped) { + if (this.options.highlight) { + var out = this.options.highlight(code, lang); + if (out != null && out !== code) { + escaped = true; + code = out; + } + } + + if (!lang) { + return '
'
+      + (escaped ? code : escape(code, true))
+      + '\n
'; + } + + return '
'
+    + (escaped ? code : escape(code, true))
+    + '\n
\n'; +}; + +Renderer.prototype.blockquote = function(quote) { + return '
\n' + quote + '
\n'; +}; + +Renderer.prototype.html = function(html) { + return html; +}; + +Renderer.prototype.heading = function(text, level, raw) { + return '' + + text + + '\n'; +}; + +Renderer.prototype.hr = function() { + return this.options.xhtml ? '
\n' : '
\n'; +}; + +Renderer.prototype.list = function(body, ordered) { + var type = ordered ? 'ol' : 'ul'; + return '<' + type + '>\n' + body + '\n'; +}; + +Renderer.prototype.listitem = function(text) { + return '
  • ' + text + '
  • \n'; +}; + +Renderer.prototype.paragraph = function(text) { + return '

    ' + text + '

    \n'; +}; + +Renderer.prototype.table = function(header, body) { + return '\n' + + '\n' + + header + + '\n' + + '\n' + + body + + '\n' + + '
    \n'; +}; + +Renderer.prototype.tablerow = function(content) { + return '\n' + content + '\n'; +}; + +Renderer.prototype.tablecell = function(content, flags) { + var type = flags.header ? 'th' : 'td'; + var tag = flags.align + ? '<' + type + ' style="text-align:' + flags.align + '">' + : '<' + type + '>'; + return tag + content + '\n'; +}; + +// span level renderer +Renderer.prototype.strong = function(text) { + return '' + text + ''; +}; + +Renderer.prototype.em = function(text) { + return '' + text + ''; +}; + +Renderer.prototype.codespan = function(text) { + return '' + text + ''; +}; + +Renderer.prototype.br = function() { + return this.options.xhtml ? '
    ' : '
    '; +}; + +Renderer.prototype.del = function(text) { + return '' + text + ''; +}; + +Renderer.prototype.link = function(href, title, text) { + if (this.options.sanitize) { + try { + var prot = decodeURIComponent(unescape(href)) + .replace(/[^\w:]/g, '') + .toLowerCase(); + } catch (e) { + return ''; + } + if (prot.indexOf('javascript:') === 0 || prot.indexOf('vbscript:') === 0 || prot.indexOf('data:') === 0) { + return ''; + } + } + var out = '
    '; + return out; +}; + +Renderer.prototype.image = function(href, title, text) { + var out = '' + text + '' : '>'; + return out; +}; + +Renderer.prototype.text = function(text) { + return text; +}; + +/** + * Parsing & Compiling + */ + +function Parser(options) { + this.tokens = []; + this.token = null; + this.options = options || marked.defaults; + this.options.renderer = this.options.renderer || new Renderer; + this.renderer = this.options.renderer; + this.renderer.options = this.options; +} + +/** + * Static Parse Method + */ + +Parser.parse = function(src, options, renderer) { + var parser = new Parser(options, renderer); + return parser.parse(src); +}; + +/** + * Parse Loop + */ + +Parser.prototype.parse = function(src) { + this.inline = new InlineLexer(src.links, this.options, this.renderer); + this.tokens = src.reverse(); + + var out = ''; + while (this.next()) { + out += this.tok(); + } + + return out; +}; + +/** + * Next Token + */ + +Parser.prototype.next = function() { + return this.token = this.tokens.pop(); +}; + +/** + * Preview Next Token + */ + +Parser.prototype.peek = function() { + return this.tokens[this.tokens.length - 1] || 0; +}; + +/** + * Parse Text Tokens + */ + +Parser.prototype.parseText = function() { + var body = this.token.text; + + while (this.peek().type === 'text') { + body += '\n' + this.next().text; + } + + return this.inline.output(body); +}; + +/** + * Parse Current Token + */ + +Parser.prototype.tok = function() { + switch (this.token.type) { + case 'space': { + return ''; + } + case 'hr': { + return this.renderer.hr(); + } + case 'heading': { + return this.renderer.heading( + this.inline.output(this.token.text), + this.token.depth, + this.token.text); + } + case 'code': { + return this.renderer.code(this.token.text, + this.token.lang, + this.token.escaped); + } + case 'table': { + var header = '' + , body = '' + , i + , row + , cell + , flags + , j; + + // header + cell = ''; + for (i = 0; i < this.token.header.length; i++) { + flags = { header: true, align: this.token.align[i] }; + cell += this.renderer.tablecell( + this.inline.output(this.token.header[i]), + { header: true, align: this.token.align[i] } + ); + } + header += this.renderer.tablerow(cell); + + for (i = 0; i < this.token.cells.length; i++) { + row = this.token.cells[i]; + + cell = ''; + for (j = 0; j < row.length; j++) { + cell += this.renderer.tablecell( + this.inline.output(row[j]), + { header: false, align: this.token.align[j] } + ); + } + + body += this.renderer.tablerow(cell); + } + return this.renderer.table(header, body); + } + case 'blockquote_start': { + var body = ''; + + while (this.next().type !== 'blockquote_end') { + body += this.tok(); + } + + return this.renderer.blockquote(body); + } + case 'list_start': { + var body = '' + , ordered = this.token.ordered; + + while (this.next().type !== 'list_end') { + body += this.tok(); + } + + return this.renderer.list(body, ordered); + } + case 'list_item_start': { + var body = ''; + + while (this.next().type !== 'list_item_end') { + body += this.token.type === 'text' + ? this.parseText() + : this.tok(); + } + + return this.renderer.listitem(body); + } + case 'loose_item_start': { + var body = ''; + + while (this.next().type !== 'list_item_end') { + body += this.tok(); + } + + return this.renderer.listitem(body); + } + case 'html': { + var html = !this.token.pre && !this.options.pedantic + ? this.inline.output(this.token.text) + : this.token.text; + return this.renderer.html(html); + } + case 'paragraph': { + return this.renderer.paragraph(this.inline.output(this.token.text)); + } + case 'text': { + return this.renderer.paragraph(this.parseText()); + } + } +}; + +/** + * Helpers + */ + +function escape(html, encode) { + return html + .replace(!encode ? /&(?!#?\w+;)/g : /&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"') + .replace(/'/g, '''); +} + +function unescape(html) { + // explicitly match decimal, hex, and named HTML entities + return html.replace(/&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/g, function(_, n) { + n = n.toLowerCase(); + if (n === 'colon') return ':'; + if (n.charAt(0) === '#') { + return n.charAt(1) === 'x' + ? String.fromCharCode(parseInt(n.substring(2), 16)) + : String.fromCharCode(+n.substring(1)); + } + return ''; + }); +} + +function replace(regex, opt) { + regex = regex.source; + opt = opt || ''; + return function self(name, val) { + if (!name) return new RegExp(regex, opt); + val = val.source || val; + val = val.replace(/(^|[^\[])\^/g, '$1'); + regex = regex.replace(name, val); + return self; + }; +} + +function noop() {} +noop.exec = noop; + +function merge(obj) { + var i = 1 + , target + , key; + + for (; i < arguments.length; i++) { + target = arguments[i]; + for (key in target) { + if (Object.prototype.hasOwnProperty.call(target, key)) { + obj[key] = target[key]; + } + } + } + + return obj; +} + + +/** + * Marked + */ + +function marked(src, opt, callback) { + if (callback || typeof opt === 'function') { + if (!callback) { + callback = opt; + opt = null; + } + + opt = merge({}, marked.defaults, opt || {}); + + var highlight = opt.highlight + , tokens + , pending + , i = 0; + + try { + tokens = Lexer.lex(src, opt) + } catch (e) { + return callback(e); + } + + pending = tokens.length; + + var done = function(err) { + if (err) { + opt.highlight = highlight; + return callback(err); + } + + var out; + + try { + out = Parser.parse(tokens, opt); + } catch (e) { + err = e; + } + + opt.highlight = highlight; + + return err + ? callback(err) + : callback(null, out); + }; + + if (!highlight || highlight.length < 3) { + return done(); + } + + delete opt.highlight; + + if (!pending) return done(); + + for (; i < tokens.length; i++) { + (function(token) { + if (token.type !== 'code') { + return --pending || done(); + } + return highlight(token.text, token.lang, function(err, code) { + if (err) return done(err); + if (code == null || code === token.text) { + return --pending || done(); + } + token.text = code; + token.escaped = true; + --pending || done(); + }); + })(tokens[i]); + } + + return; + } + try { + if (opt) opt = merge({}, marked.defaults, opt); + return Parser.parse(Lexer.lex(src, opt), opt); + } catch (e) { + e.message += '\nPlease report this to https://github.com/chjj/marked.'; + if ((opt || marked.defaults).silent) { + return '

    An error occured:

    '
    +        + escape(e.message + '', true)
    +        + '
    '; + } + throw e; + } +} + +/** + * Options + */ + +marked.options = +marked.setOptions = function(opt) { + merge(marked.defaults, opt); + return marked; +}; + +marked.defaults = { + gfm: true, + tables: true, + breaks: false, + pedantic: false, + sanitize: false, + sanitizer: null, + mangle: true, + smartLists: false, + silent: false, + highlight: null, + langPrefix: 'lang-', + smartypants: false, + headerPrefix: '', + renderer: new Renderer, + xhtml: false +}; + +/** + * Expose + */ + +marked.Parser = Parser; +marked.parser = Parser.parse; + +marked.Renderer = Renderer; + +marked.Lexer = Lexer; +marked.lexer = Lexer.lex; + +marked.InlineLexer = InlineLexer; +marked.inlineLexer = InlineLexer.output; + +marked.parse = marked; + +if (typeof module !== 'undefined' && typeof exports === 'object') { + module.exports = marked; +} else if (typeof define === 'function' && define.amd) { + define(function() { return marked; }); +} else { + this.marked = marked; +} + +}).call(function() { + return this || (typeof window !== 'undefined' ? window : global); +}());