Mercurial > prosody-modules
comparison mod_http_index/mod_http_index.lua @ 1573:0d8cc6971cdb
mod_http_index: Generates an index of local HTTP apps
author | Kim Alvefur <zash@zash.se> |
---|---|
date | Thu, 20 Nov 2014 14:48:46 +0100 |
parents | |
children | 1b5c817cb642 |
comparison
equal
deleted
inserted
replaced
1572:1aa894db3585 | 1573:0d8cc6971cdb |
---|---|
1 local st = require "util.stanza"; | |
2 local url = require"socket.url"; | |
3 | |
4 module:depends"http"; | |
5 | |
6 -- local dump = require"util.serialization".new"dump".serialize; | |
7 | |
8 local function template(data) | |
9 --[[ DOC | |
10 Like util.template, but deals with plain text | |
11 Returns a closure that is called with a table of values | |
12 {name} is substituted for values["name"] and is XML escaped | |
13 {name!} is substituted without XML escaping | |
14 {name?} is optional and is replaced with an empty string if no value exists | |
15 ]] | |
16 return function(values) | |
17 return (data:gsub("{([^}]-)(%p?)}", function (name, opt) | |
18 local value = values[name]; | |
19 if value then | |
20 if opt ~= "!" then | |
21 return st.xml_escape(value); | |
22 end | |
23 return value; | |
24 elseif opt == "?" then | |
25 return ""; | |
26 end | |
27 end)); | |
28 end | |
29 end | |
30 | |
31 -- TODO Move templates into files | |
32 local base = template(template[[ | |
33 <!DOCTYPE html> | |
34 <html> | |
35 <head> | |
36 <meta charset="utf-8"> | |
37 <meta name="viewport" content="width=device-width, initial-scale=1"> | |
38 <meta name="generator" value="prosody/{prosody_version} mod_{mod_name}"> | |
39 <link rel="canonical" href="{canonical}"> | |
40 <title>{title}</title> | |
41 <style> | |
42 body{background-color:#eeeeec;margin:1ex 0;padding-bottom:3em;font-family:Arial,Helvetica,sans-serif;} | |
43 header,footer{margin:1ex 1em;} | |
44 footer{font-size:smaller;color:#babdb6;} | |
45 .content{background-color:white;padding:1em;list-style-position:inside;} | |
46 nav{font-size:large;margin:1ex 1ex;clear:both;line-height:1.5em;} | |
47 nav a{padding: 1ex;text-decoration:none;} | |
48 nav a[rel="up"]{font-size:smaller;} | |
49 nav a[rel="prev"]{float:left;} | |
50 nav a[rel="next"]{float:right;} | |
51 nav a[rel="next::after"]{content:" →";} | |
52 nav a[rel="prev::before"]{content:"← ";} | |
53 nav a:empty::after,nav a:empty::before{content:""} | |
54 @media screen and (min-width: 460px) { | |
55 nav{font-size:x-large;margin:1ex 1em;} | |
56 } | |
57 a:link,a:visited{color:#2e3436;text-decoration:none;} | |
58 a:link:hover,a:visited:hover{color:#3465a4;} | |
59 ul,ol{padding:0;} | |
60 li{list-style:none;} | |
61 hr{visibility:hidden;clear:both;} | |
62 br{clear:both;} | |
63 li time{float:right;font-size:small;opacity:0.2;} | |
64 li:hover time{opacity:1;} | |
65 .room-list .description{font-size:smaller;} | |
66 q.body::before,q.body::after{content:"";} | |
67 .presence .verb{font-style:normal;color:#30c030;} | |
68 .presence.unavailable .verb{color:#c03030;} | |
69 </style> | |
70 </head> | |
71 <body> | |
72 <header> | |
73 <h1>{title}</h1> | |
74 {header!} | |
75 </header> | |
76 <hr> | |
77 <div class="content"> | |
78 {body!} | |
79 </div> | |
80 <hr> | |
81 <footer> | |
82 {footer!} | |
83 <br> | |
84 <div class="powered-by">Prosody {prosody_version?}</div> | |
85 </footer> | |
86 </body> | |
87 </html> | |
88 ]] { prosody_version = prosody.version, mod_name = module.name }); | |
89 | |
90 local canonical = module:http_url(nil, "/"); | |
91 local page_template = template(base{ | |
92 canonical = canonical; | |
93 title = "HTTP stuff"; | |
94 header = ""; | |
95 body = [[ | |
96 <nav> | |
97 <ul> | |
98 {lines!} | |
99 </ul> | |
100 </nav> | |
101 ]]; | |
102 footer = ""; | |
103 }); | |
104 local line_template = template[[ | |
105 <li><a href="{url}" title="{module}">{name}</a></li> | |
106 ]]; | |
107 | |
108 local function relative(base, link) | |
109 base = url.parse(base); | |
110 link = url.parse(link); | |
111 for k,v in pairs(base) do | |
112 if link[k] == v then | |
113 link[k] = nil; | |
114 end | |
115 end | |
116 return url.build(link); | |
117 end | |
118 | |
119 local function handler(event) | |
120 local items = module:get_host_items("http-provider"); | |
121 local item; | |
122 for i = 1, #items do | |
123 item = items[i]; | |
124 if module.name ~= item._provided_by then | |
125 items[i] = line_template{ | |
126 name = item.name; | |
127 module = "mod_" .. item._provided_by; | |
128 url = relative(canonical, module:http_url(item.name, item.default_path)); | |
129 }; | |
130 else | |
131 items[i] = ""; | |
132 end | |
133 end | |
134 event.response.headers.content_type = "text/html"; | |
135 return page_template{ | |
136 lines = table.concat(items); | |
137 }; | |
138 end | |
139 | |
140 module:provides("http", { | |
141 route = { | |
142 ["GET /"] = handler; | |
143 }; | |
144 default_path = "/"; | |
145 }); |