2019-10-01 11:35:00 +00:00
( function ( ) { function r ( e , n , t ) { function o ( i , f ) { if ( ! n [ i ] ) { if ( ! e [ i ] ) { var c = "function" == typeof require && require ; if ( ! f && c ) return c ( i , ! 0 ) ; if ( u ) return u ( i , ! 0 ) ; var a = new Error ( "Cannot find module '" + i + "'" ) ; throw a . code = "MODULE_NOT_FOUND" , a } var p = n [ i ] = { exports : { } } ; e [ i ] [ 0 ] . call ( p . exports , function ( r ) { var n = e [ i ] [ 1 ] [ r ] ; return o ( n || r ) } , p , p . exports , r , e , n , t ) } return n [ i ] . exports } for ( var u = "function" == typeof require && require , i = 0 ; i < t . length ; i ++ ) o ( t [ i ] ) ; return o } return r } ) ( ) ( { 1 : [ function ( require , module , exports ) {
const EditPage = require ( './admin/editpage' )
const AdminPages = require ( './admin/pages' )
const AdminArticles = require ( './admin/articles' )
const EditArticle = require ( './admin/editarticle' )
const AdminStaffList = require ( './admin/stafflist' )
const EditStaff = require ( './admin/editstaff' )
window . addAdminRoutes = [
[ '/admin/pages' , AdminPages ] ,
[ '/admin/pages/:key' , EditPage ] ,
[ '/admin/articles' , AdminArticles ] ,
[ '/admin/articles/:id' , EditArticle ] ,
[ '/admin/staff' , AdminStaffList ] ,
[ '/admin/staff/:id' , EditStaff ] ,
]
} , { "./admin/articles" : 2 , "./admin/editarticle" : 3 , "./admin/editpage" : 4 , "./admin/editstaff" : 5 , "./admin/pages" : 7 , "./admin/stafflist" : 8 } ] , 2 : [ function ( require , module , exports ) {
const Article = require ( '../api/article' )
const pagination = require ( '../api/pagination' )
const Dialogue = require ( '../widgets/dialogue' )
const Pages = require ( '../widgets/pages' )
const AdminArticles = {
oninit : function ( vnode ) {
this . error = ''
this . lastpage = m . route . param ( 'page' ) || '1'
this . articles = [ ]
this . removeArticle = null
this . fetchArticles ( vnode )
} ,
onupdate : function ( vnode ) {
if ( m . route . param ( 'page' ) && m . route . param ( 'page' ) !== this . lastpage ) {
this . fetchArticles ( vnode )
}
} ,
fetchArticles : function ( vnode ) {
this . loading = true
this . links = null
this . lastpage = m . route . param ( 'page' ) || '1'
return pagination . fetchPage ( Article . getAllArticlesPagination ( {
per _page : 10 ,
page : this . lastpage ,
includes : [ 'parent' ] ,
} ) )
. then ( function ( result ) {
vnode . state . articles = result . data
vnode . state . links = result . links
} )
. catch ( function ( err ) {
vnode . state . error = err . message
} )
. then ( function ( ) {
vnode . state . loading = false
m . redraw ( )
} )
} ,
confirmRemoveArticle : function ( vnode ) {
let removingArticle = this . removeArticle
this . removeArticle = null
this . loading = true
Article . removeArticle ( removingArticle , removingArticle . id )
. then ( this . oninit . bind ( this , vnode ) )
. catch ( function ( err ) {
vnode . state . error = err . message
vnode . state . loading = false
m . redraw ( )
} )
} ,
drawArticle : function ( vnode , article ) {
let parent
if ( article . parent ) {
parent = {
path : '/page/' + article . parent . path ,
name : article . parent . name ,
}
} else {
parent = {
path : '/' ,
name : '-- Frontpage --' ,
}
}
return [
m ( 'tr' , [
m ( 'td' , m ( m . route . Link , { href : '/admin/articles/' + article . id } , article . name ) ) ,
m ( 'td' , m ( m . route . Link , { href : parent . path } , parent . name ) ) ,
m ( 'td' , m ( m . route . Link , { href : '/article/' + article . path } , '/article/' + article . path ) ) ,
m ( 'td.right' , article . updated _at . replace ( 'T' , ' ' ) . split ( '.' ) [ 0 ] ) ,
m ( 'td.right' , m ( 'button' , { onclick : function ( ) { vnode . state . removeArticle = article } } , 'Remove' ) ) ,
] ) ,
]
} ,
view : function ( vnode ) {
return [
m ( 'div.admin-wrapper' , [
m ( 'div.admin-actions' , [
m ( 'span' , 'Actions:' ) ,
m ( m . route . Link , { href : '/admin/articles/add' } , 'Create new article' ) ,
] ) ,
m ( 'article.editarticle' , [
m ( 'header' , m ( 'h1' , 'All articles' ) ) ,
m ( 'div.error' , {
hidden : ! this . error ,
onclick : function ( ) { vnode . state . error = '' } ,
} , this . error ) ,
( this . loading
? m ( 'div.loading-spinner.full' )
: m ( 'table' , [
m ( 'thead' ,
m ( 'tr' , [
m ( 'th' , 'Title' ) ,
m ( 'th' , 'Page' ) ,
m ( 'th' , 'Path' ) ,
m ( 'th.right' , 'Updated' ) ,
m ( 'th.right' , 'Actions' ) ,
] )
) ,
m ( 'tbody' , this . articles . map ( AdminArticles . drawArticle . bind ( this , vnode ) ) ) ,
] )
) ,
m ( Pages , {
base : '/admin/articles' ,
links : this . links ,
} ) ,
] ) ,
] ) ,
m ( Dialogue , {
hidden : vnode . state . removeArticle === null ,
title : 'Delete ' + ( vnode . state . removeArticle ? vnode . state . removeArticle . name : '' ) ,
message : 'Are you sure you want to remove "' + ( vnode . state . removeArticle ? vnode . state . removeArticle . name : '' ) + '" (' + ( vnode . state . removeArticle ? vnode . state . removeArticle . path : '' ) + ')' ,
yes : 'Remove' ,
yesclass : 'alert' ,
no : 'Cancel' ,
noclass : 'cancel' ,
onyes : this . confirmRemoveArticle . bind ( this , vnode ) ,
onno : function ( ) { vnode . state . removeArticle = null } ,
} ) ,
]
} ,
}
module . exports = AdminArticles
} , { "../api/article" : 9 , "../api/pagination" : 14 , "../widgets/dialogue" : 17 , "../widgets/pages" : 20 } ] , 3 : [ function ( require , module , exports ) {
const Authentication = require ( '../authentication' )
const FileUpload = require ( '../widgets/fileupload' )
const Froala = require ( './froala' )
const Page = require ( '../api/page' )
const File = require ( '../api/file' )
const Fileinfo = require ( '../widgets/fileinfo' )
const Article = require ( '../api/article' )
const EditArticle = {
getFroalaOptions : function ( ) {
return {
theme : 'gray' ,
heightMin : 150 ,
videoUpload : false ,
imageUploadURL : '/api/media' ,
imageManagerLoadURL : '/api/media' ,
imageManagerDeleteMethod : 'DELETE' ,
imageManagerDeleteURL : '/api/media' ,
events : {
'imageManager.beforeDeleteImage' : function ( img ) {
this . opts . imageManagerDeleteURL = '/api/media/' + img . data ( 'id' )
} ,
} ,
requestHeaders : {
'Authorization' : 'Bearer ' + Authentication . getToken ( ) ,
} ,
}
} ,
oninit : function ( vnode ) {
this . froala = null
this . loadedFroala = Froala . loadedFroala
if ( ! this . loadedFroala ) {
Froala . createFroalaScript ( )
. then ( function ( ) {
vnode . state . loadedFroala = true
m . redraw ( )
} )
}
this . fetchArticle ( vnode )
} ,
onupdate : function ( vnode ) {
if ( this . lastid !== m . route . param ( 'id' ) ) {
this . fetchArticle ( vnode )
}
} ,
fetchArticle : function ( vnode ) {
this . lastid = m . route . param ( 'id' )
this . loading = this . lastid !== 'add'
this . creating = this . lastid === 'add'
this . loadingFile = false
this . error = ''
this . article = {
name : '' ,
path : '' ,
description : '' ,
media : null ,
banner : null ,
files : [ ] ,
}
this . editedPath = false
this . froala = null
this . loadedFroala = Froala . loadedFroala
if ( this . lastid !== 'add' ) {
Article . getArticle ( this . lastid )
. then ( function ( result ) {
vnode . state . editedPath = true
vnode . state . article = result
} )
. catch ( function ( err ) {
vnode . state . error = err . message
} )
. then ( function ( ) {
vnode . state . loading = false
m . redraw ( )
} )
}
} ,
updateValue : function ( name , e ) {
this . article [ name ] = e . currentTarget . value
if ( name === 'path' ) {
this . editedPath = true
} else if ( name === 'name' && ! this . editedPath ) {
this . article . path = this . article . name . toLowerCase ( ) . replace ( / /g , '-' )
}
} ,
updateParent : function ( e ) {
this . article . parent _id = Number ( e . currentTarget . value )
if ( this . article . parent _id === - 1 ) {
this . article . parent _id = null
}
} ,
mediaUploaded : function ( type , media ) {
this . article [ type ] = media
} ,
mediaRemoved : function ( type ) {
this . article [ type ] = null
} ,
save : function ( vnode , e ) {
e . preventDefault ( )
if ( ! this . article . name ) {
this . error = 'Name is missing'
} else if ( ! this . article . path ) {
this . error = 'Path is missing'
} else {
this . error = ''
}
if ( this . error ) return
this . article . description = vnode . state . froala && vnode . state . froala . html . get ( ) || this . article . description
if ( this . article . description ) {
this . article . description = this . article . description . replace ( /<p[^>]+data-f-id="pbf"[^>]+>[^>]+>[^>]+>[^>]+>/ , '' )
}
this . loading = true
let promise
if ( this . article . id ) {
promise = Article . updateArticle ( this . article . id , {
name : this . article . name ,
path : this . article . path ,
parent _id : this . article . parent _id ,
description : this . article . description ,
banner _id : this . article . banner && this . article . banner . id ,
media _id : this . article . media && this . article . media . id ,
} )
} else {
promise = Article . createArticle ( {
name : this . article . name ,
path : this . article . path ,
parent _id : this . article . parent _id ,
description : this . article . description ,
banner _id : this . article . banner && this . article . banner . id ,
media _id : this . article . media && this . article . media . id ,
} )
}
promise . then ( function ( res ) {
if ( vnode . state . article . id ) {
res . media = vnode . state . article . media
res . banner = vnode . state . article . banner
res . files = vnode . state . article . files
vnode . state . article = res
} else {
m . route . set ( '/admin/articles/' + res . id )
}
} )
. catch ( function ( err ) {
vnode . state . error = err . message
} )
. then ( function ( ) {
vnode . state . loading = false
m . redraw ( )
} )
} ,
uploadFile : function ( vnode , event ) {
if ( ! event . target . files [ 0 ] ) return
vnode . state . error = ''
vnode . state . loadingFile = true
File . uploadFile ( this . article . id , event . target . files [ 0 ] )
. then ( function ( res ) {
vnode . state . article . files . push ( res )
} )
. catch ( function ( err ) {
vnode . state . error = err . message
} )
. then ( function ( ) {
event . target . value = null
vnode . state . loadingFile = false
m . redraw ( )
} )
} ,
getFlatTree : function ( ) {
let out = [ { id : null , name : '-- Frontpage --' } ]
Page . Tree . forEach ( function ( page ) {
out . push ( { id : page . id , name : page . name } )
if ( page . children . length ) {
page . children . forEach ( function ( sub ) {
out . push ( { id : sub . id , name : page . name + ' -> ' + sub . name } )
} )
}
} )
return out
} ,
view : function ( vnode ) {
const parents = this . getFlatTree ( )
return (
this . loading ?
m ( 'div.loading-spinner' )
: m ( 'div.admin-wrapper' , [
m ( 'div.admin-actions' , this . article . id
? [
m ( 'span' , 'Actions:' ) ,
m ( m . route . Link , { href : '/article/' + this . article . path } , 'View article' ) ,
]
: null ) ,
m ( 'article.editarticle' , [
m ( 'header' , m ( 'h1' , this . creating ? 'Create Article' : 'Edit ' + ( this . article . name || '(untitled)' ) ) ) ,
m ( 'div.error' , {
hidden : ! this . error ,
onclick : function ( ) { vnode . state . error = '' } ,
} , this . error ) ,
m ( FileUpload , {
onupload : this . mediaUploaded . bind ( this , 'banner' ) ,
onerror : function ( e ) { vnode . state . error = e } ,
ondelete : this . mediaRemoved . bind ( this , 'banner' ) ,
media : this . article && this . article . banner ,
} ) ,
m ( FileUpload , {
class : 'cover' ,
useimg : true ,
onupload : this . mediaUploaded . bind ( this , 'media' ) ,
ondelete : this . mediaRemoved . bind ( this , 'media' ) ,
onerror : function ( e ) { vnode . state . error = e } ,
media : this . article && this . article . media ,
} ) ,
m ( 'form.editarticle.content' , {
onsubmit : this . save . bind ( this , vnode ) ,
} , [
m ( 'label' , 'Parent' ) ,
m ( 'select' , {
onchange : this . updateParent . bind ( this ) ,
} , parents . map ( function ( item ) { return m ( 'option' , { value : item . id || - 1 , selected : item . id === vnode . state . article . parent _id } , item . name ) } ) ) ,
m ( 'label' , 'Name' ) ,
m ( 'input' , {
type : 'text' ,
value : this . article . name ,
oninput : this . updateValue . bind ( this , 'name' ) ,
} ) ,
m ( 'label' , 'Description' ) ,
(
this . loadedFroala ?
m ( 'div' , {
oncreate : function ( div ) {
vnode . state . froala = new FroalaEditor ( div . dom , EditArticle . getFroalaOptions ( ) , function ( ) {
vnode . state . froala . html . set ( vnode . state . article . description )
} )
} ,
} )
: null
) ,
m ( 'label' , 'Path' ) ,
m ( 'input' , {
type : 'text' ,
value : this . article . path ,
oninput : this . updateValue . bind ( this , 'path' ) ,
} ) ,
m ( 'div.loading-spinner' , { hidden : this . loadedFroala } ) ,
m ( 'input' , {
type : 'submit' ,
value : 'Save' ,
} ) ,
] ) ,
this . article . files . length
? m ( 'files' , [
m ( 'h4' , 'Files' ) ,
this . article . files . map ( function ( item ) { return m ( Fileinfo , { file : item } ) } ) ,
] )
: null ,
this . article . id
? m ( 'div.fileupload' , [
'Add file' ,
m ( 'input' , {
accept : '*' ,
type : 'file' ,
onchange : this . uploadFile . bind ( this , vnode ) ,
} ) ,
( vnode . state . loadingFile ? m ( 'div.loading-spinner' ) : null ) ,
] )
: null ,
] ) ,
] )
)
} ,
}
module . exports = EditArticle
} , { "../api/article" : 9 , "../api/file" : 11 , "../api/page" : 13 , "../authentication" : 16 , "../widgets/fileinfo" : 18 , "../widgets/fileupload" : 19 , "./froala" : 6 } ] , 4 : [ function ( require , module , exports ) {
const Authentication = require ( '../authentication' )
const FileUpload = require ( '../widgets/fileupload' )
const Froala = require ( './froala' )
const Page = require ( '../api/page' )
const EditPage = {
getFroalaOptions : function ( ) {
return {
theme : 'gray' ,
heightMin : 150 ,
videoUpload : false ,
imageUploadURL : '/api/media' ,
imageManagerLoadURL : '/api/media' ,
imageManagerDeleteMethod : 'DELETE' ,
imageManagerDeleteURL : '/api/media' ,
events : {
'imageManager.beforeDeleteImage' : function ( img ) {
this . opts . imageManagerDeleteURL = '/api/media/' + img . data ( 'id' )
} ,
} ,
requestHeaders : {
'Authorization' : 'Bearer ' + Authentication . getToken ( ) ,
} ,
}
} ,
oninit : function ( vnode ) {
this . loading = m . route . param ( 'key' ) !== 'add'
this . creating = m . route . param ( 'key' ) === 'add'
this . error = ''
this . page = {
name : '' ,
path : '' ,
description : '' ,
media : null ,
}
this . editedPath = false
this . froala = null
this . loadedFroala = Froala . loadedFroala
if ( m . route . param ( 'key' ) !== 'add' ) {
Page . getPage ( m . route . param ( 'key' ) )
. then ( function ( result ) {
vnode . state . editedPath = true
vnode . state . page = result
} )
. catch ( function ( err ) {
vnode . state . error = err . message
} )
. then ( function ( ) {
vnode . state . loading = false
m . redraw ( )
} )
}
if ( ! this . loadedFroala ) {
Froala . createFroalaScript ( )
. then ( function ( ) {
vnode . state . loadedFroala = true
m . redraw ( )
} )
}
} ,
updateValue : function ( name , e ) {
this . page [ name ] = e . currentTarget . value
if ( name === 'path' ) {
this . editedPath = true
} else if ( name === 'name' && ! this . editedPath ) {
this . page . path = this . page . name . toLowerCase ( ) . replace ( / /g , '-' )
}
} ,
updateParent : function ( e ) {
this . page . parent _id = Number ( e . currentTarget . value )
if ( this . page . parent _id === - 1 ) {
this . page . parent _id = null
}
} ,
fileUploaded : function ( type , media ) {
this . page [ type ] = media
} ,
fileRemoved : function ( type ) {
this . page [ type ] = null
} ,
save : function ( vnode , e ) {
e . preventDefault ( )
if ( ! this . page . name ) {
this . error = 'Name is missing'
} else if ( ! this . page . path ) {
this . error = 'Path is missing'
}
if ( this . error ) return
this . page . description = vnode . state . froala ? vnode . state . froala . html . get ( ) : this . page . description
if ( this . page . description ) {
this . page . description = this . page . description . replace ( /<p[^>]+data-f-id="pbf"[^>]+>[^>]+>[^>]+>[^>]+>/ , '' )
}
this . loading = true
let promise
if ( this . page . id ) {
promise = Page . updatePage ( this . page . id , {
name : this . page . name ,
path : this . page . path ,
parent _id : this . page . parent _id ,
description : this . page . description ,
banner _id : this . page . banner && this . page . banner . id || null ,
media _id : this . page . media && this . page . media . id || null ,
} )
} else {
promise = Page . createPage ( {
name : this . page . name ,
path : this . page . path ,
parent _id : this . page . parent _id ,
description : this . page . description ,
banner _id : this . page . banner && this . page . banner . id || null ,
media _id : this . page . media && this . page . media . id || null ,
} )
}
promise . then ( function ( res ) {
if ( vnode . state . page . id ) {
res . media = vnode . state . page . media
res . banner = vnode . state . page . banner
vnode . state . page = res
} else {
m . route . set ( '/admin/pages/' + res . id )
}
} )
. catch ( function ( err ) {
vnode . state . error = err . message
} )
. then ( function ( ) {
vnode . state . loading = false
m . redraw ( )
} )
return false
} ,
view : function ( vnode ) {
const parents = [ { id : null , name : '-- Frontpage --' } ] . concat ( Page . Tree ) . filter ( function ( page ) { return ! vnode . state . page || page . id !== vnode . state . page . id } )
return (
this . loading ?
m ( 'div.loading-spinner' )
: m ( 'div.admin-wrapper' , [
m ( 'div.admin-actions' , this . page . id
? [
m ( 'span' , 'Actions:' ) ,
m ( m . route . Link , { href : '/page/' + this . page . path } , 'View page' ) ,
m ( m . route . Link , { href : '/admin/pages/add' } , 'Create new page' ) ,
]
: null ) ,
m ( 'article.editpage' , [
m ( 'header' , m ( 'h1' , this . creating ? 'Create Page' : 'Edit ' + ( this . page . name || '(untitled)' ) ) ) ,
m ( 'div.error' , {
hidden : ! this . error ,
onclick : function ( ) { vnode . state . error = '' } ,
} , this . error ) ,
m ( FileUpload , {
onupload : this . fileUploaded . bind ( this , 'banner' ) ,
ondelete : this . fileRemoved . bind ( this , 'banner' ) ,
onerror : function ( e ) { vnode . state . error = e } ,
media : this . page && this . page . banner ,
} ) ,
m ( FileUpload , {
class : 'cover' ,
useimg : true ,
onupload : this . fileUploaded . bind ( this , 'media' ) ,
ondelete : this . fileRemoved . bind ( this , 'media' ) ,
onerror : function ( e ) { vnode . state . error = e } ,
media : this . page && this . page . media ,
} ) ,
m ( 'form.editpage.content' , {
onsubmit : this . save . bind ( this , vnode ) ,
} , [
m ( 'label' , 'Parent' ) ,
m ( 'select' , {
onchange : this . updateParent . bind ( this ) ,
} , parents . map ( function ( item ) {
return m ( 'option' , { value : item . id || - 1 , selected : item . id === vnode . state . page . parent _id } , item . name )
} ) ) ,
m ( 'label' , 'Name' ) ,
m ( 'input' , {
type : 'text' ,
value : this . page . name ,
oninput : this . updateValue . bind ( this , 'name' ) ,
} ) ,
m ( 'label' , 'Description' ) ,
(
this . loadedFroala ?
m ( 'div' , {
oncreate : function ( div ) {
vnode . state . froala = new FroalaEditor ( div . dom , EditPage . getFroalaOptions ( ) , function ( ) {
vnode . state . froala . html . set ( vnode . state . page . description )
} )
} ,
} )
: null
) ,
m ( 'label' , 'Path' ) ,
m ( 'input' , {
type : 'text' ,
value : this . page . path ,
oninput : this . updateValue . bind ( this , 'path' ) ,
} ) ,
m ( 'div.loading-spinner' , { hidden : this . loadedFroala } ) ,
m ( 'input' , {
type : 'submit' ,
value : 'Save' ,
} ) ,
] ) ,
] ) ,
] )
)
} ,
}
module . exports = EditPage
} , { "../api/page" : 13 , "../authentication" : 16 , "../widgets/fileupload" : 19 , "./froala" : 6 } ] , 5 : [ function ( require , module , exports ) {
const Staff = require ( '../api/staff' )
const EditStaff = {
oninit : function ( vnode ) {
this . fetchStaff ( vnode )
} ,
onupdate : function ( vnode ) {
if ( this . lastid !== m . route . param ( 'id' ) ) {
this . fetchStaff ( vnode )
}
} ,
fetchStaff : function ( vnode ) {
this . lastid = m . route . param ( 'id' )
this . loading = this . lastid !== 'add'
this . creating = this . lastid === 'add'
this . error = ''
this . staff = {
fullname : '' ,
email : '' ,
password : '' ,
level : 10 ,
}
if ( this . lastid !== 'add' ) {
Staff . getStaff ( this . lastid )
. then ( function ( result ) {
vnode . state . editedPath = true
vnode . state . staff = result
} )
. catch ( function ( err ) {
vnode . state . error = err . message
} )
. then ( function ( ) {
vnode . state . loading = false
m . redraw ( )
} )
}
} ,
updateValue : function ( fullname , e ) {
this . staff [ fullname ] = e . currentTarget . value
} ,
save : function ( vnode , e ) {
e . preventDefault ( )
if ( ! this . staff . fullname ) {
this . error = 'Fullname is missing'
} else if ( ! this . staff . email ) {
this . error = 'Email is missing'
} else {
this . error = ''
}
if ( this . error ) return
this . staff . description = vnode . state . froala && vnode . state . froala . html . get ( ) || this . staff . description
this . loading = true
let promise
if ( this . staff . id ) {
promise = Staff . updateStaff ( this . staff . id , {
fullname : this . staff . fullname ,
email : this . staff . email ,
level : this . staff . level ,
password : this . staff . password ,
} )
} else {
promise = Staff . createStaff ( {
fullname : this . staff . fullname ,
email : this . staff . email ,
level : this . staff . level ,
password : this . staff . password ,
} )
}
promise . then ( function ( res ) {
m . route . set ( '/admin/staff' )
} )
. catch ( function ( err ) {
vnode . state . error = err . message
} )
. then ( function ( ) {
vnode . state . loading = false
m . redraw ( )
} )
} ,
updateLevel : function ( e ) {
this . staff . level = Number ( e . currentTarget . value )
} ,
view : function ( vnode ) {
const levels = [ [ 10 , 'Manager' ] , [ 100 , 'Admin' ] ]
return (
this . loading ?
m ( 'div.loading-spinner' )
: m ( 'div.admin-wrapper' , [
m ( 'div.admin-actions' , this . staff . id
? [
m ( 'span' , 'Actions:' ) ,
m ( m . route . Link , { href : '/admin/staff' } , 'Staff list' ) ,
]
: null ) ,
m ( 'article.editstaff' , [
m ( 'header' , m ( 'h1' , this . creating ? 'Create Staff' : 'Edit ' + ( this . staff . fullname || '(untitled)' ) ) ) ,
m ( 'div.error' , {
hidden : ! this . error ,
onclick : function ( ) { vnode . state . error = '' } ,
} , this . error ) ,
m ( 'form.editstaff.content' , {
onsubmit : this . save . bind ( this , vnode ) ,
} , [
m ( 'label' , 'Level' ) ,
m ( 'select' , {
onchange : this . updateLevel . bind ( this ) ,
} , levels . map ( function ( level ) { return m ( 'option' , { value : level [ 0 ] , selected : level [ 0 ] === vnode . state . staff . level } , level [ 1 ] ) } ) ) ,
m ( 'label' , 'Fullname' ) ,
m ( 'input' , {
type : 'text' ,
value : this . staff . fullname ,
oninput : this . updateValue . bind ( this , 'fullname' ) ,
} ) ,
m ( 'label' , 'Email' ) ,
m ( 'input' , {
type : 'text' ,
value : this . staff . email ,
oninput : this . updateValue . bind ( this , 'email' ) ,
} ) ,
m ( 'label' , 'Password (optional)' ) ,
m ( 'input' , {
type : 'text' ,
value : this . staff . password ,
oninput : this . updateValue . bind ( this , 'password' ) ,
} ) ,
m ( 'input' , {
type : 'submit' ,
value : 'Save' ,
} ) ,
] ) ,
] ) ,
] )
)
} ,
}
module . exports = EditStaff
} , { "../api/staff" : 15 } ] , 6 : [ function ( require , module , exports ) {
const Froala = {
files : [
{ type : 'css' , url : 'https://cdn.jsdelivr.net/npm/froala-editor@3.0.4/css/froala_editor.pkgd.min.css' } ,
{ type : 'css' , url : 'https://cdn.jsdelivr.net/npm/froala-editor@3.0.4/css/themes/gray.min.css' } ,
{ type : 'js' , url : 'https://cdn.jsdelivr.net/npm/froala-editor@3.0.4/js/froala_editor.pkgd.min.js' } ,
] ,
loadedFiles : 0 ,
loadedFroala : false ,
checkLoadedAll : function ( res ) {
if ( Froala . loadedFiles < Froala . files . length ) {
return
}
Froala . loadedFroala = true
res ( )
} ,
createFroalaScript : function ( ) {
if ( Froala . loadedFroala ) return Promise . resolve ( )
return new Promise ( function ( res ) {
let onload = function ( ) {
Froala . loadedFiles ++
Froala . checkLoadedAll ( res )
}
let head = document . getElementsByTagName ( 'head' ) [ 0 ]
for ( var i = 0 ; i < Froala . files . length ; i ++ ) {
let element
if ( Froala . files [ i ] . type === 'css' ) {
element = document . createElement ( 'link' )
element . setAttribute ( 'rel' , 'stylesheet' )
element . setAttribute ( 'type' , 'text/css' )
element . setAttribute ( 'href' , Froala . files [ i ] . url )
} else {
element = document . createElement ( 'script' )
element . setAttribute ( 'type' , 'text/javascript' )
element . setAttribute ( 'src' , Froala . files [ i ] . url )
}
element . onload = onload
head . insertBefore ( element , head . firstChild )
}
} )
} ,
}
module . exports = Froala
} , { } ] , 7 : [ function ( require , module , exports ) {
const Page = require ( '../api/page' )
const Dialogue = require ( '../widgets/dialogue' )
const AdminPages = {
parseTree : function ( pages ) {
let map = new Map ( )
for ( let i = 0 ; i < pages . length ; i ++ ) {
pages [ i ] . children = [ ]
map . set ( pages [ i ] . id , pages [ i ] )
}
for ( let i = 0 ; i < pages . length ; i ++ ) {
if ( pages [ i ] . parent _id && map . has ( pages [ i ] . parent _id ) ) {
map . get ( pages [ i ] . parent _id ) . children . push ( pages [ i ] )
pages . splice ( i , 1 )
i --
}
}
return pages
} ,
oninit : function ( vnode ) {
this . loading = true
this . error = ''
this . pages = [ ]
this . removePage = null
Page . getAllPages ( )
. then ( function ( result ) {
vnode . state . pages = AdminPages . parseTree ( result )
} )
. catch ( function ( err ) {
vnode . state . error = err . message
} )
. then ( function ( ) {
vnode . state . loading = false
m . redraw ( )
} )
} ,
confirmRemovePage : function ( vnode ) {
let removingPage = this . removePage
this . removePage = null
this . loading = true
Page . removePage ( removingPage , removingPage . id )
. then ( this . oninit . bind ( this , vnode ) )
. catch ( function ( err ) {
vnode . state . error = err . message
vnode . state . loading = false
m . redraw ( )
} )
} ,
drawPage : function ( vnode , page ) {
return [
m ( 'tr' , [
m ( 'td' , [
page . parent _id ? m ( 'span.subpage' , '| >' ) : null ,
m ( m . route . Link , { href : '/admin/pages/' + page . id } , page . name ) ,
] ) ,
m ( 'td' , m ( m . route . Link , { href : '/page/' + page . path } , '/page/' + page . path ) ) ,
m ( 'td.right' , page . updated _at . replace ( 'T' , ' ' ) . split ( '.' ) [ 0 ] ) ,
m ( 'td.right' , m ( 'button' , { onclick : function ( ) { vnode . state . removePage = page } } , 'Remove' ) ) ,
] ) ,
] . concat ( page . children . map ( AdminPages . drawPage . bind ( this , vnode ) ) )
} ,
view : function ( vnode ) {
return [
( this . loading ?
m ( 'div.loading-spinner' )
: m ( 'div.admin-wrapper' , [
m ( 'div.admin-actions' , [
m ( 'span' , 'Actions:' ) ,
m ( m . route . Link , { href : '/admin/pages/add' } , 'Create new page' ) ,
] ) ,
m ( 'article.editpage' , [
m ( 'header' , m ( 'h1' , 'All pages' ) ) ,
m ( 'div.error' , {
hidden : ! this . error ,
onclick : function ( ) { vnode . state . error = '' } ,
} , this . error ) ,
m ( 'table' , [
m ( 'thead' ,
m ( 'tr' , [
m ( 'th' , 'Title' ) ,
m ( 'th' , 'Path' ) ,
m ( 'th.right' , 'Updated' ) ,
m ( 'th.right' , 'Actions' ) ,
] )
) ,
m ( 'tbody' , this . pages . map ( AdminPages . drawPage . bind ( this , vnode ) ) ) ,
] ) ,
] ) ,
] )
) ,
m ( Dialogue , {
hidden : vnode . state . removePage === null ,
title : 'Delete ' + ( vnode . state . removePage ? vnode . state . removePage . name : '' ) ,
message : 'Are you sure you want to remove "' + ( vnode . state . removePage ? vnode . state . removePage . name : '' ) + '" (' + ( vnode . state . removePage ? vnode . state . removePage . path : '' ) + ')' ,
yes : 'Remove' ,
yesclass : 'alert' ,
no : 'Cancel' ,
noclass : 'cancel' ,
onyes : this . confirmRemovePage . bind ( this , vnode ) ,
onno : function ( ) { vnode . state . removePage = null } ,
} ) ,
]
} ,
}
module . exports = AdminPages
} , { "../api/page" : 13 , "../widgets/dialogue" : 17 } ] , 8 : [ function ( require , module , exports ) {
const Staff = require ( '../api/staff' )
const Dialogue = require ( '../widgets/dialogue' )
const Pages = require ( '../widgets/pages' )
const AdminStaffList = {
oninit : function ( vnode ) {
this . error = ''
this . lastpage = m . route . param ( 'page' ) || '1'
this . staff = [ ]
this . removeStaff = null
this . fetchStaffs ( vnode )
} ,
fetchStaffs : function ( vnode ) {
this . loading = true
return Staff . getAllStaff ( )
. then ( function ( result ) {
vnode . state . staff = result
} )
. catch ( function ( err ) {
vnode . state . error = err . message
} )
. then ( function ( ) {
vnode . state . loading = false
m . redraw ( )
} )
} ,
confirmRemoveStaff : function ( vnode ) {
let removingStaff = this . removeStaff
this . removeStaff = null
this . loading = true
Staff . removeStaff ( removingStaff . id )
. then ( this . oninit . bind ( this , vnode ) )
. catch ( function ( err ) {
vnode . state . error = err . message
vnode . state . loading = false
m . redraw ( )
} )
} ,
getLevel : function ( level ) {
if ( level === 100 ) {
return 'Admin'
}
return 'Manager'
} ,
view : function ( vnode ) {
return [
m ( 'div.admin-wrapper' , [
m ( 'div.admin-actions' , [
m ( 'span' , 'Actions:' ) ,
m ( m . route . Link , { href : '/admin/staff/add' } , 'Create new staff' ) ,
] ) ,
m ( 'article.editarticle' , [
m ( 'header' , m ( 'h1' , 'All staff' ) ) ,
m ( 'div.error' , {
hidden : ! this . error ,
onclick : function ( ) { vnode . state . error = '' } ,
} , this . error ) ,
( this . loading
? m ( 'div.loading-spinner.full' )
: m ( 'table' , [
m ( 'thead' ,
m ( 'tr' , [
m ( 'th' , 'Fullname' ) ,
m ( 'th' , 'Email' ) ,
m ( 'th' , 'Level' ) ,
m ( 'th.right' , 'Updated' ) ,
m ( 'th.right' , 'Actions' ) ,
] )
) ,
m ( 'tbody' , this . staff . map ( function ( item ) {
return m ( 'tr' , [
m ( 'td' , m ( m . route . Link , { href : '/admin/staff/' + item . id } , item . fullname ) ) ,
m ( 'td' , item . email ) ,
m ( 'td.right' , AdminStaffList . getLevel ( item . level ) ) ,
m ( 'td.right' , ( item . updated _at || '---' ) . replace ( 'T' , ' ' ) . split ( '.' ) [ 0 ] ) ,
m ( 'td.right' , m ( 'button' , { onclick : function ( ) { vnode . state . removeStaff = item } } , 'Remove' ) ) ,
] )
} ) ) ,
] )
) ,
m ( Pages , {
base : '/admin/staff' ,
links : this . links ,
} ) ,
] ) ,
] ) ,
m ( Dialogue , {
hidden : vnode . state . removeStaff === null ,
title : 'Delete ' + ( vnode . state . removeStaff ? vnode . state . removeStaff . name : '' ) ,
message : 'Are you sure you want to remove "' + ( vnode . state . removeStaff ? vnode . state . removeStaff . fullname : '' ) + '" (' + ( vnode . state . removeStaff ? vnode . state . removeStaff . email : '' ) + ')' ,
yes : 'Remove' ,
yesclass : 'alert' ,
no : 'Cancel' ,
noclass : 'cancel' ,
onyes : this . confirmRemoveStaff . bind ( this , vnode ) ,
onno : function ( ) { vnode . state . removeStaff = null } ,
} ) ,
]
} ,
}
module . exports = AdminStaffList
} , { "../api/staff" : 15 , "../widgets/dialogue" : 17 , "../widgets/pages" : 20 } ] , 9 : [ function ( require , module , exports ) {
const common = require ( './common' )
exports . createArticle = function ( body ) {
return common . sendRequest ( {
method : 'POST' ,
url : '/api/articles' ,
body : body ,
} )
}
exports . updateArticle = function ( id , body ) {
return common . sendRequest ( {
method : 'PUT' ,
url : '/api/articles/' + id ,
body : body ,
} )
}
exports . getAllArticles = function ( ) {
return common . sendRequest ( {
method : 'GET' ,
url : '/api/articles?includes=parent' ,
} )
}
exports . getAllArticlesPagination = function ( options ) {
let extra = ''
if ( options . sort ) {
extra += '&sort=' + options . sort
}
if ( options . per _page ) {
extra += '&perPage=' + options . per _page
}
if ( options . page ) {
extra += '&page=' + options . page
}
if ( options . includes ) {
extra += '&includes=' + options . includes . join ( ',' )
}
return '/api/articles?' + extra
}
exports . getAllPageArticles = function ( pageId , includes ) {
return common . sendRequest ( {
method : 'GET' ,
url : '/api/pages/' + pageId + '/articles?includes=' + includes . join ( ',' ) ,
} )
}
exports . getAllPageArticlesPagination = function ( pageId , options ) {
let extra = ''
if ( options . sort ) {
extra += '&sort=' + options . sort
}
if ( options . per _page ) {
extra += '&perPage=' + options . per _page
}
if ( options . page ) {
extra += '&page=' + options . page
}
if ( options . includes ) {
extra += '&includes=' + options . includes . join ( ',' )
}
return '/api/pages/' + pageId + '/articles?' + extra
}
exports . getArticle = function ( id ) {
return common . sendRequest ( {
method : 'GET' ,
url : '/api/articles/' + id + '?includes=media,parent,banner,files' ,
} )
}
exports . removeArticle = function ( article , id ) {
return common . sendRequest ( {
method : 'DELETE' ,
url : '/api/articles/' + id ,
} )
}
} , { "./common" : 10 } ] , 10 : [ function ( require , module , exports ) {
const Authentication = require ( '../authentication' )
exports . sendRequest = function ( options , isPagination ) {
let token = Authentication . getToken ( )
let pagination = isPagination
if ( token ) {
options . headers = options . headers || { }
options . headers [ 'Authorization' ] = 'Bearer ' + token
}
options . extract = function ( xhr ) {
let out = null
if ( pagination && xhr . status < 300 ) {
let headers = { }
xhr . getAllResponseHeaders ( ) . split ( '\r\n' ) . forEach ( function ( item ) {
var splitted = item . split ( ': ' )
headers [ splitted [ 0 ] ] = splitted [ 1 ]
} )
out = {
headers : headers || { } ,
data : JSON . parse ( xhr . responseText ) ,
}
} else {
if ( xhr . responseText ) {
out = JSON . parse ( xhr . responseText )
} else {
out = { }
}
}
if ( xhr . status >= 300 ) {
throw out
}
return out
}
return m . request ( options )
. catch ( function ( error ) {
if ( error . code === 403 ) {
Authentication . clearToken ( )
m . route . set ( '/login' , { redirect : m . route . get ( ) } )
}
if ( error . response && error . response . status ) {
return Promise . reject ( error . response )
}
return Promise . reject ( error )
} )
}
} , { "../authentication" : 16 } ] , 11 : [ function ( require , module , exports ) {
const common = require ( './common' )
exports . uploadFile = function ( articleId , file ) {
let formData = new FormData ( )
formData . append ( 'file' , file )
return common . sendRequest ( {
method : 'POST' ,
url : '/api/articles/' + articleId + '/file' ,
body : formData ,
} )
}
} , { "./common" : 10 } ] , 12 : [ function ( require , module , exports ) {
const common = require ( './common' )
exports . uploadMedia = function ( file ) {
let formData = new FormData ( )
formData . append ( 'file' , file )
return common . sendRequest ( {
method : 'POST' ,
url : '/api/media' ,
body : formData ,
} )
}
} , { "./common" : 10 } ] , 13 : [ function ( require , module , exports ) {
const common = require ( './common' )
const Tree = window . _ _nfptree || [ ]
exports . Tree = Tree
exports . createPage = function ( body ) {
return common . sendRequest ( {
method : 'POST' ,
url : '/api/pages' ,
body : body ,
} ) . then ( function ( res ) {
res . children = [ ]
if ( ! res . parent _id ) {
Tree . push ( res )
} else {
for ( let i = 0 ; i < Tree . length ; i ++ ) {
if ( Tree [ i ] . id === res . parent _id ) {
Tree [ i ] . children . push ( res )
break
}
}
}
return res
} )
}
exports . getTree = function ( ) {
return common . sendRequest ( {
method : 'GET' ,
url : '/api/pages?tree=true&includes=children&fields=id,name,path,children(id,name,path)' ,
} )
}
exports . updatePage = function ( id , body ) {
return common . sendRequest ( {
method : 'PUT' ,
url : '/api/pages/' + id ,
body : body ,
} ) . then ( function ( res ) {
for ( let i = 0 ; i < Tree . length ; i ++ ) {
if ( Tree [ i ] . id === res . id ) {
res . children = Tree [ i ] . children
Tree [ i ] = res
break
} else if ( Tree [ i ] . id === res . parent _id ) {
for ( let x = 0 ; x < Tree [ i ] . children . length ; x ++ ) {
if ( Tree [ i ] . children [ x ] . id === res . id ) {
res . children = Tree [ i ] . children [ x ] . children
Tree [ i ] . children [ x ] = res
break
}
}
break
}
}
if ( ! res . children ) {
res . children = [ ]
}
return res
} )
}
exports . getAllPages = function ( ) {
return common . sendRequest ( {
method : 'GET' ,
url : '/api/pages' ,
} )
}
exports . getPage = function ( id ) {
return common . sendRequest ( {
method : 'GET' ,
url : '/api/pages/' + id + '?includes=media,banner,children,news,news.media' ,
} )
}
exports . removePage = function ( page , id ) {
return common . sendRequest ( {
method : 'DELETE' ,
url : '/api/pages/' + id ,
} ) . then ( function ( ) {
for ( let i = 0 ; i < Tree . length ; i ++ ) {
if ( Tree [ i ] . id === page . id ) {
Tree . splice ( i , 1 )
break
} else if ( Tree [ i ] . id === page . parent _id ) {
for ( let x = 0 ; x < Tree [ i ] . children . length ; x ++ ) {
if ( Tree [ i ] . children [ x ] . id === page . id ) {
Tree [ i ] . children . splice ( x , 1 )
break
}
}
break
}
}
return null
} )
}
} , { "./common" : 10 } ] , 14 : [ function ( require , module , exports ) {
const parse = require ( 'parse-link-header' )
const common = require ( './common' )
exports . fetchPage = function ( url ) {
return common . sendRequest ( {
method : 'GET' ,
url : url ,
} , true )
. then ( function ( result ) {
return {
data : result . data ,
links : parse ( result . headers . link || '' ) ,
total : Number ( result . headers . pagination _total || '0' ) ,
}
} )
}
} , { "./common" : 10 , "parse-link-header" : 21 } ] , 15 : [ function ( require , module , exports ) {
const common = require ( './common' )
exports . createStaff = function ( body ) {
return common . sendRequest ( {
method : 'POST' ,
url : '/api/staff' ,
body : body ,
} )
}
exports . updateStaff = function ( id , body ) {
return common . sendRequest ( {
method : 'PUT' ,
url : '/api/staff/' + id ,
body : body ,
} )
}
exports . getAllStaff = function ( ) {
return common . sendRequest ( {
method : 'GET' ,
url : '/api/staff' ,
} )
}
exports . getStaff = function ( id ) {
return common . sendRequest ( {
method : 'GET' ,
url : '/api/staff/' + id ,
} )
}
exports . removeStaff = function ( id ) {
return common . sendRequest ( {
method : 'DELETE' ,
url : '/api/staff/' + id ,
} )
}
} , { "./common" : 10 } ] , 16 : [ function ( require , module , exports ) {
const storageName = 'logintoken'
const Authentication = {
currentUser : null ,
isAdmin : false ,
loadedGoogle : false ,
loadingGoogle : false ,
loadingListeners : [ ] ,
authListeners : [ ] ,
updateToken : function ( token ) {
if ( ! token ) return Authentication . clearToken ( )
localStorage . setItem ( storageName , token )
Authentication . currentUser = JSON . parse ( atob ( token . split ( '.' ) [ 1 ] ) )
if ( Authentication . authListeners . length ) {
Authentication . authListeners . forEach ( function ( x ) { x ( Authentication . currentUser ) } )
}
} ,
clearToken : function ( ) {
Authentication . currentUser = null
localStorage . removeItem ( storageName )
Authentication . isAdmin = false
} ,
addEvent : function ( event ) {
Authentication . authListeners . push ( event )
} ,
setAdmin : function ( item ) {
Authentication . isAdmin = item
} ,
createGoogleScript : function ( ) {
if ( Authentication . loadedGoogle ) return Promise . resolve ( )
return new Promise ( function ( res ) {
if ( Authentication . loadedGoogle ) return res ( )
Authentication . loadingListeners . push ( res )
if ( Authentication . loadingGoogle ) return
Authentication . loadingGoogle = true
let gscript = document . createElement ( 'script' )
gscript . type = 'text/javascript'
gscript . async = true
gscript . defer = true
gscript . src = 'https://apis.google.com/js/platform.js?onload=googleLoaded'
document . body . appendChild ( gscript )
} )
} ,
getToken : function ( ) {
return localStorage . getItem ( storageName )
} ,
}
if ( ! window . googleLoaded ) {
window . googleLoaded = function ( ) {
Authentication . loadedGoogle = true
while ( Authentication . loadingListeners . length ) {
Authentication . loadingListeners . pop ( ) ( )
}
}
}
Authentication . updateToken ( localStorage . getItem ( storageName ) )
module . exports = Authentication
} , { } ] , 17 : [ function ( require , module , exports ) {
const Dialogue = {
view : function ( vnode ) {
return m ( 'div.floating-container' , {
hidden : vnode . attrs . hidden ,
} , m ( 'dialogue' , [
m ( 'h2' , vnode . attrs . title ) ,
m ( 'p' , vnode . attrs . message ) ,
m ( 'div.buttons' , [
m ( 'button' , { class : vnode . attrs . yesclass || '' , onclick : vnode . attrs . onyes } , vnode . attrs . yes ) ,
m ( 'button' , { class : vnode . attrs . noclass || '' , onclick : vnode . attrs . onno } , vnode . attrs . no ) ,
] ) ,
] )
)
} ,
}
module . exports = Dialogue
} , { } ] , 18 : [ function ( require , module , exports ) {
const Fileinfo = {
getPrefix : function ( vnode ) {
if ( ! vnode . attrs . file . filename . endsWith ( '.torrent' ) ) {
return vnode . attrs . file . filename . split ( '.' ) . slice ( - 1 )
}
if ( vnode . attrs . file . filename . indexOf ( '720 ' ) >= 0 ) {
return '720p'
}
if ( vnode . attrs . file . filename . indexOf ( '1080 ' ) >= 0 ) {
return '1080p'
}
if ( vnode . attrs . file . filename . indexOf ( '480 ' ) >= 0 ) {
return '480p'
}
return 'Other'
} ,
getTitle : function ( vnode ) {
if ( vnode . attrs . file . meta . torrent ) {
return vnode . attrs . file . meta . torrent . name
}
return vnode . attrs . file . filename
} ,
getDownloadName : function ( vnode ) {
if ( vnode . attrs . file . meta . torrent ) {
return 'Torrent'
}
return 'Download'
} ,
getSize : function ( orgSize ) {
var size = orgSize
var i = - 1
var byteUnits = [ ' kB' , ' MB' , ' GB' , ' TB' , 'PB' , 'EB' , 'ZB' , 'YB' ]
do {
size = size / 1024
i ++
} while ( size > 1024 )
return Math . max ( size , 0.1 ) . toFixed ( 1 ) + byteUnits [ i ]
} ,
view : function ( vnode ) {
return m ( 'fileinfo' , { class : vnode . attrs . slim ? 'slim' : '' } , [
m ( 'div.filetitle' , [
m ( 'span.prefix' , this . getPrefix ( vnode ) + ':' ) ,
m ( 'a' , {
target : '_blank' ,
rel : 'noopener' ,
href : vnode . attrs . file . url ,
} , this . getDownloadName ( vnode ) ) ,
vnode . attrs . file . magnet
? m ( 'a' , {
href : vnode . attrs . file . magnet ,
} , 'Magnet' )
: null ,
m ( 'span' , this . getTitle ( vnode ) ) ,
] ) ,
vnode . attrs . file . meta . torrent && ! vnode . attrs . slim
? m ( 'ul' , vnode . attrs . file . meta . torrent . files . map ( function ( file ) {
return m ( 'li' , [
file . name + ' ' ,
m ( 'span.meta' , '(' + Fileinfo . getSize ( file . size ) + ')' ) ,
] )
} ) )
: null ,
] )
} ,
}
module . exports = Fileinfo
} , { } ] , 19 : [ function ( require , module , exports ) {
const Media = require ( '../api/media' )
const FileUpload = {
uploadFile : function ( vnode , event ) {
if ( ! event . target . files [ 0 ] ) return
vnode . state . updateError ( vnode , '' )
vnode . state . loading = true
Media . uploadMedia ( event . target . files [ 0 ] )
. then ( function ( res ) {
if ( vnode . attrs . onupload ) {
vnode . attrs . onupload ( res )
}
} )
. catch ( function ( err ) {
vnode . state . updateError ( vnode , err . message )
} )
. then ( function ( ) {
event . target . value = null
vnode . state . loading = false
m . redraw ( )
} )
} ,
updateError : function ( vnode , error ) {
if ( vnode . attrs . onerror ) {
vnode . attrs . onerror ( error )
} else {
vnode . state . error = error
}
} ,
oninit : function ( vnode ) {
vnode . state . loading = false
vnode . state . error = ''
} ,
view : function ( vnode ) {
let media = vnode . attrs . media
return m ( 'fileupload' , {
class : vnode . attrs . class || null ,
} , [
m ( 'div.error' , {
hidden : ! vnode . state . error ,
} , vnode . state . error ) ,
( media
? vnode . attrs . useimg
? [ m ( 'img' , { src : media . large _url } ) , m ( 'div.showicon' ) ]
: m ( 'a.display.inside' , {
href : media . large _url ,
style : {
'background-image' : 'url("' + media . large _url + '")' ,
} ,
} , m ( 'div.showicon' ) )
: m ( 'div.inside.showbordericon' )
) ,
m ( 'input' , {
accept : 'image/*' ,
type : 'file' ,
onchange : this . uploadFile . bind ( this , vnode ) ,
} ) ,
( media && vnode . attrs . ondelete ? m ( 'button.remove' , { onclick : vnode . attrs . ondelete } ) : null ) ,
( vnode . state . loading ? m ( 'div.loading-spinner' ) : null ) ,
] )
} ,
}
module . exports = FileUpload
} , { "../api/media" : 12 } ] , 20 : [ function ( require , module , exports ) {
const Pages = {
oninit : function ( vnode ) {
this . onpage = vnode . attrs . onpage || function ( ) { }
} ,
view : function ( vnode ) {
if ( ! vnode . attrs . links ) return null
return m ( 'pages' , [
vnode . attrs . links . first
? m ( m . route . Link , {
href : vnode . attrs . base + '?page=' + vnode . attrs . links . first . page ,
onclick : function ( ) { vnode . state . onpage ( vnode . attrs . links . first . page ) } ,
} , 'First' )
: m ( 'div' ) ,
vnode . attrs . links . previous
? m ( m . route . Link , {
href : vnode . attrs . base + '?page=' + vnode . attrs . links . previous . page ,
onclick : function ( ) { vnode . state . onpage ( vnode . attrs . links . previous . page ) } ,
} , vnode . attrs . links . previous . title )
: m ( 'div' ) ,
m ( 'div' , vnode . attrs . links . current && vnode . attrs . links . current . title || 'Current page' ) ,
vnode . attrs . links . next
? m ( m . route . Link , {
href : vnode . attrs . base + '?page=' + vnode . attrs . links . next . page ,
onclick : function ( ) { vnode . state . onpage ( vnode . attrs . links . next . page ) } ,
} , vnode . attrs . links . next . title )
: m ( 'div' ) ,
vnode . attrs . links . last
? m ( m . route . Link , {
href : vnode . attrs . base + '?page=' + vnode . attrs . links . last . page ,
onclick : function ( ) { vnode . state . onpage ( vnode . attrs . links . last . page ) } ,
} , 'Last' )
: m ( 'div' ) ,
] )
} ,
}
module . exports = Pages
} , { } ] , 21 : [ function ( require , module , exports ) {
'use strict' ;
var qs = require ( 'querystring' )
, url = require ( 'url' )
, xtend = require ( 'xtend' ) ;
function hasRel ( x ) {
return x && x . rel ;
}
function intoRels ( acc , x ) {
function splitRel ( rel ) {
acc [ rel ] = xtend ( x , { rel : rel } ) ;
}
x . rel . split ( /\s+/ ) . forEach ( splitRel ) ;
return acc ;
}
function createObjects ( acc , p ) {
// rel="next" => 1: rel 2: next
var m = p . match ( /\s*(.+)\s*=\s*"?([^"]+)"?/ )
if ( m ) acc [ m [ 1 ] ] = m [ 2 ] ;
return acc ;
}
function parseLink ( link ) {
try {
var m = link . match ( /<?([^>]*)>(.*)/ )
, linkUrl = m [ 1 ]
, parts = m [ 2 ] . split ( ';' )
, parsedUrl = url . parse ( linkUrl )
, qry = qs . parse ( parsedUrl . query ) ;
parts . shift ( ) ;
var info = parts
. reduce ( createObjects , { } ) ;
info = xtend ( qry , info ) ;
info . url = linkUrl ;
return info ;
} catch ( e ) {
return null ;
}
}
module . exports = function ( linkHeader ) {
if ( ! linkHeader ) return null ;
return linkHeader . split ( /,\s*</ )
. map ( parseLink )
. filter ( hasRel )
. reduce ( intoRels , { } ) ;
} ;
} , { "querystring" : 25 , "url" : 26 , "xtend" : 28 } ] , 22 : [ function ( require , module , exports ) {
( function ( global ) {
/*! https://mths.be/punycode v1.4.1 by @mathias */
; ( function ( root ) {
/** Detect free variables */
var freeExports = typeof exports == 'object' && exports &&
! exports . nodeType && exports ;
var freeModule = typeof module == 'object' && module &&
! module . nodeType && module ;
var freeGlobal = typeof global == 'object' && global ;
if (
freeGlobal . global === freeGlobal ||
freeGlobal . window === freeGlobal ||
freeGlobal . self === freeGlobal
) {
root = freeGlobal ;
}
/ * *
* The ` punycode ` object .
* @ name punycode
* @ type Object
* /
var punycode ,
/** Highest positive signed 32-bit float value */
maxInt = 2147483647 , // aka. 0x7FFFFFFF or 2^31-1
/** Bootstring parameters */
base = 36 ,
tMin = 1 ,
tMax = 26 ,
skew = 38 ,
damp = 700 ,
initialBias = 72 ,
initialN = 128 , // 0x80
delimiter = '-' , // '\x2D'
/** Regular expressions */
regexPunycode = /^xn--/ ,
regexNonASCII = /[^\x20-\x7E]/ , // unprintable ASCII chars + non-ASCII chars
regexSeparators = /[\x2E\u3002\uFF0E\uFF61]/g , // RFC 3490 separators
/** Error messages */
errors = {
'overflow' : 'Overflow: input needs wider integers to process' ,
'not-basic' : 'Illegal input >= 0x80 (not a basic code point)' ,
'invalid-input' : 'Invalid input'
} ,
/** Convenience shortcuts */
baseMinusTMin = base - tMin ,
floor = Math . floor ,
stringFromCharCode = String . fromCharCode ,
/** Temporary variable */
key ;
/*--------------------------------------------------------------------------*/
/ * *
* A generic error utility function .
* @ private
* @ param { String } type The error type .
* @ returns { Error } Throws a ` RangeError ` with the applicable error message .
* /
function error ( type ) {
throw new RangeError ( errors [ type ] ) ;
}
/ * *
* A generic ` Array#map ` utility function .
* @ private
* @ param { Array } array The array to iterate over .
* @ param { Function } callback The function that gets called for every array
* item .
* @ returns { Array } A new array of values returned by the callback function .
* /
function map ( array , fn ) {
var length = array . length ;
var result = [ ] ;
while ( length -- ) {
result [ length ] = fn ( array [ length ] ) ;
}
return result ;
}
/ * *
* A simple ` Array#map ` - like wrapper to work with domain name strings or email
* addresses .
* @ private
* @ param { String } domain The domain name or email address .
* @ param { Function } callback The function that gets called for every
* character .
* @ returns { Array } A new string of characters returned by the callback
* function .
* /
function mapDomain ( string , fn ) {
var parts = string . split ( '@' ) ;
var result = '' ;
if ( parts . length > 1 ) {
// In email addresses, only the domain name should be punycoded. Leave
// the local part (i.e. everything up to `@`) intact.
result = parts [ 0 ] + '@' ;
string = parts [ 1 ] ;
}
// Avoid `split(regex)` for IE8 compatibility. See #17.
string = string . replace ( regexSeparators , '\x2E' ) ;
var labels = string . split ( '.' ) ;
var encoded = map ( labels , fn ) . join ( '.' ) ;
return result + encoded ;
}
/ * *
* Creates an array containing the numeric code points of each Unicode
* character in the string . While JavaScript uses UCS - 2 internally ,
* this function will convert a pair of surrogate halves ( each of which
* UCS - 2 exposes as separate characters ) into a single code point ,
* matching UTF - 16.
* @ see ` punycode.ucs2.encode `
* @ see < https : //mathiasbynens.be/notes/javascript-encoding>
* @ memberOf punycode . ucs2
* @ name decode
* @ param { String } string The Unicode input string ( UCS - 2 ) .
* @ returns { Array } The new array of code points .
* /
function ucs2decode ( string ) {
var output = [ ] ,
counter = 0 ,
length = string . length ,
value ,
extra ;
while ( counter < length ) {
value = string . charCodeAt ( counter ++ ) ;
if ( value >= 0xD800 && value <= 0xDBFF && counter < length ) {
// high surrogate, and there is a next character
extra = string . charCodeAt ( counter ++ ) ;
if ( ( extra & 0xFC00 ) == 0xDC00 ) { // low surrogate
output . push ( ( ( value & 0x3FF ) << 10 ) + ( extra & 0x3FF ) + 0x10000 ) ;
} else {
// unmatched surrogate; only append this code unit, in case the next
// code unit is the high surrogate of a surrogate pair
output . push ( value ) ;
counter -- ;
}
} else {
output . push ( value ) ;
}
}
return output ;
}
/ * *
* Creates a string based on an array of numeric code points .
* @ see ` punycode.ucs2.decode `
* @ memberOf punycode . ucs2
* @ name encode
* @ param { Array } codePoints The array of numeric code points .
* @ returns { String } The new Unicode string ( UCS - 2 ) .
* /
function ucs2encode ( array ) {
return map ( array , function ( value ) {
var output = '' ;
if ( value > 0xFFFF ) {
value -= 0x10000 ;
output += stringFromCharCode ( value >>> 10 & 0x3FF | 0xD800 ) ;
value = 0xDC00 | value & 0x3FF ;
}
output += stringFromCharCode ( value ) ;
return output ;
} ) . join ( '' ) ;
}
/ * *
* Converts a basic code point into a digit / integer .
* @ see ` digitToBasic() `
* @ private
* @ param { Number } codePoint The basic numeric code point value .
* @ returns { Number } The numeric value of a basic code point ( for use in
* representing integers ) in the range ` 0 ` to ` base - 1 ` , or ` base ` if
* the code point does not represent a value .
* /
function basicToDigit ( codePoint ) {
if ( codePoint - 48 < 10 ) {
return codePoint - 22 ;
}
if ( codePoint - 65 < 26 ) {
return codePoint - 65 ;
}
if ( codePoint - 97 < 26 ) {
return codePoint - 97 ;
}
return base ;
}
/ * *
* Converts a digit / integer into a basic code point .
* @ see ` basicToDigit() `
* @ private
* @ param { Number } digit The numeric value of a basic code point .
* @ returns { Number } The basic code point whose value ( when used for
* representing integers ) is ` digit ` , which needs to be in the range
* ` 0 ` to ` base - 1 ` . If ` flag ` is non - zero , the uppercase form is
* used ; else , the lowercase form is used . The behavior is undefined
* if ` flag ` is non - zero and ` digit ` has no uppercase form .
* /
function digitToBasic ( digit , flag ) {
// 0..25 map to ASCII a..z or A..Z
// 26..35 map to ASCII 0..9
return digit + 22 + 75 * ( digit < 26 ) - ( ( flag != 0 ) << 5 ) ;
}
/ * *
* Bias adaptation function as per section 3.4 of RFC 3492.
* https : //tools.ietf.org/html/rfc3492#section-3.4
* @ private
* /
function adapt ( delta , numPoints , firstTime ) {
var k = 0 ;
delta = firstTime ? floor ( delta / damp ) : delta >> 1 ;
delta += floor ( delta / numPoints ) ;
for ( /* no initialization */ ; delta > baseMinusTMin * tMax >> 1 ; k += base ) {
delta = floor ( delta / baseMinusTMin ) ;
}
return floor ( k + ( baseMinusTMin + 1 ) * delta / ( delta + skew ) ) ;
}
/ * *
* Converts a Punycode string of ASCII - only symbols to a string of Unicode
* symbols .
* @ memberOf punycode
* @ param { String } input The Punycode string of ASCII - only symbols .
* @ returns { String } The resulting string of Unicode symbols .
* /
function decode ( input ) {
// Don't use UCS-2
var output = [ ] ,
inputLength = input . length ,
out ,
i = 0 ,
n = initialN ,
bias = initialBias ,
basic ,
j ,
index ,
oldi ,
w ,
k ,
digit ,
t ,
/** Cached calculation results */
baseMinusT ;
// Handle the basic code points: let `basic` be the number of input code
// points before the last delimiter, or `0` if there is none, then copy
// the first basic code points to the output.
basic = input . lastIndexOf ( delimiter ) ;
if ( basic < 0 ) {
basic = 0 ;
}
for ( j = 0 ; j < basic ; ++ j ) {
// if it's not a basic code point
if ( input . charCodeAt ( j ) >= 0x80 ) {
error ( 'not-basic' ) ;
}
output . push ( input . charCodeAt ( j ) ) ;
}
// Main decoding loop: start just after the last delimiter if any basic code
// points were copied; start at the beginning otherwise.
for ( index = basic > 0 ? basic + 1 : 0 ; index < inputLength ; /* no final expression */ ) {
// `index` is the index of the next character to be consumed.
// Decode a generalized variable-length integer into `delta`,
// which gets added to `i`. The overflow checking is easier
// if we increase `i` as we go, then subtract off its starting
// value at the end to obtain `delta`.
for ( oldi = i , w = 1 , k = base ; /* no condition */ ; k += base ) {
if ( index >= inputLength ) {
error ( 'invalid-input' ) ;
}
digit = basicToDigit ( input . charCodeAt ( index ++ ) ) ;
if ( digit >= base || digit > floor ( ( maxInt - i ) / w ) ) {
error ( 'overflow' ) ;
}
i += digit * w ;
t = k <= bias ? tMin : ( k >= bias + tMax ? tMax : k - bias ) ;
if ( digit < t ) {
break ;
}
baseMinusT = base - t ;
if ( w > floor ( maxInt / baseMinusT ) ) {
error ( 'overflow' ) ;
}
w *= baseMinusT ;
}
out = output . length + 1 ;
bias = adapt ( i - oldi , out , oldi == 0 ) ;
// `i` was supposed to wrap around from `out` to `0`,
// incrementing `n` each time, so we'll fix that now:
if ( floor ( i / out ) > maxInt - n ) {
error ( 'overflow' ) ;
}
n += floor ( i / out ) ;
i %= out ;
// Insert `n` at position `i` of the output
output . splice ( i ++ , 0 , n ) ;
}
return ucs2encode ( output ) ;
}
/ * *
* Converts a string of Unicode symbols ( e . g . a domain name label ) to a
* Punycode string of ASCII - only symbols .
* @ memberOf punycode
* @ param { String } input The string of Unicode symbols .
* @ returns { String } The resulting Punycode string of ASCII - only symbols .
* /
function encode ( input ) {
var n ,
delta ,
handledCPCount ,
basicLength ,
bias ,
j ,
m ,
q ,
k ,
t ,
currentValue ,
output = [ ] ,
/** `inputLength` will hold the number of code points in `input`. */
inputLength ,
/** Cached calculation results */
handledCPCountPlusOne ,
baseMinusT ,
qMinusT ;
// Convert the input in UCS-2 to Unicode
input = ucs2decode ( input ) ;
// Cache the length
inputLength = input . length ;
// Initialize the state
n = initialN ;
delta = 0 ;
bias = initialBias ;
// Handle the basic code points
for ( j = 0 ; j < inputLength ; ++ j ) {
currentValue = input [ j ] ;
if ( currentValue < 0x80 ) {
output . push ( stringFromCharCode ( currentValue ) ) ;
}
}
handledCPCount = basicLength = output . length ;
// `handledCPCount` is the number of code points that have been handled;
// `basicLength` is the number of basic code points.
// Finish the basic string - if it is not empty - with a delimiter
if ( basicLength ) {
output . push ( delimiter ) ;
}
// Main encoding loop:
while ( handledCPCount < inputLength ) {
// All non-basic code points < n have been handled already. Find the next
// larger one:
for ( m = maxInt , j = 0 ; j < inputLength ; ++ j ) {
currentValue = input [ j ] ;
if ( currentValue >= n && currentValue < m ) {
m = currentValue ;
}
}
// Increase `delta` enough to advance the decoder's <n,i> state to <m,0>,
// but guard against overflow
handledCPCountPlusOne = handledCPCount + 1 ;
if ( m - n > floor ( ( maxInt - delta ) / handledCPCountPlusOne ) ) {
error ( 'overflow' ) ;
}
delta += ( m - n ) * handledCPCountPlusOne ;
n = m ;
for ( j = 0 ; j < inputLength ; ++ j ) {
currentValue = input [ j ] ;
if ( currentValue < n && ++ delta > maxInt ) {
error ( 'overflow' ) ;
}
if ( currentValue == n ) {
// Represent delta as a generalized variable-length integer
for ( q = delta , k = base ; /* no condition */ ; k += base ) {
t = k <= bias ? tMin : ( k >= bias + tMax ? tMax : k - bias ) ;
if ( q < t ) {
break ;
}
qMinusT = q - t ;
baseMinusT = base - t ;
output . push (
stringFromCharCode ( digitToBasic ( t + qMinusT % baseMinusT , 0 ) )
) ;
q = floor ( qMinusT / baseMinusT ) ;
}
output . push ( stringFromCharCode ( digitToBasic ( q , 0 ) ) ) ;
bias = adapt ( delta , handledCPCountPlusOne , handledCPCount == basicLength ) ;
delta = 0 ;
++ handledCPCount ;
}
}
++ delta ;
++ n ;
}
return output . join ( '' ) ;
}
/ * *
* Converts a Punycode string representing a domain name or an email address
* to Unicode . Only the Punycoded parts of the input will be converted , i . e .
* it doesn ' t matter if you call it on a string that has already been
* converted to Unicode .
* @ memberOf punycode
* @ param { String } input The Punycoded domain name or email address to
* convert to Unicode .
* @ returns { String } The Unicode representation of the given Punycode
* string .
* /
function toUnicode ( input ) {
return mapDomain ( input , function ( string ) {
return regexPunycode . test ( string )
? decode ( string . slice ( 4 ) . toLowerCase ( ) )
: string ;
} ) ;
}
/ * *
* Converts a Unicode string representing a domain name or an email address to
* Punycode . Only the non - ASCII parts of the domain name will be converted ,
* i . e . it doesn 't matter if you call it with a domain that' s already in
* ASCII .
* @ memberOf punycode
* @ param { String } input The domain name or email address to convert , as a
* Unicode string .
* @ returns { String } The Punycode representation of the given domain name or
* email address .
* /
function toASCII ( input ) {
return mapDomain ( input , function ( string ) {
return regexNonASCII . test ( string )
? 'xn--' + encode ( string )
: string ;
} ) ;
}
/*--------------------------------------------------------------------------*/
/** Define the public API */
punycode = {
/ * *
* A string representing the current Punycode . js version number .
* @ memberOf punycode
* @ type String
* /
'version' : '1.4.1' ,
/ * *
* An object of methods to convert from JavaScript ' s internal character
* representation ( UCS - 2 ) to Unicode code points , and back .
* @ see < https : //mathiasbynens.be/notes/javascript-encoding>
* @ memberOf punycode
* @ type Object
* /
'ucs2' : {
'decode' : ucs2decode ,
'encode' : ucs2encode
} ,
'decode' : decode ,
'encode' : encode ,
'toASCII' : toASCII ,
'toUnicode' : toUnicode
} ;
/** Expose `punycode` */
// Some AMD build optimizers, like r.js, check for specific condition patterns
// like the following:
if (
typeof define == 'function' &&
typeof define . amd == 'object' &&
define . amd
) {
define ( 'punycode' , function ( ) {
return punycode ;
} ) ;
} else if ( freeExports && freeModule ) {
if ( module . exports == freeExports ) {
// in Node.js, io.js, or RingoJS v0.8.0+
freeModule . exports = punycode ;
} else {
// in Narwhal or RingoJS v0.7.0-
for ( key in punycode ) {
punycode . hasOwnProperty ( key ) && ( freeExports [ key ] = punycode [ key ] ) ;
}
}
} else {
// in Rhino or a web browser
root . punycode = punycode ;
}
} ( this ) ) ;
} ) . call ( this , typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : { } )
} , { } ] , 23 : [ function ( require , module , exports ) {
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
'use strict' ;
// If obj.hasOwnProperty has been overridden, then calling
// obj.hasOwnProperty(prop) will break.
// See: https://github.com/joyent/node/issues/1707
function hasOwnProperty ( obj , prop ) {
return Object . prototype . hasOwnProperty . call ( obj , prop ) ;
}
module . exports = function ( qs , sep , eq , options ) {
sep = sep || '&' ;
eq = eq || '=' ;
var obj = { } ;
if ( typeof qs !== 'string' || qs . length === 0 ) {
return obj ;
}
var regexp = /\+/g ;
qs = qs . split ( sep ) ;
var maxKeys = 1000 ;
if ( options && typeof options . maxKeys === 'number' ) {
maxKeys = options . maxKeys ;
}
var len = qs . length ;
// maxKeys <= 0 means that we should not limit keys count
if ( maxKeys > 0 && len > maxKeys ) {
len = maxKeys ;
}
for ( var i = 0 ; i < len ; ++ i ) {
var x = qs [ i ] . replace ( regexp , '%20' ) ,
idx = x . indexOf ( eq ) ,
kstr , vstr , k , v ;
if ( idx >= 0 ) {
kstr = x . substr ( 0 , idx ) ;
vstr = x . substr ( idx + 1 ) ;
} else {
kstr = x ;
vstr = '' ;
}
k = decodeURIComponent ( kstr ) ;
v = decodeURIComponent ( vstr ) ;
if ( ! hasOwnProperty ( obj , k ) ) {
obj [ k ] = v ;
} else if ( isArray ( obj [ k ] ) ) {
obj [ k ] . push ( v ) ;
} else {
obj [ k ] = [ obj [ k ] , v ] ;
}
}
return obj ;
} ;
var isArray = Array . isArray || function ( xs ) {
return Object . prototype . toString . call ( xs ) === '[object Array]' ;
} ;
} , { } ] , 24 : [ function ( require , module , exports ) {
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
'use strict' ;
var stringifyPrimitive = function ( v ) {
switch ( typeof v ) {
case 'string' :
return v ;
case 'boolean' :
return v ? 'true' : 'false' ;
case 'number' :
return isFinite ( v ) ? v : '' ;
default :
return '' ;
}
} ;
module . exports = function ( obj , sep , eq , name ) {
sep = sep || '&' ;
eq = eq || '=' ;
if ( obj === null ) {
obj = undefined ;
}
if ( typeof obj === 'object' ) {
return map ( objectKeys ( obj ) , function ( k ) {
var ks = encodeURIComponent ( stringifyPrimitive ( k ) ) + eq ;
if ( isArray ( obj [ k ] ) ) {
return map ( obj [ k ] , function ( v ) {
return ks + encodeURIComponent ( stringifyPrimitive ( v ) ) ;
} ) . join ( sep ) ;
} else {
return ks + encodeURIComponent ( stringifyPrimitive ( obj [ k ] ) ) ;
}
} ) . join ( sep ) ;
}
if ( ! name ) return '' ;
return encodeURIComponent ( stringifyPrimitive ( name ) ) + eq +
encodeURIComponent ( stringifyPrimitive ( obj ) ) ;
} ;
var isArray = Array . isArray || function ( xs ) {
return Object . prototype . toString . call ( xs ) === '[object Array]' ;
} ;
function map ( xs , f ) {
if ( xs . map ) return xs . map ( f ) ;
var res = [ ] ;
for ( var i = 0 ; i < xs . length ; i ++ ) {
res . push ( f ( xs [ i ] , i ) ) ;
}
return res ;
}
var objectKeys = Object . keys || function ( obj ) {
var res = [ ] ;
for ( var key in obj ) {
if ( Object . prototype . hasOwnProperty . call ( obj , key ) ) res . push ( key ) ;
}
return res ;
} ;
} , { } ] , 25 : [ function ( require , module , exports ) {
'use strict' ;
exports . decode = exports . parse = require ( './decode' ) ;
exports . encode = exports . stringify = require ( './encode' ) ;
} , { "./decode" : 23 , "./encode" : 24 } ] , 26 : [ function ( require , module , exports ) {
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
'use strict' ;
var punycode = require ( 'punycode' ) ;
var util = require ( './util' ) ;
exports . parse = urlParse ;
exports . resolve = urlResolve ;
exports . resolveObject = urlResolveObject ;
exports . format = urlFormat ;
exports . Url = Url ;
function Url ( ) {
this . protocol = null ;
this . slashes = null ;
this . auth = null ;
this . host = null ;
this . port = null ;
this . hostname = null ;
this . hash = null ;
this . search = null ;
this . query = null ;
this . pathname = null ;
this . path = null ;
this . href = null ;
}
// Reference: RFC 3986, RFC 1808, RFC 2396
// define these here so at least they only have to be
// compiled once on the first module load.
var protocolPattern = /^([a-z0-9.+-]+:)/i ,
portPattern = /:[0-9]*$/ ,
// Special case for a simple path URL
simplePathPattern = /^(\/\/?(?!\/)[^\?\s]*)(\?[^\s]*)?$/ ,
// RFC 2396: characters reserved for delimiting URLs.
// We actually just auto-escape these.
delims = [ '<' , '>' , '"' , '`' , ' ' , '\r' , '\n' , '\t' ] ,
// RFC 2396: characters not allowed for various reasons.
unwise = [ '{' , '}' , '|' , '\\' , '^' , '`' ] . concat ( delims ) ,
// Allowed by RFCs, but cause of XSS attacks. Always escape these.
autoEscape = [ '\'' ] . concat ( unwise ) ,
// Characters that are never ever allowed in a hostname.
// Note that any invalid chars are also handled, but these
// are the ones that are *expected* to be seen, so we fast-path
// them.
nonHostChars = [ '%' , '/' , '?' , ';' , '#' ] . concat ( autoEscape ) ,
hostEndingChars = [ '/' , '?' , '#' ] ,
hostnameMaxLen = 255 ,
hostnamePartPattern = /^[+a-z0-9A-Z_-]{0,63}$/ ,
hostnamePartStart = /^([+a-z0-9A-Z_-]{0,63})(.*)$/ ,
// protocols that can allow "unsafe" and "unwise" chars.
unsafeProtocol = {
'javascript' : true ,
'javascript:' : true
} ,
// protocols that never have a hostname.
hostlessProtocol = {
'javascript' : true ,
'javascript:' : true
} ,
// protocols that always contain a // bit.
slashedProtocol = {
'http' : true ,
'https' : true ,
'ftp' : true ,
'gopher' : true ,
'file' : true ,
'http:' : true ,
'https:' : true ,
'ftp:' : true ,
'gopher:' : true ,
'file:' : true
} ,
querystring = require ( 'querystring' ) ;
function urlParse ( url , parseQueryString , slashesDenoteHost ) {
if ( url && util . isObject ( url ) && url instanceof Url ) return url ;
var u = new Url ;
u . parse ( url , parseQueryString , slashesDenoteHost ) ;
return u ;
}
Url . prototype . parse = function ( url , parseQueryString , slashesDenoteHost ) {
if ( ! util . isString ( url ) ) {
throw new TypeError ( "Parameter 'url' must be a string, not " + typeof url ) ;
}
// Copy chrome, IE, opera backslash-handling behavior.
// Back slashes before the query string get converted to forward slashes
// See: https://code.google.com/p/chromium/issues/detail?id=25916
var queryIndex = url . indexOf ( '?' ) ,
splitter =
( queryIndex !== - 1 && queryIndex < url . indexOf ( '#' ) ) ? '?' : '#' ,
uSplit = url . split ( splitter ) ,
slashRegex = /\\/g ;
uSplit [ 0 ] = uSplit [ 0 ] . replace ( slashRegex , '/' ) ;
url = uSplit . join ( splitter ) ;
var rest = url ;
// trim before proceeding.
// This is to support parse stuff like " http://foo.com \n"
rest = rest . trim ( ) ;
if ( ! slashesDenoteHost && url . split ( '#' ) . length === 1 ) {
// Try fast path regexp
var simplePath = simplePathPattern . exec ( rest ) ;
if ( simplePath ) {
this . path = rest ;
this . href = rest ;
this . pathname = simplePath [ 1 ] ;
if ( simplePath [ 2 ] ) {
this . search = simplePath [ 2 ] ;
if ( parseQueryString ) {
this . query = querystring . parse ( this . search . substr ( 1 ) ) ;
} else {
this . query = this . search . substr ( 1 ) ;
}
} else if ( parseQueryString ) {
this . search = '' ;
this . query = { } ;
}
return this ;
}
}
var proto = protocolPattern . exec ( rest ) ;
if ( proto ) {
proto = proto [ 0 ] ;
var lowerProto = proto . toLowerCase ( ) ;
this . protocol = lowerProto ;
rest = rest . substr ( proto . length ) ;
}
// figure out if it's got a host
// user@server is *always* interpreted as a hostname, and url
// resolution will treat //foo/bar as host=foo,path=bar because that's
// how the browser resolves relative URLs.
if ( slashesDenoteHost || proto || rest . match ( /^\/\/[^@\/]+@[^@\/]+/ ) ) {
var slashes = rest . substr ( 0 , 2 ) === '//' ;
if ( slashes && ! ( proto && hostlessProtocol [ proto ] ) ) {
rest = rest . substr ( 2 ) ;
this . slashes = true ;
}
}
if ( ! hostlessProtocol [ proto ] &&
( slashes || ( proto && ! slashedProtocol [ proto ] ) ) ) {
// there's a hostname.
// the first instance of /, ?, ;, or # ends the host.
//
// If there is an @ in the hostname, then non-host chars *are* allowed
// to the left of the last @ sign, unless some host-ending character
// comes *before* the @-sign.
// URLs are obnoxious.
//
// ex:
// http://a@b@c/ => user:a@b host:c
// http://a@b?@c => user:a host:c path:/?@c
// v0.12 TODO(isaacs): This is not quite how Chrome does things.
// Review our test case against browsers more comprehensively.
// find the first instance of any hostEndingChars
var hostEnd = - 1 ;
for ( var i = 0 ; i < hostEndingChars . length ; i ++ ) {
var hec = rest . indexOf ( hostEndingChars [ i ] ) ;
if ( hec !== - 1 && ( hostEnd === - 1 || hec < hostEnd ) )
hostEnd = hec ;
}
// at this point, either we have an explicit point where the
// auth portion cannot go past, or the last @ char is the decider.
var auth , atSign ;
if ( hostEnd === - 1 ) {
// atSign can be anywhere.
atSign = rest . lastIndexOf ( '@' ) ;
} else {
// atSign must be in auth portion.
// http://a@b/c@d => host:b auth:a path:/c@d
atSign = rest . lastIndexOf ( '@' , hostEnd ) ;
}
// Now we have a portion which is definitely the auth.
// Pull that off.
if ( atSign !== - 1 ) {
auth = rest . slice ( 0 , atSign ) ;
rest = rest . slice ( atSign + 1 ) ;
this . auth = decodeURIComponent ( auth ) ;
}
// the host is the remaining to the left of the first non-host char
hostEnd = - 1 ;
for ( var i = 0 ; i < nonHostChars . length ; i ++ ) {
var hec = rest . indexOf ( nonHostChars [ i ] ) ;
if ( hec !== - 1 && ( hostEnd === - 1 || hec < hostEnd ) )
hostEnd = hec ;
}
// if we still have not hit it, then the entire thing is a host.
if ( hostEnd === - 1 )
hostEnd = rest . length ;
this . host = rest . slice ( 0 , hostEnd ) ;
rest = rest . slice ( hostEnd ) ;
// pull out port.
this . parseHost ( ) ;
// we've indicated that there is a hostname,
// so even if it's empty, it has to be present.
this . hostname = this . hostname || '' ;
// if hostname begins with [ and ends with ]
// assume that it's an IPv6 address.
var ipv6Hostname = this . hostname [ 0 ] === '[' &&
this . hostname [ this . hostname . length - 1 ] === ']' ;
// validate a little.
if ( ! ipv6Hostname ) {
var hostparts = this . hostname . split ( /\./ ) ;
for ( var i = 0 , l = hostparts . length ; i < l ; i ++ ) {
var part = hostparts [ i ] ;
if ( ! part ) continue ;
if ( ! part . match ( hostnamePartPattern ) ) {
var newpart = '' ;
for ( var j = 0 , k = part . length ; j < k ; j ++ ) {
if ( part . charCodeAt ( j ) > 127 ) {
// we replace non-ASCII char with a temporary placeholder
// we need this to make sure size of hostname is not
// broken by replacing non-ASCII by nothing
newpart += 'x' ;
} else {
newpart += part [ j ] ;
}
}
// we test again with ASCII char only
if ( ! newpart . match ( hostnamePartPattern ) ) {
var validParts = hostparts . slice ( 0 , i ) ;
var notHost = hostparts . slice ( i + 1 ) ;
var bit = part . match ( hostnamePartStart ) ;
if ( bit ) {
validParts . push ( bit [ 1 ] ) ;
notHost . unshift ( bit [ 2 ] ) ;
}
if ( notHost . length ) {
rest = '/' + notHost . join ( '.' ) + rest ;
}
this . hostname = validParts . join ( '.' ) ;
break ;
}
}
}
}
if ( this . hostname . length > hostnameMaxLen ) {
this . hostname = '' ;
} else {
// hostnames are always lower case.
this . hostname = this . hostname . toLowerCase ( ) ;
}
if ( ! ipv6Hostname ) {
// IDNA Support: Returns a punycoded representation of "domain".
// It only converts parts of the domain name that
// have non-ASCII characters, i.e. it doesn't matter if
// you call it with a domain that already is ASCII-only.
this . hostname = punycode . toASCII ( this . hostname ) ;
}
var p = this . port ? ':' + this . port : '' ;
var h = this . hostname || '' ;
this . host = h + p ;
this . href += this . host ;
// strip [ and ] from the hostname
// the host field still retains them, though
if ( ipv6Hostname ) {
this . hostname = this . hostname . substr ( 1 , this . hostname . length - 2 ) ;
if ( rest [ 0 ] !== '/' ) {
rest = '/' + rest ;
}
}
}
// now rest is set to the post-host stuff.
// chop off any delim chars.
if ( ! unsafeProtocol [ lowerProto ] ) {
// First, make 100% sure that any "autoEscape" chars get
// escaped, even if encodeURIComponent doesn't think they
// need to be.
for ( var i = 0 , l = autoEscape . length ; i < l ; i ++ ) {
var ae = autoEscape [ i ] ;
if ( rest . indexOf ( ae ) === - 1 )
continue ;
var esc = encodeURIComponent ( ae ) ;
if ( esc === ae ) {
esc = escape ( ae ) ;
}
rest = rest . split ( ae ) . join ( esc ) ;
}
}
// chop off from the tail first.
var hash = rest . indexOf ( '#' ) ;
if ( hash !== - 1 ) {
// got a fragment string.
this . hash = rest . substr ( hash ) ;
rest = rest . slice ( 0 , hash ) ;
}
var qm = rest . indexOf ( '?' ) ;
if ( qm !== - 1 ) {
this . search = rest . substr ( qm ) ;
this . query = rest . substr ( qm + 1 ) ;
if ( parseQueryString ) {
this . query = querystring . parse ( this . query ) ;
}
rest = rest . slice ( 0 , qm ) ;
} else if ( parseQueryString ) {
// no query string, but parseQueryString still requested
this . search = '' ;
this . query = { } ;
}
if ( rest ) this . pathname = rest ;
if ( slashedProtocol [ lowerProto ] &&
this . hostname && ! this . pathname ) {
this . pathname = '/' ;
}
//to support http.request
if ( this . pathname || this . search ) {
var p = this . pathname || '' ;
var s = this . search || '' ;
this . path = p + s ;
}
// finally, reconstruct the href based on what has been validated.
this . href = this . format ( ) ;
return this ;
} ;
// format a parsed object into a url string
function urlFormat ( obj ) {
// ensure it's an object, and not a string url.
// If it's an obj, this is a no-op.
// this way, you can call url_format() on strings
// to clean up potentially wonky urls.
if ( util . isString ( obj ) ) obj = urlParse ( obj ) ;
if ( ! ( obj instanceof Url ) ) return Url . prototype . format . call ( obj ) ;
return obj . format ( ) ;
}
Url . prototype . format = function ( ) {
var auth = this . auth || '' ;
if ( auth ) {
auth = encodeURIComponent ( auth ) ;
auth = auth . replace ( /%3A/i , ':' ) ;
auth += '@' ;
}
var protocol = this . protocol || '' ,
pathname = this . pathname || '' ,
hash = this . hash || '' ,
host = false ,
query = '' ;
if ( this . host ) {
host = auth + this . host ;
} else if ( this . hostname ) {
host = auth + ( this . hostname . indexOf ( ':' ) === - 1 ?
this . hostname :
'[' + this . hostname + ']' ) ;
if ( this . port ) {
host += ':' + this . port ;
}
}
if ( this . query &&
util . isObject ( this . query ) &&
Object . keys ( this . query ) . length ) {
query = querystring . stringify ( this . query ) ;
}
var search = this . search || ( query && ( '?' + query ) ) || '' ;
if ( protocol && protocol . substr ( - 1 ) !== ':' ) protocol += ':' ;
// only the slashedProtocols get the //. Not mailto:, xmpp:, etc.
// unless they had them to begin with.
if ( this . slashes ||
( ! protocol || slashedProtocol [ protocol ] ) && host !== false ) {
host = '//' + ( host || '' ) ;
if ( pathname && pathname . charAt ( 0 ) !== '/' ) pathname = '/' + pathname ;
} else if ( ! host ) {
host = '' ;
}
if ( hash && hash . charAt ( 0 ) !== '#' ) hash = '#' + hash ;
if ( search && search . charAt ( 0 ) !== '?' ) search = '?' + search ;
pathname = pathname . replace ( /[?#]/g , function ( match ) {
return encodeURIComponent ( match ) ;
} ) ;
search = search . replace ( '#' , '%23' ) ;
return protocol + host + pathname + search + hash ;
} ;
function urlResolve ( source , relative ) {
return urlParse ( source , false , true ) . resolve ( relative ) ;
}
Url . prototype . resolve = function ( relative ) {
return this . resolveObject ( urlParse ( relative , false , true ) ) . format ( ) ;
} ;
function urlResolveObject ( source , relative ) {
if ( ! source ) return relative ;
return urlParse ( source , false , true ) . resolveObject ( relative ) ;
}
Url . prototype . resolveObject = function ( relative ) {
if ( util . isString ( relative ) ) {
var rel = new Url ( ) ;
rel . parse ( relative , false , true ) ;
relative = rel ;
}
var result = new Url ( ) ;
var tkeys = Object . keys ( this ) ;
for ( var tk = 0 ; tk < tkeys . length ; tk ++ ) {
var tkey = tkeys [ tk ] ;
result [ tkey ] = this [ tkey ] ;
}
// hash is always overridden, no matter what.
// even href="" will remove it.
result . hash = relative . hash ;
// if the relative url is empty, then there's nothing left to do here.
if ( relative . href === '' ) {
result . href = result . format ( ) ;
return result ;
}
// hrefs like //foo/bar always cut to the protocol.
if ( relative . slashes && ! relative . protocol ) {
// take everything except the protocol from relative
var rkeys = Object . keys ( relative ) ;
for ( var rk = 0 ; rk < rkeys . length ; rk ++ ) {
var rkey = rkeys [ rk ] ;
if ( rkey !== 'protocol' )
result [ rkey ] = relative [ rkey ] ;
}
//urlParse appends trailing / to urls like http://www.example.com
if ( slashedProtocol [ result . protocol ] &&
result . hostname && ! result . pathname ) {
result . path = result . pathname = '/' ;
}
result . href = result . format ( ) ;
return result ;
}
if ( relative . protocol && relative . protocol !== result . protocol ) {
// if it's a known url protocol, then changing
// the protocol does weird things
// first, if it's not file:, then we MUST have a host,
// and if there was a path
// to begin with, then we MUST have a path.
// if it is file:, then the host is dropped,
// because that's known to be hostless.
// anything else is assumed to be absolute.
if ( ! slashedProtocol [ relative . protocol ] ) {
var keys = Object . keys ( relative ) ;
for ( var v = 0 ; v < keys . length ; v ++ ) {
var k = keys [ v ] ;
result [ k ] = relative [ k ] ;
}
result . href = result . format ( ) ;
return result ;
}
result . protocol = relative . protocol ;
if ( ! relative . host && ! hostlessProtocol [ relative . protocol ] ) {
var relPath = ( relative . pathname || '' ) . split ( '/' ) ;
while ( relPath . length && ! ( relative . host = relPath . shift ( ) ) ) ;
if ( ! relative . host ) relative . host = '' ;
if ( ! relative . hostname ) relative . hostname = '' ;
if ( relPath [ 0 ] !== '' ) relPath . unshift ( '' ) ;
if ( relPath . length < 2 ) relPath . unshift ( '' ) ;
result . pathname = relPath . join ( '/' ) ;
} else {
result . pathname = relative . pathname ;
}
result . search = relative . search ;
result . query = relative . query ;
result . host = relative . host || '' ;
result . auth = relative . auth ;
result . hostname = relative . hostname || relative . host ;
result . port = relative . port ;
// to support http.request
if ( result . pathname || result . search ) {
var p = result . pathname || '' ;
var s = result . search || '' ;
result . path = p + s ;
}
result . slashes = result . slashes || relative . slashes ;
result . href = result . format ( ) ;
return result ;
}
var isSourceAbs = ( result . pathname && result . pathname . charAt ( 0 ) === '/' ) ,
isRelAbs = (
relative . host ||
relative . pathname && relative . pathname . charAt ( 0 ) === '/'
) ,
mustEndAbs = ( isRelAbs || isSourceAbs ||
( result . host && relative . pathname ) ) ,
removeAllDots = mustEndAbs ,
srcPath = result . pathname && result . pathname . split ( '/' ) || [ ] ,
relPath = relative . pathname && relative . pathname . split ( '/' ) || [ ] ,
psychotic = result . protocol && ! slashedProtocol [ result . protocol ] ;
// if the url is a non-slashed url, then relative
// links like ../.. should be able
// to crawl up to the hostname, as well. This is strange.
// result.protocol has already been set by now.
// Later on, put the first path part into the host field.
if ( psychotic ) {
result . hostname = '' ;
result . port = null ;
if ( result . host ) {
if ( srcPath [ 0 ] === '' ) srcPath [ 0 ] = result . host ;
else srcPath . unshift ( result . host ) ;
}
result . host = '' ;
if ( relative . protocol ) {
relative . hostname = null ;
relative . port = null ;
if ( relative . host ) {
if ( relPath [ 0 ] === '' ) relPath [ 0 ] = relative . host ;
else relPath . unshift ( relative . host ) ;
}
relative . host = null ;
}
mustEndAbs = mustEndAbs && ( relPath [ 0 ] === '' || srcPath [ 0 ] === '' ) ;
}
if ( isRelAbs ) {
// it's absolute.
result . host = ( relative . host || relative . host === '' ) ?
relative . host : result . host ;
result . hostname = ( relative . hostname || relative . hostname === '' ) ?
relative . hostname : result . hostname ;
result . search = relative . search ;
result . query = relative . query ;
srcPath = relPath ;
// fall through to the dot-handling below.
} else if ( relPath . length ) {
// it's relative
// throw away the existing file, and take the new path instead.
if ( ! srcPath ) srcPath = [ ] ;
srcPath . pop ( ) ;
srcPath = srcPath . concat ( relPath ) ;
result . search = relative . search ;
result . query = relative . query ;
} else if ( ! util . isNullOrUndefined ( relative . search ) ) {
// just pull out the search.
// like href='?foo'.
// Put this after the other two cases because it simplifies the booleans
if ( psychotic ) {
result . hostname = result . host = srcPath . shift ( ) ;
//occationaly the auth can get stuck only in host
//this especially happens in cases like
//url.resolveObject('mailto:local1@domain1', 'local2@domain2')
var authInHost = result . host && result . host . indexOf ( '@' ) > 0 ?
result . host . split ( '@' ) : false ;
if ( authInHost ) {
result . auth = authInHost . shift ( ) ;
result . host = result . hostname = authInHost . shift ( ) ;
}
}
result . search = relative . search ;
result . query = relative . query ;
//to support http.request
if ( ! util . isNull ( result . pathname ) || ! util . isNull ( result . search ) ) {
result . path = ( result . pathname ? result . pathname : '' ) +
( result . search ? result . search : '' ) ;
}
result . href = result . format ( ) ;
return result ;
}
if ( ! srcPath . length ) {
// no path at all. easy.
// we've already handled the other stuff above.
result . pathname = null ;
//to support http.request
if ( result . search ) {
result . path = '/' + result . search ;
} else {
result . path = null ;
}
result . href = result . format ( ) ;
return result ;
}
// if a url ENDs in . or .., then it must get a trailing slash.
// however, if it ends in anything else non-slashy,
// then it must NOT get a trailing slash.
var last = srcPath . slice ( - 1 ) [ 0 ] ;
var hasTrailingSlash = (
( result . host || relative . host || srcPath . length > 1 ) &&
( last === '.' || last === '..' ) || last === '' ) ;
// strip single dots, resolve double dots to parent dir
// if the path tries to go above the root, `up` ends up > 0
var up = 0 ;
for ( var i = srcPath . length ; i >= 0 ; i -- ) {
last = srcPath [ i ] ;
if ( last === '.' ) {
srcPath . splice ( i , 1 ) ;
} else if ( last === '..' ) {
srcPath . splice ( i , 1 ) ;
up ++ ;
} else if ( up ) {
srcPath . splice ( i , 1 ) ;
up -- ;
}
}
// if the path is allowed to go above the root, restore leading ..s
if ( ! mustEndAbs && ! removeAllDots ) {
for ( ; up -- ; up ) {
srcPath . unshift ( '..' ) ;
}
}
if ( mustEndAbs && srcPath [ 0 ] !== '' &&
( ! srcPath [ 0 ] || srcPath [ 0 ] . charAt ( 0 ) !== '/' ) ) {
srcPath . unshift ( '' ) ;
}
if ( hasTrailingSlash && ( srcPath . join ( '/' ) . substr ( - 1 ) !== '/' ) ) {
srcPath . push ( '' ) ;
}
var isAbsolute = srcPath [ 0 ] === '' ||
( srcPath [ 0 ] && srcPath [ 0 ] . charAt ( 0 ) === '/' ) ;
// put the host back
if ( psychotic ) {
result . hostname = result . host = isAbsolute ? '' :
srcPath . length ? srcPath . shift ( ) : '' ;
//occationaly the auth can get stuck only in host
//this especially happens in cases like
//url.resolveObject('mailto:local1@domain1', 'local2@domain2')
var authInHost = result . host && result . host . indexOf ( '@' ) > 0 ?
result . host . split ( '@' ) : false ;
if ( authInHost ) {
result . auth = authInHost . shift ( ) ;
result . host = result . hostname = authInHost . shift ( ) ;
}
}
mustEndAbs = mustEndAbs || ( result . host && srcPath . length ) ;
if ( mustEndAbs && ! isAbsolute ) {
srcPath . unshift ( '' ) ;
}
if ( ! srcPath . length ) {
result . pathname = null ;
result . path = null ;
} else {
result . pathname = srcPath . join ( '/' ) ;
}
//to support request.http
if ( ! util . isNull ( result . pathname ) || ! util . isNull ( result . search ) ) {
result . path = ( result . pathname ? result . pathname : '' ) +
( result . search ? result . search : '' ) ;
}
result . auth = relative . auth || result . auth ;
result . slashes = result . slashes || relative . slashes ;
result . href = result . format ( ) ;
return result ;
} ;
Url . prototype . parseHost = function ( ) {
var host = this . host ;
var port = portPattern . exec ( host ) ;
if ( port ) {
port = port [ 0 ] ;
if ( port !== ':' ) {
this . port = port . substr ( 1 ) ;
}
host = host . substr ( 0 , host . length - port . length ) ;
}
if ( host ) this . hostname = host ;
} ;
} , { "./util" : 27 , "punycode" : 22 , "querystring" : 25 } ] , 27 : [ function ( require , module , exports ) {
'use strict' ;
module . exports = {
isString : function ( arg ) {
return typeof ( arg ) === 'string' ;
} ,
isObject : function ( arg ) {
return typeof ( arg ) === 'object' && arg !== null ;
} ,
isNull : function ( arg ) {
return arg === null ;
} ,
isNullOrUndefined : function ( arg ) {
return arg == null ;
}
} ;
} , { } ] , 28 : [ function ( require , module , exports ) {
module . exports = extend
var hasOwnProperty = Object . prototype . hasOwnProperty ;
function extend ( ) {
var target = { }
for ( var i = 0 ; i < arguments . length ; i ++ ) {
var source = arguments [ i ]
for ( var key in source ) {
if ( hasOwnProperty . call ( source , key ) ) {
target [ key ] = source [ key ]
}
}
}
return target
}
} , { } ] } , { } , [ 1 ] )
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCJhcHAvYWRtaW4uanMiLCJhcHAvYWRtaW4vYXJ0aWNsZXMuanMiLCJhcHAvYWRtaW4vZWRpdGFydGljbGUuanMiLCJhcHAvYWRtaW4vZWRpdHBhZ2UuanMiLCJhcHAvYWRtaW4vZWRpdHN0YWZmLmpzIiwiYXBwL2FkbWluL2Zyb2FsYS5qcyIsImFwcC9hZG1pbi9wYWdlcy5qcyIsImFwcC9hZG1pbi9zdGFmZmxpc3QuanMiLCJhcHAvYXBpL2FydGljbGUuanMiLCJhcHAvYXBpL2NvbW1vbi5qcyIsImFwcC9hcGkvZmlsZS5qcyIsImFwcC9hcGkvbWVkaWEuanMiLCJhcHAvYXBpL3BhZ2UuanMiLCJhcHAvYXBpL3BhZ2luYXRpb24uanMiLCJhcHAvYXBpL3N0YWZmLmpzIiwiYXBwL2F1dGhlbnRpY2F0aW9uLmpzIiwiYXBwL3dpZGdldHMvZGlhbG9ndWUuanMiLCJhcHAvd2lkZ2V0cy9maWxlaW5mby5qcyIsImFwcC93aWRnZXRzL2ZpbGV1cGxvYWQuanMiLCJhcHAvd2lkZ2V0cy9wYWdlcy5qcyIsIm5vZGVfbW9kdWxlcy9wYXJzZS1saW5rLWhlYWRlci9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9wdW55Y29kZS9wdW55Y29kZS5qcyIsIm5vZGVfbW9kdWxlcy9xdWVyeXN0cmluZy1lczMvZGVjb2RlLmpzIiwibm9kZV9tb2R1bGVzL3F1ZXJ5c3RyaW5nLWVzMy9lbmNvZGUuanMiLCJub2RlX21vZHVsZXMvcXVlcnlzdHJpbmctZXMzL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL3VybC91cmwuanMiLCJub2RlX21vZHVsZXMvdXJsL3V0aWwuanMiLCJub2RlX21vZHVsZXMveHRlbmQvaW1tdXRhYmxlLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0FDQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDZkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ25JQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0F