まだ全然機能がないけど。
#include <iostream> #include <fstream> #include <string> #include <ctime> #include <sys/stat.h> #include <unistd.h> #include <vector> #include <boost/filesystem.hpp> #include <boost/format.hpp> #include <boost/regex.hpp> using namespace std; // for noveltable typedef struct{ int size; // 章数 string title; // title string author; // author string publicdir; // Web Directory string basename; // basename string cssfilename; // CSS filename string data; // honbun string tmplate; // tmplate vector<string> subtitle; vector<string> dx; vector<string> header; } novel; // 指定テキストファイルを読み出す。(vector版) vector<string> vget_file(string fn) { boost::regex rlf("\\r"); boost::regex rcr("\\n"); vector<string> r; string a = ""; ifstream ifs(fn.c_str()); if(ifs) { while(getline(ifs,a)){ if(boost::regex_search(a,rlf)||boost::regex_search(a,rcr)) // なんか改行してるっぽい { r.push_back(a); }else{ // 改行っぽいコードが見当たらないよ? r.push_back(a + "\n"); // とりあえずつけとけ。 } } ifs.close(); }else{ r.push_back("ERROR"); } return(r); } // 指定ファイルに内容を書き込む。 void set_file(string fn,string str){ ofstream ofs(fn.c_str()); ofs << str; } // 指定テキストファイルを読み込む。(string) string get_file(string fn) { boost::regex rlf("\\r"); boost::regex rcr("\\n"); string r = ""; string a = ""; ifstream ifs(fn.c_str()); if(ifs) { while(getline(ifs,a)){ if(boost::regex_search(a,rlf)||boost::regex_search(a,rcr)) // なんか改行してるっぽい { r += a; }else{ // 改行っぽいコードが見当たらないよ? r += (a + "\n"); // とりあえずつけとけ。 } } ifs.close(); }else{ r += "ERROR"; } return(r); } // index.cssをpublic領域に複写する。 int copy_indexcss(novel n1) { string f = "index.css"; string fn = ""; fn = n1.publicdir + "/" + f; boost::filesystem::path fpath(fn); if(boost::filesystem::exists(fpath)){ cout << "already exists index.css("<<fn<<")"<<endl; }else{ try{ boost::filesystem::path srce(f); boost::filesystem::path drst(fn); boost::filesystem::copy_file(srce, drst); }catch(boost::filesystem::filesystem_error& ex){ cout<<ex.what()<<endl; throw; } } return(0); } // テンプレートを読み込む。 string read_tmplate(string fn) { return(get_file(fn)); } string kill_crlf(string x) // 改行よさようなら。 { boost::regex reg("(\\r|\\n)"); string r = regex_replace(x,reg,""); return(r); } string get_subtitle(string x) { boost::regex subt("\\A\\*\\ "); string r = regex_replace(x,subt,""); r = kill_crlf(r); return(r); } bool make_dir(string dir) // 指定ディレクトリを作成する。存在するなら抜ける。 { bool r = true; if(mkdir(dir.c_str(), 0755) != 0) { r = false; } return(r); } string get_basename(string fn) { string r = fn; boost::regex reg1("\\A.*/"); boost::regex reg2("\\.txt\\z"); r = regex_replace(fn,reg1,""); r = regex_replace(r,reg2,""); return(r); } string make_novel_directory(string fn, string pubdir) { string r = ""; string basename = get_basename(fn); if(make_dir(pubdir) == true){ if(make_dir(pubdir + "/" + basename) == true){ r = basename; } } return(r); } // サブタイトル一覧を<ul></ul>にして返す。 string vector2link(vector<string> subtitle, string sufx){ string r = ""; string fn = ""; if(subtitle.size() > 1){ r = "<ul>"; for(int i=1;i<subtitle.size();i++){ fn = (boost::format("%1%%2%") % i % sufx).str();; r = r + "<li><a href=\"" + fn + "\">" + subtitle[i] + "</a></li>"; } } return(r); } string make_link(string name, string base, string sufx){ string fn = (boost::format("%1%%2%") % base % sufx).str(); if(fn == "0.html"){ fn = "index.html"; } return("<a href=\"" + fn + "\">" + name + " "); } string make_ffn(int n){ string fn = (boost::format("%1%") % n).str(); return(fn); } // ヘッダ(またはフッタ)を作成して返す。 string make_HeaderOrFooter(vector<string> subtitle, string sufx, int n){ string r = ""; int i = 0, ii = 0; // 単ページなら、もっとも単純なイメージを返す。 // 下の端(0ページでなおかつ1以上がある)なら、+1つきのを返す。 // 末端ページなら、-1のみを返す。 // どれでもないのなら、-1と+1を返す。 if(subtitle.size() == 1){ r = make_link("戻る","../index",sufx); }else if(n == 0){ // 単頁ではなく、しかも最初の頁 r = make_link("戻る","../index",sufx) + make_link("進む",make_ffn(n+1),sufx); }else if(n == (subtitle.size() - 1)){ // 単頁ではなく、そして末尾の頁 r = make_link("最初","0",sufx) + make_link("戻る",make_ffn(n-1),sufx); }else{ r = make_link("最初","0",sufx) + make_link("戻る",make_ffn(n-1),sufx) + make_link("進む",make_ffn(n+1),sufx); } return(r); } // テンプレート適用 string check_tmplate(novel n1, int i) { string r = n1.tmplate; boost::regex startend("\\A(\\ |\\r|\\n|)+(.*)(\\ |\\r|\\n|)+\\z"); boost::regex kaigyo("\\n"); boost::regex honbun(":__CONTENTS__:"); boost::regex subt(":__SUBTITLE__:"); boost::regex maint(":__TITLE__:"); boost::regex header(":__HEADER__:"); boost::regex footer(":__FOOTER__:"); boost::regex cssfile(":__CSSFILE__:"); n1.dx[i] = regex_replace(n1.dx[i], startend,"<p>$2</p>"); n1.dx[i] = regex_replace(n1.dx[i], kaigyo,"<br />\\n"); r = regex_replace(r, maint, n1.title); r = regex_replace(r, cssfile, n1.cssfilename); r = regex_replace(r, honbun, n1.dx[i]); r = regex_replace(r, subt, n1.subtitle[i]); r = regex_replace(r, header, n1.header[i]); r = regex_replace(r, footer, n1.header[i]); return(r); } void out_data(novel n1) { string fn = ""; string x = ""; string y = ""; for(int i=0;i<n1.dx.size();i++) { // ファイル名を決定する。 fn = (boost::format("%1%.html") % i).str(); if(fn == "0.html"){ fn = "index.html"; } x = n1.dx[i]; y = n1.subtitle[i]; if((i == 0) && (n1.dx.size() > 1)){ // 単ページでなく、そして最初のページ // ページ目録を作成する。 n1.dx[i] += vector2link(n1.subtitle, ".html"); } //set_file(fn,check_tmplate(x,y,n1.tmplate)); cout<<"set_file:"<<fn<<endl; set_file(fn,check_tmplate(n1,i)); } } int main(int argc, char *argv[]) { string fn = "genko/2ndc.txt"; novel n1; if(argc > 1){ fn = (boost::format("genko/%1%") % argv[1]).str(); } boost::regex subt("\\A\\*\\ "); // public_html n1.publicdir = "public_html"; // テンプレートの読み込み n1.tmplate = read_tmplate("tmplate.html"); // CSSの所在はここ。 n1.cssfilename = "index.css"; vector<string> d = vget_file(fn); n1.title = kill_crlf(d[0]); n1.author = kill_crlf(d[1]); // n1.dx.push_back(""); n1.subtitle.push_back(n1.title); int s = 0; int c = d.size(); for(int i=0;i<c;i++){ if(regex_search(d[i],subt)){ // 章の区切りキタ━(゚∀゚)━! n1.dx.push_back(""); // ここでd[i]を入れるとタイトル文字が入ってしまうので、飛ばす。 n1.subtitle.push_back(get_subtitle(d[i])); s++; }else{ n1.dx[s] += (kill_crlf(d[i]) + "\n"); } } cout<<"タイトル:"<<n1.title<<endl; cout<<"作者:"<<n1.author<<endl; cout<<"行数 "<<c<<endl; cout<<"章数 "<<n1.dx.size()<<endl; //if(n1.subtitle.size() > 1) //{ for(int ii=0;ii<n1.subtitle.size();ii++){ cout<<"副題:"<<n1.subtitle[ii]<<endl; n1.header.push_back(make_HeaderOrFooter(n1.subtitle,".html", ii)); } //} cout<<"ディレクトリを作成します。 ...."; n1.basename = make_novel_directory(fn,n1.publicdir); copy_indexcss(n1); if(n1.basename != ""){ cout<<"OK"<<endl; cout<<get_current_dir_name()<<endl; cout<<n1.basename<<endl; chdir(n1.publicdir.c_str()); chdir(n1.basename.c_str()); cout<<get_current_dir_name()<<endl; cout<<"ファイルを吐き出します。(開始)"<<endl;; //out_data(n1.dx, n1.subtitle, n1.tmplate); out_data(n1); cout<<"ファイルを吐き出します。(終了)"<<endl; }else{ cout<<"NG"<<endl; } }
カレントディレクトリに、tmplate.htmlという名前で保管しておく。
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xml:lang="ja-JP" xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Style-Type" content="text/css" /> <link rel="stylesheet" type="text/css" href="../:__CSSFILE__:" title="Normal" /> <meta http-equiv="content-type" content="application/xhtml+xml; charset=UTF-8" /> <title>:__SUBTITLE__: / :__TITLE__:</title> </head> <body> <div class="header">:__HEADER__:</div> <div class="title"> <h1>:__SUBTITLE__:</h1> </div> <div class="honbun"> <div class="wadai"> <div class="setu"> :__CONTENTS__: </div> </div> </div> <hr /> <div class="footer">:__FOOTER__:</div> <hr /> <div class="footer"> <div class="update">:__LASTUPDATE__:</div> </div> <div class="wadai"><h2>感想メールフォーム</h2> <form method="post" action="http://ellidanus-b.ddo.jp/cgi-bin/form.cgi" enctype="text/html"> <div> <input type="hidden" name="return" value=":__BASEURL__:"> <input type="hidden" name="subject" value="感想『:__TITLE__:』" /> <input type="hidden" name="mail" value="iris_von_einzbern@yahoo.co.jp" /> <input type="hidden" name="style" value="../index.css" /> <label for="OName">お名前(ハンドル等):</label><input id="OName" accesskey="a" tabindex="0" type="text" name="name1" value="名無しのナボコフ" /><br /> <label for="OMail">メールアドレス(なくてもいいです):</label><input id="OMail" accesskey="b" tabindex="1" type="text" name="mailfrom" value="" /> </div> <h3>PLZ 選んでください(未選択だとエラー)</h3> <div> <label for="n1">素晴らしい!</label><input id="n1" accesskey="h" tabindex="6" type="radio" name="kansou" value="素晴らしい!" /><br /> <label for="n2">なかなか</label><input id="n2" accesskey="i" tabindex="7" type="radio" name="kansou" value="なかなか" /><br /> <label for="n3">それなりかな</label><input id="n3" accesskey="j" tabindex="8" type="radio" name="kansou" value="それなりかな" /><br /> <label for="n4">微妙〜</label><input id="n4" accesskey="k" tabindex="9" type="radio" name="kansou" value="微妙〜" /><br /> <label for="n5">ドン引き orz</label><input id="n5" accesskey="l" tabindex="10" type="radio" name="kansou" value="ドン引き orz" /><br /> <textarea accesskey="c" tabindex="2" rows="8" name="comment">(コメント)</textarea><br /> <input accesskey="d" tabindex="3" type="submit" name="wei" value="送信" />-+-<input accesskey="e" tabindex="4" type="reset" name="nap" value="消去" /> </div> </form> </div> </body> </html>
こんな感じの原稿を、たとえば genko/sample.txt にいれておく。
テスト原稿 hachikun テスト テスト原稿なんだよん。 * 第一章 テストです。 * 第ニ章 テストテスト。 * 第三章 これがテストだ!
index.cssという名前でテンプレートを、やっぱりカレントディレクトリに用意してください。