haveapi 0.6.0 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.editorconfig +15 -0
- data/CHANGELOG +15 -0
- data/README.md +66 -47
- data/doc/create-client.md +14 -5
- data/doc/json-schema.erb +16 -2
- data/doc/protocol.md +25 -3
- data/doc/protocol.plantuml +14 -8
- data/haveapi.gemspec +4 -2
- data/lib/haveapi.rb +5 -3
- data/lib/haveapi/action.rb +34 -6
- data/lib/haveapi/action_state.rb +92 -0
- data/lib/haveapi/authentication/basic/provider.rb +7 -0
- data/lib/haveapi/authentication/token/provider.rb +5 -0
- data/lib/haveapi/client_example.rb +83 -0
- data/lib/haveapi/client_examples/curl.rb +86 -0
- data/lib/haveapi/client_examples/fs_client.rb +116 -0
- data/lib/haveapi/client_examples/http.rb +91 -0
- data/lib/haveapi/client_examples/js_client.rb +149 -0
- data/lib/haveapi/client_examples/php_client.rb +122 -0
- data/lib/haveapi/client_examples/ruby_cli.rb +117 -0
- data/lib/haveapi/client_examples/ruby_client.rb +106 -0
- data/lib/haveapi/context.rb +3 -2
- data/lib/haveapi/example.rb +29 -2
- data/lib/haveapi/extensions/action_exceptions.rb +2 -2
- data/lib/haveapi/extensions/base.rb +1 -1
- data/lib/haveapi/extensions/exception_mailer.rb +339 -0
- data/lib/haveapi/hooks.rb +1 -1
- data/lib/haveapi/parameters/typed.rb +5 -3
- data/lib/haveapi/public/css/highlight.css +99 -0
- data/lib/haveapi/public/doc/protocol.png +0 -0
- data/lib/haveapi/public/js/highlight.pack.js +2 -0
- data/lib/haveapi/public/js/highlighter.js +9 -0
- data/lib/haveapi/public/js/main.js +32 -0
- data/lib/haveapi/public/js/nojs-tabs.js +196 -0
- data/lib/haveapi/resources/action_state.rb +196 -0
- data/lib/haveapi/server.rb +96 -27
- data/lib/haveapi/version.rb +2 -2
- data/lib/haveapi/views/main_layout.erb +14 -0
- data/lib/haveapi/views/version_page.erb +187 -13
- data/lib/haveapi/views/version_sidebar.erb +37 -3
- metadata +49 -5
data/lib/haveapi/hooks.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'date'
|
2
|
+
|
1
3
|
module HaveAPI::Parameters
|
2
4
|
class Typed
|
3
5
|
ATTRIBUTES = %i(label desc type db_name default fill clean)
|
@@ -67,7 +69,7 @@ module HaveAPI::Parameters
|
|
67
69
|
|
68
70
|
def clean(raw)
|
69
71
|
return instance_exec(raw, &@clean) if @clean
|
70
|
-
|
72
|
+
|
71
73
|
val = if raw.nil?
|
72
74
|
@default
|
73
75
|
|
@@ -76,7 +78,7 @@ module HaveAPI::Parameters
|
|
76
78
|
|
77
79
|
elsif @type == Integer
|
78
80
|
raw.to_i
|
79
|
-
|
81
|
+
|
80
82
|
elsif @type == Float
|
81
83
|
raw.to_f
|
82
84
|
|
@@ -85,7 +87,7 @@ module HaveAPI::Parameters
|
|
85
87
|
|
86
88
|
elsif @type == ::Datetime
|
87
89
|
begin
|
88
|
-
|
90
|
+
DateTime.iso8601(raw).to_time
|
89
91
|
|
90
92
|
rescue ArgumentError
|
91
93
|
raise HaveAPI::ValidationError.new("not in ISO 8601 format '#{raw}'")
|
@@ -0,0 +1,99 @@
|
|
1
|
+
/*
|
2
|
+
|
3
|
+
Original highlight.js style (c) Ivan Sagalaev <maniac@softwaremaniacs.org>
|
4
|
+
|
5
|
+
*/
|
6
|
+
|
7
|
+
.hljs {
|
8
|
+
display: block;
|
9
|
+
overflow-x: auto;
|
10
|
+
padding: 0.5em;
|
11
|
+
background: #F0F0F0;
|
12
|
+
}
|
13
|
+
|
14
|
+
|
15
|
+
/* Base color: saturation 0; */
|
16
|
+
|
17
|
+
.hljs,
|
18
|
+
.hljs-subst {
|
19
|
+
color: #444;
|
20
|
+
}
|
21
|
+
|
22
|
+
.hljs-comment {
|
23
|
+
color: #888888;
|
24
|
+
}
|
25
|
+
|
26
|
+
.hljs-keyword,
|
27
|
+
.hljs-attribute,
|
28
|
+
.hljs-selector-tag,
|
29
|
+
.hljs-meta-keyword,
|
30
|
+
.hljs-doctag,
|
31
|
+
.hljs-name {
|
32
|
+
font-weight: bold;
|
33
|
+
}
|
34
|
+
|
35
|
+
|
36
|
+
/* User color: hue: 0 */
|
37
|
+
|
38
|
+
.hljs-type,
|
39
|
+
.hljs-string,
|
40
|
+
.hljs-number,
|
41
|
+
.hljs-selector-id,
|
42
|
+
.hljs-selector-class,
|
43
|
+
.hljs-quote,
|
44
|
+
.hljs-template-tag,
|
45
|
+
.hljs-deletion {
|
46
|
+
color: #880000;
|
47
|
+
}
|
48
|
+
|
49
|
+
.hljs-title,
|
50
|
+
.hljs-section {
|
51
|
+
color: #880000;
|
52
|
+
font-weight: bold;
|
53
|
+
}
|
54
|
+
|
55
|
+
.hljs-regexp,
|
56
|
+
.hljs-symbol,
|
57
|
+
.hljs-variable,
|
58
|
+
.hljs-template-variable,
|
59
|
+
.hljs-link,
|
60
|
+
.hljs-selector-attr,
|
61
|
+
.hljs-selector-pseudo {
|
62
|
+
color: #BC6060;
|
63
|
+
}
|
64
|
+
|
65
|
+
|
66
|
+
/* Language color: hue: 90; */
|
67
|
+
|
68
|
+
.hljs-literal {
|
69
|
+
color: #78A960;
|
70
|
+
}
|
71
|
+
|
72
|
+
.hljs-built_in,
|
73
|
+
.hljs-bullet,
|
74
|
+
.hljs-code,
|
75
|
+
.hljs-addition {
|
76
|
+
color: #397300;
|
77
|
+
}
|
78
|
+
|
79
|
+
|
80
|
+
/* Meta color: hue: 200 */
|
81
|
+
|
82
|
+
.hljs-meta {
|
83
|
+
color: #1f7199;
|
84
|
+
}
|
85
|
+
|
86
|
+
.hljs-meta-string {
|
87
|
+
color: #4d99bf;
|
88
|
+
}
|
89
|
+
|
90
|
+
|
91
|
+
/* Misc effects */
|
92
|
+
|
93
|
+
.hljs-emphasis {
|
94
|
+
font-style: italic;
|
95
|
+
}
|
96
|
+
|
97
|
+
.hljs-strong {
|
98
|
+
font-weight: bold;
|
99
|
+
}
|
Binary file
|
@@ -0,0 +1,2 @@
|
|
1
|
+
/*! highlight.js v9.8.0 | BSD3 License | git.io/hljslicense */
|
2
|
+
!function(e){var n="object"==typeof window&&window||"object"==typeof self&&self;"undefined"!=typeof exports?e(exports):n&&(n.hljs=e({}),"function"==typeof define&&define.amd&&define([],function(){return n.hljs}))}(function(e){function n(e){return e.replace(/[&<>]/gm,function(e){return I[e]})}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){return k.test(e)}function i(e){var n,t,r,i,o=e.className+" ";if(o+=e.parentNode?e.parentNode.className:"",t=B.exec(o))return R(t[1])?t[1]:"no-highlight";for(o=o.split(/\s+/),n=0,r=o.length;r>n;n++)if(i=o[n],a(i)||R(i))return i}function o(e,n){var t,r={};for(t in e)r[t]=e[t];if(n)for(t in n)r[t]=n[t];return r}function u(e){var n=[];return function r(e,a){for(var i=e.firstChild;i;i=i.nextSibling)3===i.nodeType?a+=i.nodeValue.length:1===i.nodeType&&(n.push({event:"start",offset:a,node:i}),a=r(i,a),t(i).match(/br|hr|img|input/)||n.push({event:"stop",offset:a,node:i}));return a}(e,0),n}function c(e,r,a){function i(){return e.length&&r.length?e[0].offset!==r[0].offset?e[0].offset<r[0].offset?e:r:"start"===r[0].event?e:r:e.length?e:r}function o(e){function r(e){return" "+e.nodeName+'="'+n(e.value)+'"'}l+="<"+t(e)+w.map.call(e.attributes,r).join("")+">"}function u(e){l+="</"+t(e)+">"}function c(e){("start"===e.event?o:u)(e.node)}for(var s=0,l="",f=[];e.length||r.length;){var g=i();if(l+=n(a.substr(s,g[0].offset-s)),s=g[0].offset,g===e){f.reverse().forEach(u);do c(g.splice(0,1)[0]),g=i();while(g===e&&g.length&&g[0].offset===s);f.reverse().forEach(o)}else"start"===g[0].event?f.push(g[0].node):f.pop(),c(g.splice(0,1)[0])}return l+n(a.substr(s))}function s(e){function n(e){return e&&e.source||e}function t(t,r){return new 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 u={},c=function(n,t){e.cI&&(t=t.toLowerCase()),t.split(" ").forEach(function(e){var t=e.split("|");u[t[0]]=[n,t[1]?Number(t[1]):1]})};"string"==typeof a.k?c("keyword",a.k):E(a.k).forEach(function(e){c(e,a.k[e])}),a.k=u}a.lR=t(a.l||/\w+/,!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)),null==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 l(e,t,a,i){function o(e,n){var t,a;for(t=0,a=n.c.length;a>t;t++)if(r(n.c[t].bR,e))return n.c[t]}function u(e,n){if(r(e.eR,n)){for(;e.endsParent&&e.parent;)e=e.parent;return e}return e.eW?u(e.parent,n):void 0}function c(e,n){return!a&&r(n.iR,e)}function g(e,n){var t=N.cI?n[0].toLowerCase():n[0];return e.k.hasOwnProperty(t)&&e.k[t]}function h(e,n,t,r){var a=r?"":y.classPrefix,i='<span class="'+a,o=t?"":C;return i+=e+'">',i+n+o}function p(){var e,t,r,a;if(!E.k)return n(B);for(a="",t=0,E.lR.lastIndex=0,r=E.lR.exec(B);r;)a+=n(B.substr(t,r.index-t)),e=g(E,r),e?(M+=e[1],a+=h(e[0],n(r[0]))):a+=n(r[0]),t=E.lR.lastIndex,r=E.lR.exec(B);return a+n(B.substr(t))}function d(){var e="string"==typeof E.sL;if(e&&!x[E.sL])return n(B);var t=e?l(E.sL,B,!0,L[E.sL]):f(B,E.sL.length?E.sL:void 0);return E.r>0&&(M+=t.r),e&&(L[E.sL]=t.top),h(t.language,t.value,!1,!0)}function b(){k+=null!=E.sL?d():p(),B=""}function v(e){k+=e.cN?h(e.cN,"",!0):"",E=Object.create(e,{parent:{value:E}})}function m(e,n){if(B+=e,null==n)return b(),0;var t=o(n,E);if(t)return t.skip?B+=n:(t.eB&&(B+=n),b(),t.rB||t.eB||(B=n)),v(t,n),t.rB?0:n.length;var r=u(E,n);if(r){var a=E;a.skip?B+=n:(a.rE||a.eE||(B+=n),b(),a.eE&&(B=n));do E.cN&&(k+=C),E.skip||(M+=E.r),E=E.parent;while(E!==r.parent);return r.starts&&v(r.starts,""),a.rE?0:n.length}if(c(n,E))throw new Error('Illegal lexeme "'+n+'" for mode "'+(E.cN||"<unnamed>")+'"');return B+=n,n.length||1}var N=R(e);if(!N)throw new Error('Unknown language: "'+e+'"');s(N);var w,E=i||N,L={},k="";for(w=E;w!==N;w=w.parent)w.cN&&(k=h(w.cN,"",!0)+k);var B="",M=0;try{for(var I,j,O=0;;){if(E.t.lastIndex=O,I=E.t.exec(t),!I)break;j=m(t.substr(O,I.index-O),I[0]),O=I.index+j}for(m(t.substr(O)),w=E;w.parent;w=w.parent)w.cN&&(k+=C);return{r:M,value:k,language:e,top:E}}catch(T){if(T.message&&-1!==T.message.indexOf("Illegal"))return{r:0,value:n(t)};throw T}}function f(e,t){t=t||y.languages||E(x);var r={r:0,value:n(e)},a=r;return t.filter(R).forEach(function(n){var t=l(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 g(e){return y.tabReplace||y.useBR?e.replace(M,function(e,n){return y.useBR&&"\n"===e?"<br>":y.tabReplace?n.replace(/\t/g,y.tabReplace):void 0}):e}function h(e,n,t){var r=n?L[n]:t,a=[e.trim()];return e.match(/\bhljs\b/)||a.push("hljs"),-1===e.indexOf(r)&&a.push(r),a.join(" ").trim()}function p(e){var n,t,r,o,s,p=i(e);a(p)||(y.useBR?(n=document.createElementNS("http://www.w3.org/1999/xhtml","div"),n.innerHTML=e.innerHTML.replace(/\n/g,"").replace(/<br[ \/]*>/g,"\n")):n=e,s=n.textContent,r=p?l(p,s,!0):f(s),t=u(n),t.length&&(o=document.createElementNS("http://www.w3.org/1999/xhtml","div"),o.innerHTML=r.value,r.value=c(t,u(o),s)),r.value=g(r.value),e.innerHTML=r.value,e.className=h(e.className,p,r.language),e.result={language:r.language,re:r.r},r.second_best&&(e.second_best={language:r.second_best.language,re:r.second_best.r}))}function d(e){y=o(y,e)}function b(){if(!b.called){b.called=!0;var e=document.querySelectorAll("pre code");w.forEach.call(e,p)}}function v(){addEventListener("DOMContentLoaded",b,!1),addEventListener("load",b,!1)}function m(n,t){var r=x[n]=t(e);r.aliases&&r.aliases.forEach(function(e){L[e]=n})}function N(){return E(x)}function R(e){return e=(e||"").toLowerCase(),x[e]||x[L[e]]}var w=[],E=Object.keys,x={},L={},k=/^(no-?highlight|plain|text)$/i,B=/\blang(?:uage)?-([\w-]+)\b/i,M=/((^(<[^>]+>|\t|)+|(?:\n)))/gm,C="</span>",y={classPrefix:"hljs-",tabReplace:null,useBR:!1,languages:void 0},I={"&":"&","<":"<",">":">"};return e.highlight=l,e.highlightAuto=f,e.fixMarkup=g,e.highlightBlock=p,e.configure=d,e.initHighlighting=b,e.initHighlightingOnLoad=v,e.registerLanguage=m,e.listLanguages=N,e.getLanguage=R,e.inherit=o,e.IR="[a-zA-Z]\\w*",e.UIR="[a-zA-Z_]\\w*",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'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|like)\b/},e.C=function(n,t,r){var a=e.inherit({cN:"comment",b:n,e:t,c:[]},r||{});return a.c.push(e.PWM),a.c.push({cN:"doctag",b:"(?:TODO|FIXME|NOTE|BUG|XXX):",r:0}),a},e.CLCM=e.C("//","$"),e.CBCM=e.C("/\\*","\\*/"),e.HCM=e.C("#","$"),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.METHOD_GUARD={b:"\\.\\s*"+e.UIR,r:0},e});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",_:"-ne -eq -lt -gt -f -d -e -s -l -a"},c:[{cN:"meta",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,s,a,t]}});hljs.registerLanguage("http",function(e){var t="HTTP/[0-9\\.]+";return{aliases:["https"],i:"\\S",c:[{b:"^"+t,e:"$",c:[{cN:"number",b:"\\b\\d{3}\\b"}]},{b:"^[A-Z]+ (.*?) "+t+"$",rB:!0,e:"$",c:[{cN:"string",b:" ",e:" ",eB:!0,eE:!0},{b:t},{cN:"keyword",b:"[A-Z]+"}]},{cN:"attribute",b:"^\\w",e:": ",eE:!0,i:"\\n|\\s|=",starts:{e:"$",r:0}},{b:"\\n\\n",starts:{sL:[],eW:!0}}]}});hljs.registerLanguage("xml",function(s){var e="[A-Za-z0-9\\._:-]+",t={eW:!0,i:/</,r:0,c:[{cN:"attr",b:e,r:0},{b:/=\s*/,r:0,c:[{cN:"string",endsParent:!0,v:[{b:/"/,e:/"/},{b:/'/,e:/'/},{b:/[^\s"'=<>`]+/}]}]}]};return{aliases:["html","xhtml","rss","atom","xjb","xsd","xsl","plist"],cI:!0,c:[{cN:"meta",b:"<!DOCTYPE",e:">",r:10,c:[{b:"\\[",e:"\\]"}]},s.C("<!--","-->",{r:10}),{b:"<\\!\\[CDATA\\[",e:"\\]\\]>",r:10},{b:/<\?(php)?/,e:/\?>/,sL:"php",c:[{b:"/\\*",e:"\\*/",skip:!0}]},{cN:"tag",b:"<style(?=\\s|>|$)",e:">",k:{name:"style"},c:[t],starts:{e:"</style>",rE:!0,sL:["css","xml"]}},{cN:"tag",b:"<script(?=\\s|>|$)",e:">",k:{name:"script"},c:[t],starts:{e:"</script>",rE:!0,sL:["actionscript","javascript","handlebars","xml"]}},{cN:"meta",v:[{b:/<\?xml/,e:/\?>/,r:10},{b:/<\?\w+/,e:/\?>/}]},{cN:"tag",b:"</?",e:"/?>",c:[{cN:"name",b:/[^\/><\s]+/,r:0},t]}]}});hljs.registerLanguage("php",function(e){var c={b:"\\$+[a-zA-Z_-ÿ][a-zA-Z0-9_-ÿ]*"},i={cN:"meta",b:/<\?(php)?|\?>/},t={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})]},a={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.HCM,e.C("//","$",{c:[i]}),e.C("/\\*","\\*/",{c:[{cN:"doctag",b:"@[A-Za-z]+"}]}),e.C("__halt_compiler.+?;",!1,{eW:!0,k:"__halt_compiler",l:e.UIR}),{cN:"string",b:/<<<['"]?\w+['"]?$/,e:/^\w+;?$/,c:[e.BE,{cN:"subst",v:[{b:/\$\w+/},{b:/\{\$/,e:/\}/}]}]},i,{cN:"keyword",b:/\$this\b/},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,t,a]}]},{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:"=>"},t,a]}});hljs.registerLanguage("json",function(e){var i={literal:"true false null"},n=[e.QSM,e.CNM],r={e:",",eW:!0,eE:!0,c:n,k:i},t={b:"{",e:"}",c:[{cN:"attr",b:/"/,e:/"/,c:[e.BE],i:"\\n"},e.inherit(r,{b:/:/})],i:"\\S"},c={b:"\\[",e:"\\]",c:[e.inherit(r)],i:"\\S"};return n.splice(n.length,0,t,c),{c:n,k:i,i:"\\S"}});hljs.registerLanguage("javascript",function(e){var r="[A-Za-z$_][0-9A-Za-z$_]*",t={keyword:"in of 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 export super debugger as async await static import from as",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 Symbol Set Map WeakSet WeakMap Proxy Reflect Promise"},a={cN:"number",v:[{b:"\\b(0[bB][01]+)"},{b:"\\b(0[oO][0-7]+)"},{b:e.CNR}],r:0},n={cN:"subst",b:"\\$\\{",e:"\\}",k:t,c:[]},c={cN:"string",b:"`",e:"`",c:[e.BE,n]};n.c=[e.ASM,e.QSM,c,a,e.RM];var s=n.c.concat([e.CBCM,e.CLCM]);return{aliases:["js","jsx"],k:t,c:[{cN:"meta",r:10,b:/^\s*['"]use (strict|asm)['"]/},{cN:"meta",b:/^#!/,e:/$/},e.ASM,e.QSM,c,e.CLCM,e.CBCM,a,{b:/[{,]\s*/,r:0,c:[{b:r+"\\s*:",rB:!0,r:0,c:[{cN:"attr",b:r,r:0}]}]},{b:"("+e.RSR+"|\\b(case|return|throw)\\b)\\s*",k:"return throw case",c:[e.CLCM,e.CBCM,e.RM,{cN:"function",b:"(\\(.*?\\)|"+r+")\\s*=>",rB:!0,e:"\\s*=>",c:[{cN:"params",v:[{b:r},{b:/\(\s*\)/},{b:/\(/,e:/\)/,eB:!0,eE:!0,k:t,c:s}]}]},{b:/</,e:/(\/\w+|\w+\/)>/,sL:"xml",c:[{b:/<\w+\s*\/>/,skip:!0},{b:/<\w+/,e:/(\/\w+|\w+\/)>/,skip:!0,c:[{b:/<\w+\s*\/>/,skip:!0},"self"]}]}],r:0},{cN:"function",bK:"function",e:/\{/,eE:!0,c:[e.inherit(e.TM,{b:r}),{cN:"params",b:/\(/,e:/\)/,eB:!0,eE:!0,c:s}],i:/\[|%/},{b:/\$[(.]/},e.METHOD_GUARD,{cN:"class",bK:"class",e:/[{;=]/,eE:!0,i:/[:"\[\]]/,c:[{bK:"extends"},e.UTM]},{bK:"constructor",e:/\{/,eE:!0}],i:/#(?!!)/}});hljs.registerLanguage("ruby",function(e){var b="[a-zA-Z_]\\w*[!?=]?|[-+~]\\@|<<|>>|=~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~`|]|\\[\\]=?",r={keyword:"and then defined module in return redo if BEGIN retry end for self when next until do begin unless END rescue else break undef not super class case require yield alias while ensure elsif or include attr_reader attr_writer attr_accessor",literal:"true false nil"},c={cN:"doctag",b:"@[A-Za-z]+"},a={b:"#<",e:">"},s=[e.C("#","$",{c:[c]}),e.C("^\\=begin","^\\=end",{c:[c],r:10}),e.C("^__END__","\\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/},{b:/<<(-?)\w+$/,e:/^\s*\w+$/}]},i={cN:"params",b:"\\(",e:"\\)",endsParent:!0,k:r},d=[t,a,{cN:"class",bK:"class module",e:"$|;",i:/=/,c:[e.inherit(e.TM,{b:"[A-Za-z_]\\w*(::\\w+)*(\\?|\\!)?"}),{b:"<\\s*",c:[{b:"("+e.IR+"::)?"+e.IR}]}].concat(s)},{cN:"function",bK:"def",e:"$|;",c:[e.inherit(e.TM,{b:b}),i].concat(s)},{b:e.IR+"::"},{cN:"symbol",b:e.UIR+"(\\!|\\?)?:",r:0},{cN:"symbol",b:":(?!\\s)",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},{b:"(\\$\\W)|((\\$|\\@\\@?)(\\w+))"},{cN:"params",b:/\|/,e:/\|/,k:r},{b:"("+e.RSR+")\\s*",c:[a,{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]*"}]}].concat(s),r:0}].concat(s);n.c=d,i.c=d;var l="[>?]>",o="[\\w#]+\\(\\w+\\):\\d+:\\d+>",w="(\\w+-)?\\d+\\.\\d+\\.\\d(p\\d+)?[^>]+>",u=[{b:/^\s*=>/,starts:{e:"$",c:d}},{cN:"meta",b:"^("+l+"|"+o+"|"+w+")",starts:{e:"$",c:d}}];return{aliases:["rb","gemspec","podspec","thor","irb"],k:r,i:/\/\*/,c:s.concat(u).concat(d)}});
|
@@ -0,0 +1,32 @@
|
|
1
|
+
(function () {
|
2
|
+
|
3
|
+
$(document).ready(function () {
|
4
|
+
if (window.Worker) {
|
5
|
+
var worker = new Worker('/js/highlighter.js');
|
6
|
+
var codes = $('pre code').toArray();
|
7
|
+
var currentElement;
|
8
|
+
|
9
|
+
var highlightNext = function () {
|
10
|
+
if (!codes.length)
|
11
|
+
return;
|
12
|
+
|
13
|
+
currentElement = codes.shift();
|
14
|
+
worker.postMessage({
|
15
|
+
language: currentElement.classList.item(0),
|
16
|
+
code: currentElement.textContent
|
17
|
+
});
|
18
|
+
};
|
19
|
+
|
20
|
+
worker.onmessage = function (e) {
|
21
|
+
currentElement.innerHTML = e.data;
|
22
|
+
highlightNext();
|
23
|
+
};
|
24
|
+
|
25
|
+
highlightNext();
|
26
|
+
|
27
|
+
} else {
|
28
|
+
hljs.initHighlighting();
|
29
|
+
}
|
30
|
+
});
|
31
|
+
|
32
|
+
})();
|
@@ -0,0 +1,196 @@
|
|
1
|
+
(function (root) {
|
2
|
+
var nojsTabs = function (opts) {
|
3
|
+
this.opts = opts;
|
4
|
+
|
5
|
+
var ul = this.createElement(document.createElement('UL'));
|
6
|
+
var tabNum = opts.tabs.children.length;
|
7
|
+
|
8
|
+
for (var i = 0; i < tabNum; i++) {
|
9
|
+
var tab = opts.tabs.children[i];
|
10
|
+
|
11
|
+
ul.appendChild(this.createTab(tab));
|
12
|
+
}
|
13
|
+
|
14
|
+
opts.tabBar.appendChild(ul);
|
15
|
+
|
16
|
+
this.init();
|
17
|
+
|
18
|
+
var that = this;
|
19
|
+
var prevOnPopState = window.onpopstate;
|
20
|
+
|
21
|
+
window.onpopstate = function(e) {
|
22
|
+
if (!e.state || !e.state.tabBar || that.opts.tabBar.id !== e.state.tabBar) {
|
23
|
+
if (prevOnPopState)
|
24
|
+
prevOnPopState(e);
|
25
|
+
|
26
|
+
return;
|
27
|
+
}
|
28
|
+
|
29
|
+
that.switchTab(document.getElementById(e.state.tab), false);
|
30
|
+
};
|
31
|
+
};
|
32
|
+
|
33
|
+
nojsTabs.Version = '0.2.0';
|
34
|
+
|
35
|
+
nojsTabs.prototype.createElement = function (el) {
|
36
|
+
if (this.opts.createElement !== undefined) {
|
37
|
+
var ret = this.opts.createElement(el);
|
38
|
+
|
39
|
+
return ret === undefined ? el : ret;
|
40
|
+
}
|
41
|
+
|
42
|
+
return el;
|
43
|
+
}
|
44
|
+
|
45
|
+
nojsTabs.prototype.createTab = function (tab) {
|
46
|
+
var li = this.createElement(document.createElement('LI'));
|
47
|
+
li.id = 'tab-anchor-' + tab.id;
|
48
|
+
|
49
|
+
var a = this.createElement(document.createElement('A'));
|
50
|
+
var a_text = document.createTextNode(this.getTitle(tab));
|
51
|
+
|
52
|
+
a.href = '#' + tab.id;
|
53
|
+
|
54
|
+
var that = this;
|
55
|
+
|
56
|
+
a.addEventListener('click', function (e) {
|
57
|
+
that.switchTab(tab);
|
58
|
+
|
59
|
+
if (history.pushState)
|
60
|
+
e.preventDefault();
|
61
|
+
});
|
62
|
+
|
63
|
+
a.appendChild(a_text);
|
64
|
+
li.appendChild(a);
|
65
|
+
|
66
|
+
tab.tabAnchor = li;
|
67
|
+
tab.tabAnchor.activate = function () {
|
68
|
+
that.activate([this]);
|
69
|
+
};
|
70
|
+
|
71
|
+
tab.tabAnchor.deactivate = function () {
|
72
|
+
that.deactivate([this]);
|
73
|
+
};
|
74
|
+
|
75
|
+
return li;
|
76
|
+
};
|
77
|
+
|
78
|
+
nojsTabs.prototype.getTitle = function (tab) {
|
79
|
+
var s = this.opts.titleSelector;
|
80
|
+
|
81
|
+
if (typeof s === 'string' || s instanceof String) {
|
82
|
+
var el = tab.querySelector(s);
|
83
|
+
var ret = el.innerHTML;
|
84
|
+
|
85
|
+
if (this.opts.removeHeading === undefined || this.opts.removeHeading)
|
86
|
+
el.parentElement.removeChild(el);
|
87
|
+
|
88
|
+
return ret;
|
89
|
+
|
90
|
+
} else
|
91
|
+
return s(tab);
|
92
|
+
};
|
93
|
+
|
94
|
+
nojsTabs.prototype.init = function () {
|
95
|
+
var that = this;
|
96
|
+
var targetTab = this.opts.tabs.children[0];
|
97
|
+
|
98
|
+
// Find initial tab
|
99
|
+
if (location.hash) {
|
100
|
+
this.eachTab(function (tab) {
|
101
|
+
if (location.hash == '#'+tab.id) {
|
102
|
+
targetTab = tab;
|
103
|
+
return true;
|
104
|
+
}
|
105
|
+
});
|
106
|
+
|
107
|
+
} else {
|
108
|
+
this.eachTab(function (tab) {
|
109
|
+
if (tab.classList.contains(that.opts.activeClass)) {
|
110
|
+
targetTab = tab;
|
111
|
+
return true;
|
112
|
+
}
|
113
|
+
});
|
114
|
+
}
|
115
|
+
|
116
|
+
// Show/hide tabs
|
117
|
+
this.eachTab(function (tab, i) {
|
118
|
+
var a = that.opts.tabBar.getElementsByTagName('li')[i];
|
119
|
+
|
120
|
+
if (targetTab.id == tab.id)
|
121
|
+
that.activate([tab, a]);
|
122
|
+
else
|
123
|
+
that.deactivate([tab, a]);
|
124
|
+
});
|
125
|
+
};
|
126
|
+
|
127
|
+
nojsTabs.prototype.eachTab = function (fn) {
|
128
|
+
var tabs = this.opts.tabs.children;
|
129
|
+
var tabNum = tabs.length;
|
130
|
+
|
131
|
+
for (var i = 0; i < tabNum; i++) {
|
132
|
+
if (fn(tabs[i], i))
|
133
|
+
break;
|
134
|
+
}
|
135
|
+
};
|
136
|
+
|
137
|
+
nojsTabs.prototype.switchTab = function (targetTab, pushState) {
|
138
|
+
var that = this;
|
139
|
+
var activeTab = this.opts.tabs.querySelector('.'+this.opts.activeClass);
|
140
|
+
|
141
|
+
if (activeTab.id == targetTab.id)
|
142
|
+
return;
|
143
|
+
|
144
|
+
// beforeChange
|
145
|
+
if (this.opts.beforeChange !== undefined)
|
146
|
+
this.opts.beforeChange(activeTab, targetTab);
|
147
|
+
|
148
|
+
// transition
|
149
|
+
if (this.opts.transition !== undefined)
|
150
|
+
this.opts.transition(activeTab, targetTab, function () {
|
151
|
+
that.transition(activeTab, targetTab);
|
152
|
+
});
|
153
|
+
|
154
|
+
else
|
155
|
+
this.transition(activeTab, targetTab);
|
156
|
+
|
157
|
+
if ((pushState === undefined || pushState) && history.pushState) {
|
158
|
+
history.pushState({
|
159
|
+
tabBar: this.opts.tabBar.id,
|
160
|
+
tab: targetTab.id
|
161
|
+
}, null, '#'+targetTab.id);
|
162
|
+
}
|
163
|
+
};
|
164
|
+
|
165
|
+
nojsTabs.prototype.transition = function(activeTab, targetTab) {
|
166
|
+
this.deactivate([activeTab, activeTab.tabAnchor]);
|
167
|
+
this.activate([targetTab, targetTab.tabAnchor]);
|
168
|
+
|
169
|
+
// afterChange
|
170
|
+
if (this.opts.beforeChange !== undefined)
|
171
|
+
this.opts.afterChange(targetTab, activeTab);
|
172
|
+
};
|
173
|
+
|
174
|
+
nojsTabs.prototype.activate = function (elems) {
|
175
|
+
var len = elems.length;
|
176
|
+
|
177
|
+
for (var i = 0; i < len; i++) {
|
178
|
+
elems[i].classList.remove(this.opts.hiddenClass);
|
179
|
+
elems[i].classList.add(this.opts.activeClass);
|
180
|
+
}
|
181
|
+
};
|
182
|
+
|
183
|
+
nojsTabs.prototype.deactivate = function (elems) {
|
184
|
+
var len = elems.length;
|
185
|
+
|
186
|
+
for (var i = 0; i < len; i++) {
|
187
|
+
elems[i].classList.remove(this.opts.activeClass);
|
188
|
+
elems[i].classList.add(this.opts.hiddenClass);
|
189
|
+
}
|
190
|
+
};
|
191
|
+
|
192
|
+
root.nojsTabs = function (opts) {
|
193
|
+
return new nojsTabs(opts);
|
194
|
+
};
|
195
|
+
|
196
|
+
})(window);
|
@@ -0,0 +1,196 @@
|
|
1
|
+
module HaveAPI::Resources
|
2
|
+
class ActionState < HaveAPI::Resource
|
3
|
+
desc 'Browse states of blocking actions'
|
4
|
+
auth false
|
5
|
+
version :all
|
6
|
+
|
7
|
+
params(:all) do
|
8
|
+
id :id
|
9
|
+
string :label, label: 'Label'
|
10
|
+
bool :finished, label: 'Finished'
|
11
|
+
bool :status, label: 'Status',
|
12
|
+
desc: 'Determines whether the action is proceeding or failing'
|
13
|
+
integer :current, label: 'Current progress'
|
14
|
+
integer :total, label: 'Total',
|
15
|
+
desc: 'The action is finished when current equals to total'
|
16
|
+
string :unit, label: 'Unit', desc: 'Unit of current and total'
|
17
|
+
bool :can_cancel, label: 'Can cancel',
|
18
|
+
desc: 'When true, execution of this action can be cancelled'
|
19
|
+
datetime :created_at, label: 'Created at'
|
20
|
+
datetime :updated_at, label: 'Updated at',
|
21
|
+
desc: 'When was the progress last updated'
|
22
|
+
end
|
23
|
+
|
24
|
+
module Mixin
|
25
|
+
def state_to_hash(state)
|
26
|
+
hash = {
|
27
|
+
id: state.id,
|
28
|
+
label: state.label,
|
29
|
+
status: state.status,
|
30
|
+
created_at: state.created_at,
|
31
|
+
updated_at: state.updated_at,
|
32
|
+
can_cancel: state.can_cancel?,
|
33
|
+
}
|
34
|
+
|
35
|
+
if state.finished?
|
36
|
+
hash[:finished] = true
|
37
|
+
|
38
|
+
else
|
39
|
+
hash[:finished] = false
|
40
|
+
end
|
41
|
+
|
42
|
+
progress = state.progress
|
43
|
+
hash[:current] = progress[:current] || 0
|
44
|
+
hash[:total] = progress[:total] || 0
|
45
|
+
hash[:unit] = progress[:unit]
|
46
|
+
|
47
|
+
hash
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
class Index < HaveAPI::Actions::Default::Index
|
52
|
+
include Mixin
|
53
|
+
|
54
|
+
desc 'List states of pending actions'
|
55
|
+
|
56
|
+
input(:hash) do
|
57
|
+
string :order, choices: %w(newest oldest), default: 'newest', fill: true
|
58
|
+
end
|
59
|
+
|
60
|
+
output(:hash_list) do
|
61
|
+
use :all
|
62
|
+
end
|
63
|
+
|
64
|
+
authorize { allow }
|
65
|
+
|
66
|
+
def exec
|
67
|
+
ret = []
|
68
|
+
actions = @context.server.action_state.list_pending(
|
69
|
+
current_user,
|
70
|
+
input[:offset],
|
71
|
+
input[:limit],
|
72
|
+
input[:order].to_sym
|
73
|
+
)
|
74
|
+
|
75
|
+
actions.each do |state|
|
76
|
+
ret << state_to_hash(state)
|
77
|
+
end
|
78
|
+
|
79
|
+
ret
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
class Poll < HaveAPI::Action
|
84
|
+
include Mixin
|
85
|
+
|
86
|
+
desc 'Returns when the action is completed or timeout occurs'
|
87
|
+
http_method :get
|
88
|
+
route ':%{resource}_id/poll'
|
89
|
+
|
90
|
+
input(:hash) do
|
91
|
+
float :timeout, label: 'Timeout', desc: 'in seconds', default: 15, fill: true
|
92
|
+
float :update_in, label: 'Progress',
|
93
|
+
desc: 'number of seconds after which the state is returned if the progress '+
|
94
|
+
'has changed'
|
95
|
+
bool :status, desc: 'status to check with if update_in is set'
|
96
|
+
integer :current, desc: 'progress to check with if update_in is set'
|
97
|
+
integer :total, desc: 'progress to check with if update_in is set'
|
98
|
+
end
|
99
|
+
|
100
|
+
output(:hash) do
|
101
|
+
use :all
|
102
|
+
end
|
103
|
+
|
104
|
+
authorize { allow }
|
105
|
+
|
106
|
+
def exec
|
107
|
+
t = Time.now
|
108
|
+
|
109
|
+
loop do
|
110
|
+
state = @context.server.action_state.new(
|
111
|
+
current_user,
|
112
|
+
id: params[:action_state_id]
|
113
|
+
)
|
114
|
+
|
115
|
+
error('action state not found') unless state.valid?
|
116
|
+
|
117
|
+
if state.finished? || (Time.now - t) >= input[:timeout]
|
118
|
+
return state_to_hash(state)
|
119
|
+
|
120
|
+
elsif input[:update_in]
|
121
|
+
new_state = state_to_hash(state)
|
122
|
+
|
123
|
+
%i(status current total).each do |v|
|
124
|
+
return new_state if input[v] != new_state[v]
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
return state_to_hash(state.poll(input)) if state.respond_to?(:poll)
|
129
|
+
|
130
|
+
sleep(1)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
class Show < HaveAPI::Actions::Default::Show
|
136
|
+
include Mixin
|
137
|
+
|
138
|
+
desc 'Show state of a pending action'
|
139
|
+
|
140
|
+
output(:hash) do
|
141
|
+
use :all
|
142
|
+
end
|
143
|
+
|
144
|
+
authorize { allow }
|
145
|
+
|
146
|
+
def exec
|
147
|
+
state = @context.server.action_state.new(
|
148
|
+
current_user,
|
149
|
+
id: params[:action_state_id]
|
150
|
+
)
|
151
|
+
|
152
|
+
return state_to_hash(state) if state.valid?
|
153
|
+
|
154
|
+
error('action state not found')
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
class Cancel < HaveAPI::Action
|
159
|
+
http_method :post
|
160
|
+
route ':%{resource}_id/cancel'
|
161
|
+
blocking true
|
162
|
+
|
163
|
+
output(:hash) {}
|
164
|
+
|
165
|
+
authorize { allow }
|
166
|
+
|
167
|
+
def exec
|
168
|
+
state = @context.server.action_state.new(
|
169
|
+
current_user,
|
170
|
+
id: params[:action_state_id]
|
171
|
+
)
|
172
|
+
|
173
|
+
error('action state not found') unless state.valid?
|
174
|
+
|
175
|
+
ret = state.cancel
|
176
|
+
|
177
|
+
if ret.is_a?(::Numeric)
|
178
|
+
@state_id = ret
|
179
|
+
|
180
|
+
elsif ret
|
181
|
+
ok
|
182
|
+
|
183
|
+
else
|
184
|
+
error('cancellation failed')
|
185
|
+
end
|
186
|
+
|
187
|
+
rescue RuntimeError, NotImplementedError => e
|
188
|
+
error(e.message)
|
189
|
+
end
|
190
|
+
|
191
|
+
def state_id
|
192
|
+
@state_id
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|