├── README.md
├── img
├── bg.png
└── loading.gif
├── data-default
├── data.json
└── users
│ └── content-default.json
├── js
├── utils
│ ├── RateLimit.coffee
│ ├── Class.coffee
│ ├── Time.coffee
│ ├── ZeroFrame.coffee
│ ├── Text.coffee
│ └── InlineEditor.coffee
├── lib
│ ├── jquery.cssanim.coffee
│ ├── jquery.csslater.coffee
│ ├── identicon.js
│ ├── pnglib.js
│ ├── marked.min.js
│ └── highlight.pack.js
├── Comments.coffee
└── Gifs.coffee
├── data
└── users
│ └── content.json
├── updater
├── cleanup.py
└── updater.py
├── dbschema.json
├── css
├── icons.css
├── Comments.css
└── Gifs.css
├── index.html
└── LICENSE
/README.md:
--------------------------------------------------------------------------------
1 | # ReactionGIFs
2 | ReactionGIFs ZeroNet site
3 |
--------------------------------------------------------------------------------
/img/bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HelloZeroNet/ReactionGIFs/master/img/bg.png
--------------------------------------------------------------------------------
/img/loading.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HelloZeroNet/ReactionGIFs/master/img/loading.gif
--------------------------------------------------------------------------------
/data-default/data.json:
--------------------------------------------------------------------------------
1 | {
2 | "title": "MyZeroBlog",
3 | "description": "My ZeroBlog.",
4 | "links": "- [Source code](https://github.com/HelloZeroNet)",
5 | "next_post_id": 2,
6 | "demo": false,
7 | "modified": 1432515193,
8 | "post": [
9 | {
10 | "post_id": 1,
11 | "title": "Congratulations!",
12 | "date_published": 1433033779.604,
13 | "body": "Your zeronet blog has been successfully created!"
14 | }
15 | ]
16 | }
--------------------------------------------------------------------------------
/js/utils/RateLimit.coffee:
--------------------------------------------------------------------------------
1 | limits = {}
2 | call_after_interval = {}
3 | window.RateLimit = (interval, fn) ->
4 | if not limits[fn]
5 | call_after_interval[fn] = false
6 | fn() # First call is not delayed
7 | limits[fn] = setTimeout (->
8 | if call_after_interval[fn]
9 | fn()
10 | delete limits[fn]
11 | delete call_after_interval[fn]
12 | ), interval
13 | else # Called within iterval, delay the call
14 | call_after_interval[fn] = true
15 |
--------------------------------------------------------------------------------
/js/utils/Class.coffee:
--------------------------------------------------------------------------------
1 | class Class
2 | trace: true
3 |
4 | log: (args...) ->
5 | return unless @trace
6 | return if typeof console is 'undefined'
7 | args.unshift("[#{@.constructor.name}]")
8 | console.log(args...)
9 | @
10 |
11 | logStart: (name, args...) ->
12 | return unless @trace
13 | @logtimers or= {}
14 | @logtimers[name] = +(new Date)
15 | @log "#{name}", args..., "(started)" if args.length > 0
16 | @
17 |
18 | logEnd: (name, args...) ->
19 | ms = +(new Date)-@logtimers[name]
20 | @log "#{name}", args..., "(Done in #{ms}ms)"
21 | @
22 |
23 | window.Class = Class
--------------------------------------------------------------------------------
/data/users/content.json:
--------------------------------------------------------------------------------
1 | {
2 | "files": {},
3 | "ignore": ".*",
4 | "modified": 1447023686.64,
5 | "signs": {
6 | "1Gif7PqWTzVWDQ42Mo7np3zXmGAo3DXc7h": "HE/+syGEMkrg20HJsDPCDfM8IkauzrkfoL0N3Nw9O1u9H+II1V6+RYA3SthoMAVF7p+zot6Chczb1zDZHsX02K8="
7 | },
8 | "user_contents": {
9 | "cert_signers": {
10 | "zeroid.bit": [ "1iD5ZQJMNXu43w1qLB8sfdHVKppVMduGz" ]
11 | },
12 | "permission_rules": {
13 | ".*": {
14 | "files_allowed": "data.json",
15 | "max_size": 10000
16 | },
17 | "bitid/.*@zeroid.bit": { "max_size": 40000 },
18 | "bitmsg/.*@zeroid.bit": { "max_size": 15000 }
19 | },
20 | "permissions": {
21 | "banexample@zeroid.bit": false,
22 | "nofish@zeroid.bit": { "max_size": 20000 }
23 | }
24 | }
25 | }
--------------------------------------------------------------------------------
/data-default/users/content-default.json:
--------------------------------------------------------------------------------
1 | {
2 | "files": {},
3 | "ignore": ".*",
4 | "modified": 1432466966.003,
5 | "signs": {
6 | "1BLogC9LN4oPDcruNz3qo1ysa133E9AGg8": "HChU28lG4MCnAiui6wDAaVCD4QUrgSy4zZ67+MMHidcUJRkLGnO3j4Eb1N0AWQ86nhSBwoOQf08Rha7gRyTDlAk="
7 | },
8 | "user_contents": {
9 | "cert_signers": {
10 | "zeroid.bit": [ "1iD5ZQJMNXu43w1qLB8sfdHVKppVMduGz" ]
11 | },
12 | "permission_rules": {
13 | ".*": {
14 | "files_allowed": "data.json",
15 | "max_size": 10000
16 | },
17 | "bitid/.*@zeroid.bit": { "max_size": 40000 },
18 | "bitmsg/.*@zeroid.bit": { "max_size": 15000 }
19 | },
20 | "permissions": {
21 | "banexample@zeroid.bit": false,
22 | "nofish@zeroid.bit": { "max_size": 20000 }
23 | }
24 | }
25 | }
--------------------------------------------------------------------------------
/js/lib/jquery.cssanim.coffee:
--------------------------------------------------------------------------------
1 | jQuery.fn.cssSlideDown = ->
2 | elem = @
3 | elem.css({"opacity": 0, "margin-bottom": 0, "margin-top": 0, "padding-bottom": 0, "padding-top": 0, "display": "none", "transform": "scale(0.8)"})
4 | setTimeout (->
5 | elem.css("display", "")
6 | height = elem.outerHeight()
7 | elem.css({"height": 0, "display": ""}).cssLater("transition", "all 0.3s ease-out", 20)
8 | elem.cssLater({"height": height, "opacity": 1, "margin-bottom": "", "margin-top": "", "padding-bottom": "", "padding-top": "", "transform": "scale(1)"}, null, 40)
9 | elem.cssLater("transition", "", 1000, "noclear")
10 | ), 10
11 | return @
12 |
13 |
14 | jQuery.fn.fancySlideDown = ->
15 | elem = @
16 | elem.css({"opacity": 0, "transform":"scale(0.9)"}).slideDown().animate({"opacity": 1, "scale": 1}, {"duration": 600, "queue": false, "easing": "easeOutBack"})
17 |
18 |
19 | jQuery.fn.fancySlideUp = ->
20 | elem = @
21 | elem.delay(600).slideUp(600).animate({"opacity": 0, "scale": 0.9}, {"duration": 600, "queue": false, "easing": "easeOutQuad"})
22 |
--------------------------------------------------------------------------------
/js/utils/Time.coffee:
--------------------------------------------------------------------------------
1 | class Time
2 | since: (time) ->
3 | now = +(new Date)/1000
4 | secs = now - time
5 | if secs < 60
6 | back = "Just now"
7 | else if secs < 60*60
8 | back = "#{Math.round(secs/60)} minutes ago"
9 | else if secs < 60*60*24
10 | back = "#{Math.round(secs/60/60)} hours ago"
11 | else if secs < 60*60*24*3
12 | back = "#{Math.round(secs/60/60/24)} days ago"
13 | else
14 | back = "on "+@date(time)
15 | back = back.replace(/1 ([a-z]+)s/, "1 $1") # 1 days ago fix
16 | return back
17 |
18 |
19 | date: (timestamp, format="short") ->
20 | parts = (new Date(timestamp*1000)).toString().split(" ")
21 | if format == "short"
22 | display = parts.slice(1, 4)
23 | else
24 | display = parts.slice(1, 5)
25 | return display.join(" ").replace(/( [0-9]{4})/, ",$1")
26 |
27 |
28 | timestamp: (date="") ->
29 | if date == "now" or date == ""
30 | return parseInt(+(new Date)/1000)
31 | else
32 | return parseInt(Date.parse(date)/1000)
33 |
34 |
35 | # Get elistamated read time for post
36 | readtime: (text) ->
37 | chars = text.length
38 | if chars > 1500
39 | return parseInt(chars/1500)+" min read"
40 | else
41 | return "less than 1 min read"
42 |
43 |
44 | window.Time = new Time
--------------------------------------------------------------------------------
/updater/cleanup.py:
--------------------------------------------------------------------------------
1 | import sqlite3
2 | import re
3 | import json
4 | import os
5 | import time
6 |
7 | db = sqlite3.connect("../data/zeroblog.db")
8 | db.row_factory = sqlite3.Row
9 | c = db.cursor()
10 |
11 | query = """
12 | SELECT
13 | post.*, COUNT(comment_id) AS comments, MAX(comment.date_added) AS last_comment,
14 | (SELECT COUNT(*) FROM post_vote WHERE post_vote.post_id = post.post_id) AS votes
15 | FROM post
16 | LEFT JOIN comment USING (post_id)
17 | WHERE date_published < strftime('%s', 'now','-20 day')
18 | GROUP BY post_id
19 | HAVING comments = 0 AND votes < 4
20 | ORDER BY date_published
21 | LIMIT 500
22 | """
23 | deleted = 0
24 | data = json.load(open("../data/data.json", "rb"))
25 | print "Posts:", len(data["post"])
26 | for row in c.execute(query):
27 | days = float(time.time() - row["date_published"]) / (60*60*24)
28 | if days < 20:
29 | print "! Skipping, days: %.3f" % days
30 | continue
31 | deleted += 1
32 | mp4_file = re.match('.*?src="(.*?)"', row["body"]).group(1)
33 | data["post"] = filter(lambda post: post["post_id"] != row["post_id"], data["post"])
34 | print u"Deleting %s / %s" % (row["source"], repr(row["title"])), mp4_file, round(days, 2)
35 | try:
36 | os.unlink("../" + mp4_file)
37 | except Exception, err:
38 | print "Error deleting: %s" % err
39 | raw_input("Continue?")
40 |
41 | print "Deleted:", deleted,
42 | print "Posts:", len(data["post"])
43 | json.dump(data, open("../data/data.json-new", "wb"), indent=1, sort_keys=True)
44 |
--------------------------------------------------------------------------------
/js/utils/ZeroFrame.coffee:
--------------------------------------------------------------------------------
1 | class ZeroFrame extends Class
2 | constructor: (url) ->
3 | @url = url
4 | @waiting_cb = {}
5 | @connect()
6 | @next_message_id = 1
7 | @init()
8 |
9 |
10 | init: ->
11 | @
12 |
13 |
14 | connect: ->
15 | @target = window.parent
16 | window.addEventListener("message", @onMessage, false)
17 | @cmd("innerReady")
18 |
19 |
20 | onMessage: (e) =>
21 | message = e.data
22 | cmd = message.cmd
23 | if cmd == "response"
24 | if @waiting_cb[message.to]?
25 | @waiting_cb[message.to](message.result)
26 | else
27 | @log "Websocket callback not found:", message
28 | else if cmd == "wrapperReady" # Wrapper inited later
29 | @cmd("innerReady")
30 | else if cmd == "ping"
31 | @response message.id, "pong"
32 | else if cmd == "wrapperOpenedWebsocket"
33 | @onOpenWebsocket()
34 | else if cmd == "wrapperClosedWebsocket"
35 | @onCloseWebsocket()
36 | else
37 | @onRequest cmd, message
38 |
39 |
40 | onRequest: (cmd, message) =>
41 | @log "Unknown request", message
42 |
43 |
44 | response: (to, result) ->
45 | @send {"cmd": "response", "to": to, "result": result}
46 |
47 |
48 | cmd: (cmd, params={}, cb=null) ->
49 | @send {"cmd": cmd, "params": params}, cb
50 |
51 |
52 | send: (message, cb=null) ->
53 | message.id = @next_message_id
54 | @next_message_id += 1
55 | @target.postMessage(message, "*")
56 | if cb
57 | @waiting_cb[message.id] = cb
58 |
59 |
60 | onOpenWebsocket: =>
61 | @log "Websocket open"
62 |
63 |
64 | onCloseWebsocket: =>
65 | @log "Websocket close"
66 |
67 |
68 |
69 | window.ZeroFrame = ZeroFrame
70 |
--------------------------------------------------------------------------------
/js/utils/Text.coffee:
--------------------------------------------------------------------------------
1 | class Renderer extends marked.Renderer
2 | image: (href, title, text) ->
3 | return (" "+text+"")
4 |
5 | class Text
6 | toColor: (text) ->
7 | hash = 0
8 | for i in [0..text.length-1]
9 | hash = text.charCodeAt(i) + ((hash << 5) - hash)
10 | color = '#'
11 | return "hsl(" + (hash % 360) + ",30%,70%)";
12 | for i in [0..2]
13 | value = (hash >> (i * 8)) & 0xFF
14 | color += ('00' + value.toString(16)).substr(-2)
15 | return color
16 |
17 |
18 | renderMarked: (text, options={}) ->
19 | options["gfm"] = true
20 | options["breaks"] = true
21 | if options.sanitize
22 | options["renderer"] = renderer # Dont allow images
23 | text = @fixReply(text)
24 | text = marked(text, options)
25 | return @fixHtmlLinks text
26 |
27 |
28 | # Convert zeronet html links to relaitve
29 | fixHtmlLinks: (text) ->
30 | if window.is_proxy
31 | return text.replace(/href="http:\/\/(127.0.0.1|localhost):43110/g, 'href="http://zero')
32 | else
33 | return text.replace(/href="http:\/\/(127.0.0.1|localhost):43110/g, 'href="')
34 |
35 |
36 | # Convert a single link to relative
37 | fixLink: (link) ->
38 | if window.is_proxy
39 | return link.replace(/http:\/\/(127.0.0.1|localhost):43110/, 'http://zero')
40 | else
41 | return link.replace(/http:\/\/(127.0.0.1|localhost):43110/, '')
42 |
43 |
44 | fixReply: (text) ->
45 | return text.replace(/(>.*\n)([^\n>])/gm, "$1\n$2")
46 |
47 |
48 | toUrl: (text) =>
49 | return text.replace(/[^A-Za-z0-9]/g, "+").replace(/[+]+/g, "+").replace(/[+]+$/, "")
50 |
51 | window.is_proxy = (window.location.pathname == "/")
52 | window.renderer = new Renderer()
53 | window.Text = new Text()
54 |
--------------------------------------------------------------------------------
/js/lib/jquery.csslater.coffee:
--------------------------------------------------------------------------------
1 | jQuery.fn.readdClass = (class_name) ->
2 | elem = @
3 | elem.removeClass class_name
4 | setTimeout ( ->
5 | elem.addClass class_name
6 | ), 1
7 | return @
8 |
9 | jQuery.fn.removeLater = (time = 500) ->
10 | elem = @
11 | setTimeout ( ->
12 | elem.remove()
13 | ), time
14 | return @
15 |
16 | jQuery.fn.hideLater = (time = 500) ->
17 | @.cssLater("display", "none", time)
18 | return @
19 |
20 | jQuery.fn.addClassLater = (class_name, time=5, mode="clear") ->
21 | elem = @
22 | elem[0].timers ?= {}
23 | timers = elem[0].timers
24 |
25 | if timers[class_name] and mode == "clear" then clearInterval(timers[class_name])
26 | timers[class_name] = setTimeout ( ->
27 | elem.addClass(class_name)
28 | ), time
29 | return @
30 |
31 | jQuery.fn.removeClassLater = (class_name, time=500, mode="clear") ->
32 | elem = @
33 | elem[0].timers ?= {}
34 | timers = elem[0].timers
35 |
36 | if timers[class_name] and mode == "clear" then clearInterval(timers[class_name])
37 | timers[class_name] = setTimeout ( ->
38 | elem.removeClass(class_name)
39 | ), time
40 | return @
41 |
42 | jQuery.fn.cssLater = (name, val, time=500, mode="clear") ->
43 | elem = @
44 | elem[0].timers ?= {}
45 | timers = elem[0].timers
46 |
47 | if timers[name] and mode == "clear" then clearInterval(timers[name])
48 | if time == "now"
49 | elem.css name, val
50 | else
51 | timers[name] = setTimeout ( ->
52 | elem.css name, val
53 | ), time
54 | return @
55 |
56 |
57 | jQuery.fn.toggleClassLater = (name, val, time=10, mode="clear") ->
58 | elem = @
59 | elem[0].timers ?= {}
60 | timers = elem[0].timers
61 |
62 | if timers[name] and mode == "clear" then clearInterval(timers[name])
63 | timers[name] = setTimeout ( ->
64 | elem.toggleClass name, val
65 | ), time
66 | return @
--------------------------------------------------------------------------------
/dbschema.json:
--------------------------------------------------------------------------------
1 | {
2 | "db_name": "ZeroBlog",
3 | "db_file": "data/zeroblog.db",
4 | "version": 2,
5 | "maps": {
6 | "users/.+/data.json": {
7 | "to_table": [
8 | "comment",
9 | {"node": "comment_vote", "table": "comment_vote", "key_col": "comment_uri", "val_col": "vote"},
10 | {"node": "post_vote", "table": "post_vote", "key_col": "post_id", "val_col": "vote"}
11 | ]
12 | },
13 | "users/.+/content.json": {
14 | "to_keyvalue": [ "cert_user_id" ]
15 | },
16 | "data.json": {
17 | "to_table": [ "post" ],
18 | "to_keyvalue": [ "title", "description", "links", "next_post_id", "demo", "modified" ]
19 | }
20 |
21 | },
22 | "tables": {
23 | "comment": {
24 | "cols": [
25 | ["comment_id", "INTEGER"],
26 | ["post_id", "INTEGER"],
27 | ["body", "TEXT"],
28 | ["date_added", "INTEGER"],
29 | ["json_id", "INTEGER REFERENCES json (json_id)"]
30 | ],
31 | "indexes": ["CREATE UNIQUE INDEX comment_key ON comment(json_id, comment_id)", "CREATE INDEX comment_post_id ON comment(post_id)"],
32 | "schema_changed": 1426195823
33 | },
34 | "comment_vote": {
35 | "cols": [
36 | ["comment_uri", "TEXT"],
37 | ["vote", "INTEGER"],
38 | ["json_id", "INTEGER REFERENCES json (json_id)"]
39 | ],
40 | "indexes": ["CREATE INDEX comment_vote_comment_uri ON comment_vote(comment_uri)", "CREATE INDEX comment_vote_json_id ON comment_vote(json_id)"],
41 | "schema_changed": 1426195822
42 | },
43 | "post": {
44 | "cols": [
45 | ["post_id", "INTEGER"],
46 | ["title", "TEXT"],
47 | ["body", "TEXT"],
48 | ["source", "TEXT"],
49 | ["date_published", "INTEGER"],
50 | ["json_id", "INTEGER REFERENCES json (json_id)"]
51 | ],
52 | "indexes": ["CREATE UNIQUE INDEX post_uri ON post(json_id, post_id)", "CREATE INDEX post_id ON post(post_id)", "CREATE INDEX post_source ON post(source)"],
53 | "schema_changed": 1426195824
54 | },
55 | "post_vote": {
56 | "cols": [
57 | ["post_id", "INTEGER"],
58 | ["vote", "INTEGER"],
59 | ["json_id", "INTEGER REFERENCES json (json_id)"]
60 | ],
61 | "indexes": ["CREATE INDEX post_vote_post_id ON post_vote(post_id)", "CREATE INDEX post_vote_json_id ON post_vote(post_id)"],
62 | "schema_changed": 1426195826
63 | }
64 | }
65 | }
--------------------------------------------------------------------------------
/css/icons.css:
--------------------------------------------------------------------------------
1 | .icon { display: inline-block; vertical-align: text-bottom; background-repeat: no-repeat; }
2 | .icon-profile { font-size: 6px; top: 0em; border-radius: 0.7em 0.7em 0 0; background: #FFFFFF; width: 1.5em; height: 0.7em; position: relative; display: inline-block; margin-right: 4px }
3 | .icon-profile:before { position: absolute; content: ""; top: -1em; left: 0.38em; width: 0.8em; height: 0.85em; border-radius: 50%; background: #FFFFFF; }
4 |
5 | .icon-comment { width: 16px; height: 10px; border-radius: 2px; background: #464545; margin-top: 0px; display: inline-block; position: relative; top: 0px; }
6 | .icon-comment:after { left: 9px; border: 2px solid transparent; border-top-color: #464545; border-left-color: #333; background: transparent; content: ""; display: block; margin-top: 10px; width: 0px; margin-left: 7px; }
7 |
8 | .icon-edit {
9 | width: 16px; height: 16px; background-repeat: no-repeat; background-position: 20px center;
10 | background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAOVBMVEUAAAC9w8e9w8e9w8e9w8e/xMi9w8e9w8e+w8e9w8e9w8e9w8e9w8e9w8e9w8e+w8e/xMi9w8e9w8fvY4+KAAAAEnRSTlMASPv3WQbwOTCkt4/psX4YDMWr+RRCAAAAUUlEQVQY06XLORKAMAxDUTs7kA3d/7AYGju0UfffjIgoHkxm0vB5bZyxKHx9eX0FJw0Y4bcXKQ4/CTtS5yqp5GFFOjGpVGl00k1pNDIb3Nv9AHC7BOZC4ZjvAAAAAElFTkSuQmCC+d0ckOwyAMRVGHUOO0gUyd+P8f7WApz4Iki9wFmyOEATrXLZcFp5LrGogPOxKp6zfFf9fZ1/I/cY7YZSS3U6S3XFZJmGBwL+FuJX/F1K0wUUlZyZGlXgXESthTEs4B8fh7xoVUDPGYJnsfkCRarKAgz8cAKbpD6pqDPz3XB8K6HdUEeN9NAAAAAElFTkSuQmCC);
11 | }
12 | .icon-reply {
13 | width: 16px; height: 16px;
14 | background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAIVBMVEUAAABmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmYs5FxxAAAAC3RSTlMAgBFwYExAMHgoCDJmUTYAAAA3SURBVAjXY8APGGEMQZgAjCEoKBwEEQCCAoiIh6AQVM1kMaguJhGYOSJQjexiUMbiAChDCclCAOHqBBdHpwQTAAAAAElFTkSuQmCC);
15 | }
16 | .icon-heart { position: absolute; width: 17px; height: 13px; margin-top: 5px }
17 | .icon-heart:before, .icon-heart:after {
18 | position: absolute; content: ""; left: 8px; top: 0; width: 8px; height: 13px;
19 | background: #FA6C8D; /*border-radius: 25px 25px 0 0;*/ transform: rotate(-45deg); transform-origin: 0 100%
20 | }
21 | .icon-heart:after { left: 0; transform: rotate(45deg); transform-origin :100% 100% }
22 | .icon-up { font-weight: normal !important; font-size: 15px; font-family: Tahoma; vertical-align: -4px; padding-right: 5px; display: inline; height: 1px; }
--------------------------------------------------------------------------------
/css/Comments.css:
--------------------------------------------------------------------------------
1 | h2#Comments { clear: both }
2 | .comments { margin-bottom: 60px }
3 | .comment { background-color: transparent; padding: 25px 0px; margin: 1px; border-top: 1px solid #35373C }
4 | .comment .user_name { font-size: 14px; font-weight: bold }
5 | .comment .added { color: #AAA }
6 | .comment .reply { color: #CCC; opacity: 0; transition: opacity 0.3s; border: none; position: relative; }
7 | .comment:hover .reply { opacity: 1 }
8 | .comment .reply .icon { opacity: 0.3 }
9 | .comment .reply:hover { border-bottom: none; color: #666 }
10 | .comment .reply:hover .icon { opacity: 1 }
11 | .comment .info { font-size: 12px; color: #AAA; margin-bottom: 7px }
12 | .comment .info .score { margin-left: 5px }
13 | .comment .comment-body { line-height: 1.5em; margin-top: 0.5em; margin-bottom: 0.5em }
14 | .comment .comment-body p { margin-bottom: 0px; margin-top: 0.5em; }
15 | .comment .comment-body p:first-child { margin: 0px; margin-top: 0px; }
16 | .comment .comment-body.editor { margin-top: 0.5em !important; margin-bottom: 0.5em !important }
17 | .comment .comment-body h1, .comment .body h2, .comment .body h3 { font-size: 110% }
18 | .comment .comment-body blockquote { padding: 1px 15px; border-left: 2px solid #3A3939; margin: 0px; margin-top: 30px }
19 | .comment .comment-body blockquote:first-child { margin-top: 0px }
20 | .comment .comment-body blockquote p { margin: 0px; color: #999; font-size: 90% }
21 | .comment .comment-body blockquote a { color: #FFF; font-weight: normal; border-bottom: 0px }
22 | .comment .comment-body blockquote a:hover { border-bottom: 1px solid #999 }
23 | .comment .editable-edit { margin-top: -5px }
24 |
25 | .comment-new { margin-bottom: 5px; border-top: 0px }
26 | .comment-new .button-submit {
27 | margin: 0px; font-weight: normal; padding: 5px 15px; display: inline-block;
28 | background-color: #FFDA00; border-bottom: 2px solid #CDBD1E; font-size: 15px; line-height: 30px
29 | }
30 | .comment-new h2 { margin-bottom: 25px }
31 |
32 | /* Input */
33 | .comment-new textarea {
34 | line-height: 1.5em; width: 100%; padding: 10px; font-family: 'Roboto', sans-serif; font-size: 16px; color: white;
35 | transition: border 0.3s; border: 1px solid #222; box-sizing: border-box; overflow-y: auto; background-color: #1D1D1D;
36 | }
37 | input.text:focus, textarea:focus { border-color: #28404A; outline: none; background-color: #111 }
38 |
39 | .comment-nocert textarea { opacity: 0.5; pointer-events: none }
40 | .comment-nocert .info { opacity: 0.1; pointer-events: none }
41 | .comment-nocert .button-submit-comment { opacity: 0.1; pointer-events: none }
42 | .comment-nocert .button.button-certselect { display: inherit }
43 | .button.button-certselect {
44 | position: absolute; left: 50%; white-space: nowrap; transform: translateX(-50%); z-index: 99;
45 | margin-top: 13px; background-color: #007AFF; color: white; border-bottom-color: #3543F9; display: none
46 | }
47 | .button.button-certselect:hover { background-color: #3396FF; color: white; border-bottom-color: #5D68FF; }
48 | .button.button-certselect:active { position: absolute; transform: translateX(-50%) translateY(1px); top: auto; }
49 |
50 | .user-size { font-size: 11px; margin-top: 6px; box-sizing: border-box; text-transform: uppercase; display: inline-block; color: #AAA }
51 | .user-size-used { position: absolute; color: #B10DC9; overflow: hidden; width: 40px; white-space: nowrap }
52 |
--------------------------------------------------------------------------------
/js/lib/identicon.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Identicon.js v1.0
3 | * http://github.com/stewartlord/identicon.js
4 | *
5 | * Requires PNGLib
6 | * http://www.xarg.org/download/pnglib.js
7 | *
8 | * Copyright 2013, Stewart Lord
9 | * Released under the BSD license
10 | * http://www.opensource.org/licenses/bsd-license.php
11 | */
12 |
13 | (function() {
14 | Identicon = function(hash, size, margin){
15 | this.hash = hash;
16 | this.size = size || 64;
17 | this.margin = margin || .08;
18 | }
19 |
20 | Identicon.prototype = {
21 | hash: null,
22 | size: null,
23 | margin: null,
24 |
25 | render: function(){
26 | var hash = this.hash,
27 | size = this.size,
28 | margin = Math.floor(size * this.margin),
29 | cell = Math.floor((size - (margin * 2)) / 5),
30 | image = new PNGlib(size, size, 256);
31 |
32 | // light-grey background
33 | var bg = image.color(240, 240, 240);
34 |
35 | // foreground is last 7 chars as hue at 50% saturation, 70% brightness
36 | var rgb = this.hsl2rgb(parseInt(hash.substr(-7), 16) / 0xfffffff, .5, .7),
37 | fg = image.color(rgb[0] * 255, rgb[1] * 255, rgb[2] * 255);
38 |
39 | // the first 15 characters of the hash control the pixels (even/odd)
40 | // they are drawn down the middle first, then mirrored outwards
41 | var i, color;
42 | for (i = 0; i < 15; i++) {
43 | color = parseInt(hash.charAt(i), 16) % 2 ? bg : fg;
44 | if (i < 5) {
45 | this.rectangle(2 * cell + margin, i * cell + margin, cell, cell, color, image);
46 | } else if (i < 10) {
47 | this.rectangle(1 * cell + margin, (i - 5) * cell + margin, cell, cell, color, image);
48 | this.rectangle(3 * cell + margin, (i - 5) * cell + margin, cell, cell, color, image);
49 | } else if (i < 15) {
50 | this.rectangle(0 * cell + margin, (i - 10) * cell + margin, cell, cell, color, image);
51 | this.rectangle(4 * cell + margin, (i - 10) * cell + margin, cell, cell, color, image);
52 | }
53 | }
54 |
55 | return image;
56 | },
57 |
58 | rectangle: function(x, y, w, h, color, image) {
59 | var i, j;
60 | for (i = x; i < x + w; i++) {
61 | for (j = y; j < y + h; j++) {
62 | image.buffer[image.index(i, j)] = color;
63 | }
64 | }
65 | },
66 |
67 | // adapted from: https://gist.github.com/aemkei/1325937
68 | hsl2rgb: function(h, s, b){
69 | h *= 6;
70 | s = [
71 | b += s *= b < .5 ? b : 1 - b,
72 | b - h % 1 * s * 2,
73 | b -= s *= 2,
74 | b,
75 | b + h % 1 * s,
76 | b + s
77 | ];
78 |
79 | return[
80 | s[ ~~h % 6 ], // red
81 | s[ (h|16) % 6 ], // green
82 | s[ (h|8) % 6 ] // blue
83 | ];
84 | },
85 |
86 | toString: function(){
87 | return this.render().getBase64();
88 | }
89 | }
90 |
91 | window.Identicon = Identicon;
92 | })();
--------------------------------------------------------------------------------
/js/utils/InlineEditor.coffee:
--------------------------------------------------------------------------------
1 | class InlineEditor
2 | constructor: (@elem, @getContent, @saveContent, @getObject) ->
3 | @edit_button = $("")
4 | @edit_button.on "click", @startEdit
5 | @elem.addClass("editable").before(@edit_button)
6 | @editor = null
7 | @elem.on "mouseenter", (e) =>
8 | @edit_button.css("opacity", "0.4")
9 | # Keep in display
10 | scrolltop = $(window).scrollTop()
11 | top = @edit_button.offset().top-parseInt(@edit_button.css("margin-top"))
12 | if scrolltop > top
13 | @edit_button.css("margin-top", scrolltop-top+e.clientY-20)
14 | else
15 | @edit_button.css("margin-top", "")
16 | @elem.on "mouseleave", =>
17 | @edit_button.css("opacity", "")
18 |
19 | if @elem.is(":hover") then @elem.trigger "mouseenter"
20 |
21 |
22 | startEdit: =>
23 | @content_before = @elem.html() # Save current to restore on cancel
24 |
25 | @editor = $("")
26 | #@editor.css("outline", "10000px solid rgba(255,255,255,0)").cssLater("transition", "outline 0.3s", 5).cssLater("outline", "10000px solid rgba(255,255,255,0.9)", 10) # Animate other elements fadeout
27 | @editor.val @getContent(@elem, "raw")
28 | @elem.after(@editor)
29 |
30 | @elem.html [1..50].join("fill the width") # To make sure we span the editor as far as we can
31 | @copyStyle(@elem, @editor) # Copy elem style to editor
32 | @elem.html @content_before # Restore content
33 |
34 |
35 | @autoExpand(@editor) # Set editor to autoexpand
36 | @elem.css("display", "none") # Hide elem
37 |
38 | if $(window).scrollTop() == 0 # Focus textfield if scroll on top
39 | @editor[0].selectionEnd = 0
40 | @editor.focus()
41 |
42 | $(".editable-edit").css("display", "none") # Hide all edit button until its not finished
43 |
44 | $(".editbar").css("display", "inline-block").addClassLater("visible", 10)
45 | $(".publishbar").css("opacity", 0) # Hide publishbar
46 | $(".editbar .object").text @getObject(@elem).data("object")+"."+@elem.data("editable")
47 | $(".editbar .button").removeClass("loading")
48 |
49 | $(".editbar .save").off("click").on "click", @saveEdit
50 | $(".editbar .delete").off("click").on "click", @deleteObject
51 | $(".editbar .cancel").off("click").on "click", @cancelEdit
52 |
53 | # Deletable button show/hide
54 | if @getObject(@elem).data("deletable")
55 | $(".editbar .delete").css("display", "").html("Delete "+@getObject(@elem).data("object").split(":")[0])
56 | else
57 | $(".editbar .delete").css("display", "none")
58 |
59 | window.onbeforeunload = ->
60 | return 'Your unsaved blog changes will be lost!'
61 |
62 | return false
63 |
64 |
65 | stopEdit: =>
66 | @editor.remove()
67 | @editor = null
68 | @elem.css("display", "")
69 |
70 | $(".editable-edit").css("display", "") # Show edit buttons
71 |
72 | $(".editbar").cssLater("display", "none", 1000).removeClass("visible") # Hide editbar
73 | $(".publishbar").css("opacity", 1) # Show publishbar
74 |
75 | window.onbeforeunload = null
76 |
77 |
78 | saveEdit: =>
79 | content = @editor.val()
80 | $(".editbar .save").addClass("loading")
81 | @saveContent @elem, content, (content_html) =>
82 | if content_html # File write ok
83 | $(".editbar .save").removeClass("loading")
84 | @stopEdit()
85 | if typeof content_html == "string" # Returned the new content
86 | @elem.html content_html
87 |
88 | $('pre code').each (i, block) -> # Higlight code blocks
89 | hljs.highlightBlock(block)
90 | else
91 | $(".editbar .save").removeClass("loading")
92 |
93 | return false
94 |
95 |
96 | deleteObject: =>
97 | object_type = @getObject(@elem).data("object").split(":")[0]
98 | Page.cmd "wrapperConfirm", ["Are you sure you sure to delete this #{object_type}?", "Delete"], (confirmed) =>
99 | $(".editbar .delete").addClass("loading")
100 | Page.saveContent @getObject(@elem), null, =>
101 | @stopEdit()
102 | return false
103 |
104 |
105 | cancelEdit: =>
106 | @stopEdit()
107 | @elem.html @content_before
108 |
109 | $('pre code').each (i, block) -> # Higlight code blocks
110 | hljs.highlightBlock(block)
111 |
112 | return false
113 |
114 |
115 | copyStyle: (elem_from, elem_to) ->
116 | elem_to.addClass(elem_from[0].className)
117 | from_style = getComputedStyle(elem_from[0])
118 |
119 | elem_to.css
120 | fontFamily: from_style.fontFamily
121 | fontSize: from_style.fontSize
122 | fontWeight: from_style.fontWeight
123 | marginTop: from_style.marginTop
124 | marginRight: from_style.marginRight
125 | marginBottom: from_style.marginBottom
126 | marginLeft: from_style.marginLeft
127 | paddingTop: from_style.paddingTop
128 | paddingRight: from_style.paddingRight
129 | paddingBottom: from_style.paddingBottom
130 | paddingLeft: from_style.paddingLeft
131 | lineHeight: from_style.lineHeight
132 | textAlign: from_style.textAlign
133 | backgroundColor:from_style.backgroundColor
134 | color: from_style.color
135 | letterSpacing: from_style.letterSpacing
136 |
137 | if elem_from.innerWidth() < 1000 # inline elems fix
138 | elem_to.css "minWidth", elem_from.innerWidth()
139 |
140 |
141 | autoExpand: (elem) ->
142 | editor = elem[0]
143 | # Autoexpand
144 | elem.height(1)
145 | elem.on "input", ->
146 | if editor.scrollHeight > elem.height()
147 | elem.height(1).height(editor.scrollHeight + parseFloat(elem.css("borderTopWidth")) + parseFloat(elem.css("borderBottomWidth")))
148 | elem.trigger "input"
149 |
150 | # Tab key support
151 | elem.on 'keydown', (e) ->
152 | if e.which == 9
153 | e.preventDefault()
154 | s = this.selectionStart
155 | val = elem.val()
156 | elem.val(val.substring(0,this.selectionStart) + "\t" + val.substring(this.selectionEnd))
157 | this.selectionEnd = s+1;
158 |
159 |
160 | window.InlineEditor = InlineEditor
--------------------------------------------------------------------------------
/js/lib/pnglib.js:
--------------------------------------------------------------------------------
1 | /**
2 | * A handy class to calculate color values.
3 | *
4 | * @version 1.0
5 | * @author Robert Eisele 0 Comments:
140 |
141 |
"}return'"+(escaped?code:escape(code,true))+"\n
\n"};Renderer.prototype.blockquote=function(quote){return"'+(escaped?code:escape(code,true))+"\n\n"+quote+"
\n"};Renderer.prototype.html=function(html){return html};Renderer.prototype.heading=function(text,level,raw){return"
\n":"
\n"};Renderer.prototype.list=function(body,ordered){var type=ordered?"ol":"ul";return"<"+type+">\n"+body+""+type+">\n"};Renderer.prototype.listitem=function(text){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+""+type+">\n"};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){return""}}var out='"+text+"";return out};Renderer.prototype.image=function(href,title,text){var out='":">";return out};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}Parser.parse=function(src,options,renderer){var parser=new Parser(options,renderer);return parser.parse(src)};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};Parser.prototype.next=function(){return this.token=this.tokens.pop()};Parser.prototype.peek=function(){return this.tokens[this.tokens.length-1]||0};Parser.prototype.parseText=function(){var body=this.token.text;while(this.peek().type==="text"){body+="\n"+this.next().text}return this.inline.output(body)};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;cell="";for(i=0;i
"+escape(e.message+"",true)+""}throw e}}marked.options=marked.setOptions=function(opt){merge(marked.defaults,opt);return marked};marked.defaults={gfm:true,tables:true,breaks:false,pedantic:false,sanitize:false,smartLists:false,silent:false,highlight:null,langPrefix:"lang-",smartypants:false,headerPrefix:"",renderer:new Renderer,xhtml:false};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)}()); -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
.*?\<\/blockquote\>/g, " " # Remove quotes 128 | body = body.replace /\<.*?\>/g, " " # Remove html codes 129 | if body.length > 60 # Strip if too long 130 | body = body[0..60].replace(/(.*) .*?$/, "$1") + " ..." # Keep the last 60 character and strip back until last space 131 | elem.find(".body").html(body) 132 | 133 | title_hash = lastcomment.post_title.replace(/[#?& ]/g, "+").replace(/[+]+/g, "+") 134 | elem.find(".postlink").text(lastcomment.post_title).attr("href", "?#{@section}&Post:#{lastcomment.post_id}:#{title_hash}") 135 | 136 | applyPagerdata: (page, limit, has_next) -> 137 | pager = $(".pager") 138 | if page > 1 139 | pager.find(".prev").css("display", "inline-block").attr "href", "?#{@section}&page=#{page-1}" + (if @orderby then "&orderby=#{@orderby}" else "") 140 | if has_next 141 | pager.find(".next").css("display", "inline-block").attr "href", "?#{@section}&page=#{page+1}" + (if @orderby then "&orderby=#{@orderby}" else "") 142 | 143 | routeUrl: (url) -> 144 | @log "Routing url:", url 145 | if match = url.match("^(DevopsReactions|RedditGifs|RedditNsfwGifs)") 146 | @section = match[1] 147 | $("body").addClass("page-#{@section}") 148 | 149 | if match = url.match /Post:([0-9]+)/ 150 | $("body").addClass("page-post") 151 | @post_id = parseInt(match[1]) 152 | @pagePost() 153 | else 154 | $("body").addClass("page-main") 155 | if match = url.match /page=([0-9]+)/ 156 | @page = parseInt(match[1]) 157 | if match = url.match /orderby=([a-z_]+)/ 158 | @orderby = match[1] 159 | if match[1] == "like" 160 | @sql_orderby = "votes DESC" 161 | $(".head-link-mostliked").addClass("active") 162 | else if match[1] == "last_comment" 163 | @sql_orderby = "last_comment DESC" 164 | $(".head-link-mostcommented").addClass("active") 165 | $("body").on "keyup", (e) => 166 | if e.keyCode == 37 # Left 167 | $("a.prev")[0].click() 168 | if e.keyCode == 39 # Right 169 | $("a.next")[0].click() 170 | @pageMain() 171 | 172 | # - Pages - 173 | 174 | pagePost: () -> 175 | s = (+ new Date) 176 | @cmd "dbQuery", ["SELECT *, (SELECT COUNT(*) FROM post_vote WHERE post_vote.post_id = post.post_id) AS votes FROM post WHERE post_id = #{@post_id} LIMIT 1"], (res) => 177 | parse_res = (res) => 178 | if res.length 179 | post = res[0] 180 | @applyPostdata($(".post-full"), post, true) 181 | $(".post-full .like").attr("id", "post_like_#{post.post_id}").on "click", @submitPostVote 182 | Comments.pagePost(@post_id) 183 | else 184 | $(".post-full").html("Not found
") 185 | @pageLoaded() 186 | Comments.checkCert() 187 | 188 | # Temporary dbschema bug workaround 189 | if res.error 190 | @cmd "dbQuery", ["SELECT *, -1 AS votes FROM post WHERE post_id = #{@post_id} LIMIT 1"], parse_res 191 | else 192 | parse_res(res) 193 | 194 | 195 | pageMain: (type="normal") -> 196 | limit = 15 197 | query = """ 198 | SELECT 199 | post.*, COUNT(comment_id) AS comments, MAX(comment.date_added) AS last_comment, 200 | (SELECT COUNT(*) FROM post_vote WHERE post_vote.post_id = post.post_id) AS votes 201 | FROM post 202 | LEFT JOIN comment USING (post_id) 203 | WHERE source = '#{@section}' 204 | GROUP BY post_id 205 | ORDER BY #{@sql_orderby} 206 | LIMIT #{(@page-1)*limit}, #{limit+1} 207 | """ 208 | @cmd "dbQuery", [query], (res) => 209 | if @server_info and @server_info.rev < 570 and type == "normal" 210 | @cmd "wrapperNotification", ["error", "This site requires ZeroNet 0.3.2 rev570 or newer!
Please update!"] 211 | return 212 | 213 | parse_res = (res) => 214 | s = (+ new Date) 215 | if res.length > limit # Has next page 216 | res.pop() 217 | @applyPagerdata(@page, limit, true) 218 | else 219 | @applyPagerdata(@page, limit, false) 220 | for post, i in res 221 | elem = $("#post_#{post.post_id}") 222 | if elem.length == 0 # Not exits yet 223 | elem = $(".post.template").clone().removeClass("template").attr("id", "post_#{post.post_id}") 224 | elem.appendTo(".posts") 225 | # elem.find(".score").attr("id", "post_score_#{post.post_id}").on "click", @submitPostVote # Submit vote 226 | elem.find(".like").attr("id", "post_like_#{post.post_id}").on "click", @submitPostVote 227 | if i > 3 228 | delay = 800 229 | else 230 | delay = 0 231 | @applyPostdata(elem, post, full=false, delay=delay) 232 | @pageLoaded() 233 | setTimeout ( => @addLazyVideos() ), 1000 # Add delayed videos to lazy loading 234 | @log "Posts loaded in", ((+ new Date)-s),"ms" 235 | 236 | if type == "normal" 237 | $(".posts .new").on "click", => # Create new blog post 238 | @cmd "fileGet", ["data/data.json"], (res) => 239 | data = JSON.parse(res) 240 | # Add to data 241 | data.post.unshift 242 | post_id: data.next_post_id 243 | title: "New blog post" 244 | date_published: (+ new Date)/1000 245 | body: "Blog post body" 246 | data.next_post_id += 1 247 | 248 | # Create html elements 249 | elem = $(".post.template").clone().removeClass("template") 250 | @applyPostdata(elem, data.post[0]) 251 | elem.hide() 252 | elem.prependTo(".posts").slideDown() 253 | @addInlineEditors(elem) 254 | 255 | @writeData(data) 256 | return false 257 | 258 | # Temporary dbschema bug workaround 259 | if res.error 260 | query = """ 261 | SELECT 262 | post.*, COUNT(comment_id) AS comments, 263 | -1 AS votes 264 | FROM post 265 | LEFT JOIN comment USING (post_id) 266 | GROUP BY post_id 267 | ORDER BY date_published DESC 268 | LIMIT #{(@page-1)*limit}, #{limit+1} 269 | """ 270 | @cmd "dbQuery", [query], parse_res 271 | else 272 | parse_res(res) 273 | 274 | 275 | # - EOF Pages - 276 | 277 | 278 | # All page content loaded 279 | pageLoaded: => 280 | $("body").addClass("loaded") # Back/forward button keep position support 281 | $('pre code').each (i, block) -> # Higlight code blocks 282 | hljs.highlightBlock(block) 283 | @addLazyVideos() 284 | @checkLazyVideos() 285 | @event_page_load.resolve() 286 | @cmd "innerLoaded", true 287 | 288 | 289 | addInlineEditors: (parent) -> 290 | @logStart "Adding inline editors" 291 | elems = $("[data-editable]:visible", parent) 292 | for elem in elems 293 | elem = $(elem) 294 | if not elem.data("editor") and not elem.hasClass("editor") 295 | editor = new InlineEditor(elem, @getContent, @saveContent, @getObject) 296 | elem.data("editor", editor) 297 | @logEnd "Adding inline editors" 298 | 299 | 300 | # Check if publishing is necessary 301 | checkPublishbar: -> 302 | if not @data["modified"] or @data["modified"] > @site_info.content.modified 303 | $(".publishbar").addClass("visible") 304 | else 305 | $(".publishbar").removeClass("visible") 306 | 307 | 308 | # Sign and Publish site 309 | publish: => 310 | if @site_info.privatekey # Privatekey stored in users.json 311 | @cmd "sitePublish", ["stored"], (res) => 312 | @log "Publish result:", res 313 | else 314 | @cmd "wrapperPrompt", ["Enter your private key:", "password"], (privatekey) => # Prompt the private key 315 | $(".publishbar .button").addClass("loading") 316 | @cmd "sitePublish", [privatekey], (res) => 317 | $(".publishbar .button").removeClass("loading") 318 | @log "Publish result:", res 319 | 320 | return false # Ignore link default event 321 | 322 | 323 | # Apply from data to post html element 324 | applyPostdata: (elem, post, full=false, delay=0) -> 325 | title_hash = post.title.replace(/[#?& ]/g, "+").replace(/[+]+/g, "+") 326 | elem.data("object", "Post:"+post.post_id) 327 | $(".title .editable", elem).html(post.title).attr("href", "?#{@section}&Post:#{post.post_id}:#{title_hash}").data("content", post.title) 328 | date_published = Time.since(post.date_published) 329 | # Published date 330 | if post.body.match /^---/m # Has more over fold 331 | date_published += " · #{Time.readtime(post.body)}" # If has break add readtime 332 | $(".more", elem).css("display", "inline-block").attr("href", "?#{@section}&Post:#{post.post_id}:#{title_hash}") 333 | $(".details .published", elem).html(date_published).data("content", post.date_published) 334 | # Comments num 335 | if post.comments > 0 336 | $(".details .comments-num", elem).css("display", "inline").attr("href", "?#{@section}&Post:#{post.post_id}:#{title_hash}") 337 | $(".details .comments-num .num", elem).text("#{post.comments} comments") 338 | else 339 | $(".details .comments-num", elem).css("display", "none") 340 | 341 | ### 342 | if @my_post_votes[post.post_id] # Voted on it 343 | $(".score-inactive .score-num", elem).text post.votes-1 344 | $(".score-active .score-num", elem).text post.votes 345 | $(".score", elem).addClass("active") 346 | else # Not voted on it 347 | $(".score-inactive .score-num", elem).text post.votes 348 | $(".score-active .score-num", elem).text post.votes+1 349 | 350 | if post.votes == 0 351 | $(".score", elem).addClass("noscore") 352 | else 353 | $(".score", elem).removeClass("noscore") 354 | ### 355 | if post.votes > 0 356 | $(".like .num", elem).text post.votes+" Likes" 357 | else if post.votes == -1 # DB bug 358 | $(".like", elem).css("display", "none") 359 | else 360 | $(".like .num", elem).text "Like!" 361 | 362 | if @my_post_votes[post.post_id] # Voted on it 363 | $(".like", elem).addClass("active") 364 | 365 | 366 | if full 367 | body = post.body 368 | else # On main page only show post until the first --- hr separator 369 | body = post.body.replace(/^([\s\S]*?)\n---\n[\s\S]*$/, "$1") 370 | 371 | if $(".body", elem).data("content") != post.body 372 | if delay 373 | setTimeout ( -> 374 | $(".body", elem).html(Text.renderMarked(body)).data("content", post.body) 375 | ), delay 376 | else 377 | $(".body", elem).html(Text.renderMarked(body)).data("content", post.body) 378 | 379 | 380 | # Wrapper websocket connection ready 381 | onOpenWebsocket: (e) => 382 | @loadData() 383 | @cmd "siteInfo", {}, (site_info) => 384 | @setSiteinfo(site_info) 385 | query_my_votes = """ 386 | SELECT 387 | 'post_vote' AS type, 388 | post_id AS uri 389 | FROM json 390 | LEFT JOIN post_vote USING (json_id) 391 | WHERE directory = 'users/#{@site_info.auth_address}' AND file_name = 'data.json' 392 | """ 393 | @cmd "dbQuery", [query_my_votes], (res) => 394 | for row in res 395 | @my_post_votes[row["uri"]] = 1 396 | @routeUrl(window.location.search.substring(1)) 397 | 398 | @cmd "serverInfo", {}, (ret) => # Get server info 399 | @server_info = ret 400 | if @server_info.rev < 160 401 | @loadData("old") 402 | @loadLastcomments("noanim") 403 | 404 | 405 | # Returns the elem parent object 406 | getObject: (elem) => 407 | return elem.parents("[data-object]:first") 408 | 409 | 410 | # Get content from data.json 411 | getContent: (elem, raw=false) => 412 | [type, id] = @getObject(elem).data("object").split(":") 413 | id = parseInt(id) 414 | content = elem.data("content") 415 | if elem.data("editable-mode") == "timestamp" # Convert to time 416 | content = Time.date(content, "full") 417 | 418 | if elem.data("editable-mode") == "simple" or raw # No markdown 419 | return content 420 | else 421 | return Text.renderMarked(content) 422 | 423 | 424 | # Save content to data.json 425 | saveContent: (elem, content, cb=false) => 426 | if elem.data("deletable") and content == null then return @deleteObject(elem, cb) # Its a delete request 427 | elem.data("content", content) 428 | [type, id] = @getObject(elem).data("object").split(":") 429 | id = parseInt(id) 430 | if type == "Post" or type == "Site" 431 | @saveSite(elem, type, id, content, cb) 432 | else if type == "Comment" 433 | @saveComment(elem, type, id, content, cb) 434 | 435 | 436 | 437 | saveSite: (elem, type, id, content, cb) -> 438 | @cmd "fileGet", ["data/data.json"], (res) => 439 | data = JSON.parse(res) 440 | if type == "Post" 441 | post = (post for post in data.post when post.post_id == id)[0] 442 | 443 | if elem.data("editable-mode") == "timestamp" # Time parse to timestamp 444 | content = Time.timestamp(content) 445 | 446 | post[elem.data("editable")] = content 447 | else if type == "Site" 448 | data[elem.data("editable")] = content 449 | 450 | @writeData data, (res) => 451 | if cb 452 | if res == true # OK 453 | if elem.data("editable-mode") == "simple" # No markdown 454 | cb(content) 455 | else if elem.data("editable-mode") == "timestamp" # Format timestamp 456 | cb(Time.since(content)) 457 | else 458 | cb(Text.renderMarked(content)) 459 | else # Error 460 | cb(false) 461 | 462 | 463 | 464 | saveComment: (elem, type, id, content, cb) -> 465 | @log "Saving comment...", id 466 | @getObject(elem).css "height", "auto" 467 | inner_path = "data/users/#{Page.site_info.auth_address}/data.json" 468 | Page.cmd "fileGet", {"inner_path": inner_path, "required": false}, (data) => 469 | data = JSON.parse(data) 470 | comment = (comment for comment in data.comment when comment.comment_id == id)[0] 471 | comment[elem.data("editable")] = content 472 | json_raw = unescape(encodeURIComponent(JSON.stringify(data, undefined, '\t'))) 473 | @writePublish inner_path, btoa(json_raw), (res) => 474 | if res == true 475 | Comments.checkCert("updaterules") 476 | if cb then cb(Text.renderMarked(content, {"sanitize": true})) 477 | else 478 | @cmd "wrapperNotification", ["error", "File write error: #{res}"] 479 | if cb then cb(false) 480 | 481 | 482 | 483 | 484 | deleteObject: (elem, cb=False) -> 485 | [type, id] = elem.data("object").split(":") 486 | id = parseInt(id) 487 | 488 | if type == "Post" 489 | @cmd "fileGet", ["data/data.json"], (res) => 490 | data = JSON.parse(res) 491 | if type == "Post" 492 | post = (post for post in data.post when post.post_id == id)[0] 493 | if not post then return false # No post found for this id 494 | data.post.splice(data.post.indexOf(post), 1) # Remove from data 495 | 496 | @writeData data, (res) => 497 | if cb then cb() 498 | if res == true then elem.slideUp() 499 | else if type == "Comment" 500 | inner_path = "data/users/#{Page.site_info.auth_address}/data.json" 501 | @cmd "fileGet", {"inner_path": inner_path, "required": false}, (data) => 502 | data = JSON.parse(data) 503 | comment = (comment for comment in data.comment when comment.comment_id == id)[0] 504 | data.comment.splice(data.comment.indexOf(comment), 1) 505 | json_raw = unescape(encodeURIComponent(JSON.stringify(data, undefined, '\t'))) 506 | @writePublish inner_path, btoa(json_raw), (res) => 507 | if res == true 508 | elem.slideUp() 509 | if cb then cb() 510 | 511 | 512 | 513 | writeData: (data, cb=null) -> 514 | if not data 515 | return @log "Data missing" 516 | @data["modified"] = data.modified = Time.timestamp() 517 | json_raw = unescape(encodeURIComponent(JSON.stringify(data, undefined, '\t'))) # Encode to json, encode utf8 518 | @cmd "fileWrite", ["data/data.json", btoa(json_raw)], (res) => # Convert to to base64 and send 519 | if res == "ok" 520 | if cb then cb(true) 521 | else 522 | @cmd "wrapperNotification", ["error", "File write error: #{res}"] 523 | if cb then cb(false) 524 | @checkPublishbar() 525 | 526 | # Updating title in content.json 527 | @cmd "fileGet", ["content.json"], (content) => 528 | content = content.replace /"title": ".*?"/, "\"title\": \"#{data.title}\"" # Load as raw html to prevent js bignumber problems 529 | @cmd "fileWrite", ["content.json", btoa(content)], (res) => 530 | if res != "ok" 531 | @cmd "wrapperNotification", ["error", "Content.json write error: #{res}"] 532 | 533 | # If the privatekey is stored sign the new content 534 | if @site_info["privatekey"] 535 | @cmd "siteSign", ["stored", "content.json"], (res) => 536 | @log "Sign result", res 537 | 538 | 539 | writePublish: (inner_path, data, cb) -> 540 | @cmd "fileWrite", [inner_path, data], (res) => 541 | if res != "ok" # fileWrite failed 542 | @cmd "wrapperNotification", ["error", "File write error: #{res}"] 543 | cb(false) 544 | return false 545 | 546 | @cmd "sitePublish", {"inner_path": inner_path}, (res) => 547 | if res == "ok" 548 | cb(true) 549 | else 550 | cb(res) 551 | 552 | submitPostVote: (e) => 553 | if not Page.site_info.cert_user_id # No selected cert 554 | Page.cmd "certSelect", [["zeroid.bit", "zeroverse.bit"]] 555 | return false 556 | 557 | elem = $(e.currentTarget) 558 | elem.toggleClass("active").addClass("loading") 559 | inner_path = "data/users/#{@site_info.auth_address}/data.json" 560 | Page.cmd "fileGet", {"inner_path": inner_path, "required": false}, (data) => 561 | if data 562 | data = JSON.parse(data) 563 | else # Default data 564 | data = {"next_comment_id": 1, "comment": [], "comment_vote": {}, "post_vote": {} } 565 | 566 | if not data.post_vote 567 | data.post_vote = {} 568 | post_id = elem.attr("id").match("_([0-9]+)$")[1] 569 | 570 | if elem.hasClass("active") 571 | data.post_vote[post_id] = 1 572 | else 573 | delete data.post_vote[post_id] 574 | json_raw = unescape(encodeURIComponent(JSON.stringify(data, undefined, '\t'))) 575 | 576 | current_num = parseInt elem.find(".num").text() 577 | if not current_num 578 | current_num = 0 579 | if elem.hasClass("active") 580 | elem.find(".num").text(current_num+1+" Likes") 581 | else 582 | elem.find(".num").text(current_num-1+" Likes") 583 | 584 | Page.writePublish inner_path, btoa(json_raw), (res) => 585 | elem.removeClass("loading") 586 | @log "Writepublish result", res 587 | 588 | return false 589 | 590 | # Parse incoming requests 591 | onRequest: (cmd, message) -> 592 | if cmd == "setSiteInfo" # Site updated 593 | @actionSetSiteInfo(message) 594 | else 595 | @log "Unknown command", message 596 | 597 | 598 | # Siteinfo changed 599 | actionSetSiteInfo: (message) => 600 | @setSiteinfo(message.params) 601 | @checkPublishbar() 602 | 603 | 604 | setSiteinfo: (site_info) => 605 | @site_info = site_info 606 | @event_site_info.resolve(site_info) 607 | if $("body").hasClass("page-post") then Comments.checkCert() # Update if username changed 608 | # User commented 609 | if site_info.event?[0] == "file_done" and site_info.event[1].match /.*users.*data.json$/ 610 | if $("body").hasClass("page-post") 611 | @pagePost() 612 | Comments.loadComments() # Post page, reload comments 613 | @loadLastcomments() 614 | if $("body").hasClass("page-main") 615 | RateLimit 500, => 616 | @pageMain("update") 617 | @loadLastcomments() 618 | else if site_info.event?[0] == "file_done" and site_info.event[1] == "data/data.json" 619 | @loadData() 620 | if $("body").hasClass("page-main") then @pageMain("update") 621 | if $("body").hasClass("page-post") then @pagePost() 622 | 623 | 624 | window.Page = new ZeroBlog() 625 | -------------------------------------------------------------------------------- /js/lib/highlight.pack.js: -------------------------------------------------------------------------------- 1 | !function(e){"undefined"!=typeof exports?e(exports):(window.hljs=e({}),"function"==typeof define&&define.amd&&define([],function(){return window.hljs}))}(function(e){function n(e){return e.replace(/&/gm,"&").replace(//gm,">")}function t(e){return e.nodeName.toLowerCase()}function r(e,n){var t=e&&e.exec(n);return t&&0==t.index}function a(e){var n=(e.className+" "+(e.parentNode?e.parentNode.className:"")).split(/\s+/);return n=n.map(function(e){return e.replace(/^lang(uage)?-/,"")}),n.filter(function(e){return N(e)||/no(-?)highlight/.test(e)})[0]}function o(e,n){var t={};for(var r in e)t[r]=e[r];if(n)for(var r in n)t[r]=n[r];return t}function i(e){var n=[];return function r(e,a){for(var o=e.firstChild;o;o=o.nextSibling)3==o.nodeType?a+=o.nodeValue.length:1==o.nodeType&&(n.push({event:"start",offset:a,node:o}),a=r(o,a),t(o).match(/br|hr|img|input/)||n.push({event:"stop",offset:a,node:o}));return a}(e,0),n}function c(e,r,a){function o(){return e.length&&r.length?e[0].offset!=r[0].offset?e[0].offset"}function c(e){l+=""+t(e)+">"}function u(e){("start"==e.event?i:c)(e.node)}for(var s=0,l="",f=[];e.length||r.length;){var g=o();if(l+=n(a.substr(s,g[0].offset-s)),s=g[0].offset,g==e){f.reverse().forEach(c);do u(g.splice(0,1)[0]),g=o();while(g==e&&g.length&&g[0].offset==s);f.reverse().forEach(i)}else"start"==g[0].event?f.push(g[0].node):f.pop(),u(g.splice(0,1)[0])}return l+n(a.substr(s))}function u(e){function n(e){return e&&e.source||e}function t(t,r){return RegExp(n(t),"m"+(e.cI?"i":"")+(r?"g":""))}function r(a,i){if(!a.compiled){if(a.compiled=!0,a.k=a.k||a.bK,a.k){var c={},u=function(n,t){e.cI&&(t=t.toLowerCase()),t.split(" ").forEach(function(e){var t=e.split("|");c[t[0]]=[n,t[1]?Number(t[1]):1]})};"string"==typeof a.k?u("keyword",a.k):Object.keys(a.k).forEach(function(e){u(e,a.k[e])}),a.k=c}a.lR=t(a.l||/\b[A-Za-z0-9_]+\b/,!0),i&&(a.bK&&(a.b="\\b("+a.bK.split(" ").join("|")+")\\b"),a.b||(a.b=/\B|\b/),a.bR=t(a.b),a.e||a.eW||(a.e=/\B|\b/),a.e&&(a.eR=t(a.e)),a.tE=n(a.e)||"",a.eW&&i.tE&&(a.tE+=(a.e?"|":"")+i.tE)),a.i&&(a.iR=t(a.i)),void 0===a.r&&(a.r=1),a.c||(a.c=[]);var s=[];a.c.forEach(function(e){e.v?e.v.forEach(function(n){s.push(o(e,n))}):s.push("self"==e?a:e)}),a.c=s,a.c.forEach(function(e){r(e,a)}),a.starts&&r(a.starts,i);var l=a.c.map(function(e){return e.bK?"\\.?("+e.b+")\\.?":e.b}).concat([a.tE,a.i]).map(n).filter(Boolean);a.t=l.length?t(l.join("|"),!0):{exec:function(){return null}}}}r(e)}function s(e,t,a,o){function i(e,n){for(var t=0;t ";return o+=e+'">',o+n+i}function d(){if(!w.k)return n(y);var e="",t=0;w.lR.lastIndex=0;for(var r=w.lR.exec(y);r;){e+=n(y.substr(t,r.index-t));var a=g(w,r);a?(B+=a[1],e+=p(a[0],n(r[0]))):e+=n(r[0]),t=w.lR.lastIndex,r=w.lR.exec(y)}return e+n(y.substr(t))}function h(){if(w.sL&&!R[w.sL])return n(y);var e=w.sL?s(w.sL,y,!0,L[w.sL]):l(y);return w.r>0&&(B+=e.r),"continuous"==w.subLanguageMode&&(L[w.sL]=e.top),p(e.language,e.value,!1,!0)}function v(){return void 0!==w.sL?h():d()}function b(e,t){var r=e.cN?p(e.cN,"",!0):"";e.rB?(M+=r,y=""):e.eB?(M+=n(t)+r,y=""):(M+=r,y=t),w=Object.create(e,{parent:{value:w}})}function m(e,t){if(y+=e,void 0===t)return M+=v(),0;var r=i(t,w);if(r)return M+=v(),b(r,t),r.rB?0:t.length;var a=c(w,t);if(a){var o=w;o.rE||o.eE||(y+=t),M+=v();do w.cN&&(M+=""),B+=w.r,w=w.parent;while(w!=a.parent);return o.eE&&(M+=n(t)),y="",a.starts&&b(a.starts,""),o.rE?0:t.length}if(f(t,w))throw new Error('Illegal lexeme "'+t+'" for mode "'+(w.cN||" ")+'"');return y+=t,t.length||1}var x=N(e);if(!x)throw new Error('Unknown language: "'+e+'"');u(x);for(var w=o||x,L={},M="",k=w;k!=x;k=k.parent)k.cN&&(M=p(k.cN,"",!0)+M);var y="",B=0;try{for(var C,j,I=0;;){if(w.t.lastIndex=I,C=w.t.exec(t),!C)break;j=m(t.substr(I,C.index-I),C[0]),I=C.index+j}m(t.substr(I));for(var k=w;k.parent;k=k.parent)k.cN&&(M+="");return{r:B,value:M,language:e,top:w}}catch(A){if(-1!=A.message.indexOf("Illegal"))return{r:0,value:n(t)};throw A}}function l(e,t){t=t||E.languages||Object.keys(R);var r={r:0,value:n(e)},a=r;return t.forEach(function(n){if(N(n)){var t=s(n,e,!1);t.language=n,t.r>a.r&&(a=t),t.r>r.r&&(a=r,r=t)}}),a.language&&(r.second_best=a),r}function f(e){return E.tabReplace&&(e=e.replace(/^((<[^>]+>|\t)+)/gm,function(e,n){return n.replace(/\t/g,E.tabReplace)})),E.useBR&&(e=e.replace(/\n/g,"
")),e}function g(e,n,t){var r=n?x[n]:t,a=[e.trim()];return e.match(/(\s|^)hljs(\s|$)/)||a.push("hljs"),r&&a.push(r),a.join(" ").trim()}function p(e){var n=a(e);if(!/no(-?)highlight/.test(n)){var t;E.useBR?(t=document.createElementNS("http://www.w3.org/1999/xhtml","div"),t.innerHTML=e.innerHTML.replace(/\n/g,"").replace(/
/g,"\n")):t=e;var r=t.textContent,o=n?s(n,r,!0):l(r),u=i(t);if(u.length){var p=document.createElementNS("http://www.w3.org/1999/xhtml","div");p.innerHTML=o.value,o.value=c(u,i(p),r)}o.value=f(o.value),e.innerHTML=o.value,e.className=g(e.className,n,o.language),e.result={language:o.language,re:o.r},o.second_best&&(e.second_best={language:o.second_best.language,re:o.second_best.r})}}function d(e){E=o(E,e)}function h(){if(!h.called){h.called=!0;var e=document.querySelectorAll("pre code");Array.prototype.forEach.call(e,p)}}function v(){addEventListener("DOMContentLoaded",h,!1),addEventListener("load",h,!1)}function b(n,t){var r=R[n]=t(e);r.aliases&&r.aliases.forEach(function(e){x[e]=n})}function m(){return Object.keys(R)}function N(e){return R[e]||R[x[e]]}var E={classPrefix:"hljs-",tabReplace:null,useBR:!1,languages:void 0},R={},x={};return e.highlight=s,e.highlightAuto=l,e.fixMarkup=f,e.highlightBlock=p,e.configure=d,e.initHighlighting=h,e.initHighlightingOnLoad=v,e.registerLanguage=b,e.listLanguages=m,e.getLanguage=N,e.inherit=o,e.IR="[a-zA-Z][a-zA-Z0-9_]*",e.UIR="[a-zA-Z_][a-zA-Z0-9_]*",e.NR="\\b\\d+(\\.\\d+)?",e.CNR="(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",e.BNR="\\b(0b[01]+)",e.RSR="!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~",e.BE={b:"\\\\[\\s\\S]",r:0},e.ASM={cN:"string",b:"'",e:"'",i:"\\n",c:[e.BE]},e.QSM={cN:"string",b:'"',e:'"',i:"\\n",c:[e.BE]},e.PWM={b:/\b(a|an|the|are|I|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such)\b/},e.CLCM={cN:"comment",b:"//",e:"$",c:[e.PWM]},e.CBCM={cN:"comment",b:"/\\*",e:"\\*/",c:[e.PWM]},e.HCM={cN:"comment",b:"#",e:"$",c:[e.PWM]},e.NM={cN:"number",b:e.NR,r:0},e.CNM={cN:"number",b:e.CNR,r:0},e.BNM={cN:"number",b:e.BNR,r:0},e.CSSNM={cN:"number",b:e.NR+"(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?",r:0},e.RM={cN:"regexp",b:/\//,e:/\/[gimuy]*/,i:/\n/,c:[e.BE,{b:/\[/,e:/\]/,r:0,c:[e.BE]}]},e.TM={cN:"title",b:e.IR,r:0},e.UTM={cN:"title",b:e.UIR,r:0},e});hljs.registerLanguage("cpp",function(t){var i={keyword:"false int float while private char catch export virtual operator sizeof dynamic_cast|10 typedef const_cast|10 const struct for static_cast|10 union namespace unsigned long volatile static protected bool template mutable if public friend do goto auto void enum else break extern using true class asm case typeid short reinterpret_cast|10 default double register explicit signed typename try this switch continue wchar_t inline delete alignof char16_t char32_t constexpr decltype noexcept nullptr static_assert thread_local restrict _Bool complex _Complex _Imaginaryintmax_t uintmax_t int8_t uint8_t int16_t uint16_t int32_t uint32_t int64_t uint64_tint_least8_t uint_least8_t int_least16_t uint_least16_t int_least32_t uint_least32_tint_least64_t uint_least64_t int_fast8_t uint_fast8_t int_fast16_t uint_fast16_t int_fast32_tuint_fast32_t int_fast64_t uint_fast64_t intptr_t uintptr_t atomic_bool atomic_char atomic_scharatomic_uchar atomic_short atomic_ushort atomic_int atomic_uint atomic_long atomic_ulong atomic_llongatomic_ullong atomic_wchar_t atomic_char16_t atomic_char32_t atomic_intmax_t atomic_uintmax_tatomic_intptr_t atomic_uintptr_t atomic_size_t atomic_ptrdiff_t atomic_int_least8_t atomic_int_least16_tatomic_int_least32_t atomic_int_least64_t atomic_uint_least8_t atomic_uint_least16_t atomic_uint_least32_tatomic_uint_least64_t atomic_int_fast8_t atomic_int_fast16_t atomic_int_fast32_t atomic_int_fast64_tatomic_uint_fast8_t atomic_uint_fast16_t atomic_uint_fast32_t atomic_uint_fast64_t",built_in:"std string cin cout cerr clog stringstream istringstream ostringstream auto_ptr deque list queue stack vector map set bitset multiset multimap unordered_set unordered_map unordered_multiset unordered_multimap array shared_ptr abort abs acos asin atan2 atan calloc ceil cosh cos exit exp fabs floor fmod fprintf fputs free frexp fscanf isalnum isalpha iscntrl isdigit isgraph islower isprint ispunct isspace isupper isxdigit tolower toupper labs ldexp log10 log malloc memchr memcmp memcpy memset modf pow printf putchar puts scanf sinh sin snprintf sprintf sqrt sscanf strcat strchr strcmp strcpy strcspn strlen strncat strncmp strncpy strpbrk strrchr strspn strstr tanh tan vfprintf vprintf vsprintf"};return{aliases:["c","h","c++","h++"],k:i,i:"",c:[t.CLCM,t.CBCM,t.QSM,{cN:"string",b:"'\\\\?.",e:"'",i:"."},{cN:"number",b:"\\b(\\d+(\\.\\d*)?|\\.\\d+)(u|U|l|L|ul|UL|f|F)"},t.CNM,{cN:"preprocessor",b:"#",e:"$",k:"if else elif endif define undef warning error line pragma",c:[{b:'include\\s*[<"]',e:'[>"]',k:"include",i:"\\n"},t.CLCM]},{cN:"stl_container",b:"\\b(deque|list|queue|stack|vector|map|set|bitset|multiset|multimap|unordered_map|unordered_set|unordered_multiset|unordered_multimap|array)\\s*<",e:">",k:i,c:["self"]},{b:t.IR+"::"},{bK:"new throw return",r:0},{cN:"function",b:"("+t.IR+"\\s+)+"+t.IR+"\\s*\\(",rB:!0,e:/[{;=]/,eE:!0,k:i,c:[{b:t.IR+"\\s*\\(",rB:!0,c:[t.TM],r:0},{cN:"params",b:/\(/,e:/\)/,k:i,r:0,c:[t.CBCM]},t.CLCM,t.CBCM]}]}});hljs.registerLanguage("ruby",function(e){var b="[a-zA-Z_]\\w*[!?=]?|[-+~]\\@|<<|>>|=~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~`|]|\\[\\]=?",r="and false then defined module in return redo if BEGIN retry end for true self when next until do begin unless END rescue nil else break undef not super class case require yield alias while ensure elsif or include attr_reader attr_writer attr_accessor",c={cN:"yardoctag",b:"@[A-Za-z]+"},a={cN:"value",b:"#<",e:">"},s={cN:"comment",v:[{b:"#",e:"$",c:[c]},{b:"^\\=begin",e:"^\\=end",c:[c],r:10},{b:"^__END__",e:"\\n$"}]},n={cN:"subst",b:"#\\{",e:"}",k:r},t={cN:"string",c:[e.BE,n],v:[{b:/'/,e:/'/},{b:/"/,e:/"/},{b:/`/,e:/`/},{b:"%[qQwWx]?\\(",e:"\\)"},{b:"%[qQwWx]?\\[",e:"\\]"},{b:"%[qQwWx]?{",e:"}"},{b:"%[qQwWx]?<",e:">"},{b:"%[qQwWx]?/",e:"/"},{b:"%[qQwWx]?%",e:"%"},{b:"%[qQwWx]?-",e:"-"},{b:"%[qQwWx]?\\|",e:"\\|"},{b:/\B\?(\\\d{1,3}|\\x[A-Fa-f0-9]{1,2}|\\u[A-Fa-f0-9]{4}|\\?\S)\b/}]},i={cN:"params",b:"\\(",e:"\\)",k:r},d=[t,a,s,{cN:"class",bK:"class module",e:"$|;",i:/=/,c:[e.inherit(e.TM,{b:"[A-Za-z_]\\w*(::\\w+)*(\\?|\\!)?"}),{cN:"inheritance",b:"<\\s*",c:[{cN:"parent",b:"("+e.IR+"::)?"+e.IR}]},s]},{cN:"function",bK:"def",e:" |$|;",r:0,c:[e.inherit(e.TM,{b:b}),i,s]},{cN:"constant",b:"(::)?(\\b[A-Z]\\w*(::)?)+",r:0},{cN:"symbol",b:e.UIR+"(\\!|\\?)?:",r:0},{cN:"symbol",b:":",c:[t,{b:b}],r:0},{cN:"number",b:"(\\b0[0-7_]+)|(\\b0x[0-9a-fA-F_]+)|(\\b[1-9][0-9_]*(\\.[0-9_]+)?)|[0_]\\b",r:0},{cN:"variable",b:"(\\$\\W)|((\\$|\\@\\@?)(\\w+))"},{b:"("+e.RSR+")\\s*",c:[a,s,{cN:"regexp",c:[e.BE,n],i:/\n/,v:[{b:"/",e:"/[a-z]*"},{b:"%r{",e:"}[a-z]*"},{b:"%r\\(",e:"\\)[a-z]*"},{b:"%r!",e:"![a-z]*"},{b:"%r\\[",e:"\\][a-z]*"}]}],r:0}];n.c=d,i.c=d;var l="[>?]>",u="[\\w#]+\\(\\w+\\):\\d+:\\d+>",N="(\\w+-)?\\d+\\.\\d+\\.\\d(p\\d+)?[^>]+>",o=[{b:/^\s*=>/,cN:"status",starts:{e:"$",c:d}},{cN:"prompt",b:"^("+l+"|"+u+"|"+N+")",starts:{e:"$",c:d}}];return{aliases:["rb","gemspec","podspec","thor","irb"],k:r,c:[s].concat(o).concat(d)}});hljs.registerLanguage("apache",function(e){var r={cN:"number",b:"[\\$%]\\d+"};return{aliases:["apacheconf"],cI:!0,c:[e.HCM,{cN:"tag",b:"?",e:">"},{cN:"keyword",b:/\w+/,r:0,k:{common:"order deny allow setenv rewriterule rewriteengine rewritecond documentroot sethandler errordocument loadmodule options header listen serverroot servername"},starts:{e:/$/,r:0,k:{literal:"on off all"},c:[{cN:"sqbracket",b:"\\s\\[",e:"\\]$"},{cN:"cbracket",b:"[\\$%]\\{",e:"\\}",c:["self",r]},r,e.QSM]}}],i:/\S/}});hljs.registerLanguage("python",function(e){var r={cN:"prompt",b:/^(>>>|\.\.\.) /},b={cN:"string",c:[e.BE],v:[{b:/(u|b)?r?'''/,e:/'''/,c:[r],r:10},{b:/(u|b)?r?"""/,e:/"""/,c:[r],r:10},{b:/(u|r|ur)'/,e:/'/,r:10},{b:/(u|r|ur)"/,e:/"/,r:10},{b:/(b|br)'/,e:/'/},{b:/(b|br)"/,e:/"/},e.ASM,e.QSM]},l={cN:"number",r:0,v:[{b:e.BNR+"[lLjJ]?"},{b:"\\b(0o[0-7]+)[lLjJ]?"},{b:e.CNR+"[lLjJ]?"}]},c={cN:"params",b:/\(/,e:/\)/,c:["self",r,l,b]};return{aliases:["py","gyp"],k:{keyword:"and elif is global as in if from raise for except finally print import pass return exec else break not with class assert yield try while continue del or def lambda nonlocal|10 None True False",built_in:"Ellipsis NotImplemented"},i:/(<\/|->|\?)/,c:[r,l,b,e.HCM,{v:[{cN:"function",bK:"def",r:10},{cN:"class",bK:"class"}],e:/:/,i:/[${=;\n]/,c:[e.UTM,c]},{cN:"decorator",b:/@/,e:/$/},{b:/\b(print|exec)\(/}]}});hljs.registerLanguage("javascript",function(r){return{aliases:["js"],k:{keyword:"in if for while finally var new function do return void else break catch instanceof with throw case default try this switch continue typeof delete let yield const class",literal:"true false null undefined NaN Infinity",built_in:"eval isFinite isNaN parseFloat parseInt decodeURI decodeURIComponent encodeURI encodeURIComponent escape unescape Object Function Boolean Error EvalError InternalError RangeError ReferenceError StopIteration SyntaxError TypeError URIError Number Math Date String RegExp Array Float32Array Float64Array Int16Array Int32Array Int8Array Uint16Array Uint32Array Uint8Array Uint8ClampedArray ArrayBuffer DataView JSON Intl arguments require module console window document"},c:[{cN:"pi",r:10,v:[{b:/^\s*('|")use strict('|")/},{b:/^\s*('|")use asm('|")/}]},r.ASM,r.QSM,r.CLCM,r.CBCM,r.CNM,{b:"("+r.RSR+"|\\b(case|return|throw)\\b)\\s*",k:"return throw case",c:[r.CLCM,r.CBCM,r.RM,{b:/,e:/>;/,r:0,sL:"xml"}],r:0},{cN:"function",bK:"function",e:/\{/,eE:!0,c:[r.inherit(r.TM,{b:/[A-Za-z$_][0-9A-Za-z$_]*/}),{cN:"params",b:/\(/,e:/\)/,c:[r.CLCM,r.CBCM],i:/["'\(]/}],i:/\[|%/},{b:/\$[(.]/},{b:"\\."+r.IR,r:0}]}});hljs.registerLanguage("coffeescript",function(e){var c={keyword:"in if for while finally new do return else break catch instanceof throw try this switch continue typeof delete debugger super then unless until loop of by when and or is isnt not",literal:"true false null undefined yes no on off",reserved:"case default function var void with const let enum export import native __hasProp __extends __slice __bind __indexOf",built_in:"npm require console print module global window document"},n="[A-Za-z$_][0-9A-Za-z$_]*",t={cN:"subst",b:/#\{/,e:/}/,k:c},r=[e.BNM,e.inherit(e.CNM,{starts:{e:"(\\s*/)?",r:0}}),{cN:"string",v:[{b:/'''/,e:/'''/,c:[e.BE]},{b:/'/,e:/'/,c:[e.BE]},{b:/"""/,e:/"""/,c:[e.BE,t]},{b:/"/,e:/"/,c:[e.BE,t]}]},{cN:"regexp",v:[{b:"///",e:"///",c:[t,e.HCM]},{b:"//[gim]*",r:0},{b:/\/(?![ *])(\\\/|.)*?\/[gim]*(?=\W|$)/}]},{cN:"property",b:"@"+n},{b:"`",e:"`",eB:!0,eE:!0,sL:"javascript"}];t.c=r;var i=e.inherit(e.TM,{b:n}),s="(\\(.*\\))?\\s*\\B[-=]>",o={cN:"params",b:"\\([^\\(]",rB:!0,c:[{b:/\(/,e:/\)/,k:c,c:["self"].concat(r)}]};return{aliases:["coffee","cson","iced"],k:c,i:/\/\*/,c:r.concat([{cN:"comment",b:"###",e:"###",c:[e.PWM]},e.HCM,{cN:"function",b:"^\\s*"+n+"\\s*=\\s*"+s,e:"[-=]>",rB:!0,c:[i,o]},{b:/[:\(,=]\s*/,r:0,c:[{cN:"function",b:s,e:"[-=]>",rB:!0,c:[o]}]},{cN:"class",bK:"class",e:"$",i:/[:="\[\]]/,c:[{bK:"extends",eW:!0,i:/[:="\[\]]/,c:[i]},i]},{cN:"attribute",b:n+":",e:":",rB:!0,rE:!0,r:0}])}});hljs.registerLanguage("http",function(){return{i:"\\S",c:[{cN:"status",b:"^HTTP/[0-9\\.]+",e:"$",c:[{cN:"number",b:"\\b\\d{3}\\b"}]},{cN:"request",b:"^[A-Z]+ (.*?) HTTP/[0-9\\.]+$",rB:!0,e:"$",c:[{cN:"string",b:" ",e:" ",eB:!0,eE:!0}]},{cN:"attribute",b:"^\\w",e:": ",eE:!0,i:"\\n|\\s|=",starts:{cN:"string",e:"$"}},{b:"\\n\\n",starts:{sL:"",eW:!0}}]}});hljs.registerLanguage("css",function(e){var c="[a-zA-Z-][a-zA-Z0-9_-]*",a={cN:"function",b:c+"\\(",rB:!0,eE:!0,e:"\\("};return{cI:!0,i:"[=/|']",c:[e.CBCM,{cN:"id",b:"\\#[A-Za-z0-9_-]+"},{cN:"class",b:"\\.[A-Za-z0-9_-]+",r:0},{cN:"attr_selector",b:"\\[",e:"\\]",i:"$"},{cN:"pseudo",b:":(:)?[a-zA-Z0-9\\_\\-\\+\\(\\)\\\"\\']+"},{cN:"at_rule",b:"@(font-face|page)",l:"[a-z-]+",k:"font-face page"},{cN:"at_rule",b:"@",e:"[{;]",c:[{cN:"keyword",b:/\S+/},{b:/\s/,eW:!0,eE:!0,r:0,c:[a,e.ASM,e.QSM,e.CSSNM]}]},{cN:"tag",b:c,r:0},{cN:"rules",b:"{",e:"}",i:"[^\\s]",r:0,c:[e.CBCM,{cN:"rule",b:"[^\\s]",rB:!0,e:";",eW:!0,c:[{cN:"attribute",b:"[A-Z\\_\\.\\-]+",e:":",eE:!0,i:"[^\\s]",starts:{cN:"value",eW:!0,eE:!0,c:[a,e.CSSNM,e.QSM,e.ASM,e.CBCM,{cN:"hexcolor",b:"#[0-9A-Fa-f]+"},{cN:"important",b:"!important"}]}}]}]}]}});hljs.registerLanguage("ini",function(e){return{cI:!0,i:/\S/,c:[{cN:"comment",b:";",e:"$"},{cN:"title",b:"^\\[",e:"\\]"},{cN:"setting",b:"^[a-z0-9\\[\\]_-]+[ \\t]*=[ \\t]*",e:"$",c:[{cN:"value",eW:!0,k:"on off true false yes no",c:[e.QSM,e.NM],r:0}]}]}});hljs.registerLanguage("objectivec",function(e){var t={keyword:"int float while char export sizeof typedef const struct for union unsigned long volatile static bool mutable if do return goto void enum else break extern asm case short default double register explicit signed typename this switch continue wchar_t inline readonly assign readwrite self @synchronized id typeof nonatomic super unichar IBOutlet IBAction strong weak copy in out inout bycopy byref oneway __strong __weak __block __autoreleasing @private @protected @public @try @property @end @throw @catch @finally @autoreleasepool @synthesize @dynamic @selector @optional @required",literal:"false true FALSE TRUE nil YES NO NULL",built_in:"NSString NSData NSDictionary CGRect CGPoint UIButton UILabel UITextView UIWebView MKMapView NSView NSViewController NSWindow NSWindowController NSSet NSUUID NSIndexSet UISegmentedControl NSObject UITableViewDelegate UITableViewDataSource NSThread UIActivityIndicator UITabbar UIToolBar UIBarButtonItem UIImageView NSAutoreleasePool UITableView BOOL NSInteger CGFloat NSException NSLog NSMutableString NSMutableArray NSMutableDictionary NSURL NSIndexPath CGSize UITableViewCell UIView UIViewController UINavigationBar UINavigationController UITabBarController UIPopoverController UIPopoverControllerDelegate UIImage NSNumber UISearchBar NSFetchedResultsController NSFetchedResultsChangeType UIScrollView UIScrollViewDelegate UIEdgeInsets UIColor UIFont UIApplication NSNotFound NSNotificationCenter NSNotification UILocalNotification NSBundle NSFileManager NSTimeInterval NSDate NSCalendar NSUserDefaults UIWindow NSRange NSArray NSError NSURLRequest NSURLConnection NSURLSession NSURLSessionDataTask NSURLSessionDownloadTask NSURLSessionUploadTask NSURLResponseUIInterfaceOrientation MPMoviePlayerController dispatch_once_t dispatch_queue_t dispatch_sync dispatch_async dispatch_once"},o=/[a-zA-Z@][a-zA-Z0-9_]*/,a="@interface @class @protocol @implementation";return{aliases:["m","mm","objc","obj-c"],k:t,l:o,i:"",c:[e.CLCM,e.CBCM,e.CNM,e.QSM,{cN:"string",v:[{b:'@"',e:'"',i:"\\n",c:[e.BE]},{b:"'",e:"[^\\\\]'",i:"[^\\\\][^']"}]},{cN:"preprocessor",b:"#",e:"$",c:[{cN:"title",v:[{b:'"',e:'"'},{b:"<",e:">"}]}]},{cN:"class",b:"("+a.split(" ").join("|")+")\\b",e:"({|$)",eE:!0,k:a,l:o,c:[e.UTM]},{cN:"variable",b:"\\."+e.UIR,r:0}]}});hljs.registerLanguage("bash",function(e){var t={cN:"variable",v:[{b:/\$[\w\d#@][\w\d_]*/},{b:/\$\{(.*?)\}/}]},s={cN:"string",b:/"/,e:/"/,c:[e.BE,t,{cN:"variable",b:/\$\(/,e:/\)/,c:[e.BE]}]},a={cN:"string",b:/'/,e:/'/};return{aliases:["sh","zsh"],l:/-?[a-z\.]+/,k:{keyword:"if then else elif fi for while in do done case esac function",literal:"true false",built_in:"break cd continue eval exec exit export getopts hash pwd readonly return shift test times trap umask unset alias bind builtin caller command declare echo enable help let local logout mapfile printf read readarray source type typeset ulimit unalias set shopt autoload bg bindkey bye cap chdir clone comparguments compcall compctl compdescribe compfiles compgroups compquote comptags comptry compvalues dirs disable disown echotc echoti emulate fc fg float functions getcap getln history integer jobs kill limit log noglob popd print pushd pushln rehash sched setcap setopt stat suspend ttyctl unfunction unhash unlimit unsetopt vared wait whence where which zcompile zformat zftp zle zmodload zparseopts zprof zpty zregexparse zsocket zstyle ztcp",operator:"-ne -eq -lt -gt -f -d -e -s -l -a"},c:[{cN:"shebang",b:/^#![^\n]+sh\s*$/,r:10},{cN:"function",b:/\w[\w\d_]*\s*\(\s*\)\s*\{/,rB:!0,c:[e.inherit(e.TM,{b:/\w[\w\d_]*/})],r:0},e.HCM,e.NM,s,a,t]}});hljs.registerLanguage("markdown",function(){return{aliases:["md","mkdown","mkd"],c:[{cN:"header",v:[{b:"^#{1,6}",e:"$"},{b:"^.+?\\n[=-]{2,}$"}]},{b:"<",e:">",sL:"xml",r:0},{cN:"bullet",b:"^([*+-]|(\\d+\\.))\\s+"},{cN:"strong",b:"[*_]{2}.+?[*_]{2}"},{cN:"emphasis",v:[{b:"\\*.+?\\*"},{b:"_.+?_",r:0}]},{cN:"blockquote",b:"^>\\s+",e:"$"},{cN:"code",v:[{b:"`.+?`"},{b:"^( {4}| )",e:"$",r:0}]},{cN:"horizontal_rule",b:"^[-\\*]{3,}",e:"$"},{b:"\\[.+?\\][\\(\\[].*?[\\)\\]]",rB:!0,c:[{cN:"link_label",b:"\\[",e:"\\]",eB:!0,rE:!0,r:0},{cN:"link_url",b:"\\]\\(",e:"\\)",eB:!0,eE:!0},{cN:"link_reference",b:"\\]\\[",e:"\\]",eB:!0,eE:!0}],r:10},{b:"^\\[.+\\]:",rB:!0,c:[{cN:"link_reference",b:"\\[",e:"\\]:",eB:!0,eE:!0,starts:{cN:"link_url",e:"$"}}]}]}});hljs.registerLanguage("java",function(e){var a=e.UIR+"(<"+e.UIR+">)?",t="false synchronized int abstract float private char boolean static null if const for true while long strictfp finally protected import native final void enum else break transient catch instanceof byte super volatile case assert short package default double public try this switch continue throws protected public private",c="(\\b(0b[01_]+)|\\b0[xX][a-fA-F0-9_]+|(\\b[\\d_]+(\\.[\\d_]*)?|\\.[\\d_]+)([eE][-+]?\\d+)?)[lLfF]?",r={cN:"number",b:c,r:0};return{aliases:["jsp"],k:t,i:/<\//,c:[{cN:"javadoc",b:"/\\*\\*",e:"\\*/",r:0,c:[{cN:"javadoctag",b:"(^|\\s)@[A-Za-z]+"}]},e.CLCM,e.CBCM,e.ASM,e.QSM,{cN:"class",bK:"class interface",e:/[{;=]/,eE:!0,k:"class interface",i:/[:"\[\]]/,c:[{bK:"extends implements"},e.UTM]},{bK:"new throw return",r:0},{cN:"function",b:"("+a+"\\s+)+"+e.UIR+"\\s*\\(",rB:!0,e:/[{;=]/,eE:!0,k:t,c:[{b:e.UIR+"\\s*\\(",rB:!0,r:0,c:[e.UTM]},{cN:"params",b:/\(/,e:/\)/,k:t,r:0,c:[e.ASM,e.QSM,e.CNM,e.CBCM]},e.CLCM,e.CBCM]},r,{cN:"annotation",b:"@[A-Za-z]+"}]}});hljs.registerLanguage("diff",function(){return{aliases:["patch"],c:[{cN:"chunk",r:10,v:[{b:/^\@\@ +\-\d+,\d+ +\+\d+,\d+ +\@\@$/},{b:/^\*\*\* +\d+,\d+ +\*\*\*\*$/},{b:/^\-\-\- +\d+,\d+ +\-\-\-\-$/}]},{cN:"header",v:[{b:/Index: /,e:/$/},{b:/=====/,e:/=====$/},{b:/^\-\-\-/,e:/$/},{b:/^\*{3} /,e:/$/},{b:/^\+\+\+/,e:/$/},{b:/\*{5}/,e:/\*{5}$/}]},{cN:"addition",b:"^\\+",e:"$"},{cN:"deletion",b:"^\\-",e:"$"},{cN:"change",b:"^\\!",e:"$"}]}});hljs.registerLanguage("perl",function(e){var t="getpwent getservent quotemeta msgrcv scalar kill dbmclose undef lc ma syswrite tr send umask sysopen shmwrite vec qx utime local oct semctl localtime readpipe do return format read sprintf dbmopen pop getpgrp not getpwnam rewinddir qqfileno qw endprotoent wait sethostent bless s|0 opendir continue each sleep endgrent shutdown dump chomp connect getsockname die socketpair close flock exists index shmgetsub for endpwent redo lstat msgctl setpgrp abs exit select print ref gethostbyaddr unshift fcntl syscall goto getnetbyaddr join gmtime symlink semget splice x|0 getpeername recv log setsockopt cos last reverse gethostbyname getgrnam study formline endhostent times chop length gethostent getnetent pack getprotoent getservbyname rand mkdir pos chmod y|0 substr endnetent printf next open msgsnd readdir use unlink getsockopt getpriority rindex wantarray hex system getservbyport endservent int chr untie rmdir prototype tell listen fork shmread ucfirst setprotoent else sysseek link getgrgid shmctl waitpid unpack getnetbyname reset chdir grep split require caller lcfirst until warn while values shift telldir getpwuid my getprotobynumber delete and sort uc defined srand accept package seekdir getprotobyname semop our rename seek if q|0 chroot sysread setpwent no crypt getc chown sqrt write setnetent setpriority foreach tie sin msgget map stat getlogin unless elsif truncate exec keys glob tied closedirioctl socket readlink eval xor readline binmode setservent eof ord bind alarm pipe atan2 getgrent exp time push setgrent gt lt or ne m|0 break given say state when",r={cN:"subst",b:"[$@]\\{",e:"\\}",k:t},s={b:"->{",e:"}"},n={cN:"variable",v:[{b:/\$\d/},{b:/[\$\%\@](\^\w\b|#\w+(\:\:\w+)*|{\w+}|\w+(\:\:\w*)*)/},{b:/[\$\%\@][^\s\w{]/,r:0}]},o={cN:"comment",b:"^(__END__|__DATA__)",e:"\\n$",r:5},i=[e.BE,r,n],c=[n,e.HCM,o,{cN:"comment",b:"^\\=\\w",e:"\\=cut",eW:!0},s,{cN:"string",c:i,v:[{b:"q[qwxr]?\\s*\\(",e:"\\)",r:5},{b:"q[qwxr]?\\s*\\[",e:"\\]",r:5},{b:"q[qwxr]?\\s*\\{",e:"\\}",r:5},{b:"q[qwxr]?\\s*\\|",e:"\\|",r:5},{b:"q[qwxr]?\\s*\\<",e:"\\>",r:5},{b:"qw\\s+q",e:"q",r:5},{b:"'",e:"'",c:[e.BE]},{b:'"',e:'"'},{b:"`",e:"`",c:[e.BE]},{b:"{\\w+}",c:[],r:0},{b:"-?\\w+\\s*\\=\\>",c:[],r:0}]},{cN:"number",b:"(\\b0[0-7_]+)|(\\b0x[0-9a-fA-F_]+)|(\\b[1-9][0-9_]*(\\.[0-9_]+)?)|[0_]\\b",r:0},{b:"(\\/\\/|"+e.RSR+"|\\b(split|return|print|reverse|grep)\\b)\\s*",k:"split return print reverse grep",r:0,c:[e.HCM,o,{cN:"regexp",b:"(s|tr|y)/(\\\\.|[^/])*/(\\\\.|[^/])*/[a-z]*",r:10},{cN:"regexp",b:"(m|qr)?/",e:"/[a-z]*",c:[e.BE],r:0}]},{cN:"sub",bK:"sub",e:"(\\s*\\(.*?\\))?[;{]",r:5},{cN:"operator",b:"-\\w\\b",r:0}];return r.c=c,s.c=c,{aliases:["pl"],k:t,c:c}});hljs.registerLanguage("makefile",function(e){var a={cN:"variable",b:/\$\(/,e:/\)/,c:[e.BE]};return{aliases:["mk","mak"],c:[e.HCM,{b:/^\w+\s*\W*=/,rB:!0,r:0,starts:{cN:"constant",e:/\s*\W*=/,eE:!0,starts:{e:/$/,r:0,c:[a]}}},{cN:"title",b:/^[\w]+:\s*$/},{cN:"phony",b:/^\.PHONY:/,e:/$/,k:".PHONY",l:/[\.\w]+/},{b:/^\t+/,e:/$/,r:0,c:[e.QSM,a]}]}});hljs.registerLanguage("cs",function(e){var r="abstract as base bool break byte case catch char checked const continue decimal default delegate do double else enum event explicit extern false finally fixed float for foreach goto if implicit in int interface internal is lock long null object operator out override params private protected public readonly ref sbyte sealed short sizeof stackalloc static string struct switch this true try typeof uint ulong unchecked unsafe ushort using virtual volatile void while async protected public private internal ascending descending from get group into join let orderby partial select set value var where yield",t=e.IR+"(<"+e.IR+">)?";return{aliases:["csharp"],k:r,i:/::/,c:[{cN:"comment",b:"///",e:"$",rB:!0,c:[{cN:"xmlDocTag",v:[{b:"///",r:0},{b:""},{b:"?",e:">"}]}]},e.CLCM,e.CBCM,{cN:"preprocessor",b:"#",e:"$",k:"if else elif endif define undef warning error line region endregion pragma checksum"},{cN:"string",b:'@"',e:'"',c:[{b:'""'}]},e.ASM,e.QSM,e.CNM,{bK:"class namespace interface",e:/[{;=]/,i:/[^\s:]/,c:[e.TM,e.CLCM,e.CBCM]},{bK:"new return throw await",r:0},{cN:"function",b:"("+t+"\\s+)+"+e.IR+"\\s*\\(",rB:!0,e:/[{;=]/,eE:!0,k:r,c:[{b:e.IR+"\\s*\\(",rB:!0,c:[e.TM],r:0},{cN:"params",b:/\(/,e:/\)/,k:r,r:0,c:[e.ASM,e.QSM,e.CNM,e.CBCM]},e.CLCM,e.CBCM]}]}});hljs.registerLanguage("json",function(e){var t={literal:"true false null"},i=[e.QSM,e.CNM],l={cN:"value",e:",",eW:!0,eE:!0,c:i,k:t},c={b:"{",e:"}",c:[{cN:"attribute",b:'\\s*"',e:'"\\s*:\\s*',eB:!0,eE:!0,c:[e.BE],i:"\\n",starts:l}],i:"\\S"},n={b:"\\[",e:"\\]",c:[e.inherit(l,{cN:null})],i:"\\S"};return i.splice(i.length,0,c,n),{c:i,k:t,i:"\\S"}});hljs.registerLanguage("nginx",function(e){var r={cN:"variable",v:[{b:/\$\d+/},{b:/\$\{/,e:/}/},{b:"[\\$\\@]"+e.UIR}]},b={eW:!0,l:"[a-z/_]+",k:{built_in:"on off yes no true false none blocked debug info notice warn error crit select break last permanent redirect kqueue rtsig epoll poll /dev/poll"},r:0,i:"=>",c:[e.HCM,{cN:"string",c:[e.BE,r],v:[{b:/"/,e:/"/},{b:/'/,e:/'/}]},{cN:"url",b:"([a-z]+):/",e:"\\s",eW:!0,eE:!0,c:[r]},{cN:"regexp",c:[e.BE,r],v:[{b:"\\s\\^",e:"\\s|{|;",rE:!0},{b:"~\\*?\\s+",e:"\\s|{|;",rE:!0},{b:"\\*(\\.[a-z\\-]+)+"},{b:"([a-z\\-]+\\.)+\\*"}]},{cN:"number",b:"\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}(:\\d{1,5})?\\b"},{cN:"number",b:"\\b\\d+[kKmMgGdshdwy]*\\b",r:0},r]};return{aliases:["nginxconf"],c:[e.HCM,{b:e.UIR+"\\s",e:";|{",rB:!0,c:[{cN:"title",b:e.UIR,starts:b}],r:0}],i:"[^\\s\\}]"}});hljs.registerLanguage("sql",function(e){var t={cN:"comment",b:"--",e:"$"};return{cI:!0,i:/[<>]/,c:[{cN:"operator",bK:"begin end start commit rollback savepoint lock alter create drop rename call delete do handler insert load replace select truncate update set show pragma grant merge describe use explain help declare prepare execute deallocate savepoint release unlock purge reset change stop analyze cache flush optimize repair kill install uninstall checksum restore check backup",e:/;/,eW:!0,k:{keyword:"abs absolute acos action add adddate addtime aes_decrypt aes_encrypt after aggregate all allocate alter analyze and any are as asc ascii asin assertion at atan atan2 atn2 authorization authors avg backup before begin benchmark between bin binlog bit_and bit_count bit_length bit_or bit_xor both by cache call cascade cascaded case cast catalog ceil ceiling chain change changed char_length character_length charindex charset check checksum checksum_agg choose close coalesce coercibility collate collation collationproperty column columns columns_updated commit compress concat concat_ws concurrent connect connection connection_id consistent constraint constraints continue contributors conv convert convert_tz corresponding cos cot count count_big crc32 create cross cume_dist curdate current current_date current_time current_timestamp current_user cursor curtime data database databases datalength date_add date_format date_sub dateadd datediff datefromparts datename datepart datetime2fromparts datetimeoffsetfromparts day dayname dayofmonth dayofweek dayofyear deallocate declare decode default deferrable deferred degrees delayed delete des_decrypt des_encrypt des_key_file desc describe descriptor diagnostics difference disconnect distinct distinctrow div do domain double drop dumpfile each else elt enclosed encode encrypt end end-exec engine engines eomonth errors escape escaped event eventdata events except exception exec execute exists exp explain export_set extended external extract fast fetch field fields find_in_set first first_value floor flush for force foreign format found found_rows from from_base64 from_days from_unixtime full function get get_format get_lock getdate getutcdate global go goto grant grants greatest group group_concat grouping grouping_id gtid_subset gtid_subtract handler having help hex high_priority hosts hour ident_current ident_incr ident_seed identified identity if ifnull ignore iif ilike immediate in index indicator inet6_aton inet6_ntoa inet_aton inet_ntoa infile initially inner innodb input insert install instr intersect into is is_free_lock is_ipv4 is_ipv4_compat is_ipv4_mapped is_not is_not_null is_used_lock isdate isnull isolation join key kill language last last_day last_insert_id last_value lcase lead leading least leaves left len lenght level like limit lines ln load load_file local localtime localtimestamp locate lock log log10 log2 logfile logs low_priority lower lpad ltrim make_set makedate maketime master master_pos_wait match matched max md5 medium merge microsecond mid min minute mod mode module month monthname mutex name_const names national natural nchar next no no_write_to_binlog not now nullif nvarchar oct octet_length of old_password on only open optimize option optionally or ord order outer outfile output pad parse partial partition password patindex percent_rank percentile_cont percentile_disc period_add period_diff pi plugin position pow power pragma precision prepare preserve primary prior privileges procedure procedure_analyze processlist profile profiles public publishingservername purge quarter query quick quote quotename radians rand read references regexp relative relaylog release release_lock rename repair repeat replace replicate reset restore restrict return returns reverse revoke right rlike rollback rollup round row row_count rows rpad rtrim savepoint schema scroll sec_to_time second section select serializable server session session_user set sha sha1 sha2 share show sign sin size slave sleep smalldatetimefromparts snapshot some soname soundex sounds_like space sql sql_big_result sql_buffer_result sql_cache sql_calc_found_rows sql_no_cache sql_small_result sql_variant_property sqlstate sqrt square start starting status std stddev stddev_pop stddev_samp stdev stdevp stop str str_to_date straight_join strcmp string stuff subdate substr substring subtime subtring_index sum switchoffset sysdate sysdatetime sysdatetimeoffset system_user sysutcdatetime table tables tablespace tan temporary terminated tertiary_weights then time time_format time_to_sec timediff timefromparts timestamp timestampadd timestampdiff timezone_hour timezone_minute to to_base64 to_days to_seconds todatetimeoffset trailing transaction translation trigger trigger_nestlevel triggers trim truncate try_cast try_convert try_parse ucase uncompress uncompressed_length unhex unicode uninstall union unique unix_timestamp unknown unlock update upgrade upped upper usage use user user_resources using utc_date utc_time utc_timestamp uuid uuid_short validate_password_strength value values var var_pop var_samp variables variance varp version view warnings week weekday weekofyear weight_string when whenever where with work write xml xor year yearweek zon",literal:"true false null",built_in:"array bigint binary bit blob boolean char character date dec decimal float int integer interval number numeric real serial smallint varchar varying int8 serial8 text"},c:[{cN:"string",b:"'",e:"'",c:[e.BE,{b:"''"}]},{cN:"string",b:'"',e:'"',c:[e.BE,{b:'""'}]},{cN:"string",b:"`",e:"`",c:[e.BE]},e.CNM,e.CBCM,t]},e.CBCM,t]}});hljs.registerLanguage("xml",function(){var t="[A-Za-z0-9\\._:-]+",e={b:/<\?(php)?(?!\w)/,e:/\?>/,sL:"php",subLanguageMode:"continuous"},c={eW:!0,i:/,r:0,c:[e,{cN:"attribute",b:t,r:0},{b:"=",r:0,c:[{cN:"value",c:[e],v:[{b:/"/,e:/"/},{b:/'/,e:/'/},{b:/[^\s\/>]+/}]}]}]};return{aliases:["html","xhtml","rss","atom","xsl","plist"],cI:!0,c:[{cN:"doctype",b:"",r:10,c:[{b:"\\[",e:"\\]"}]},{cN:"comment",b:"",r:10},{cN:"cdata",b:"<\\!\\[CDATA\\[",e:"\\]\\]>",r:10},{cN:"tag",b:"",rE:!0,sL:"css"}},{cN:"tag",b:"",rE:!0,sL:"javascript"}},e,{cN:"pi",b:/<\?\w+/,e:/\?>/,r:10},{cN:"tag",b:"?",e:"/?>",c:[{cN:"title",b:/[^ \/><\n\t]+/,r:0},c]}]}});hljs.registerLanguage("php",function(e){var c={cN:"variable",b:"\\$+[a-zA-Z_-ÿ][a-zA-Z0-9_-ÿ]*"},i={cN:"preprocessor",b:/<\?(php)?|\?>/},a={cN:"string",c:[e.BE,i],v:[{b:'b"',e:'"'},{b:"b'",e:"'"},e.inherit(e.ASM,{i:null}),e.inherit(e.QSM,{i:null})]},n={v:[e.BNM,e.CNM]};return{aliases:["php3","php4","php5","php6"],cI:!0,k:"and include_once list abstract global private echo interface as static endswitch array null if endwhile or const for endforeach self var while isset public protected exit foreach throw elseif include __FILE__ empty require_once do xor return parent clone use __CLASS__ __LINE__ else break print eval new catch __METHOD__ case exception default die require __FUNCTION__ enddeclare final try switch continue endfor endif declare unset true false trait goto instanceof insteadof __DIR__ __NAMESPACE__ yield finally",c:[e.CLCM,e.HCM,{cN:"comment",b:"/\\*",e:"\\*/",c:[{cN:"phpdoc",b:"\\s@[A-Za-z]+"},i]},{cN:"comment",b:"__halt_compiler.+?;",eW:!0,k:"__halt_compiler",l:e.UIR},{cN:"string",b:"<<<['\"]?\\w+['\"]?$",e:"^\\w+;",c:[e.BE]},i,c,{b:/->+[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/},{cN:"function",bK:"function",e:/[;{]/,eE:!0,i:"\\$|\\[|%",c:[e.UTM,{cN:"params",b:"\\(",e:"\\)",c:["self",c,e.CBCM,a,n]}]},{cN:"class",bK:"class interface",e:"{",eE:!0,i:/[:\(\$"]/,c:[{bK:"extends implements"},e.UTM]},{bK:"namespace",e:";",i:/[\.']/,c:[e.UTM]},{bK:"use",e:";",c:[e.UTM]},{b:"=>"},a,n]}}); --------------------------------------------------------------------------------
Latest comments:
81 |82 |-
83 | nofish:
84 | WebGL under linux can be problematic, here is some tips...
85 |
86 | @
87 | Changelog, August 16, 2015
88 |
89 |
90 |
91 |