Commits

Anonymous committed 5c35f06

something more fun on the root resource - an html interpretation of the dispatch table

Comments (0)

Files changed (6)

priv/dispatch.conf

 %% -*- mode: erlang -*-
 
-{[], wmexamples_resource, []}.
+%% General Hello + Dispatch Info
+%% This resource returns some general "hello world", along with
+%% a "prettier" interpretation of this dispatch file.
+{[],                  %% expose resource at /
+ wmexamples_resource, %% defined in wmexamples_resource.erl
+ []}.                 %% no configuration
 
 %% CouchDB proxy example
 %% This will expose all couchdb functionality through webmachine
 {["sampletrace"],         
  sampletrace_resource,
  []}.
+
+
+%% File Resource
+%% Serve files from disk.
+{['*'],                 %% match anything not matched by
+                        %% previous clauses
+ static_resource,       %% defined in static_resource.erl
+ [{root, "priv/www"}]}. %% serve from priv/www

priv/www/index.css

+table {
+    margin-bottom: 1.5em;
+}
+
+th {
+    text-align: left;
+    font-size: larger;
+}
+
+td.label {
+    text-align: right;
+    font-size: smaller;
+    color: #ccc;
+}
+
+span.pathmatch {
+    font-style: italic;
+    color: #909;
+}
+
+pre {
+    margin: 0px;
+}

priv/www/index.html

-<html>
-<head>
-<title>It Worked</title>
-</head>
-<body>
-MochiWeb running.
-</body>
-</html>
+%% @author Bryan Fink
+%% @doc Simple functions for generating HTML.  This first appeared
+%%      in webmachine's wmtrace utility.  I'm extracting it to its
+%%      own module for easy reuse.
+%%      Example:
+%%        html([],
+%%             [body([],
+%%                   [h1([], ["Hello, World!"]),
+%%                    p([{"style", "font-type:italic"}],
+%%                      "That's easy")
+%%                   ])
+%%             ])
+%%      Should produce:
+%%        <html><body>
+%%        <h1>Hello, World!</h1>
+%%        <p style="font-type:italic">That's easy</p>
+%%        </body></html>
+-module(html).
+-compile(export_all).
+
+-define(TAG(T), T(Attrs, Content) ->
+                   tag(??T, Attrs, Content)).
+
+?TAG(head).
+?TAG(script).
+?TAG(title).
+?TAG(body).
+?TAG(h1).
+?TAG(h2).
+?TAG(h3).
+?TAG(ul).
+?TAG(li).
+?TAG(a).
+?TAG(p).
+?TAG(canvas).
+?TAG(select).
+?TAG(pre).
+?TAG(span).
+?TAG(button).
+?TAG(em).
+?TAG(strong).
+?TAG(table).
+?TAG(th).
+?TAG(tr).
+?TAG(td).
+
+html(_Attrs, Content) ->
+    [<<"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n">>,
+     <<"<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">">>,
+     Content,
+     <<"</html>">>].
+
+divblock(Attrs, Content) ->
+    tag("div", Attrs, Content). %% div is a reserved word
+
+linkblock(Attrs, Content) ->
+    tag("link", Attrs, Content). %% link is a reserved word
+
+tag(Name, Attrs, Content) ->
+    ["<",Name,
+     [ [" ",K,"=\"",V,"\""] || {K, V} <- Attrs ],
+     if Content == empty -> "/>";
+        true ->
+             [">",
+              Content,
+              "</",Name,">"]
+     end].

src/static_resource.erl

+%% @author Bryan Fink
+%% @doc Serve static content from disk
+%%      Note: for a much more full-featured filesystem
+%%      resource, have a look at demo_fs_resource.erl
+%%      in webmachine's demo directory.
+-module(static_resource).
+-export([init/1,
+	 content_types_provided/2,
+	 resource_exists/2,
+	 content/2]).
+
+-record(context, {root, filepath}).
+
+-include_lib("webmachine/include/webmachine.hrl").
+
+init(Opts) ->
+    {ok, #context{root=proplists:get_value(root, Opts)}}.
+
+content_types_provided(RD, Context) ->
+    Path = wrq:disp_path(RD),
+    Mime = webmachine_util:guess_mime(Path),
+    {[{Mime, content}], RD, Context}.
+
+resource_exists(RD, Context=#context{root=Root}) ->
+    FP = filename:join([Root, wrq:disp_path(RD)]),
+    case filelib:is_regular(FP) of
+	true ->
+	    {true, RD, Context#context{filepath=FP}};
+	_ ->
+	    {false, RD, Context}
+    end.
+
+content(RD, Context=#context{filepath=FP}) ->
+    {ok, Data} = file:read_file(FP),
+    {Data, RD, Context}.

src/wmexamples_resource.erl

-%% @author author <author@example.com>
-%% @copyright YYYY author.
-%% @doc Example webmachine_resource.
-
+%% @author Bryan Fink
+%% @doc This is a "hello world" resource, with a "pretty"
+%%      rendered interpretation of the file defining the
+%%      webmachine dispatch table for this application.
 -module(wmexamples_resource).
 -export([init/1, to_html/2]).
 
+-import(html, [html/2, head/2, body/2,
+               linkblock/2,
+               h1/2, p/2, pre/2, span/2,
+               table/2, th/2, tr/2, td/2]).
+
 -include_lib("webmachine/include/webmachine.hrl").
 
+%%-import(html, [html/2, body/2]).
+
 init([]) -> {ok, undefined}.
 
 to_html(ReqData, State) ->
-    {"<html><body>Hello, new world</body></html>", ReqData, State}.
+    {html([],
+          ["\n",head([], [linkblock([{"rel", "stylesheet"},
+                                     {"type", "text/css"},
+                                     {"href", "index.css"}], [])]),
+           "\n",body([], [h1([], "Welcome to wmexamples"),
+                          dispatch_details()])
+          ]),
+     ReqData, State}.
+
+-define(DISPATCH_FILENAME, "priv/dispatch.conf").
+
+dispatch_details() ->
+    {ok, Dispatch} = file:consult(?DISPATCH_FILENAME),
+    [p([], [?DISPATCH_FILENAME, " is exposing the following paths:"]),
+     [["\n",dispatch_detail(D)] || D <- Dispatch]].
+
+dispatch_detail({Path, Resource, Args}) ->
+    table([],
+          [tr([], th([{"colspan", "2"}], dispatch_path(Path))), "\n",
+           tr([],
+              [td([{"class", "label"}], "resource"),
+               td([], dispatch_resource(Resource))]), "\n",
+           tr([],
+              [td([{"class", "label"}], "argument"),
+               td([], dispatch_args(Args))])
+          ]).
+
+dispatch_path([]) ->
+    "/";
+dispatch_path(Path) ->
+    [["/", dispatch_path_part(P)] || P <- Path].
+
+dispatch_path_part(Literal) when is_list(Literal) ->
+    Literal;
+dispatch_path_part('*') ->
+    "&hellip;";
+dispatch_path_part(Match) when is_atom(Match) ->
+    span([{"class", "pathmatch"}], atom_to_list(Match)).
+
+
+dispatch_resource(Resource) ->
+    atom_to_list(Resource).
+
+dispatch_args(Args) ->
+    pre([], io_lib:format("~p", [Args])).