update gitignore, add assets and files
10
.gitignore
vendored
|
|
@ -1,11 +1 @@
|
||||||
.bundle
|
.bundle
|
||||||
_blog
|
|
||||||
public/js/*.js
|
|
||||||
public/css/*.css
|
|
||||||
discussd/discuss.dirty
|
|
||||||
public/blog
|
|
||||||
public/proj
|
|
||||||
node_modules
|
|
||||||
public/s42/.htaccess
|
|
||||||
public/images/blog
|
|
||||||
public/f
|
|
||||||
|
|
|
||||||
179
public/css/blog.css
Normal file
|
|
@ -0,0 +1,179 @@
|
||||||
|
body { margin: 0
|
||||||
|
; padding: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 { margin: 0
|
||||||
|
; padding: 0.2em
|
||||||
|
; color: #9ab
|
||||||
|
}
|
||||||
|
|
||||||
|
.center { text-align: center
|
||||||
|
; font-size: 1.2em
|
||||||
|
}
|
||||||
|
|
||||||
|
.hidden { display: none }
|
||||||
|
|
||||||
|
#index { width: 80%
|
||||||
|
; min-width: 300px
|
||||||
|
; max-width: 800px
|
||||||
|
; border: solid 1px #999
|
||||||
|
; -moz-border-radius: 10px
|
||||||
|
; -webkit-border-radius: 10px
|
||||||
|
; border-radius: 10px
|
||||||
|
; background-color: #eee
|
||||||
|
; margin: 1em auto
|
||||||
|
; padding: 1em
|
||||||
|
; font-size: 1.2em
|
||||||
|
; line-height: 1.5em
|
||||||
|
; list-style-type: none
|
||||||
|
}
|
||||||
|
|
||||||
|
.date { float: right }
|
||||||
|
|
||||||
|
#article,
|
||||||
|
article { width: 80%
|
||||||
|
; min-width: 400px
|
||||||
|
; max-width: 800px
|
||||||
|
; margin: 0.6em auto
|
||||||
|
; font-size: 1.2em
|
||||||
|
; line-height: 1.4em
|
||||||
|
; color: #222
|
||||||
|
}
|
||||||
|
|
||||||
|
#article h1,
|
||||||
|
article h1 { text-align: left
|
||||||
|
; font-size: 2em
|
||||||
|
; line-height: 1.2em
|
||||||
|
; font-weight: normal
|
||||||
|
; color: #222
|
||||||
|
; margin: 0
|
||||||
|
; padding-left: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
#article h1 a,
|
||||||
|
article h1 a { color: #222
|
||||||
|
; text-decoration: underline
|
||||||
|
; border-bottom: none
|
||||||
|
; text-shadow: #ccc 1px 1px 5px
|
||||||
|
; -webkit-transition: text-shadow 0.4s ease-in
|
||||||
|
}
|
||||||
|
|
||||||
|
#article h1 a:hover,
|
||||||
|
article h1 a:hover { text-shadow: 1px 1px 6px #ffc
|
||||||
|
; color: #000
|
||||||
|
}
|
||||||
|
|
||||||
|
#article h2,
|
||||||
|
article h2 { font-size: 1.8em
|
||||||
|
; font-weight: normal
|
||||||
|
; text-align: left
|
||||||
|
; margin: 1em 0
|
||||||
|
; padding: 0
|
||||||
|
; color: #222
|
||||||
|
}
|
||||||
|
|
||||||
|
#article h3,
|
||||||
|
article h3 { font-size: 1.6em
|
||||||
|
; font-weight: normal
|
||||||
|
}
|
||||||
|
|
||||||
|
.time,
|
||||||
|
time { color: #444
|
||||||
|
; font-size: 1.2em
|
||||||
|
}
|
||||||
|
|
||||||
|
.permalink { font-size: 1em }
|
||||||
|
|
||||||
|
.gist { font-size: 0.8em }
|
||||||
|
|
||||||
|
/* show discussion */
|
||||||
|
#sd-container { margin: 3em 0 }
|
||||||
|
|
||||||
|
input[type=submit],
|
||||||
|
#sd { border: solid 1px #999
|
||||||
|
; border-right-color: #333
|
||||||
|
; border-bottom-color: #333
|
||||||
|
; padding: 0.4em 1em
|
||||||
|
; color: #444
|
||||||
|
; background-color: #ececec
|
||||||
|
; -moz-border-radius: 5px
|
||||||
|
; -webkit-border-radius: 5px
|
||||||
|
; border-radius: 5px
|
||||||
|
; text-decoration: none
|
||||||
|
; margin: 0 2px 2px 0
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type=submit]:active,
|
||||||
|
#sd:active { margin: 2px 0 0 2px
|
||||||
|
; color: #000
|
||||||
|
; background-color: #ffc
|
||||||
|
}
|
||||||
|
|
||||||
|
#comment-stuff { display: none
|
||||||
|
; color: #efefef
|
||||||
|
; margin: 0
|
||||||
|
; padding: 2em 0
|
||||||
|
}
|
||||||
|
|
||||||
|
#comments-spinner { text-align: center }
|
||||||
|
|
||||||
|
#comments { width: 70%
|
||||||
|
; max-width: 600px
|
||||||
|
; margin: 0 auto
|
||||||
|
}
|
||||||
|
|
||||||
|
.comment { color: #555
|
||||||
|
; border-top: solid 2px #ccc
|
||||||
|
; padding-bottom: 2em
|
||||||
|
; margin-bottom: 2em
|
||||||
|
}
|
||||||
|
|
||||||
|
.comment big { font-size: 2em
|
||||||
|
; font-family: Verdana, sans-serif
|
||||||
|
}
|
||||||
|
|
||||||
|
#comment-form { width: 400px
|
||||||
|
; margin: 2em auto 0
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type=text],
|
||||||
|
textarea { font-size: 1.4em
|
||||||
|
; color: #333
|
||||||
|
; width: 100%
|
||||||
|
; padding: 0.2em
|
||||||
|
; border: solid 1px #999
|
||||||
|
; -moz-border-radius: 5px
|
||||||
|
; -webkit-border-radius: 5px
|
||||||
|
; border-radius: 5px
|
||||||
|
; font-family: verdana, sans-serif
|
||||||
|
}
|
||||||
|
|
||||||
|
input:focus[type=text],
|
||||||
|
textarea:focus { border: solid 1px #333 }
|
||||||
|
|
||||||
|
textarea { height: 100px }
|
||||||
|
|
||||||
|
input[type=submit] { font-size: 1.1em
|
||||||
|
; cursor: pointer
|
||||||
|
}
|
||||||
|
|
||||||
|
pre { background-color: #eeeef3
|
||||||
|
; margin: 0.5em 1em 1em
|
||||||
|
; padding: 0.5em
|
||||||
|
; border: dashed 1px #ccc
|
||||||
|
}
|
||||||
|
|
||||||
|
footer { margin: 0 auto
|
||||||
|
; padding: 0.2em 0
|
||||||
|
; border-top: solid 1px #ddd
|
||||||
|
; clear: both
|
||||||
|
; width: 80%
|
||||||
|
}
|
||||||
|
|
||||||
|
footer p { margin: 0.5em }
|
||||||
|
|
||||||
|
footer a { border-bottom: none
|
||||||
|
; color: #25c
|
||||||
|
; font-size: 1.2em
|
||||||
|
; text-decoration: none
|
||||||
|
}
|
||||||
7
public/css/ie6.css
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
ul { behavior: none
|
||||||
|
; padding-bottom: 25px
|
||||||
|
}
|
||||||
|
|
||||||
|
img { behavior: url(../js/iepngfix.htc)
|
||||||
|
; behavior: url(../../js/iepngfix.htc)
|
||||||
|
}
|
||||||
1
public/css/ie7.css
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
ul#projects li { list-style-type: none }
|
||||||
140
public/css/mobile.css
Normal file
|
|
@ -0,0 +1,140 @@
|
||||||
|
/* phones and iPad */
|
||||||
|
|
||||||
|
@media only screen and (orientation: portrait) and (min-device-width: 768px) and (max-device-width: 1024px),
|
||||||
|
only screen and (min-device-width: 320px) and (max-device-width: 480px),
|
||||||
|
only screen and (max-device-width: 800px)
|
||||||
|
{
|
||||||
|
ul.nav { padding: 0.5em
|
||||||
|
; width: 60%
|
||||||
|
; max-width: 600px
|
||||||
|
}
|
||||||
|
|
||||||
|
ul.nav li { display: block
|
||||||
|
; font-size: 1.5em
|
||||||
|
; line-height: 1.8em
|
||||||
|
}
|
||||||
|
|
||||||
|
ul.nav li:after { content: '' }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* phones */
|
||||||
|
@media only screen and (min-device-width: 320px) and (max-device-width: 480px),
|
||||||
|
handheld and (max-device-width: 800px)
|
||||||
|
{
|
||||||
|
/* common */
|
||||||
|
|
||||||
|
h1 { font-size: 2em
|
||||||
|
; margin-top: 0.5em
|
||||||
|
}
|
||||||
|
h2 { font-size: 1.3em; line-height: 1.2em }
|
||||||
|
|
||||||
|
.navbar { font-size: 0.9em }
|
||||||
|
.navbar { width: 32% }
|
||||||
|
#breadcrumbs { margin-left: 5px }
|
||||||
|
|
||||||
|
#show-posts { margin-top: 1em
|
||||||
|
; font-size: 0.8em
|
||||||
|
}
|
||||||
|
|
||||||
|
#forkme { display: none }
|
||||||
|
|
||||||
|
ul.nav { width: 80% }
|
||||||
|
|
||||||
|
ul.nav li { font-size: 1.4em
|
||||||
|
; line-height: 1.6em
|
||||||
|
}
|
||||||
|
|
||||||
|
td { font-size: 1em
|
||||||
|
; line-height: 1.1em
|
||||||
|
}
|
||||||
|
|
||||||
|
img { max-width: 100% }
|
||||||
|
|
||||||
|
#index { width: 90%
|
||||||
|
; min-width: 200px
|
||||||
|
; margin: 0.3em auto 1em
|
||||||
|
; padding: 0.5em
|
||||||
|
; font-size: 1em
|
||||||
|
}
|
||||||
|
|
||||||
|
#index li > span.date { display: block
|
||||||
|
; float: none
|
||||||
|
; color: #666
|
||||||
|
; font-size: 0.8em
|
||||||
|
}
|
||||||
|
|
||||||
|
#article h1,
|
||||||
|
article h1 { font-size: 1.6em
|
||||||
|
; line-height: 1.2em
|
||||||
|
; margin-top: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
article h2 { font-size: 1.4em }
|
||||||
|
|
||||||
|
#article,
|
||||||
|
article { min-width: 310px
|
||||||
|
; margin: 0
|
||||||
|
; padding: 0.6em 0.4em
|
||||||
|
; font-size: 0.8em
|
||||||
|
}
|
||||||
|
|
||||||
|
.time,
|
||||||
|
time { font-size: 1.0em }
|
||||||
|
|
||||||
|
pre, .gist { font-size: 0.8em }
|
||||||
|
|
||||||
|
#comment-stuff { padding: 0
|
||||||
|
; margin-top: 2em
|
||||||
|
}
|
||||||
|
|
||||||
|
#comments { width: 100% }
|
||||||
|
|
||||||
|
#comment-form { width: 90%
|
||||||
|
; margin: 0 auto
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type=text],
|
||||||
|
textarea { font-size: 1.2em
|
||||||
|
; width: 95%
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type=submit] { font-size: 1em }
|
||||||
|
|
||||||
|
/* proj */
|
||||||
|
#info { width: 70%
|
||||||
|
; padding: 0 1em
|
||||||
|
}
|
||||||
|
|
||||||
|
#info > div { clear: left
|
||||||
|
; width: 100%
|
||||||
|
; max-width: 100%
|
||||||
|
; padding: 0.5em 0.2em 1em
|
||||||
|
; border-left: none
|
||||||
|
; font-size: 1em
|
||||||
|
}
|
||||||
|
|
||||||
|
#stats { font-size: 1em; margin-bottom: 0.5em }
|
||||||
|
|
||||||
|
footer { margin: 0
|
||||||
|
; padding: 0.5em 0
|
||||||
|
; font-size: 1em
|
||||||
|
; width: 100%
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* landscape */
|
||||||
|
|
||||||
|
@media only screen and (orientation: landscape) and (min-device-width: 768px) and (max-device-width: 1024px),
|
||||||
|
only screen and (orientation: landscape) and (min-device-width: 320px) and (max-device-width: 480px),
|
||||||
|
handheld and (orientation: landscape) and (max-device-width: 800px)
|
||||||
|
{
|
||||||
|
body { font-size: 0.8em }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* iPad portrait */
|
||||||
|
@media only screen and (orientation: portrait) and (min-device-width: 768px) and (max-device-width: 1024px)
|
||||||
|
{
|
||||||
|
article > header > h1 { font-size: 1.8em }
|
||||||
|
}
|
||||||
51
public/css/projects.css
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
td { font-size: 1.5em
|
||||||
|
; line-height: 1.6em
|
||||||
|
}
|
||||||
|
|
||||||
|
td:nth-child(2) { padding: 0 10px }
|
||||||
|
|
||||||
|
.highlight { font-size: 1.2em }
|
||||||
|
|
||||||
|
#stats a { text-decoration: none }
|
||||||
|
|
||||||
|
#info { text-align: center
|
||||||
|
; margin: 1em auto
|
||||||
|
; padding: 1em
|
||||||
|
; border: solid 1px #ccc
|
||||||
|
; width: 90%
|
||||||
|
; max-width: 950px
|
||||||
|
; background-color: #fff
|
||||||
|
; -moz-border-radius: 20px
|
||||||
|
; -webkit-border-radius: 20px
|
||||||
|
; border-radius: 20px
|
||||||
|
; behavior: url(../js/border-radius.htc)
|
||||||
|
; behavior: url(../../js/border-radius.htc)
|
||||||
|
}
|
||||||
|
|
||||||
|
h4 { margin: 0.5em 0 0.7em }
|
||||||
|
|
||||||
|
#info > div { text-align: center
|
||||||
|
; font-size: 1.3em
|
||||||
|
; width: 31%
|
||||||
|
; max-width: 400px
|
||||||
|
; float: left
|
||||||
|
; display: inline
|
||||||
|
; padding: 0.5em 0.2em
|
||||||
|
; border-left: dashed 1px #aaa
|
||||||
|
}
|
||||||
|
|
||||||
|
#info > div:first-child { border-left: none }
|
||||||
|
|
||||||
|
#info ul { list-style-type: none
|
||||||
|
; text-align: center
|
||||||
|
; padding: 0
|
||||||
|
; margin: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
#info li { padding: 0.2em 0
|
||||||
|
; margin: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
#info > br.clear { clear: both }
|
||||||
|
|
||||||
|
#contributors-box a { line-height: 1.8em }
|
||||||
92
public/css/style.css
Normal file
|
|
@ -0,0 +1,92 @@
|
||||||
|
TODO: include mobile.css here, just one set of styles
|
||||||
|
|
||||||
|
body { background-color: #f7f7f7
|
||||||
|
; color: #222
|
||||||
|
; font-family: 'Helvetica Neue', Verdana, sans-serif
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 { text-align: center
|
||||||
|
; font-size: 2em
|
||||||
|
; font-weight: normal
|
||||||
|
; margin: 0.8em 0 0.4em
|
||||||
|
; padding: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 { text-align: center
|
||||||
|
; font-size: 1.7em
|
||||||
|
; line-height: 1.1em
|
||||||
|
; font-weight: normal
|
||||||
|
; margin: 0.2em 0 1em
|
||||||
|
; padding: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
a { color: #0E539C }
|
||||||
|
|
||||||
|
a.img { border: none }
|
||||||
|
|
||||||
|
.navbar { display: inline-block
|
||||||
|
; width: 33%
|
||||||
|
; font-size: 1.5em
|
||||||
|
; line-height: 1.8em
|
||||||
|
; margin: 0
|
||||||
|
; padding: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar a { text-shadow: none }
|
||||||
|
|
||||||
|
#breadcrumbs a { color: #222 }
|
||||||
|
#title { text-align: center }
|
||||||
|
#archive { text-align: right }
|
||||||
|
|
||||||
|
#forkme { position: absolute
|
||||||
|
; top: 0
|
||||||
|
; right: 0
|
||||||
|
; border: none
|
||||||
|
}
|
||||||
|
|
||||||
|
ul.nav { text-align: center
|
||||||
|
; max-width: 400px
|
||||||
|
; margin: 0 auto
|
||||||
|
; padding: 1em
|
||||||
|
; border: solid 1px #ccc
|
||||||
|
; background-color: #fff
|
||||||
|
; -moz-border-radius: 20px
|
||||||
|
; -webkit-border-radius: 20px
|
||||||
|
; border-radius: 20px
|
||||||
|
; behavior: url(js/border-radius.htc)
|
||||||
|
; behavior: url(../js/border-radius.htc)
|
||||||
|
}
|
||||||
|
|
||||||
|
ul.nav li { display: block
|
||||||
|
; font-size: 1.6em
|
||||||
|
; line-height: 1.8em
|
||||||
|
; margin: 0
|
||||||
|
; padding: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
ul.nav li a { padding: 5px
|
||||||
|
; text-decoration: none
|
||||||
|
; border-bottom: solid 1px #fff
|
||||||
|
; text-shadow: #ccc 2px 2px 3px
|
||||||
|
}
|
||||||
|
ul.nav li a:visited { color: #227 }
|
||||||
|
|
||||||
|
ul.nav li a:hover,
|
||||||
|
ul.nav li a:active { text-shadow: #cca 2px 2px 3px
|
||||||
|
; border-bottom: solid 1px #aaa
|
||||||
|
}
|
||||||
|
|
||||||
|
ul.nav li a:active { text-shadow: none }
|
||||||
|
|
||||||
|
footer { text-align: center
|
||||||
|
; font-size: 1.2em
|
||||||
|
; margin: 1em
|
||||||
|
}
|
||||||
|
|
||||||
|
footer a { border-bottom: none }
|
||||||
|
|
||||||
|
#promote-js { margin-top: 3em
|
||||||
|
; text-align: center
|
||||||
|
}
|
||||||
|
|
||||||
|
#promote-js img { border: none }
|
||||||
77
public/css/typocode.css
Normal file
|
|
@ -0,0 +1,77 @@
|
||||||
|
/* Syntax highlighting */
|
||||||
|
.typocode_ruby .normal {}
|
||||||
|
.typocode_ruby .comment { color: #005; font-style: italic; }
|
||||||
|
.typocode_ruby .keyword { color: #A00; font-weight: bold; }
|
||||||
|
.typocode_ruby .method { color: #077; }
|
||||||
|
.typocode_ruby .class { color: #074; }
|
||||||
|
.typocode_ruby .module { color: #050; }
|
||||||
|
.typocode_ruby .punct { color: #447; font-weight: bold; }
|
||||||
|
.typocode_ruby .symbol { color: #099; }
|
||||||
|
.typocode_ruby .string { color: #944; background: #FFE; }
|
||||||
|
.typocode_ruby .char { color: #F07; }
|
||||||
|
.typocode_ruby .ident { color: #004; }
|
||||||
|
.typocode_ruby .constant { color: #07F; }
|
||||||
|
.typocode_ruby .regex { color: #B66; background: #FEF; }
|
||||||
|
.typocode_ruby .number { color: #F99; }
|
||||||
|
.typocode_ruby .attribute { color: #7BB; }
|
||||||
|
.typocode_ruby .global { color: #7FB; }
|
||||||
|
.typocode_ruby .expr { color: #227; }
|
||||||
|
.typocode_ruby .escape { color: #277; }
|
||||||
|
.typocode_xml .normal {}
|
||||||
|
.typocode_xml .namespace { color: #B66; font-weight: bold; }
|
||||||
|
.typocode_xml .tag { color: #F88; }
|
||||||
|
.typocode_xml .comment { color: #005; font-style: italic; }
|
||||||
|
.typocode_xml .punct { color: #447; font-weight: bold; }
|
||||||
|
.typocode_xml .string { color: #944; }
|
||||||
|
.typocode_xml .number { color: #F99; }
|
||||||
|
.typocode_xml .attribute { color: #BB7; }
|
||||||
|
.typocode_yaml .normal {}
|
||||||
|
.typocode_yaml .document { font-weight: bold; color: #07F; }
|
||||||
|
.typocode_yaml .type { font-weight: bold; color: #05C; }
|
||||||
|
.typocode_yaml .key { color: #F88; }
|
||||||
|
.typocode_yaml .comment { color: #005; font-style: italic; }
|
||||||
|
.typocode_yaml .punct { color: #447; font-weight: bold; }
|
||||||
|
.typocode_yaml .string { color: #944; }
|
||||||
|
.typocode_yaml .number { color: #F99; }
|
||||||
|
.typocode_yaml .time { color: #F99; }
|
||||||
|
.typocode_yaml .date { color: #F99; }
|
||||||
|
.typocode_yaml .ref { color: #944; }
|
||||||
|
.typocode_yaml .anchor { color: #944; }
|
||||||
|
|
||||||
|
.typocode {
|
||||||
|
background-color:#eee;
|
||||||
|
padding:2px;
|
||||||
|
margin:5px;
|
||||||
|
margin-left:1em;
|
||||||
|
margin-bottom:1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.typocode pre {
|
||||||
|
padding: 0px;
|
||||||
|
margin: 0px;
|
||||||
|
border: none;
|
||||||
|
background: transparent;
|
||||||
|
font-family: monospace;
|
||||||
|
overflow:auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.typocode .lineno {
|
||||||
|
text-align: right;
|
||||||
|
/* color: #B00;*/
|
||||||
|
font-family: monospace;
|
||||||
|
padding-right: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
code {
|
||||||
|
font-family: "Andale Mono", "Lucida Typewriter", "Bitstream Vera Sans Mono", fixed-width, monospace;
|
||||||
|
font-size: 0.9em;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
background: #555;
|
||||||
|
border: 1px dashed #5189ea;
|
||||||
|
margin-bottom: 30px;
|
||||||
|
margin-top: -10px;
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
BIN
public/f/Carmina Burana - O Fortuna.m4r
Normal file
BIN
public/f/Carmina Burana - O Fortuna.mp3
Normal file
BIN
public/f/IntelligentMigrationSnippets-0.1.dmg
Normal file
BIN
public/f/SJRailsBundle-0.2.dmg
Normal file
BIN
public/f/assert_snippets.zip
Normal file
260
public/f/cheat.el
Normal file
|
|
@ -0,0 +1,260 @@
|
||||||
|
;; cheat.el
|
||||||
|
;; Time-stamp: <2007-08-22 10:00:04 sjs>
|
||||||
|
;;
|
||||||
|
;; Copyright (c) 2007 Sami Samhuri <sami.samhuri@gmail.com>
|
||||||
|
;;
|
||||||
|
;; See http://sami.samhuri.net/2007/08/10/cheat-from-emacs for updates.
|
||||||
|
;;
|
||||||
|
;; License
|
||||||
|
;;
|
||||||
|
;; This program is free software; you can redistribute it and/or
|
||||||
|
;; modify it under the terms of the GNU General Public License
|
||||||
|
;; as published by the Free Software Foundation; either version 2
|
||||||
|
;; of the License, or (at your option) any later version.
|
||||||
|
;;
|
||||||
|
;; This program is distributed in the hope that it will be useful,
|
||||||
|
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
;; GNU General Public License for more details.
|
||||||
|
;;
|
||||||
|
;; You should have received a copy of the GNU General Public License
|
||||||
|
;; along with this program; if not, write to the Free Software
|
||||||
|
;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
;;
|
||||||
|
;;
|
||||||
|
;; Provide a handy interface to cheat.
|
||||||
|
;; See http://cheat.errtheblog.com for details on cheat itself.
|
||||||
|
;;
|
||||||
|
;; sjs 2007.08.21
|
||||||
|
;; * Cache the list of cheat sheets, update it once a day (configurable).
|
||||||
|
;; * Strictly complete cheat sheet names.
|
||||||
|
|
||||||
|
(defvar *cheat-host* "cheat.errtheblog.com")
|
||||||
|
(defvar *cheat-port* "80")
|
||||||
|
(defvar *cheat-uri* (concat *cheat-host* ":" *cheat-port*))
|
||||||
|
|
||||||
|
(defvar *cheat-directory* "~/.cheat")
|
||||||
|
(defvar *cheat-sheets-cache-file* (concat *cheat-directory* "/sheets"))
|
||||||
|
|
||||||
|
(defvar *cheat-last-sheet* nil
|
||||||
|
"Name of the most recently viewed cheat sheet.")
|
||||||
|
|
||||||
|
(defvar *cheat-sheet-history* nil
|
||||||
|
"List of the most recently viewed cheat sheets.")
|
||||||
|
|
||||||
|
(defconst +seconds-per-day+ 86400)
|
||||||
|
|
||||||
|
(defvar *cheat-cache-ttl* +seconds-per-day+
|
||||||
|
"The minimum age of a stale cache file, in seconds.")
|
||||||
|
|
||||||
|
|
||||||
|
;;; interactive functions
|
||||||
|
|
||||||
|
(defun cheat (name &optional silent)
|
||||||
|
"Show the specified cheat sheet.
|
||||||
|
|
||||||
|
If SILENT is non-nil then do not print any output, but return it
|
||||||
|
as a string instead."
|
||||||
|
(interactive (list (cheat-read-sheet-name)))
|
||||||
|
(if silent
|
||||||
|
(cheat-command-silent name)
|
||||||
|
(cheat-command name)))
|
||||||
|
|
||||||
|
(defun cheat-sheets ()
|
||||||
|
"List all cheat sheets."
|
||||||
|
(interactive)
|
||||||
|
(cheat-command "sheets"))
|
||||||
|
|
||||||
|
(defun cheat-recent ()
|
||||||
|
"Show recently added cheat sheets."
|
||||||
|
(interactive)
|
||||||
|
(cheat-command "recent"))
|
||||||
|
|
||||||
|
(defun cheat-clear-cache ()
|
||||||
|
"Clear the local cheat cache, located in ~/.cheat."
|
||||||
|
(interactive)
|
||||||
|
(cheat-command "--clear-cache")
|
||||||
|
(make-directory *cheat-directory*))
|
||||||
|
|
||||||
|
(defun cheat-versions (name)
|
||||||
|
"Version history of the specified cheat sheet."
|
||||||
|
(interactive (list (cheat-read-sheet-name)))
|
||||||
|
(cheat-command name "--versions"))
|
||||||
|
|
||||||
|
(defun cheat-diff (name version)
|
||||||
|
"Show the diff between the given version and the current version of the named cheat.
|
||||||
|
If VERSION is of the form m:n then show the diff between versions m and n."
|
||||||
|
(interactive (list (cheat-read-sheet-name)
|
||||||
|
(read-string "Cheat version(s): ")))
|
||||||
|
(cheat-command name "--diff" version))
|
||||||
|
|
||||||
|
(defun cheat-add-current-buffer (name)
|
||||||
|
"Add a new cheat with the specified name and the current buffer as the body."
|
||||||
|
(interactive "sCheat name: \n")
|
||||||
|
(post-cheat name (buffer-string) t)
|
||||||
|
(if (interactive-p)
|
||||||
|
(print (concat "Cheat added (" name ")"))))
|
||||||
|
|
||||||
|
(defun cheat-edit (name)
|
||||||
|
"Fetch the named cheat and open a buffer containing its body.
|
||||||
|
The cheat can be saved with `cheat-save-current-buffer'."
|
||||||
|
(interactive (list (cheat-read-sheet-name)))
|
||||||
|
(cheat-clear-cache name) ; make sure we're working with the latest version
|
||||||
|
(switch-to-buffer (get-buffer-create (cheat->buffer name)))
|
||||||
|
(insert (cheat-body name))
|
||||||
|
(if (interactive-p)
|
||||||
|
(print "Run `cheat-save-current-buffer' when you're done editing.")))
|
||||||
|
|
||||||
|
(defun cheat-save-current-buffer ()
|
||||||
|
"Save the current buffer using the buffer name for the title and the contents as the body."
|
||||||
|
(interactive)
|
||||||
|
(let ((name (buffer->cheat (buffer-name (current-buffer)))))
|
||||||
|
(post-cheat name (buffer-string))
|
||||||
|
;; TODO check for errors and kill the buffer on success
|
||||||
|
(if (interactive-p)
|
||||||
|
(print (concat "Cheat saved (" name ")")))
|
||||||
|
(cheat-clear-cache name)
|
||||||
|
(cheat name)))
|
||||||
|
|
||||||
|
|
||||||
|
;;; helpers
|
||||||
|
|
||||||
|
;; this is from rails-lib.el in the emacs-rails package
|
||||||
|
(defun string-join (separator strings)
|
||||||
|
"Join all STRINGS using SEPARATOR."
|
||||||
|
(mapconcat 'identity strings separator))
|
||||||
|
|
||||||
|
(defun blank (thing)
|
||||||
|
"Return T if THING is nil or an empty string, otherwise nil."
|
||||||
|
(or (null thing)
|
||||||
|
(and (stringp thing)
|
||||||
|
(= 0 (length thing)))))
|
||||||
|
|
||||||
|
(defun cheat-command (&rest rest)
|
||||||
|
"Run the cheat command with the given arguments, display the output."
|
||||||
|
(interactive "sArguments for cheat: \n")
|
||||||
|
(shell-command (concat "cheat " (string-join " " rest))))
|
||||||
|
|
||||||
|
(defun cheat-command-to-string (&rest rest)
|
||||||
|
"Run the cheat command with the given arguments and return the output as a string. Display nothing."
|
||||||
|
(shell-command-to-string (concat "cheat " (string-join " " rest))))
|
||||||
|
|
||||||
|
(defalias 'cheat-command-silent 'cheat-command-to-string)
|
||||||
|
|
||||||
|
(defun cheat-read-sheet-name (&optional prompt)
|
||||||
|
"Get the name of an existing cheat sheet, prompting with completion and history.
|
||||||
|
|
||||||
|
The name of the sheet read is stored in *cheat-last-sheet* unless it was blank."
|
||||||
|
(let* ((default (when (blank prompt) *cheat-last-sheet*))
|
||||||
|
(prompt (or prompt
|
||||||
|
(if (not (blank default))
|
||||||
|
(concat "Cheat name (default: " default "): ")
|
||||||
|
"Cheat name: ")))
|
||||||
|
(name (completing-read prompt
|
||||||
|
(cheat-sheets-list t)
|
||||||
|
nil
|
||||||
|
t
|
||||||
|
nil
|
||||||
|
'*cheat-sheet-history*
|
||||||
|
default)))
|
||||||
|
(when (not (blank name))
|
||||||
|
(setq *cheat-last-sheet* name))
|
||||||
|
name))
|
||||||
|
|
||||||
|
(defun cheat-sheets-list (&optional fetch-if-missing-or-stale)
|
||||||
|
"Get a list of all cheat sheets.
|
||||||
|
|
||||||
|
Return the cached list in *cheat-sheets-cache-file* if it's
|
||||||
|
readable and `cheat-cache-stale-p' returns nil.
|
||||||
|
|
||||||
|
When there is no cache or a stale cache, and
|
||||||
|
FETCH-IF-MISSING-OR-STALE is non-nil, cache the list and then
|
||||||
|
return it.
|
||||||
|
|
||||||
|
Otherwise return nil."
|
||||||
|
(cond ((and (file-readable-p *cheat-sheets-cache-file*)
|
||||||
|
(not (cheat-cache-stale-p)))
|
||||||
|
(save-excursion
|
||||||
|
(let* ((buffer (find-file *cheat-sheets-cache-file*))
|
||||||
|
(sheets (split-string (buffer-string))))
|
||||||
|
(kill-buffer buffer)
|
||||||
|
sheets)))
|
||||||
|
(fetch-if-missing-or-stale
|
||||||
|
(cheat-cache-list)
|
||||||
|
(cheat-sheets-list))
|
||||||
|
(t nil)))
|
||||||
|
|
||||||
|
(defun cheat-fetch-list ()
|
||||||
|
"Fetch a fresh list of all cheat sheets."
|
||||||
|
(nthcdr 3 (split-string (cheat-command-to-string "sheets"))))
|
||||||
|
|
||||||
|
(defun cheat-cache-list ()
|
||||||
|
"Cache the list of cheat sheets in *cheat-sheets-cache-file*. Return the list."
|
||||||
|
(when (not (file-exists-p *cheat-directory*))
|
||||||
|
(make-directory *cheat-directory*))
|
||||||
|
(save-excursion
|
||||||
|
(let ((buffer (find-file *cheat-sheets-cache-file*))
|
||||||
|
(sheets (cheat-fetch-list)))
|
||||||
|
(insert (string-join "\n" sheets))
|
||||||
|
(basic-save-buffer)
|
||||||
|
(kill-buffer buffer)
|
||||||
|
sheets)))
|
||||||
|
|
||||||
|
(defun cheat-cache-stale-p ()
|
||||||
|
"Non-nil if the cache in *cheat-sheets-cache-file* is more than *cheat-cache-ttl* seconds old.q
|
||||||
|
|
||||||
|
If the cache file does not exist then it is considered stale.
|
||||||
|
|
||||||
|
Also see `cheat-cache-sheets'."
|
||||||
|
(or (null (file-exists-p *cheat-sheets-cache-file*))
|
||||||
|
(let* ((now (float-time (current-time)))
|
||||||
|
(last-mod (float-time (sixth (file-attributes *cheat-sheets-cache-file*))))
|
||||||
|
(age (- now last-mod)))
|
||||||
|
(> age *cheat-cache-ttl*))))
|
||||||
|
|
||||||
|
(defun cheat-body (name)
|
||||||
|
"Call out to Ruby to load the YAML and return just the body."
|
||||||
|
(shell-command-to-string
|
||||||
|
(concat "ruby -ryaml -e '"
|
||||||
|
"puts YAML.load_file(File.expand_path(\"~/.cheat/"
|
||||||
|
name ".yml\")).to_a[0][-1]'")))
|
||||||
|
|
||||||
|
(defun url-http-post (url args)
|
||||||
|
"Send ARGS to URL as a POST request."
|
||||||
|
(let ((url-request-method "POST")
|
||||||
|
(url-request-extra-headers
|
||||||
|
'(("Content-Type" . "application/x-www-form-urlencoded")))
|
||||||
|
(url-request-data
|
||||||
|
(concat (mapconcat (lambda (arg)
|
||||||
|
(concat (url-hexify-string (car arg))
|
||||||
|
"="
|
||||||
|
(url-hexify-string (cdr arg))))
|
||||||
|
args
|
||||||
|
"&")
|
||||||
|
"\r\n")))
|
||||||
|
;; `kill-url-buffer' to discard the result
|
||||||
|
;; `switch-to-url-buffer' to view the results (debugging).
|
||||||
|
(url-retrieve url 'kill-url-buffer)))
|
||||||
|
|
||||||
|
(defun kill-url-buffer (status)
|
||||||
|
"Kill the buffer returned by `url-retrieve'."
|
||||||
|
(kill-buffer (current-buffer)))
|
||||||
|
|
||||||
|
(defun switch-to-url-buffer (status)
|
||||||
|
"Switch to the buffer returned by `url-retreive'.
|
||||||
|
The buffer contains the raw HTTP response sent by the server."
|
||||||
|
(switch-to-buffer (current-buffer)))
|
||||||
|
|
||||||
|
(defun post-cheat (title body &optional new)
|
||||||
|
(let ((uri (concat "http://" *cheat-uri* "/w/" (if new "" title))))
|
||||||
|
(url-http-post uri `(("sheet_title" . ,title)
|
||||||
|
("sheet_body" . ,body)
|
||||||
|
("from_gem" . "1")))))
|
||||||
|
|
||||||
|
(defun buffer->cheat (name)
|
||||||
|
(substring name 7 (- (length name) 1)))
|
||||||
|
|
||||||
|
(defun cheat->buffer (name)
|
||||||
|
(concat "*cheat-" name "*"))
|
||||||
|
|
||||||
|
(provide 'cheat)
|
||||||
BIN
public/f/download.png
Normal file
|
After Width: | Height: | Size: 139 B |
BIN
public/f/ember-structure.png
Normal file
|
After Width: | Height: | Size: 141 KiB |
BIN
public/f/feed-icon-48x48.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
256
public/f/feed-icon32x32.png
Normal file
|
|
@ -0,0 +1,256 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>samhuri.net</title>
|
||||||
|
<style type='text/css'>
|
||||||
|
body {
|
||||||
|
background: #000;
|
||||||
|
color: #ffc;
|
||||||
|
}
|
||||||
|
a, a:link {
|
||||||
|
color: #ff6;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
a:hover { color: #ff0; }
|
||||||
|
p { font-size: 72px; text-align: center; margin-top: 30%; }
|
||||||
|
</style>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<!-- BEGIN WAYBACK TOOLBAR INSERT -->
|
||||||
|
|
||||||
|
<script type="text/javascript" src="http://staticweb.archive.org/js/disclaim-element.js" ></script>
|
||||||
|
<script type="text/javascript" src="http://staticweb.archive.org/js/graph-calc.js" ></script>
|
||||||
|
<script type="text/javascript" src="http://staticweb.archive.org/jflot/jquery.min.js" ></script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
//<![CDATA[
|
||||||
|
var firstDate = 820454400000;
|
||||||
|
var lastDate = 1325375999999;
|
||||||
|
var wbPrefix = "http://web.archive.org/web/";
|
||||||
|
var wbCurrentUrl = "http://samhuri.net/";
|
||||||
|
|
||||||
|
var curYear = -1;
|
||||||
|
var curMonth = -1;
|
||||||
|
var yearCount = 16;
|
||||||
|
var firstYear = 1996;
|
||||||
|
var imgWidth=400;
|
||||||
|
var yearImgWidth = 25;
|
||||||
|
var monthImgWidth = 2;
|
||||||
|
var trackerVal = "none";
|
||||||
|
var displayDay = "5";
|
||||||
|
var displayMonth = "Dec";
|
||||||
|
var displayYear = "2006";
|
||||||
|
var prettyMonths = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];
|
||||||
|
|
||||||
|
function showTrackers(val) {
|
||||||
|
if(val == trackerVal) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(val == "inline") {
|
||||||
|
document.getElementById("displayYearEl").style.color = "#ec008c";
|
||||||
|
document.getElementById("displayMonthEl").style.color = "#ec008c";
|
||||||
|
document.getElementById("displayDayEl").style.color = "#ec008c";
|
||||||
|
} else {
|
||||||
|
document.getElementById("displayYearEl").innerHTML = displayYear;
|
||||||
|
document.getElementById("displayYearEl").style.color = "#ff0";
|
||||||
|
document.getElementById("displayMonthEl").innerHTML = displayMonth;
|
||||||
|
document.getElementById("displayMonthEl").style.color = "#ff0";
|
||||||
|
document.getElementById("displayDayEl").innerHTML = displayDay;
|
||||||
|
document.getElementById("displayDayEl").style.color = "#ff0";
|
||||||
|
}
|
||||||
|
document.getElementById("wbMouseTrackYearImg").style.display = val;
|
||||||
|
document.getElementById("wbMouseTrackMonthImg").style.display = val;
|
||||||
|
trackerVal = val;
|
||||||
|
}
|
||||||
|
function getElementX2(obj) {
|
||||||
|
var thing = jQuery(obj);
|
||||||
|
if((thing == undefined)
|
||||||
|
|| (typeof thing == "undefined")
|
||||||
|
|| (typeof thing.offset == "undefined")) {
|
||||||
|
return getElementX(obj);
|
||||||
|
}
|
||||||
|
return Math.round(thing.offset().left);
|
||||||
|
}
|
||||||
|
function trackMouseMove(event,element) {
|
||||||
|
|
||||||
|
var eventX = getEventX(event);
|
||||||
|
var elementX = getElementX2(element);
|
||||||
|
var xOff = eventX - elementX;
|
||||||
|
if(xOff < 0) {
|
||||||
|
xOff = 0;
|
||||||
|
} else if(xOff > imgWidth) {
|
||||||
|
xOff = imgWidth;
|
||||||
|
}
|
||||||
|
var monthOff = xOff % yearImgWidth;
|
||||||
|
|
||||||
|
var year = Math.floor(xOff / yearImgWidth);
|
||||||
|
var yearStart = year * yearImgWidth;
|
||||||
|
var monthOfYear = Math.floor(monthOff / monthImgWidth);
|
||||||
|
if(monthOfYear > 11) {
|
||||||
|
monthOfYear = 11;
|
||||||
|
}
|
||||||
|
// 1 extra border pixel at the left edge of the year:
|
||||||
|
var month = (year * 12) + monthOfYear;
|
||||||
|
var day = 1;
|
||||||
|
if(monthOff % 2 == 1) {
|
||||||
|
day = 15;
|
||||||
|
}
|
||||||
|
var dateString =
|
||||||
|
zeroPad(year + firstYear) +
|
||||||
|
zeroPad(monthOfYear+1,2) +
|
||||||
|
zeroPad(day,2) + "000000";
|
||||||
|
|
||||||
|
var monthString = prettyMonths[monthOfYear];
|
||||||
|
document.getElementById("displayYearEl").innerHTML = year + 1996;
|
||||||
|
document.getElementById("displayMonthEl").innerHTML = monthString;
|
||||||
|
// looks too jarring when it changes..
|
||||||
|
//document.getElementById("displayDayEl").innerHTML = zeroPad(day,2);
|
||||||
|
|
||||||
|
var url = wbPrefix + dateString + '/' + wbCurrentUrl;
|
||||||
|
document.getElementById('wm-graph-anchor').href = url;
|
||||||
|
|
||||||
|
//document.getElementById("wmtbURL").value="evX("+eventX+") elX("+elementX+") xO("+xOff+") y("+year+") m("+month+") monthOff("+monthOff+") DS("+dateString+") Moy("+monthOfYear+") ms("+monthString+")";
|
||||||
|
if(curYear != year) {
|
||||||
|
var yrOff = year * yearImgWidth;
|
||||||
|
document.getElementById("wbMouseTrackYearImg").style.left = yrOff + "px";
|
||||||
|
curYear = year;
|
||||||
|
}
|
||||||
|
if(curMonth != month) {
|
||||||
|
var mtOff = year + (month * monthImgWidth) + 1;
|
||||||
|
document.getElementById("wbMouseTrackMonthImg").style.left = mtOff + "px";
|
||||||
|
curMonth = month;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//]]>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style type="text/css">body{margin-top:0!important;padding-top:0!important;min-width:800px!important;}#wm-ipp a:hover{text-decoration:underline!important;}</style>
|
||||||
|
<div id="wm-ipp" style="display:none; position:relative;padding:0 5px;min-height:70px;min-width:800px; z-index:9000;">
|
||||||
|
<div id="wm-ipp-inside" style="position:fixed;padding:0!important;margin:0!important;width:97%;min-width:780px;border:5px solid #000;border-top:none;background-image:url(http://staticweb.archive.org/images/toolbar/wm_tb_bk_trns.png);text-align:center;-moz-box-shadow:1px 1px 3px #333;-webkit-box-shadow:1px 1px 3px #333;box-shadow:1px 1px 3px #333;font-size:11px!important;font-family:'Lucida Grande','Arial',sans-serif!important;">
|
||||||
|
<table style="border-collapse:collapse;margin:0;padding:0;width:100%;"><tbody><tr>
|
||||||
|
<td style="padding:10px;vertical-align:top;min-width:110px;">
|
||||||
|
<a href="http://wayback.archive.org/web/" title="Wayback Machine home page" style="background-color:transparent;border:none;"><img src="http://staticweb.archive.org/images/toolbar/wayback-toolbar-logo.png" alt="Wayback Machine" width="110" height="39" border="0"/></a>
|
||||||
|
</td>
|
||||||
|
<td style="padding:0!important;text-align:center;vertical-align:top;width:100%;">
|
||||||
|
|
||||||
|
<table style="border-collapse:collapse;margin:0 auto;padding:0;width:570px;"><tbody><tr>
|
||||||
|
<td style="padding:3px 0;" colspan="2">
|
||||||
|
<form target="_top" method="get" action="http://wayback.archive.org/web/form-submit.jsp" name="wmtb" id="wmtb" style="margin:0!important;padding:0!important;"><input type="text" name="url" id="wmtbURL" value="http://samhuri.net/" style="width:400px;font-size:11px;font-family:'Lucida Grande','Arial',sans-serif;" onfocus="javascript:this.focus();this.select();" /><input type="hidden" name="type" value="replay" /><input type="hidden" name="date" value="20061205055004" /><input type="submit" value="Go" style="font-size:11px;font-family:'Lucida Grande','Arial',sans-serif;margin-left:5px;" /><span id="wm_tb_options" style="display:block;"></span></form>
|
||||||
|
</td>
|
||||||
|
<td style="vertical-align:bottom;padding:5px 0 0 0!important;" rowspan="2">
|
||||||
|
<table style="border-collapse:collapse;width:110px;color:#99a;font-family:'Helvetica','Lucida Grande','Arial',sans-serif;"><tbody>
|
||||||
|
|
||||||
|
<!-- NEXT/PREV MONTH NAV AND MONTH INDICATOR -->
|
||||||
|
<tr style="width:110px;height:16px;font-size:10px!important;">
|
||||||
|
<td style="padding-right:9px;font-size:11px!important;font-weight:bold;text-transform:uppercase;text-align:right;white-space:nowrap;overflow:visible;" nowrap="nowrap">
|
||||||
|
|
||||||
|
<a href="http://web.archive.org/web/20061004083901/http://samhuri.net/" style="text-decoration:none;color:#33f;font-weight:bold;background-color:transparent;border:none;" title="4 Oct 2006"><strong>OCT</strong></a>
|
||||||
|
|
||||||
|
</td>
|
||||||
|
<td id="displayMonthEl" style="background:#000;color:#ff0;font-size:11px!important;font-weight:bold;text-transform:uppercase;width:34px;height:15px;padding-top:1px;text-align:center;" title="You are here: 5:50:04 Dec 5, 2006">DEC</td>
|
||||||
|
<td style="padding-left:9px;font-size:11px!important;font-weight:bold;text-transform:uppercase;white-space:nowrap;overflow:visible;" nowrap="nowrap">
|
||||||
|
|
||||||
|
Jan
|
||||||
|
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<!-- NEXT/PREV CAPTURE NAV AND DAY OF MONTH INDICATOR -->
|
||||||
|
<tr>
|
||||||
|
<td style="padding-right:9px;white-space:nowrap;overflow:visible;text-align:right!important;vertical-align:middle!important;" nowrap="nowrap">
|
||||||
|
|
||||||
|
<a href="http://web.archive.org/web/20061004083901/http://samhuri.net/" title="8:39:01 Oct 4, 2006" style="background-color:transparent;border:none;"><img src="http://staticweb.archive.org/images/toolbar/wm_tb_prv_on.png" alt="Previous capture" width="14" height="16" border="0" /></a>
|
||||||
|
|
||||||
|
</td>
|
||||||
|
<td id="displayDayEl" style="background:#000;color:#ff0;width:34px;height:24px;padding:2px 0 0 0;text-align:center;font-size:24px;font-weight: bold;" title="You are here: 5:50:04 Dec 5, 2006">5</td>
|
||||||
|
<td style="padding-left:9px;white-space:nowrap;overflow:visible;text-align:left!important;vertical-align:middle!important;" nowrap="nowrap">
|
||||||
|
|
||||||
|
<img src="http://staticweb.archive.org/images/toolbar/wm_tb_nxt_off.png" alt="Next capture" width="14" height="16" border="0"/>
|
||||||
|
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<!-- NEXT/PREV YEAR NAV AND YEAR INDICATOR -->
|
||||||
|
<tr style="width:110px;height:13px;font-size:9px!important;">
|
||||||
|
<td style="padding-right:9px;font-size:11px!important;font-weight: bold;text-align:right;white-space:nowrap;overflow:visible;" nowrap="nowrap">
|
||||||
|
|
||||||
|
2005
|
||||||
|
|
||||||
|
</td>
|
||||||
|
<td id="displayYearEl" style="background:#000;color:#ff0;font-size:11px!important;font-weight: bold;padding-top:1px;width:34px;height:13px;text-align:center;" title="You are here: 5:50:04 Dec 5, 2006">2006</td>
|
||||||
|
<td style="padding-left:9px;font-size:11px!important;font-weight: bold;white-space:nowrap;overflow:visible;" nowrap="nowrap">
|
||||||
|
|
||||||
|
2007
|
||||||
|
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody></table>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td style="vertical-align:middle;padding:0!important;">
|
||||||
|
<a href="http://wayback.archive.org/web/20061205055004*/http://samhuri.net/" style="color:#33f;font-size:11px;font-weight:bold;background-color:transparent;border:none;" title="See a list of every capture for this URL"><strong>7 captures</strong></a>
|
||||||
|
<div style="margin:0!important;padding:0!important;color:#666;font-size:9px;padding-top:2px!important;white-space:nowrap;" title="Timespan for captures of this URL">2 Apr 06 - 5 Dec 06</div>
|
||||||
|
</td>
|
||||||
|
<td style="padding:0!important;">
|
||||||
|
<a style="position:relative; white-space:nowrap; width:400px;height:27px;" href="" id="wm-graph-anchor">
|
||||||
|
<div id="wm-ipp-sparkline" style="position:relative; white-space:nowrap; width:400px;height:27px;background-color:#fff;cursor:pointer;border-right:1px solid #ccc;" title="Explore captures for this URL">
|
||||||
|
<img id="sparklineImgId" style="position:absolute; z-index:9012; top:0px; left:0px;"
|
||||||
|
onmouseover="showTrackers('inline');"
|
||||||
|
onmouseout="showTrackers('none');"
|
||||||
|
onmousemove="trackMouseMove(event,this)"
|
||||||
|
alt="sparklines"
|
||||||
|
width="400"
|
||||||
|
height="27"
|
||||||
|
border="0"
|
||||||
|
src="http://wayback.archive.org/jsp/graph.jsp?graphdata=400_27_1996:-1:000000000000_1997:-1:000000000000_1998:-1:000000000000_1999:-1:000000000000_2000:-1:000000000000_2001:-1:000000000000_2002:-1:000000000000_2003:-1:000000000000_2004:-1:000000000000_2005:-1:000000000000_2006:11:000101030101_2007:-1:000000000000_2008:-1:000000000000_2009:-1:000000000000_2010:-1:000000000000_2011:-1:000000000000"></img>
|
||||||
|
<img id="wbMouseTrackYearImg"
|
||||||
|
style="display:none; position:absolute; z-index:9010;"
|
||||||
|
width="25"
|
||||||
|
height="27"
|
||||||
|
border="0"
|
||||||
|
src="http://staticweb.archive.org/images/toolbar/transp-yellow-pixel.png"></img>
|
||||||
|
<img id="wbMouseTrackMonthImg"
|
||||||
|
style="display:none; position:absolute; z-index:9011; "
|
||||||
|
width="2"
|
||||||
|
height="27"
|
||||||
|
border="0"
|
||||||
|
src="http://staticweb.archive.org/images/toolbar/transp-red-pixel.png"></img>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
</td>
|
||||||
|
</tr></tbody></table>
|
||||||
|
</td>
|
||||||
|
<td style="text-align:right;padding:5px;width:65px;font-size:11px!important;">
|
||||||
|
<a href="javascript:;" onclick="document.getElementById('wm-ipp').style.display='none';" style="display:block;padding-right:18px;background:url(http://staticweb.archive.org/images/toolbar/wm_tb_close.png) no-repeat 100% 0;color:#33f;font-family:'Lucida Grande','Arial',sans-serif;margin-bottom:23px;background-color:transparent;border:none;" title="Close the toolbar">Close</a>
|
||||||
|
<a href="http://faq.web.archive.org/" style="display:block;padding-right:18px;background:url(http://staticweb.archive.org/images/toolbar/wm_tb_help.png) no-repeat 100% 0;color:#33f;font-family:'Lucida Grande','Arial',sans-serif;background-color:transparent;border:none;" title="Get some help using the Wayback Machine">Help</a>
|
||||||
|
</td>
|
||||||
|
</tr></tbody></table>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script type="text/javascript">
|
||||||
|
var wmDisclaimBanner = document.getElementById("wm-ipp");
|
||||||
|
if(wmDisclaimBanner != null) {
|
||||||
|
disclaimElement(wmDisclaimBanner);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<!-- END WAYBACK TOOLBAR INSERT -->
|
||||||
|
|
||||||
|
<p>samhuri.net</a>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!--
|
||||||
|
FILE ARCHIVED ON 5:50:04 Dec 5, 2006 AND RETRIEVED FROM THE
|
||||||
|
INTERNET ARCHIVE ON 2:38:29 Aug 21, 2011.
|
||||||
|
JAVASCRIPT APPENDED BY WAYBACK MACHINE, COPYRIGHT INTERNET ARCHIVE.
|
||||||
|
|
||||||
|
ALL OTHER CONTENT MAY ALSO BE PROTECTED BY COPYRIGHT (17 U.S.C.
|
||||||
|
SECTION 108(a)(3)).
|
||||||
|
-->
|
||||||
35
public/f/german_keys.txt
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
DVORAK
|
||||||
|
------
|
||||||
|
§1234567890[]
|
||||||
|
±!@#$%^&*(){}
|
||||||
|
|
||||||
|
',.pyfgcrl/=
|
||||||
|
"<>PYFGCRL?+
|
||||||
|
|
||||||
|
aoeuidhtns-\
|
||||||
|
AOEUIDHTNS_|
|
||||||
|
|
||||||
|
`;qjkxbmwvz
|
||||||
|
~:QJKXBMWVZ
|
||||||
|
|
||||||
|
|
||||||
|
QWERTY
|
||||||
|
------
|
||||||
|
§12344567890-=
|
||||||
|
±!@#$%^&*()_+
|
||||||
|
|
||||||
|
qwertyuiop[]
|
||||||
|
QWERTYUIOP{}
|
||||||
|
|
||||||
|
asdfghjkl;'\
|
||||||
|
ASDFGHJKL:"|
|
||||||
|
|
||||||
|
`zxcvbnm,./
|
||||||
|
~ZXCVBNM<>?
|
||||||
|
|
||||||
|
|
||||||
|
QWERTZ (German)
|
||||||
|
---------------
|
||||||
|
^1234567890ß´
|
||||||
|
°!"§$%&/()=?`
|
||||||
|
|
||||||
14
public/f/gtkpod-aac-fix.sh
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
mkdir /tmp/gtkpod-fix
|
||||||
|
cd /tmp/gtkpod-fix
|
||||||
|
wget http://ftp.uni-kl.de/debian-multimedia/pool/main/libm/libmpeg4ip/libmp4v2-0_1.5.0.1-0.3_amd64.deb
|
||||||
|
wget http://ftp.uni-kl.de/debian-multimedia/pool/main/libm/libmpeg4ip/libmp4v2-dev_1.5.0.1-0.3_amd64.deb
|
||||||
|
wget http://ftp.uni-kl.de/debian-multimedia/pool/main/libm/libmpeg4ip/libmpeg4ip-0_1.5.0.1-0.3_amd64.deb
|
||||||
|
wget http://ftp.uni-kl.de/debian-multimedia/pool/main/libm/libmpeg4ip/libmpeg4ip-dev_1.5.0.1-0.3_amd64.deb
|
||||||
|
for f in *.deb; do sudo gdebi -n "$f"; done
|
||||||
|
svn co https://gtkpod.svn.sourceforge.net/svnroot/gtkpod/gtkpod/trunk gtkpod
|
||||||
|
cd gtkpod
|
||||||
|
./autogen.sh --with-mp4v2 && make && sudo make install
|
||||||
|
cd
|
||||||
|
rm -rf /tmp/gtkpod-fix
|
||||||
BIN
public/f/ims-demo.mov
Normal file
438
public/f/island.css
Normal file
|
|
@ -0,0 +1,438 @@
|
||||||
|
/* Island screen styles */
|
||||||
|
|
||||||
|
body {
|
||||||
|
font: 1em/1.15em "Hoefler Text", Georgia, "Adobe Garamond Pro", Palatino, "Times New Roman", serif;
|
||||||
|
color: #eee;
|
||||||
|
background: #000;
|
||||||
|
margin: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#leftcolumn {
|
||||||
|
width: 23%;
|
||||||
|
float: right;
|
||||||
|
margin: 0 10px 0 20px;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
#header {
|
||||||
|
/* text-align: center;*/
|
||||||
|
}
|
||||||
|
|
||||||
|
#content {
|
||||||
|
/* padding-top: 50px;*/
|
||||||
|
width: 72%;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main {
|
||||||
|
}
|
||||||
|
|
||||||
|
#search {
|
||||||
|
padding: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#sidebar {
|
||||||
|
}
|
||||||
|
|
||||||
|
#footer {
|
||||||
|
text-align: center;
|
||||||
|
/* background: #333;*/
|
||||||
|
border-top: 1px solid #666;
|
||||||
|
padding-bottom: 5px;
|
||||||
|
clear: both;
|
||||||
|
}
|
||||||
|
|
||||||
|
#footer a { border: none; }
|
||||||
|
#footer img { border: none; }
|
||||||
|
|
||||||
|
/*+-------------------------------------------+
|
||||||
|
| LINKS |
|
||||||
|
+-------------------------------------------+*/
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #5189ea;
|
||||||
|
text-decoration: none;
|
||||||
|
border-bottom: 1px dotted #3179ca;
|
||||||
|
padding-top: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover {
|
||||||
|
background: #ffa;
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*+-------------------------------------------+
|
||||||
|
| UTILITY |
|
||||||
|
+-------------------------------------------+*/
|
||||||
|
|
||||||
|
h1, h2, h3, h4, h5, h6 {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
form, div { padding: 0; margin: 0; }
|
||||||
|
p { margin: 0 0 1em 0; padding: 0; }
|
||||||
|
img {
|
||||||
|
border: 0;
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*+-------------------------------------------+
|
||||||
|
| HEADER |
|
||||||
|
+-------------------------------------------+*/
|
||||||
|
|
||||||
|
#header h1 {
|
||||||
|
margin-top: 30px;
|
||||||
|
font-size: 5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#header h1 a {
|
||||||
|
color: #ffa;
|
||||||
|
background: inherit;
|
||||||
|
text-decoration: none;
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#header h1 a:hover {
|
||||||
|
background: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
#header h2 {
|
||||||
|
color: #555;
|
||||||
|
padding-top: .2em;
|
||||||
|
font-size: 1.2em;
|
||||||
|
letter-spacing: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*+-------------------------------------------+
|
||||||
|
| SEARCH |
|
||||||
|
+-------------------------------------------+*/
|
||||||
|
|
||||||
|
#sform {
|
||||||
|
padding-top: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#search-results {
|
||||||
|
text-align: left;
|
||||||
|
padding-bottom: 5px;
|
||||||
|
border-bottom: 1px dotted #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*+-------------------------------------------+
|
||||||
|
| POST |
|
||||||
|
+-------------------------------------------+*/
|
||||||
|
|
||||||
|
.post {
|
||||||
|
padding: 10px 0 10px 0;
|
||||||
|
margin: 5px 0 15px 5px;
|
||||||
|
/* clear: left;*/
|
||||||
|
}
|
||||||
|
|
||||||
|
.post h2 {
|
||||||
|
font-size: 140%;
|
||||||
|
line-height: 1.4em;
|
||||||
|
margin: 5px 0;
|
||||||
|
/* padding-top: 15px;*/
|
||||||
|
}
|
||||||
|
|
||||||
|
.post h3 {
|
||||||
|
margin: 5px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.post h2 a {
|
||||||
|
color: #fff;
|
||||||
|
text-decoration: none;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.post h2 a:before {
|
||||||
|
content: '# ';
|
||||||
|
}
|
||||||
|
|
||||||
|
.post h2 a:hover {
|
||||||
|
color: #ffa;
|
||||||
|
background: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.post p {
|
||||||
|
margin-left: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
p.meta {
|
||||||
|
font-size: 75%;
|
||||||
|
text-align: right;
|
||||||
|
margin-right: 15px;
|
||||||
|
/* border-right: 1px solid #999;*/
|
||||||
|
/* float: left;*/
|
||||||
|
/* width: 75px;*/
|
||||||
|
}
|
||||||
|
|
||||||
|
p.auth {
|
||||||
|
font-size: 85%;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*+-------------------------------------------+
|
||||||
|
| COMMENTS |
|
||||||
|
+-------------------------------------------+*/
|
||||||
|
|
||||||
|
.comment-list li, #preview {
|
||||||
|
background: #666;
|
||||||
|
padding: 5px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
color: #eee;
|
||||||
|
/*border-right: 20px solid #d3e0ea;*/
|
||||||
|
min-height: 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gravatar {
|
||||||
|
float: right;
|
||||||
|
padding: 0 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*+-------------------------------------------+
|
||||||
|
| SIDEBAR |
|
||||||
|
+-------------------------------------------+*/
|
||||||
|
|
||||||
|
#sidebar h3 {
|
||||||
|
font-size: 110%;
|
||||||
|
line-height: 1.5em;
|
||||||
|
color: #ff9d47;
|
||||||
|
margin-top: 15px;
|
||||||
|
margin-bottom: 2px;
|
||||||
|
text-transform: lowercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
#sidebar h3:before {
|
||||||
|
content: "<< ";
|
||||||
|
font-size: small;
|
||||||
|
}
|
||||||
|
#sidebar h3:after {
|
||||||
|
content: " >>";
|
||||||
|
font-size: small;
|
||||||
|
}
|
||||||
|
|
||||||
|
#sidebar h3 a {
|
||||||
|
color: #ff9d47;
|
||||||
|
border-bottom: 1px dotted #ff9d47;
|
||||||
|
}
|
||||||
|
|
||||||
|
#sidebar h3 a:hover {
|
||||||
|
color: #000;
|
||||||
|
background: #ffa;
|
||||||
|
}
|
||||||
|
|
||||||
|
#sidebar ul {
|
||||||
|
text-align: right;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
list-style-type: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#sidebar ul li {
|
||||||
|
/* background: url(http://web.archive.org/web/20060321041209/http://sami.samhuri.net/images/theme/small_arrow.png) 45% no-repeat;*/
|
||||||
|
/* padding-left: 12px;*/
|
||||||
|
}
|
||||||
|
|
||||||
|
#sidebar a.feed,
|
||||||
|
#sidebar a.feed:link,
|
||||||
|
#sidebar a.feed:hover {
|
||||||
|
display: inline;
|
||||||
|
border: none;
|
||||||
|
background: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*+-------------------------------------------+
|
||||||
|
| FOOTER |
|
||||||
|
+-------------------------------------------+*/
|
||||||
|
|
||||||
|
#footer ul {
|
||||||
|
margin: 0;
|
||||||
|
padding: 10px 0 0 0;
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#footer ul li {
|
||||||
|
display: inline;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0 5px 0 0;
|
||||||
|
font-size: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*+-------------------------------------------+
|
||||||
|
| FORMS |
|
||||||
|
+-------------------------------------------+*/
|
||||||
|
|
||||||
|
input, textarea, select {
|
||||||
|
border: 1px solid #8ab3d1;
|
||||||
|
background: #f9f9f9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.frm-tbl td { vertical-align: top; padding: 5px; }
|
||||||
|
td#frm-btns { text-align: right; }
|
||||||
|
|
||||||
|
#comment_body { height: 220px; }
|
||||||
|
#form-submit-button { background: #d3e0ea; }
|
||||||
|
|
||||||
|
/*+-------------------------------------------+
|
||||||
|
| MISC |
|
||||||
|
+-------------------------------------------+*/
|
||||||
|
|
||||||
|
.powered { border: none; }
|
||||||
|
.powered img { margin-top: 20px; }
|
||||||
|
.pullquote {
|
||||||
|
width: 30%;
|
||||||
|
float:right;
|
||||||
|
font: 150%/1.5em Times, Helvetica, "Times New Roman", serif;
|
||||||
|
color: #666;
|
||||||
|
margin:10px;
|
||||||
|
background: url(http://web.archive.org/web/20060321041209/http://sami.samhuri.net/images/theme/q-close.gif) no-repeat 70% 100% !important;
|
||||||
|
background /**/:url(); /* removing quote graphic in IE5+ */
|
||||||
|
padding: 0 25px 5px 0;
|
||||||
|
}
|
||||||
|
.pullquote:first-letter {
|
||||||
|
background: url(http://web.archive.org/web/20060321041209/http://sami.samhuri.net/images/theme/q-open.gif) no-repeat left top !important;
|
||||||
|
padding:5px 2px 10px 35px!important;
|
||||||
|
padding /**/:0px; /* resetting padding in IE5+ */
|
||||||
|
background /**/: url(); /* removing quote graphic in IE5+ */
|
||||||
|
}
|
||||||
|
|
||||||
|
.light-bg { background: #666; padding: 2px; }
|
||||||
|
.clearfix:after {
|
||||||
|
content: ".";
|
||||||
|
display: block;
|
||||||
|
height: 0;
|
||||||
|
clear: both;
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
#errors {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admintools {
|
||||||
|
float: right;
|
||||||
|
background-color: #fff;
|
||||||
|
font-size: smaller;
|
||||||
|
padding: 0 2px;
|
||||||
|
margin: 0 1px;
|
||||||
|
color: #ccc;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admintools:hover {
|
||||||
|
color: #c00;
|
||||||
|
border: 1px solid #c00;
|
||||||
|
}
|
||||||
|
|
||||||
|
a[name] { border: none; }
|
||||||
|
|
||||||
|
/* Hides from IE-mac \*/
|
||||||
|
* html .clearfix {height: 1%;}
|
||||||
|
/* End hide from IE-mac */
|
||||||
|
|
||||||
|
#categories li em, #archives li em
|
||||||
|
{
|
||||||
|
color: #98B4D1;
|
||||||
|
font-size: smaller;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Syntax highlighting */
|
||||||
|
.typocode_ruby .normal {}
|
||||||
|
.typocode_ruby .comment { color: #005; font-style: italic; }
|
||||||
|
.typocode_ruby .keyword { color: #A00; font-weight: bold; }
|
||||||
|
.typocode_ruby .method { color: #077; }
|
||||||
|
.typocode_ruby .class { color: #074; }
|
||||||
|
.typocode_ruby .module { color: #050; }
|
||||||
|
.typocode_ruby .punct { color: #447; font-weight: bold; }
|
||||||
|
.typocode_ruby .symbol { color: #099; }
|
||||||
|
.typocode_ruby .string { color: #944; background: #FFE; }
|
||||||
|
.typocode_ruby .char { color: #F07; }
|
||||||
|
.typocode_ruby .ident { color: #004; }
|
||||||
|
.typocode_ruby .constant { color: #07F; }
|
||||||
|
.typocode_ruby .regex { color: #B66; background: #FEF; }
|
||||||
|
.typocode_ruby .number { color: #F99; }
|
||||||
|
.typocode_ruby .attribute { color: #7BB; }
|
||||||
|
.typocode_ruby .global { color: #7FB; }
|
||||||
|
.typocode_ruby .expr { color: #227; }
|
||||||
|
.typocode_ruby .escape { color: #277; }
|
||||||
|
.typocode_xml .normal {}
|
||||||
|
.typocode_xml .namespace { color: #B66; font-weight: bold; }
|
||||||
|
.typocode_xml .tag { color: #F88; }
|
||||||
|
.typocode_xml .comment { color: #005; font-style: italic; }
|
||||||
|
.typocode_xml .punct { color: #447; font-weight: bold; }
|
||||||
|
.typocode_xml .string { color: #944; }
|
||||||
|
.typocode_xml .number { color: #F99; }
|
||||||
|
.typocode_xml .attribute { color: #BB7; }
|
||||||
|
.typocode_yaml .normal {}
|
||||||
|
.typocode_yaml .document { font-weight: bold; color: #07F; }
|
||||||
|
.typocode_yaml .type { font-weight: bold; color: #05C; }
|
||||||
|
.typocode_yaml .key { color: #F88; }
|
||||||
|
.typocode_yaml .comment { color: #005; font-style: italic; }
|
||||||
|
.typocode_yaml .punct { color: #447; font-weight: bold; }
|
||||||
|
.typocode_yaml .string { color: #944; }
|
||||||
|
.typocode_yaml .number { color: #F99; }
|
||||||
|
.typocode_yaml .time { color: #F99; }
|
||||||
|
.typocode_yaml .date { color: #F99; }
|
||||||
|
.typocode_yaml .ref { color: #944; }
|
||||||
|
.typocode_yaml .anchor { color: #944; }
|
||||||
|
|
||||||
|
.typocode {
|
||||||
|
background-color:#eee;
|
||||||
|
padding:2px;
|
||||||
|
margin:5px;
|
||||||
|
margin-left:1em;
|
||||||
|
margin-bottom:1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.typocode pre {
|
||||||
|
padding: 0px;
|
||||||
|
margin: 0px;
|
||||||
|
border: none;
|
||||||
|
background: transparent;
|
||||||
|
font-family: monospace;
|
||||||
|
overflow:auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.typocode .lineno {
|
||||||
|
text-align: right;
|
||||||
|
/* color: #B00;*/
|
||||||
|
font-family: monospace;
|
||||||
|
padding-right: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
code {
|
||||||
|
font-family: "Andale Mono", "Lucida Typewriter", "Bitstream Vera Sans Mono", fixed-width, monospace;
|
||||||
|
/* font-size: 120%;*/
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
background: #555;
|
||||||
|
border: 1px dashed #5189ea;
|
||||||
|
margin-bottom: 30px;
|
||||||
|
margin-top: -10px;
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*+-------------------------------------------+
|
||||||
|
| TAGLIST |
|
||||||
|
+-------------------------------------------+*/
|
||||||
|
|
||||||
|
ul#taglist li {
|
||||||
|
display: inline;
|
||||||
|
line-height: 3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tags .tags0 { font-size: 1.0em; }
|
||||||
|
.tags .tags1 { font-size: 1.2em; }
|
||||||
|
.tags .tags2 { font-size: 1.4em; }
|
||||||
|
.tags .tags3 { font-size: 1.6em; }
|
||||||
|
.tags .tags4 { font-size: 1.8em; }
|
||||||
|
.tags .tags5 { font-size: 2.0em; }
|
||||||
|
.tags .tags6 { font-size: 2.2em; }
|
||||||
|
.tags .tags7 { font-size: 2.4em; }
|
||||||
|
.tags .tags8 { font-size: 2.6em; }
|
||||||
|
.tags .tags9 { font-size: 2.8em; }
|
||||||
|
.tags .tags10 { font-size: 3.0em; }
|
||||||
BIN
public/f/menu.png
Normal file
|
After Width: | Height: | Size: 38 KiB |
81
public/f/mephisto_converters-typo-schema_version_61.patch
Normal file
|
|
@ -0,0 +1,81 @@
|
||||||
|
diff -Nupr mephisto_converters/lib/converters/typo/article.rb mephisto_converters-schema_61/lib/converters/typo/article.rb
|
||||||
|
--- mephisto_converters/lib/converters/typo/article.rb 2006-11-23 10:57:06.000000000 -0800
|
||||||
|
+++ mephisto_converters-schema_61/lib/converters/typo/article.rb 2007-05-26 01:54:19.000000000 -0700
|
||||||
|
@@ -1,7 +1,8 @@
|
||||||
|
module Typo
|
||||||
|
class Article < Content
|
||||||
|
- has_many :comments, :dependent => true, :order => "created_at ASC", :class_name => 'Typo::Comment'
|
||||||
|
+ has_many :comments, :dependent => :destroy, :order => "created_at ASC", :class_name => 'Typo::Comment'
|
||||||
|
has_and_belongs_to_many :tags, :class_name => 'Typo::Tag'
|
||||||
|
- has_and_belongs_to_many :categories, :class_name => 'Typo::Category'
|
||||||
|
+ has_many :categorizations, :class_name => 'Typo::Categorization'
|
||||||
|
+ has_many :categories, :class_name => 'Typo::Category', :through => :categorizations
|
||||||
|
end
|
||||||
|
end
|
||||||
|
diff -Nupr mephisto_converters/lib/converters/typo/categorization.rb mephisto_converters-schema_61/lib/converters/typo/categorization.rb
|
||||||
|
--- mephisto_converters/lib/converters/typo/categorization.rb 1969-12-31 16:00:00.000000000 -0800
|
||||||
|
+++ mephisto_converters-schema_61/lib/converters/typo/categorization.rb 2007-05-26 01:44:19.000000000 -0700
|
||||||
|
@@ -0,0 +1,7 @@
|
||||||
|
+module Typo
|
||||||
|
+ class Categorization < ActiveRecord::Base
|
||||||
|
+ establish_connection configurations['typo']
|
||||||
|
+ belongs_to :article, :class_name => 'Typo::Article'
|
||||||
|
+ belongs_to :category, :class_name => 'Typo::Category'
|
||||||
|
+ end
|
||||||
|
+end
|
||||||
|
diff -Nupr mephisto_converters/lib/converters/typo/category.rb mephisto_converters-schema_61/lib/converters/typo/category.rb
|
||||||
|
--- mephisto_converters/lib/converters/typo/category.rb 2006-11-23 10:57:06.000000000 -0800
|
||||||
|
+++ mephisto_converters-schema_61/lib/converters/typo/category.rb 2007-05-26 01:42:02.000000000 -0700
|
||||||
|
@@ -1,6 +1,7 @@
|
||||||
|
module Typo
|
||||||
|
class Category < ActiveRecord::Base
|
||||||
|
establish_connection configurations['typo']
|
||||||
|
- has_and_belongs_to_many :articles, :class_name => 'Typo::Article'
|
||||||
|
+ has_many :categorizations, :class_name => 'Typo::Categorization'
|
||||||
|
+ has_many :articles, :class_name => 'Typo::Article', :through => :categorizations
|
||||||
|
end
|
||||||
|
end
|
||||||
|
diff -Nupr mephisto_converters/lib/converters/typo/comment.rb mephisto_converters-schema_61/lib/converters/typo/comment.rb
|
||||||
|
--- mephisto_converters/lib/converters/typo/comment.rb 2006-11-23 10:57:06.000000000 -0800
|
||||||
|
+++ mephisto_converters-schema_61/lib/converters/typo/comment.rb 2007-05-26 01:54:30.000000000 -0700
|
||||||
|
@@ -1,5 +1,7 @@
|
||||||
|
module Typo
|
||||||
|
- class Comment < Content
|
||||||
|
-# belongs_to :article, :foreign_key => 'parentid', :class_name => 'Typo::Comment'
|
||||||
|
+ class Comment < Feedback
|
||||||
|
+ establish_connection configurations['typo']
|
||||||
|
+ belongs_to :article, :class_name => 'Typo::Article'
|
||||||
|
+ belongs_to :user, :class_name => 'Typo::User'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
diff -Nupr mephisto_converters/lib/converters/typo/feedback.rb mephisto_converters-schema_61/lib/converters/typo/feedback.rb
|
||||||
|
--- mephisto_converters/lib/converters/typo/feedback.rb 1969-12-31 16:00:00.000000000 -0800
|
||||||
|
+++ mephisto_converters-schema_61/lib/converters/typo/feedback.rb 2007-05-26 01:55:28.000000000 -0700
|
||||||
|
@@ -0,0 +1,6 @@
|
||||||
|
+module Typo
|
||||||
|
+ class Feedback < Content
|
||||||
|
+ set_table_name 'feedback'
|
||||||
|
+ establish_connection configurations['typo']
|
||||||
|
+ end
|
||||||
|
+end
|
||||||
|
diff -Nupr mephisto_converters/lib/converters/typo.rb mephisto_converters-schema_61/lib/converters/typo.rb
|
||||||
|
--- mephisto_converters/lib/converters/typo.rb 2006-11-23 10:57:06.000000000 -0800
|
||||||
|
+++ mephisto_converters-schema_61/lib/converters/typo.rb 2007-05-26 01:53:14.000000000 -0700
|
||||||
|
@@ -1,8 +1,10 @@
|
||||||
|
require 'converters/typo/content'
|
||||||
|
require 'converters/typo/page'
|
||||||
|
require 'converters/typo/article'
|
||||||
|
+require 'converters/typo/feedback'
|
||||||
|
require 'converters/typo/comment'
|
||||||
|
require 'converters/typo/category'
|
||||||
|
+require 'converters/typo/categorization'
|
||||||
|
require 'converters/typo/user'
|
||||||
|
require 'converters/typo/tag'
|
||||||
|
|
||||||
|
@@ -77,4 +79,4 @@ class TypoConverter < BaseConverter
|
||||||
|
memo << (sections[::Section.permalink_for(cat.name)] || site.sections.create(:name => cat.name)).id
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-end
|
||||||
|
\ No newline at end of file
|
||||||
|
+end
|
||||||
29
public/f/note.html
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<style>
|
||||||
|
html,body { height: 100% }
|
||||||
|
#note { width: 100%; height: 100% }
|
||||||
|
</style>
|
||||||
|
<script>
|
||||||
|
var note, html, timeout;
|
||||||
|
window.addEventListener('load', function() {
|
||||||
|
note = document.getElementById('note');
|
||||||
|
html = document.getElementsByTagName('html')[0];
|
||||||
|
html.addEventListener('keyup', function(ev) {
|
||||||
|
if (timeout) clearTimeout(timeout);
|
||||||
|
timeout = setTimeout(saveNote, 100);
|
||||||
|
});
|
||||||
|
restoreNote();
|
||||||
|
note.focus();
|
||||||
|
});
|
||||||
|
function saveNote() {
|
||||||
|
localStorage.note = note.innerText;
|
||||||
|
timeout = null;
|
||||||
|
}
|
||||||
|
function restoreNote() {
|
||||||
|
note.innerText = localStorage.note || '';
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<h1>Notepad (type below, notes persist)</h1>
|
||||||
|
<p id="note" contenteditable></p>
|
||||||
|
</html>
|
||||||
BIN
public/f/pacman-tones.zip
Normal file
BIN
public/f/pacman-tones/Pacman Dies.mp3
Normal file
BIN
public/f/pacman-tones/Pacman.mp3
Normal file
BIN
public/f/spinner-blue.gif
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
public/f/spinner.gif
Normal file
|
After Width: | Height: | Size: 2 KiB |
34
public/f/tagify.el
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
(defun wrap-region (left right)
|
||||||
|
"Wrap the region in arbitrary text, LEFT goes to the left and RIGHT goes to the right."
|
||||||
|
(interactive)
|
||||||
|
(let ((beg (region-beginning))
|
||||||
|
(end (region-end)))
|
||||||
|
(goto-char beg)
|
||||||
|
(insert left)
|
||||||
|
(goto-char (+ end (length left)))
|
||||||
|
(insert right)
|
||||||
|
(goto-char (+ end (length left) (length right)))))
|
||||||
|
|
||||||
|
(defun tagify-region-or-insert-self (arg)
|
||||||
|
"If there is a visible region, call `tagify-region-or-insert', otherwise
|
||||||
|
call `self-insert-command' passing it any prefix arg given."
|
||||||
|
(interactive "*P")
|
||||||
|
(if (and mark-active transient-mark-mode)
|
||||||
|
(call-interactively 'tagify-region-or-insert-tag)
|
||||||
|
(self-insert-command (prefix-numeric-value arg))))
|
||||||
|
|
||||||
|
(defun tagify-region-or-insert-tag (tag)
|
||||||
|
"If there is a visible region, wrap it in the given HTML/XML tag using
|
||||||
|
`wrap-region'. If any attributes are specified then they are only included
|
||||||
|
in the opening tag.
|
||||||
|
|
||||||
|
Otherwise insert the opening and closing tags and position point between the two."
|
||||||
|
(interactive "*sTag (including attributes): \n")
|
||||||
|
(let* ((open (concat "<" tag ">"))
|
||||||
|
(close (concat "</" (car (split-string tag " ")) ">")))
|
||||||
|
(if (and mark-active transient-mark-mode)
|
||||||
|
(wrap-region open close)
|
||||||
|
(insert (concat open close))
|
||||||
|
(backward-char (length close)))))
|
||||||
|
|
||||||
|
(provide 'tagify)
|
||||||
21
public/f/volume.rb
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
#!/usr/bin/env ruby
|
||||||
|
|
||||||
|
Ops = {
|
||||||
|
:+ => [lambda { |x| x + 5 > 100 ? 100 : x + 5 }, "increased"],
|
||||||
|
:- => [lambda { |x| x - 5 < 0 ? 0 : x - 5 } , "decreased"]
|
||||||
|
}
|
||||||
|
|
||||||
|
def vol_op id, vol
|
||||||
|
[Ops[id].first.call(vol), Ops[id].last]
|
||||||
|
end
|
||||||
|
|
||||||
|
op = ARGV.shift.to_sym
|
||||||
|
unless Ops.keys.include?(op)
|
||||||
|
raise "#{op} is not a valid argument. Expected one of: #{Ops.keys.join(', ')}."
|
||||||
|
else
|
||||||
|
`amixer get Master`.split("\n").grep(/%/).first =~ /\[(\d+)/
|
||||||
|
vol = $1.to_i
|
||||||
|
new_vol, action = *vol_op(op, vol)
|
||||||
|
system("amixer set Master #{new_vol}%")
|
||||||
|
system("notify-send --urgency=low --icon=~/.icons/audio-volume-medium.gif --expire-time=500 \"Volume #{action}\" \"#{new_vol}%\"")
|
||||||
|
end
|
||||||
49
public/f/wrap-region.el
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
;; help out a TextMate junkie
|
||||||
|
|
||||||
|
(defun wrap-region (left right beg end)
|
||||||
|
"Wrap the region in arbitrary text, LEFT goes to the left and RIGHT goes to the right."
|
||||||
|
(interactive)
|
||||||
|
(save-excursion
|
||||||
|
(goto-char beg)
|
||||||
|
(insert left)
|
||||||
|
(goto-char (+ end (length left)))
|
||||||
|
(insert right)))
|
||||||
|
|
||||||
|
(defmacro wrap-region-with-function (left right)
|
||||||
|
"Returns a function which, when called, will interactively `wrap-region-or-insert' using LEFT and RIGHT."
|
||||||
|
`(lambda () (interactive)
|
||||||
|
(wrap-region-or-insert ,left ,right)))
|
||||||
|
|
||||||
|
(defun wrap-region-with-tag-or-insert ()
|
||||||
|
(interactive)
|
||||||
|
(if (and mark-active transient-mark-mode)
|
||||||
|
(call-interactively 'wrap-region-with-tag)
|
||||||
|
(insert "<")))
|
||||||
|
|
||||||
|
(defun wrap-region-with-tag (tag beg end)
|
||||||
|
"Wrap the region in the given HTML/XML tag using `wrap-region'. If any
|
||||||
|
attributes are specified then they are only included in the opening tag."
|
||||||
|
(interactive "*sTag (including attributes): \nr")
|
||||||
|
(let* ((elems (split-string tag " "))
|
||||||
|
(tag-name (car elems))
|
||||||
|
(right (concat "</" tag-name ">")))
|
||||||
|
(if (= 1 (length elems))
|
||||||
|
(wrap-region (concat "<" tag-name ">") right beg end)
|
||||||
|
(wrap-region (concat "<" tag ">") right beg end))))
|
||||||
|
|
||||||
|
(defun wrap-region-or-insert (left right)
|
||||||
|
"Wrap the region with `wrap-region' if an active region is marked, otherwise insert LEFT at point."
|
||||||
|
(interactive)
|
||||||
|
(if (and mark-active transient-mark-mode)
|
||||||
|
(wrap-region left right (region-beginning) (region-end))
|
||||||
|
(insert left)))
|
||||||
|
|
||||||
|
(global-set-key "'" (wrap-region-with-function "'" "'"))
|
||||||
|
(global-set-key "\"" (wrap-region-with-function "\"" "\""))
|
||||||
|
(global-set-key "`" (wrap-region-with-function "`" "`"))
|
||||||
|
(global-set-key "(" (wrap-region-with-function "(" ")"))
|
||||||
|
(global-set-key "[" (wrap-region-with-function "[" "]"))
|
||||||
|
(global-set-key "{" (wrap-region-with-function "{" "}"))
|
||||||
|
(global-set-key "<" 'wrap-region-with-tag-or-insert) ;; I opted not to have a wrap-with-angle-brackets
|
||||||
|
|
||||||
|
(provide 'wrap-region)
|
||||||
BIN
public/f/zelda-tones.zip
Normal file
BIN
public/f/zelda-tones/Zelda Achievement.mp3
Normal file
BIN
public/f/zelda-tones/Zelda Item.mp3
Normal file
BIN
public/f/zelda-tones/Zelda Overture.mp3
Normal file
BIN
public/f/zelda-tones/Zelda Secret.mp3
Normal file
BIN
public/f/zelda-tones/Zelda Song of Storms.mp3
Normal file
BIN
public/f/zelda-tones/Zelda Theme.mp3
Normal file
BIN
public/images/blog/ch1-Z-G-4.gif
Normal file
|
After Width: | Height: | Size: 360 B |
BIN
public/images/blog/download.png
Normal file
|
After Width: | Height: | Size: 139 B |
BIN
public/images/blog/keyboard.jpg
Normal file
|
After Width: | Height: | Size: 468 KiB |
BIN
public/images/blog/menu.png
Normal file
|
After Width: | Height: | Size: 38 KiB |
766
public/js/gitter.js
Normal file
|
|
@ -0,0 +1,766 @@
|
||||||
|
/// gitter
|
||||||
|
/// http://github.com/samsonjs/gitter
|
||||||
|
/// @_sjs
|
||||||
|
///
|
||||||
|
/// Copyright 2010 - 2012 Sami Samhuri <sami@samhuri.net>
|
||||||
|
/// MIT License
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
"use strict"
|
||||||
|
|
||||||
|
var global = (function() { return this || (1, eval)('this') }())
|
||||||
|
, isBrowser = 'document' in global
|
||||||
|
, ie
|
||||||
|
|
||||||
|
if (isBrowser) {
|
||||||
|
ie = (function() {
|
||||||
|
var undef
|
||||||
|
, v = 3
|
||||||
|
, div = document.createElement('div')
|
||||||
|
, all = div.getElementsByTagName('i')
|
||||||
|
|
||||||
|
while (
|
||||||
|
div.innerHTML = '<!--[if gt IE ' + (++v) + ']><i></i><![endif]-->',
|
||||||
|
all[0]
|
||||||
|
);
|
||||||
|
|
||||||
|
return v > 4 ? v : undef
|
||||||
|
}())
|
||||||
|
}
|
||||||
|
|
||||||
|
var inherits
|
||||||
|
if ('create' in Object) {
|
||||||
|
// util.inherits from node
|
||||||
|
inherits = function(ctor, superCtor) {
|
||||||
|
ctor.super_ = superCtor
|
||||||
|
ctor.prototype = Object.create(superCtor.prototype, {
|
||||||
|
constructor: {
|
||||||
|
value: ctor,
|
||||||
|
enumerable: false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ([].__proto__) {
|
||||||
|
inherits = function(ctor, superCtor) {
|
||||||
|
ctor.super_ = superCtor
|
||||||
|
ctor.prototype.__proto__ = superCtor.prototype
|
||||||
|
ctor.prototype.constructor = ctor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else { // ie8
|
||||||
|
var __hasProp = Object.prototype.hasOwnProperty
|
||||||
|
inherits = function(child, parent) {
|
||||||
|
for (var key in parent) {
|
||||||
|
if (__hasProp.call(parent, key)) child[key] = parent[key]
|
||||||
|
}
|
||||||
|
function ctor() { this.constructor = child }
|
||||||
|
ctor.prototype = parent.prototype
|
||||||
|
child.prototype = new ctor
|
||||||
|
child.__super__ = parent.prototype
|
||||||
|
return child
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var api = {
|
||||||
|
// Blob
|
||||||
|
blob: function(user, repo, sha, cb) {
|
||||||
|
return new Blob(user, repo, sha, cb)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Branch
|
||||||
|
, branch: function(user, repo, name, cb) {
|
||||||
|
return new Branch(user, repo, name, cb)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Commit
|
||||||
|
, commit: function(user, repo, sha, cb) {
|
||||||
|
return new Commit(user, repo, sha, cb)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Download
|
||||||
|
, download: function(user, repo, id, cb) {
|
||||||
|
return new Download(user, repo, id, cb)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Issue
|
||||||
|
, issue: function(user, repo, id, cb) {
|
||||||
|
return new Issue(user, repo, id, cb)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Organization
|
||||||
|
, org: function(name, cb) {
|
||||||
|
return new Org(name, cb)
|
||||||
|
}
|
||||||
|
, members: function(name, cb) {
|
||||||
|
return new Org(name).fetchMembers(cb)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Repo
|
||||||
|
, repo: function(user, repo, cb) {
|
||||||
|
return new Repo(user, repo, cb)
|
||||||
|
}
|
||||||
|
, branches: function(user, repo, cb) {
|
||||||
|
return new Repo(user, repo).fetchBranches(cb)
|
||||||
|
}
|
||||||
|
, collaborators: function(user, repo, cb) {
|
||||||
|
return new Repo(user, repo).fetchCollaborators(cb)
|
||||||
|
}
|
||||||
|
, contributors: function(user, repo, cb) {
|
||||||
|
return new Repo(user, repo).fetchContributors(cb)
|
||||||
|
}
|
||||||
|
, downloads: function(user, repo, cb) {
|
||||||
|
return new Repo(user, repo).fetchDownloads(cb)
|
||||||
|
}
|
||||||
|
, forks: function(user, repo, cb) {
|
||||||
|
return new Repo(user, repo).fetchForks(cb)
|
||||||
|
}
|
||||||
|
, issues: function(user, repo, cb) {
|
||||||
|
return new Repo(user, repo).fetchIssues(cb)
|
||||||
|
}
|
||||||
|
, languages: function(user, repo, cb) {
|
||||||
|
return new Repo(user, repo).fetchLanguages(cb)
|
||||||
|
}
|
||||||
|
, tags: function(user, repo, cb) {
|
||||||
|
return new Repo(user, repo).fetchTags(cb)
|
||||||
|
}
|
||||||
|
, watchers: function(user, repo, cb) {
|
||||||
|
return new Repo(user, repo).fetchWatchers(cb)
|
||||||
|
}
|
||||||
|
|
||||||
|
, ref: function(user, repo, name, cb) {
|
||||||
|
return new Ref(user, repo, name, cb)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tag
|
||||||
|
, tag: function(user, repo, name, cb) {
|
||||||
|
return new Tag(user, repo, name, cb)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tree
|
||||||
|
, tree: function(user, repo, sha, cb) {
|
||||||
|
return new Tree(user, repo, sha, cb)
|
||||||
|
}
|
||||||
|
|
||||||
|
// User
|
||||||
|
, user: function(login, cb) {
|
||||||
|
return new User(login, cb)
|
||||||
|
}
|
||||||
|
, followers: function(login, cb) {
|
||||||
|
return new User(login).fetchFollowers(cb)
|
||||||
|
}
|
||||||
|
, following: function(login, cb) {
|
||||||
|
return new User(login).fetchFollowing(cb)
|
||||||
|
}
|
||||||
|
, repos: function(login, cb) {
|
||||||
|
return new User(login).fetchRepos(cb)
|
||||||
|
}
|
||||||
|
, watched: function(login, cb) {
|
||||||
|
return new User(login).fetchWatched(cb)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Why not, expose the resources directly as well.
|
||||||
|
, Blob: Blob
|
||||||
|
, Branch: Branch
|
||||||
|
, Commit: Commit
|
||||||
|
, Download: Download
|
||||||
|
, Issue: Issue
|
||||||
|
, Org: Org
|
||||||
|
, Ref: Ref
|
||||||
|
, Repo: Repo
|
||||||
|
, Tree: Tree
|
||||||
|
, User: User
|
||||||
|
}
|
||||||
|
|
||||||
|
// when running in the browser request is set later, in shim()
|
||||||
|
var request
|
||||||
|
|
||||||
|
if (isBrowser) {
|
||||||
|
shim()
|
||||||
|
global.GITR = api
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var https = require('https')
|
||||||
|
request = function(options, cb) {
|
||||||
|
var req = https.request(options, function(response) {
|
||||||
|
var bodyParts = []
|
||||||
|
response.on('data', function(b) { bodyParts.push(b) })
|
||||||
|
response.on('end', function() {
|
||||||
|
var body = bodyParts.join('')
|
||||||
|
if (response.statusCode === 200) {
|
||||||
|
cb(null, body, response)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.dir(options, response, body)
|
||||||
|
var err = new Error('http error')
|
||||||
|
err.statusCode = response.statusCode
|
||||||
|
err.body = body
|
||||||
|
cb(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
req.end()
|
||||||
|
req.on('error', function(err) { cb(err) })
|
||||||
|
}
|
||||||
|
module.exports = api
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Generic Resource //
|
||||||
|
//
|
||||||
|
// Used as the prototype by createResource. Provides
|
||||||
|
// methods for fetching the resource and related
|
||||||
|
// sub-resources.
|
||||||
|
function Resource() {}
|
||||||
|
|
||||||
|
// Fetch data for this resource and pass it to the
|
||||||
|
// callback after mixing the data into the object.
|
||||||
|
// Data is also available via the `data` property.
|
||||||
|
Resource.prototype.fetch = function(cb) {
|
||||||
|
if (this.data) {
|
||||||
|
cb(null, this.data)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var self = this
|
||||||
|
fetch(this.path, function(err, data) {
|
||||||
|
// console.log('FETCH', self.path, err, data)
|
||||||
|
if (err) {
|
||||||
|
// console.log(err)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
self.data = data
|
||||||
|
mixin(self, data)
|
||||||
|
}
|
||||||
|
if (typeof cb === 'function') {
|
||||||
|
cb.call(self, err, data)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
Resource.prototype.fetchSubResource = function(thing, cb) {
|
||||||
|
if (this['_' + thing]) {
|
||||||
|
cb(null, this['_' + thing])
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var self = this
|
||||||
|
fetch(this.path + '/' + thing, function(err, data) {
|
||||||
|
// console.log('FETCH SUBRESOURCE', self.path, thing, err, data)
|
||||||
|
if (err) {
|
||||||
|
// console.log(self.path, err)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
self['_' + thing] = data
|
||||||
|
}
|
||||||
|
if (typeof cb === 'function') {
|
||||||
|
cb.call(self, err, data)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
var __slice = Array.prototype.slice
|
||||||
|
|
||||||
|
// Create a resource w/ Resource as the prototype.
|
||||||
|
//
|
||||||
|
// spec: an object with the following properties:
|
||||||
|
//
|
||||||
|
// - constructor: a constructor function
|
||||||
|
// - has: a list of resources belonging to this resource
|
||||||
|
//
|
||||||
|
// Typically the constructor accepts one or more arguments specifying
|
||||||
|
// the name or pieces of info identifying the specific resource and
|
||||||
|
// used to build the URL to fetch it. It also accepts an optional
|
||||||
|
// callback as the last parameter.
|
||||||
|
//
|
||||||
|
// The constructor must set the `path` property which is used to
|
||||||
|
// fetch the resource.
|
||||||
|
//
|
||||||
|
// If a callback is provided then the resource is immediately
|
||||||
|
// fetched and the callback is threaded through to the `fetch`
|
||||||
|
// method. The callback function has the signature
|
||||||
|
// `function(err, data)`.
|
||||||
|
//
|
||||||
|
// The `has` list specifies sub-resources, e.g. a user has repos,
|
||||||
|
// followers, etc. An organization has members.
|
||||||
|
//
|
||||||
|
// Each related sub-resource gets a method named appropriately,
|
||||||
|
// e.g. the User resource has followers so User objects have a
|
||||||
|
// `fetchFollowers` method.
|
||||||
|
function createResource(spec) {
|
||||||
|
var subResources = spec.has ? __slice.call(spec.has) : null
|
||||||
|
, resource = function(/* ..., cb */) {
|
||||||
|
var args = __slice.call(arguments)
|
||||||
|
, lastArgIsCallback = typeof args[args.length - 1] === 'function'
|
||||||
|
, cb = lastArgIsCallback ? args.pop() : null
|
||||||
|
, result = spec.constructor.apply(this, args)
|
||||||
|
|
||||||
|
if (typeof cb === 'function') {
|
||||||
|
this.fetch(cb)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
inherits(resource, Resource)
|
||||||
|
|
||||||
|
if (subResources) {
|
||||||
|
subResources.forEach(function(thing) {
|
||||||
|
var fnName = 'fetch' + toTitleCase(thing)
|
||||||
|
resource.prototype[fnName] = function(cb) {
|
||||||
|
return this.fetchSubResource(thing, cb)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return resource
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Define Resources //
|
||||||
|
|
||||||
|
var Blob = createResource({
|
||||||
|
constructor: function(user, repo, sha) {
|
||||||
|
this.user = user
|
||||||
|
this.repo = repo
|
||||||
|
this.sha = sha
|
||||||
|
this.path = '/repos/' + [user, repo].map(encodeURIComponent).join('/') + '/git/blobs/' + sha
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
var Branch = createResource({
|
||||||
|
constructor: function (user, repo, name) {
|
||||||
|
this.user = user
|
||||||
|
this.repo = repo
|
||||||
|
this.name = name
|
||||||
|
this.path = '/repos/' + [user, repo].map(encodeURIComponent).join('/') + '/git/refs/heads/' + name
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
var Commit = createResource({
|
||||||
|
constructor: function Commit(user, repo, sha) {
|
||||||
|
this.user = user
|
||||||
|
this.repo = repo
|
||||||
|
this.sha = sha
|
||||||
|
this.path = '/repos/' + [user, repo].map(encodeURIComponent).join('/') + '/git/commits/' + sha
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
var Download = createResource({
|
||||||
|
constructor: function(user, repo, id) {
|
||||||
|
this.user = user
|
||||||
|
this.repo = repo
|
||||||
|
this.id = id
|
||||||
|
this.path = '/repos/' + [user, repo].map(encodeURIComponent).join('/') + '/downloads/' + id
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
var Issue = createResource({
|
||||||
|
constructor: function(user, repo, id) {
|
||||||
|
this.user = user
|
||||||
|
this.repo = repo
|
||||||
|
this.id = id
|
||||||
|
this.path = '/repos/' + [user, repo].map(encodeURIComponent).join('/') + '/issues/' + id
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
var Org = createResource({
|
||||||
|
constructor: function(name) {
|
||||||
|
this.name = name
|
||||||
|
this.path = '/orgs/' + encodeURIComponent(nam)
|
||||||
|
}
|
||||||
|
|
||||||
|
, has: 'members repos'.split(' ')
|
||||||
|
})
|
||||||
|
|
||||||
|
var Ref = createResource({
|
||||||
|
constructor: function (user, repo, name) {
|
||||||
|
this.user = user
|
||||||
|
this.repo = repo
|
||||||
|
this.name = name
|
||||||
|
this.path = '/repos/' + [user, repo].map(encodeURIComponent).join('/') + '/git/refs/' + name
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
var Repo = createResource({
|
||||||
|
constructor: function(user, repo) {
|
||||||
|
this.user = user
|
||||||
|
this.repo = repo
|
||||||
|
this.path = '/repos/' + [user, repo].map(encodeURIComponent).join('/')
|
||||||
|
}
|
||||||
|
|
||||||
|
, has: ('branches collaborators contributors downloads' +
|
||||||
|
' forks languages tags teams watchers').split(' ')
|
||||||
|
})
|
||||||
|
|
||||||
|
var Tag = createResource({
|
||||||
|
constructor: function (user, repo, name) {
|
||||||
|
this.user = user
|
||||||
|
this.repo = repo
|
||||||
|
this.name = name
|
||||||
|
this.path = '/repos/' + [user, repo].map(encodeURIComponent).join('/') + '/git/refs/tags/' + name
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
var Tree = createResource({
|
||||||
|
constructor: function(user, repo, sha) {
|
||||||
|
this.user = user
|
||||||
|
this.repo = repo
|
||||||
|
this.sha = sha
|
||||||
|
this.path = '/repos/' + [user, repo].map(encodeURIComponent).join('/') + '/git/trees/' + sha
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
var User = createResource({
|
||||||
|
constructor: function(login) {
|
||||||
|
// Allow creating a user from an object returned by the API
|
||||||
|
if (login.login) {
|
||||||
|
login = login.login
|
||||||
|
}
|
||||||
|
this.login = login
|
||||||
|
this.path = '/users/' + encodeURIComponent(login)
|
||||||
|
}
|
||||||
|
|
||||||
|
, has: 'followers following repos watched'.split(' ')
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
// Fetch data from github. JSON is parsed and keys are camelized.
|
||||||
|
//
|
||||||
|
// path: the path to the resource
|
||||||
|
// cb: callback(err, data)
|
||||||
|
function fetch(path, cb) {
|
||||||
|
request({ host: 'api.github.com', path: path }, function(err, body, response) {
|
||||||
|
// JSONP requests in the browser return the object directly
|
||||||
|
var data = body
|
||||||
|
|
||||||
|
// Requests in Node return json text, try to parse it
|
||||||
|
if (response && /json/i.exec(response.headers['content-type'])) {
|
||||||
|
try {
|
||||||
|
data = JSON.parse(body)
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
err = e
|
||||||
|
data = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cb(err, camelize(data))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// created_at => createdAt
|
||||||
|
function camel(s) {
|
||||||
|
return s.replace(/_(.)/g, function(_, l) { return l.toUpperCase() })
|
||||||
|
}
|
||||||
|
|
||||||
|
// camelize all keys of an object, or all objects in an array
|
||||||
|
function camelize(obj) {
|
||||||
|
if (!obj || typeof obj === 'string') return obj
|
||||||
|
if (Array.isArray(obj)) return obj.map(camelize)
|
||||||
|
if (typeof obj === 'object') {
|
||||||
|
return Object.keys(obj).reduce(function(camelizedObj, k) {
|
||||||
|
camelizedObj[camel(k)] = camelize(obj[k])
|
||||||
|
return camelizedObj
|
||||||
|
}, {})
|
||||||
|
}
|
||||||
|
return obj
|
||||||
|
}
|
||||||
|
|
||||||
|
function toTitleCase(s) {
|
||||||
|
return s.charAt(0).toUpperCase() + s.slice(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
function mixin(a, b) {
|
||||||
|
for (var k in b) {
|
||||||
|
if (b.hasOwnProperty(k)) a[k] = b[k]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Browser Utilities //
|
||||||
|
|
||||||
|
function shim() {
|
||||||
|
shimBind()
|
||||||
|
shimES5()
|
||||||
|
shimRequest()
|
||||||
|
}
|
||||||
|
|
||||||
|
function shimBind() {
|
||||||
|
// bind from Prototype
|
||||||
|
if (!Function.prototype.bind) {
|
||||||
|
(function(){
|
||||||
|
function update(array, args) {
|
||||||
|
var arrayLength = array.length, length = args.length
|
||||||
|
while (length--) array[arrayLength + length] = args[length]
|
||||||
|
return array
|
||||||
|
}
|
||||||
|
function merge(array, args) {
|
||||||
|
array = __slice.call(array, 0)
|
||||||
|
return update(array, args)
|
||||||
|
}
|
||||||
|
Function.prototype.bind = function(context) {
|
||||||
|
if (arguments.length < 2 && typeof arguments[0] === 'undefined') return this
|
||||||
|
var __method = this, args = __slice.call(arguments, 1)
|
||||||
|
return function() {
|
||||||
|
var a = merge(args, arguments)
|
||||||
|
return __method.apply(context, a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// a few functions from Kris Kowal's es5-shim
|
||||||
|
// https://github.com/kriskowal/es5-shim
|
||||||
|
function shimES5() {
|
||||||
|
var has = Object.prototype.hasOwnProperty
|
||||||
|
|
||||||
|
// ES5 15.2.3.6
|
||||||
|
if (!Object.defineProperty || ie === 8) { // ie8
|
||||||
|
Object.defineProperty = function(object, property, descriptor) {
|
||||||
|
if (typeof descriptor == "object" && object.__defineGetter__) {
|
||||||
|
if (has.call(descriptor, "value")) {
|
||||||
|
if (!object.__lookupGetter__(property) && !object.__lookupSetter__(property)) {
|
||||||
|
// data property defined and no pre-existing accessors
|
||||||
|
object[property] = descriptor.value
|
||||||
|
}
|
||||||
|
if (has.call(descriptor, "get") || has.call(descriptor, "set")) {
|
||||||
|
// descriptor has a value property but accessor already exists
|
||||||
|
throw new TypeError("Object doesn't support this action")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// fail silently if "writable", "enumerable", or "configurable"
|
||||||
|
// are requested but not supported
|
||||||
|
else if (typeof descriptor.get == "function") {
|
||||||
|
object.__defineGetter__(property, descriptor.get)
|
||||||
|
}
|
||||||
|
if (typeof descriptor.set == "function") {
|
||||||
|
object.__defineSetter__(property, descriptor.set)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return object
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ES5 15.2.3.14
|
||||||
|
// http://whattheheadsaid.com/2010/10/a-safer-object-keys-compatibility-implementation
|
||||||
|
if (!Object.keys) { // ie8
|
||||||
|
(function() {
|
||||||
|
var hasDontEnumBug = true,
|
||||||
|
dontEnums = [
|
||||||
|
'toString',
|
||||||
|
'toLocaleString',
|
||||||
|
'valueOf',
|
||||||
|
'hasOwnProperty',
|
||||||
|
'isPrototypeOf',
|
||||||
|
'propertyIsEnumerable',
|
||||||
|
'constructor'
|
||||||
|
],
|
||||||
|
dontEnumsLength = dontEnums.length
|
||||||
|
|
||||||
|
for (var key in {"toString": null}) {
|
||||||
|
hasDontEnumBug = false
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.keys = function (object) {
|
||||||
|
|
||||||
|
if (
|
||||||
|
typeof object !== "object" && typeof object !== "function"
|
||||||
|
|| object === null
|
||||||
|
)
|
||||||
|
throw new TypeError("Object.keys called on a non-object")
|
||||||
|
|
||||||
|
var keys = []
|
||||||
|
for (var name in object) {
|
||||||
|
if (has.call(object, name)) {
|
||||||
|
keys.push(name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasDontEnumBug) {
|
||||||
|
for (var i = 0, ii = dontEnumsLength; i < ii; i++) {
|
||||||
|
var dontEnum = dontEnums[i]
|
||||||
|
if (has.call(object, dontEnum)) {
|
||||||
|
keys.push(dontEnum)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return keys
|
||||||
|
}
|
||||||
|
}())
|
||||||
|
} // Object.keys
|
||||||
|
|
||||||
|
//
|
||||||
|
// Array
|
||||||
|
// =====
|
||||||
|
//
|
||||||
|
|
||||||
|
// ES5 15.4.3.2
|
||||||
|
if (!Array.isArray) {
|
||||||
|
Array.isArray = function(obj) {
|
||||||
|
return Object.prototype.toString.call(obj) == "[object Array]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ES5 15.4.4.18
|
||||||
|
if (!Array.prototype.forEach) { // ie8
|
||||||
|
Array.prototype.forEach = function(block, thisObject) {
|
||||||
|
var len = this.length >>> 0
|
||||||
|
for (var i = 0; i < len; i++) {
|
||||||
|
if (i in this) {
|
||||||
|
block.call(thisObject, this[i], i, this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ES5 15.4.4.19
|
||||||
|
// https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/map
|
||||||
|
if (!Array.prototype.map) { // ie8
|
||||||
|
Array.prototype.map = function(fun /*, thisp*/) {
|
||||||
|
var len = this.length >>> 0
|
||||||
|
if (typeof fun != "function") {
|
||||||
|
throw new TypeError()
|
||||||
|
}
|
||||||
|
|
||||||
|
var res = new Array(len)
|
||||||
|
var thisp = arguments[1]
|
||||||
|
for (var i = 0; i < len; i++) {
|
||||||
|
if (i in this) {
|
||||||
|
res[i] = fun.call(thisp, this[i], i, this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ES5 15.4.4.20
|
||||||
|
if (!Array.prototype.filter) { // ie8
|
||||||
|
Array.prototype.filter = function (block /*, thisp */) {
|
||||||
|
var values = []
|
||||||
|
, thisp = arguments[1]
|
||||||
|
for (var i = 0; i < this.length; i++) {
|
||||||
|
if (block.call(thisp, this[i])) {
|
||||||
|
values.push(this[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return values
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ES5 15.4.4.21
|
||||||
|
// https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/reduce
|
||||||
|
if (!Array.prototype.reduce) { // ie8
|
||||||
|
Array.prototype.reduce = function(fun /*, initial*/) {
|
||||||
|
var len = this.length >>> 0
|
||||||
|
if (typeof fun != "function") {
|
||||||
|
throw new TypeError()
|
||||||
|
}
|
||||||
|
|
||||||
|
// no value to return if no initial value and an empty array
|
||||||
|
if (len == 0 && arguments.length == 1) {
|
||||||
|
throw new TypeError()
|
||||||
|
}
|
||||||
|
|
||||||
|
var i = 0
|
||||||
|
if (arguments.length >= 2) {
|
||||||
|
var rv = arguments[1]
|
||||||
|
} else {
|
||||||
|
do {
|
||||||
|
if (i in this) {
|
||||||
|
rv = this[i++]
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
// if array contains no values, no initial value to return
|
||||||
|
if (++i >= len) {
|
||||||
|
throw new TypeError()
|
||||||
|
}
|
||||||
|
} while (true)
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; i < len; i++) {
|
||||||
|
if (i in this) {
|
||||||
|
rv = fun.call(null, rv, this[i], i, this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv
|
||||||
|
}
|
||||||
|
} // Array.prototype.reduce
|
||||||
|
} // function shimES5()
|
||||||
|
|
||||||
|
// jsonp request, quacks like node's http.request
|
||||||
|
function shimRequest() {
|
||||||
|
var load, _jsonpCounter = 1
|
||||||
|
|
||||||
|
// request is declared earlier
|
||||||
|
request = function(options, cb) {
|
||||||
|
var jsonpCallbackName = '_jsonpCallback' + _jsonpCounter++
|
||||||
|
, url = 'https://' + options.host + options.path + '?callback=GITR.' + jsonpCallbackName
|
||||||
|
GITR[jsonpCallbackName] = function(response) {
|
||||||
|
if (response.meta.status >= 200 && response.meta.status < 300) {
|
||||||
|
cb(null, response.data)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var err = new Error('http error')
|
||||||
|
err.statusCode = response.meta.status
|
||||||
|
err.response = response
|
||||||
|
cb(err)
|
||||||
|
}
|
||||||
|
setTimeout(function() { delete GITR[jsonpCallbackName] }, 0)
|
||||||
|
}
|
||||||
|
load(url)
|
||||||
|
}
|
||||||
|
|
||||||
|
// bootstrap loader from LABjs (load is declared earlier)
|
||||||
|
load = function(url) {
|
||||||
|
var oDOC = document
|
||||||
|
, handler
|
||||||
|
, head = oDOC.head || oDOC.getElementsByTagName("head")
|
||||||
|
|
||||||
|
// loading code borrowed directly from LABjs itself
|
||||||
|
// (now removes script elem when done and nullifies its reference --sjs)
|
||||||
|
setTimeout(function () {
|
||||||
|
if ("item" in head) { // check if ref is still a live node list
|
||||||
|
if (!head[0]) { // append_to node not yet ready
|
||||||
|
setTimeout(arguments.callee, 25)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
head = head[0]; // reassign from live node list ref to pure node ref -- avoids nasty IE bug where changes to DOM invalidate live node lists
|
||||||
|
}
|
||||||
|
var scriptElem = oDOC.createElement("script")
|
||||||
|
, scriptdone = false
|
||||||
|
|
||||||
|
scriptElem.onload = scriptElem.onreadystatechange = function () {
|
||||||
|
if ((scriptElem.readyState && scriptElem.readyState !== "complete" && scriptElem.readyState !== "loaded") || scriptdone) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
scriptElem.onload = scriptElem.onreadystatechange = null
|
||||||
|
scriptElem.parentNode.removeChild(scriptElem)
|
||||||
|
scriptElem = null
|
||||||
|
scriptdone = true
|
||||||
|
}
|
||||||
|
scriptElem.src = url
|
||||||
|
head.insertBefore(scriptElem, head.firstChild)
|
||||||
|
}, 0) // setTimeout
|
||||||
|
|
||||||
|
// required: shim for FF <= 3.5 not having document.readyState
|
||||||
|
if (oDOC.readyState == null && oDOC.addEventListener) {
|
||||||
|
oDOC.readyState = "loading"
|
||||||
|
oDOC.addEventListener("DOMContentLoaded", function handler() {
|
||||||
|
oDOC.removeEventListener("DOMContentLoaded", handler, false)
|
||||||
|
oDOC.readyState = "complete"
|
||||||
|
}, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
} // function load(url)
|
||||||
|
|
||||||
|
} // function shimRequest()
|
||||||
|
|
||||||
|
}())
|
||||||
137
public/js/projects.js
Normal file
|
|
@ -0,0 +1,137 @@
|
||||||
|
;(function() {
|
||||||
|
if (typeof console === 'undefined') {
|
||||||
|
console = {log:function(){}}
|
||||||
|
}
|
||||||
|
|
||||||
|
var global = this
|
||||||
|
global.SJS = {
|
||||||
|
proj: function(name) {
|
||||||
|
SJS.projName = name
|
||||||
|
var data = createObjectStore(name)
|
||||||
|
if (document.addEventListener) {
|
||||||
|
document.addEventListener('DOMContentLoaded', ready, false)
|
||||||
|
} else if (window.attachEvent) {
|
||||||
|
window.attachEvent('onload', ready)
|
||||||
|
}
|
||||||
|
function ready() {
|
||||||
|
function addClass(el, name) {
|
||||||
|
var c = el.className || name
|
||||||
|
if (!c.match(new RegExp('\b' + name + '\b', 'i'))) c += ' ' + name
|
||||||
|
}
|
||||||
|
function html(id, h) {
|
||||||
|
document.getElementById(id).innerHTML = h
|
||||||
|
}
|
||||||
|
|
||||||
|
var body = document.getElementsByTagName('body')[0]
|
||||||
|
, text
|
||||||
|
if ('innerText' in body) {
|
||||||
|
text = function(id, text) {
|
||||||
|
document.getElementById(id).innerText = text
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
text = function(id, text) {
|
||||||
|
document.getElementById(id).textContent = text
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function highlight(id) {
|
||||||
|
document.getElementById(id).style.className = ' highlight'
|
||||||
|
}
|
||||||
|
function textHighlight(id, t) {
|
||||||
|
text(id, t)
|
||||||
|
document.getElementById(id).className = ' highlight'
|
||||||
|
}
|
||||||
|
function hide(id) {
|
||||||
|
document.getElementById(id).style.display = 'none'
|
||||||
|
}
|
||||||
|
|
||||||
|
function langsByUsage(langs) {
|
||||||
|
return Object.keys(langs).sort(function(a, b) {
|
||||||
|
return langs[a] < langs[b] ? -1 : 1
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function listify(things) {
|
||||||
|
return '<ul><li>' + things.join('</li><li>') + '</li></ul>'
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateBranches(name, branches) {
|
||||||
|
function branchLink(b) {
|
||||||
|
return '<a href=https://github.com/samsonjs/' + name + '/tree/' + b.name + '>' + b.name + '</a>'
|
||||||
|
}
|
||||||
|
html('branches', listify(branches.map(branchLink)))
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateContributors(contributors) {
|
||||||
|
function userLink(u) {
|
||||||
|
return '<a href=https://github.com/' + u.login + '>' + (u.name || u.login) + '</a>'
|
||||||
|
}
|
||||||
|
html('contributors', listify(contributors.map(userLink)))
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateLangs(langs) {
|
||||||
|
html('langs', listify(langsByUsage(langs)))
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateN(name, things) {
|
||||||
|
textHighlight('n' + name, things.length)
|
||||||
|
if (things.length === 1) hide(name.charAt(0) + 'plural')
|
||||||
|
}
|
||||||
|
|
||||||
|
var t = data.get('t-' + name)
|
||||||
|
if (!t || +new Date() - t > 3600 * 1000) {
|
||||||
|
console.log('stale ' + String(t))
|
||||||
|
data.set('t-' + name, +new Date())
|
||||||
|
GITR.repo('samsonjs', name)
|
||||||
|
.fetchBranches(function(err, branches) {
|
||||||
|
if (err) {
|
||||||
|
text('branches', '(oops)')
|
||||||
|
} else {
|
||||||
|
data.set('branches', branches)
|
||||||
|
updateBranches(name, branches)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.fetchLanguages(function(err, langs) {
|
||||||
|
if (err) {
|
||||||
|
text('langs', '(oops)')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
data.set('langs', langs)
|
||||||
|
updateLangs(langs)
|
||||||
|
})
|
||||||
|
.fetchContributors(function(err, users) {
|
||||||
|
if (err) {
|
||||||
|
text('contributors', '(oops)')
|
||||||
|
} else {
|
||||||
|
data.set('contributors', users)
|
||||||
|
updateContributors(users)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.fetchWatchers(function(err, users) {
|
||||||
|
if (err) {
|
||||||
|
text('nwatchers', '?')
|
||||||
|
} else {
|
||||||
|
data.set('watchers', users)
|
||||||
|
updateN('watchers', users)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.fetchForks(function(err, repos) {
|
||||||
|
if (err) {
|
||||||
|
text('nforks', '?')
|
||||||
|
} else {
|
||||||
|
data.set('forks', repos)
|
||||||
|
updateN('forks', repos)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
console.log('hit ' + t + ' (' + (+new Date() - t) + ')')
|
||||||
|
updateBranches(name, data.get('branches'))
|
||||||
|
updateLangs(data.get('langs'))
|
||||||
|
updateContributors(data.get('contributors'))
|
||||||
|
updateN('watchers', data.get('watchers'))
|
||||||
|
updateN('forks', data.get('forks'))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}());
|
||||||
92
public/js/storage-polyfill.js
Normal file
|
|
@ -0,0 +1,92 @@
|
||||||
|
if (!window.localStorage || !window.sessionStorage) (function () {
|
||||||
|
|
||||||
|
var Storage = function (type) {
|
||||||
|
function createCookie(name, value, days) {
|
||||||
|
var date, expires;
|
||||||
|
|
||||||
|
if (days) {
|
||||||
|
date = new Date();
|
||||||
|
date.setTime(date.getTime()+(days*24*60*60*1000));
|
||||||
|
expires = "; expires="+date.toGMTString();
|
||||||
|
} else {
|
||||||
|
expires = "";
|
||||||
|
}
|
||||||
|
document.cookie = name+"="+value+expires+"; path=/";
|
||||||
|
}
|
||||||
|
|
||||||
|
function readCookie(name) {
|
||||||
|
var nameEQ = name + "=",
|
||||||
|
ca = document.cookie.split(';'),
|
||||||
|
i, c;
|
||||||
|
|
||||||
|
for (i=0; i < ca.length; i++) {
|
||||||
|
c = ca[i];
|
||||||
|
while (c.charAt(0)==' ') {
|
||||||
|
c = c.substring(1,c.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c.indexOf(nameEQ) == 0) {
|
||||||
|
return c.substring(nameEQ.length,c.length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setData(data) {
|
||||||
|
data = JSON.stringify(data);
|
||||||
|
if (type == 'session') {
|
||||||
|
window.top.name = data;
|
||||||
|
} else {
|
||||||
|
createCookie('localStorage', data, 365);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearData() {
|
||||||
|
if (type == 'session') {
|
||||||
|
window.top.name = '';
|
||||||
|
} else {
|
||||||
|
createCookie('localStorage', '', 365);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getData() {
|
||||||
|
var data = type == 'session' ? window.top.name : readCookie('localStorage');
|
||||||
|
return data ? JSON.parse(data) : {};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// initialise if there's already data
|
||||||
|
var data = getData();
|
||||||
|
|
||||||
|
return {
|
||||||
|
clear: function () {
|
||||||
|
data = {};
|
||||||
|
clearData();
|
||||||
|
},
|
||||||
|
getItem: function (key) {
|
||||||
|
return data[key] || null;
|
||||||
|
},
|
||||||
|
key: function (i) {
|
||||||
|
// not perfect, but works
|
||||||
|
var ctr = 0;
|
||||||
|
for (var k in data) {
|
||||||
|
if (ctr == i) return k;
|
||||||
|
else ctr++;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
removeItem: function (key) {
|
||||||
|
delete data[key];
|
||||||
|
setData(data);
|
||||||
|
},
|
||||||
|
setItem: function (key, value) {
|
||||||
|
data[key] = value+''; // forces the value to a string
|
||||||
|
setData(data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!window.localStorage) window.localStorage = new Storage('local');
|
||||||
|
if (!window.sessionStorage) window.sessionStorage = new Storage('session');
|
||||||
|
|
||||||
|
}());
|
||||||
51
public/js/store.js
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
;(function() {
|
||||||
|
var global = this
|
||||||
|
if (typeof localStorage !== 'undefined') {
|
||||||
|
global.createObjectStore = function(namespace) {
|
||||||
|
function makeKey(k) {
|
||||||
|
return '--' + namespace + '-' + (k || '')
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
clear: function() {
|
||||||
|
var i = localStorage.length
|
||||||
|
, k
|
||||||
|
, prefix = new RegExp('^' + makeKey())
|
||||||
|
while (--i) {
|
||||||
|
k = localStorage.key(i)
|
||||||
|
if (k.match(prefix)) {
|
||||||
|
localStorage.remove(k)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
get: function(key) {
|
||||||
|
var val = localStorage[makeKey(key)]
|
||||||
|
try {
|
||||||
|
while (typeof val === 'string') val = JSON.parse(val)
|
||||||
|
} catch (e) {
|
||||||
|
//console.log('string?')
|
||||||
|
}
|
||||||
|
return val
|
||||||
|
},
|
||||||
|
set: function(key, val) {
|
||||||
|
localStorage[makeKey(key)] = typeof val === 'string' ? val : JSON.stringify(val)
|
||||||
|
},
|
||||||
|
remove: function(key) {
|
||||||
|
delete localStorage[makeKey(key)]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
global.ObjectStore = createObjectStore('default')
|
||||||
|
} else {
|
||||||
|
// Create an in-memory store, should probably fall back to cookies
|
||||||
|
global.createObjectStore = function() {
|
||||||
|
var store = {}
|
||||||
|
return {
|
||||||
|
clear: function() { store = {} },
|
||||||
|
get: function(key) { return store[key] },
|
||||||
|
set: function(key, val) { store[key] = val },
|
||||||
|
remove: function(key) { delete store[key] }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
global.ObjectStore = createObjectStore()
|
||||||
|
}
|
||||||
|
}());
|
||||||