| 1 | using System;
|
|---|
| 2 | using System.Collections.Generic;
|
|---|
| 3 | using System.Linq;
|
|---|
| 4 | using System.Text;
|
|---|
| 5 | using System.IO;
|
|---|
| 6 | using System.Linq.Expressions;
|
|---|
| 7 |
|
|---|
| 8 | namespace Linqsxom
|
|---|
| 9 | {
|
|---|
| 10 | class Program
|
|---|
| 11 | {
|
|---|
| 12 | static void Main(string[] args)
|
|---|
| 13 | {
|
|---|
| 14 | Console.Write("Content-Type: text/html; charset=UTF-8\r\n\r\n" +
|
|---|
| 15 | (from i in Enumerable.Range(0, 1)
|
|---|
| 16 | let maxRecentCount = 5
|
|---|
| 17 | let dir = @"Data" //@"..\..\Data"
|
|---|
| 18 |
|
|---|
| 19 | let getString = (Func<String, String>)(s => String.IsNullOrEmpty(s) ? "" : s)
|
|---|
| 20 |
|
|---|
| 21 | let serverName = Environment.GetEnvironmentVariable("SERVER_NAME")
|
|---|
| 22 | let serverPort = Environment.GetEnvironmentVariable("SERVER_PORT")
|
|---|
| 23 | let serverUrlPrefix = String.IsNullOrEmpty(serverName) ? "" : String.Format("http://{0}{1}", serverName, (serverPort == "80" ? "" : ":" + serverPort))
|
|---|
| 24 | let scriptUrl = serverUrlPrefix + Environment.GetEnvironmentVariable("SCRIPT_NAME")
|
|---|
| 25 |
|
|---|
| 26 | let pathInfoTmp = getString(Environment.GetEnvironmentVariable("PATH_INFO")) /* "/2007/11" */
|
|---|
| 27 | let pathInfo = pathInfoTmp.EndsWith("/") ? pathInfoTmp : pathInfoTmp + "/"
|
|---|
| 28 |
|
|---|
| 29 | let headTemplate = File.Exists("head.flavor") ? File.ReadAllText("head.flavor") : "<title>Linqsxom</title>\n<h1>Linqsxom</h1>\n"
|
|---|
| 30 | let bodyTemplate = File.Exists("body.flavor") ? File.ReadAllText("body.flavor") : "<div class=\"entry\">\n<h2><a href=\"{ScriptUrl}{Path}\">{CreatedOn}</a></h2>\n<div class=\"body\">{Body}</div>\n</div>\n"
|
|---|
| 31 | let footTemplate = File.Exists("foot.flavor") ? File.ReadAllText("foot.flavor") : "<p>Genetated by Linqsxom</p>"
|
|---|
| 32 |
|
|---|
| 33 | let body = String.Join("\n", (from entry in
|
|---|
| 34 | (from f in
|
|---|
| 35 | (from f in Directory.GetFiles(dir, "*.htm*", SearchOption.AllDirectories)
|
|---|
| 36 | orderby File.GetLastWriteTime(f) descending
|
|---|
| 37 | select f).Take(maxRecentCount)
|
|---|
| 38 | let createdOn = File.GetLastWriteTime(f)
|
|---|
| 39 | select new
|
|---|
| 40 | {
|
|---|
| 41 | Path = String.Format("/{0}/{1:00}/{2:00}/{3}", createdOn.Year, createdOn.Month, createdOn.Day, Path.GetFileName(f)),
|
|---|
| 42 | FileName = f,
|
|---|
| 43 | CreatedOn = createdOn,
|
|---|
| 44 | Body = File.ReadAllText(f)
|
|---|
| 45 | })
|
|---|
| 46 | where entry.Path.StartsWith(pathInfo) || String.IsNullOrEmpty(pathInfo)
|
|---|
| 47 | let block = bodyTemplate.Replace(CreatedOn => entry.CreatedOn.ToString(),
|
|---|
| 48 | Body => entry.Body,
|
|---|
| 49 | ScriptUrl => scriptUrl,
|
|---|
| 50 | Path => entry.Path)
|
|---|
| 51 | select block).ToArray<String>())
|
|---|
| 52 | select headTemplate + body + footTemplate).First().ToString());
|
|---|
| 53 | //Console.Write("Content-Type: text/html; charset=UTF-8\r\n\r\n"+t.First().ToString());
|
|---|
| 54 | }
|
|---|
| 55 | }
|
|---|
| 56 |
|
|---|
| 57 | static class Extensions
|
|---|
| 58 | {
|
|---|
| 59 | /// <example>
|
|---|
| 60 | /// var s = "{Foo}/{Gaogao}".Replace(Foo => "ふう。", Gaogao => "がおがお。"); // => "ふう。/がおがお。"
|
|---|
| 61 | /// </example>
|
|---|
| 62 | public static String Replace(this String s, params Expression<Func<Object, String>>[] exprs)
|
|---|
| 63 | {
|
|---|
| 64 | return (from i in Enumerable.Range(0, 1)
|
|---|
| 65 | let sb = ((Func<String, StringBuilder>)(x => new StringBuilder(x)))(s)
|
|---|
| 66 | let body = (from expr in exprs
|
|---|
| 67 | where sb.Replace("{" + expr.Parameters[0].Name + "}", expr.Compile().Invoke(s)) != null
|
|---|
| 68 | select sb).Last()
|
|---|
| 69 | select body).First().ToString();
|
|---|
| 70 | }
|
|---|
| 71 | }
|
|---|
| 72 | }
|
|---|