@d at et i me@tags
$datetime
$tags
吳修慶 安徽阜陽技師學院
博客(英語:Blog,為Web Log的混成詞),意指log on the web意即在網(wǎng)絡上紀錄,是一種由個人管理、張貼新的文章、圖片或視頻的網(wǎng)站或在線日記,用來紀錄、抒發(fā)情感或分享信息。博客上的文章通常根據(jù)張貼時間(Chronological Order),以倒序方式由新到舊排列。
作為一名計算機專業(yè)教師,幫助學生編寫自己的個人技術博客對于激發(fā)學生學習興趣來說是非常重要的。而博客的發(fā)展又分為了三個階段。
第一階段:一開始大多初學者會選擇使用免費的第三方網(wǎng)站提供的博客系統(tǒng):如新浪博客,博客園,csdn等,很快,程序員就發(fā)現(xiàn)這些博客難以備份,系統(tǒng)代碼不可見,定制型差,程序員只能使用其內(nèi)置功能和內(nèi)置模版。
第二階段:隨著學習的深入,具備一定開發(fā)能力開始使用如WordPress,Typecho等開源博客系統(tǒng),將其架設在自己的個人購買的服務器上。WordPress一度成為主流的博客搭建方法,其架設在PHP服務器上。拓展性好,代碼可見,插件眾多。但WordPress有個顯著的缺點:需要一個后臺語言(WordPress需要的是PHP)支持的服務器。很多在讀的計算機專業(yè)學生沒有資金去負擔一個個人服務器。
第三階段:成立于2007年,基于Git分布式管理的全球最大開源項目管理平臺Github是當今開源軟件業(yè)的一桿旗幟。而Github向個人開發(fā)者提供了Github Pages這一服務來供個人開發(fā)者展示自己的作品。GitHub Pages提供了一個全免費的靜態(tài)http服務器,支持自制頁面和Jekyll。用戶可以非常方便的通過Git將自己的http頁面上傳至Github Pages并綁定自己的頂級域名。Github Pages不支持如PHP、Python的服務端語言,但一個無限空間、訪問穩(wěn)定的http空間已經(jīng)為我們提供了無限可能。
綜合Github Pages的特點,結(jié)合教學開發(fā)了這套靜態(tài)博客生成程序。本系統(tǒng)采用了PHP 5作為開發(fā)工具,提供了一套完整的靜態(tài)網(wǎng)頁生成程序,學生可以使用本系統(tǒng)為自己寫好的Markdown博客生成出全靜態(tài)的HTML,學生可以通過自定義css和生成html的模版文件自定義自己想要的界面,可以用過自己引入js來自定義自己想要的插件。系統(tǒng)默認提供了一套我個人使用的模版,默認集成了Highlight.js插件用于代碼高亮顯示,集成了Duoshuo評論系統(tǒng)用于使靜態(tài)頁面也能實現(xiàn)即時頁面評論。
目前Github上最著名的這類靜態(tài)博客軟件是Hexo。Hexo使用起來非常繁瑣,需要Node.js的支持,全字符界面,修改比較困難在教學中使用了PHP作為開發(fā)工具,相對于Hexo更為成熟簡便,學生容易實現(xiàn)。
結(jié)合多年的程序設計課堂教學,發(fā)現(xiàn)程序設計課堂教學存在幾個教學切入點,一方面:學生需要切合生活實際的操作性強的教學案例;另一方面:Markdown語言有助于初學者對程序設計課程的理解;除此之外:博客的建立使學生有一個自我展示的載體從而獲得較強專業(yè)成就感。常規(guī)教學案例中提供的第三方免費服務使博客文章難以備份,系統(tǒng)代碼不可見,定制型差,學生練習只能使用其內(nèi)置功能和內(nèi)置模版;而WordPress, Typecho等第三方需要服務端語言支持的博客固然好用,但服務器租用是一筆不小的支出。
因此,本文可以幫助同學利用所學知識自己動手開發(fā)一套靜態(tài)博客,用于記錄自己的學習歷程,分享技術成果,提高自我專業(yè)認可度。在下面的各章中我將詳細的闡述開發(fā)過程和開發(fā)中遇到的問題及解決方法。
可行性研究的目的是用最小的代價,在盡可能短的時間內(nèi)確定問題是否能夠解決,它的目的不是解決問題,而是確定問題是否值得去解決,結(jié)合課堂教學實際可行性主要從以下四個方面來考慮:
靜態(tài)博客生成程序是要求網(wǎng)頁將本來后臺語言分離出來提前生成好。本系統(tǒng)使用PHP 5.3實現(xiàn),默認界面模版使用了Bootstrap框架加上手動的HTML,CSS編寫。結(jié)合專業(yè)開設的多種程序設計語言,并且經(jīng)常在課堂教學中貫穿軟件開發(fā)小項目,使學生對系統(tǒng)開發(fā)有一定的了解,再加指導老師的指導,和詳細的參考文檔,所以在技術上是可行的。
運行可行性主要是分析操作學生是否具有開發(fā)和運行維護軟件開發(fā)注冊系統(tǒng)的能力。
作為一個計算機或相關專業(yè)的學生,必定接觸過服務器,編寫Markdown格式語言的博客也容易掌握。同時,本軟件的計算機的軟硬件條件運行系統(tǒng)的條很低件。用戶對系統(tǒng)的更新維護具備足夠的管理能力。
所以,本系統(tǒng)用于教學直觀易懂,有助于學生軟件開發(fā)實踐。
本教學案例中生成出的是一套靜態(tài)博客系統(tǒng),全部頁面均為html,所以一些正常博客很容易實現(xiàn)的數(shù)據(jù)關系在本軟件中難以通過原有方式實現(xiàn)。如通過標簽分類博客文章,通常博客系統(tǒng)會使用數(shù)據(jù)庫關聯(lián)表,對每篇文章的每個標簽獲取視圖。本軟件需要另辟蹊徑去解決這一問題。
同時,Markdown自身語法并沒有時間戳、標題、標簽等標記功能。本軟件在開發(fā)過程中,我首先考慮使用json,用戶在寫博客的同時寫一個里面含有文章標題、寫作日期、標簽、簡介的json文件。后來考慮到這么實現(xiàn)過于繁瑣,故拋棄。軟件要實現(xiàn)在Markdown文件內(nèi)部標志這些信息,同時讀取時過濾這些信息至內(nèi)容數(shù)組。
還有,一個正常的博客肯定會有評論功能。本軟件生成的靜態(tài)博客,本身不可能帶有數(shù)據(jù)庫,我們需要在這個前提下實現(xiàn)評論系統(tǒng)。
靜態(tài)博客生成程序應具備以下功能:
1.對Markdown文檔進行分析轉(zhuǎn)換
系統(tǒng)是基于Markdown這一通用標記型語言寫成的文檔進行轉(zhuǎn)換的。系統(tǒng)首先需要一個從Markdown文檔生成HTML標簽的轉(zhuǎn)換器。
2.對文檔進行歸納
將所有Markdown文檔轉(zhuǎn)換后,系統(tǒng)需要對所有文檔的信息進行總結(jié)歸納,生成歸檔頁面。再提取出所有標簽,通過標簽文檔的對應關系生成標簽檢索頁面。
3. 自定義博客模板本軟件不針對個人,所以需要擁有很強的自定義性。系統(tǒng)生成HTML的模板開放給用戶可編輯。同時CSS和其他插件用戶根據(jù)需要也可以自行修改。
本階段設計的基本目標是解決系統(tǒng)如何實現(xiàn)問題,也叫做概要設計,本階段主要任務是劃分出系統(tǒng)的物理元素及設計軟件的結(jié)構(gòu),完成軟件定義時期的任務之后就應該對系統(tǒng)進行總體設計,即根據(jù)系統(tǒng)分析產(chǎn)生的分析結(jié)果來確定這個系統(tǒng)由哪些系統(tǒng)和模塊組成,這些系統(tǒng)和模塊又如何有機的結(jié)合在一起,每個模塊的功能如何實現(xiàn)。系統(tǒng)設計的目標是使系統(tǒng)實現(xiàn)擁有所要求的功能,同時,力爭達到高效率、高可靠性、可修改性,并且容易掌握和使用。
模塊化的依據(jù)是:把復雜問題分解成許多容易解決的小問題。原來的問題也就變得容易解決。模塊化設計是把大型軟件按照一定的原則劃分成一個較小的相對功能獨立又相關聯(lián)的模塊。每個模塊完成一個特定的子功能。把這些模塊結(jié)合起來組成一個整體。完成指定的功能,滿足問題的要求。采用模塊化原理的優(yōu)點在于可以使軟件結(jié)構(gòu)清晰,容易測試和調(diào)試。從而提高軟件的可靠性,可修改性。有助于軟件開發(fā)的組織管理。一個大型軟件可分別編寫不同的模塊。程序設計課程教學中提到模塊化理論的幾個重要概念如下:
(1) 抽象
抽象就是抽象出事物的本質(zhì)特性而暫時不考慮它們的細節(jié)。處理復雜系統(tǒng)唯一有效的方法是用層次的方式構(gòu)造和分析它。一個復雜的動態(tài)系統(tǒng)首先可以用一些高級的抽象概念構(gòu)造和理解,這些高級概念又可以用一些較低級的理解,直到最低層次的具體元素。
(2) 信息隱蔽和局部化
信息隱蔽是指在設計和確定模塊時,應使得一個模塊內(nèi)包含的信息對于不需要這些信息的模塊來說,是不能訪問。
局部化是指把一些關系密切的軟件元素物理的放得彼此靠近。局部化有助于實現(xiàn)信息隱蔽。
信息隱蔽原理和局部化有助于在測試期間以及軟件維護期間修改軟件。因為絕大多數(shù)數(shù)據(jù)和過程對于軟件的其它部分而言是隱蔽的,從而由疏忽引入的錯誤就很少可能傳播到軟件的其它部分。
(3) 逐步求精的模塊化概念
逐步求精和模塊化的抽象是密切相關的。軟件結(jié)構(gòu)每一層中模塊表示對軟件抽象層次的次細化。用自頂向下,逐步求精的方法由抽象到具體的方式分配控制,簡化了軟件設計和實施,提高了軟件的可理解性和可測試性,并使得軟件更容易維護。
(4) 模塊獨立性
模塊的劃分要使模塊間盡可能的相互獨立,獨立模塊較易維護。度量模塊的獨立程度有兩個標準:內(nèi)聚和耦合。耦合是對一個軟件結(jié)構(gòu)內(nèi)不同模塊之間互連程度的度量。耦合強弱取決于模塊間接口的復雜程度,進入或訪問一個模塊的點,以及通過接口的數(shù)。
在軟件的設計中應追求盡可能松散的耦合。內(nèi)聚標志一個模塊內(nèi)各個元素彼此結(jié)合的緊密程度,它是信息隱藏和局部化概念的自然擴展,理想內(nèi)聚的模塊只做一件事情。在設計時應力求做到高內(nèi)聚。
4.2.1 博客構(gòu)建系統(tǒng)功能劃分
博客構(gòu)建系統(tǒng)完成分析Markdown文件和根據(jù)信息調(diào)用模版生成HTML代碼的功能,開發(fā)者系統(tǒng)包括的主要功能模塊有讀取Md文件、構(gòu)建內(nèi)容數(shù)組、構(gòu)建標簽數(shù)組、生成HTML等。
4.2.2 頁面模版劃分
頁面模版包括了一些頁面的制作。主要有首頁模板、標簽模板、頁面模板和第三方開源庫。
4.3.1 博客構(gòu)建系統(tǒng)功能描述
博客構(gòu)建系統(tǒng)包含以下4個重點功能。
1.讀取Markdown文件
讀取Markdown文件使用readfile.php中定義的readMdFile函數(shù)完成。項目一開始使用了PHP Sundown這一開源項目,Sundown是最完善,發(fā)展時間最長的一個Markdown轉(zhuǎn)HTML的項目。PHP Sundown是Sundown的一個PHP封裝。但PHP Sundown需要以php extension形式安裝,用戶需要安裝php后再去github下載PHP Sundown的源代碼,自行Make再安裝。給本軟件的用戶帶來了不小的麻煩。我最后改用了PHP-Markdown,并自行修改了一些代碼方便更適合本項目使用。同樣的項目還有Parsedown等作品。
2.構(gòu)建內(nèi)容數(shù)組
內(nèi)容數(shù)組的格式為$content[$i][’key’],$i表示文章 id,對于每個$content[$i],都是第$i篇文章對應的關聯(lián)數(shù)組。鍵包含:
$content[$i][‘postbody’] :正文
$content[$i][‘title’] :標題
$content[$i][‘datetime’] :文章創(chuàng)建時間
$content[$i][‘tags’] :用于直接在頁面顯示的標簽字符串
$content[$i][‘tagarray’] :用于后期生成tag頁面的當前頁面標簽數(shù)組
$content[$i][‘contentnext’] :對應的下一篇文章
$$content[$i][‘contentpre’] : 對應的上一篇文章
其中,Markdown文件中包含了前五個,contentnext和contentpre在scanfolder.php中對content數(shù)組按文章創(chuàng)建時間排序后設置。
3.構(gòu)建標簽數(shù)組
在scanfolder中結(jié)束對每個Markdown文件執(zhí)行readMdfile函數(shù)后,我們得到的標簽只存在于每篇文章的$content[$i][‘tagarray’]中。我們現(xiàn)在需要反向生產(chǎn)一個標簽->含有這個標簽的頁面的關聯(lián)數(shù)組。
4.生成HTML
博客構(gòu)建系統(tǒng)的最后一個功能也是最重要的功能就是HTML的生成。系統(tǒng)在生成HTML前會包含對應的模板文件,使用str_replace函數(shù)將模板中預先設定好要替換的部分替換為內(nèi)容數(shù)組中對應的部分,再將HTML對應的生成在out文件夾下。
同時,生成HTML時對應的CSS和Javascript文件不可缺少,系統(tǒng)內(nèi)包含了一個我寫的xCopy函數(shù),遞歸的將子文件夾下所有CSS,js文件復制入out文件夾內(nèi)。
本系統(tǒng)在開發(fā)時使用了Bootstrap前端框架。模板使用了Bootstrap默認布局和一些按鈕樣式。在頁面模板中還使用了Bootstrap提供的一些圖標。同時,頁面模板中代碼部分使用Highlight.js進行代碼高亮。在頁面尾部使用了多說評論系統(tǒng)。
詳細設計階段的根本目標是確定應該怎樣具體地實現(xiàn)所要求的系統(tǒng),也就是說,經(jīng)過這個階段的設計工作,應該得出目標系統(tǒng)的精確描述,從而在編碼階段可以把這個描述直接翻譯成用某種程序設計語言書寫的程序。
詳細設計的目標不僅僅是邏輯上正確地實現(xiàn)每個模塊的功能,更重要的是設計的處理過程應該盡可能簡明易懂,詳細設計階段的任務還不是具體的編寫程序,而是要設計出程序的“藍圖”,以后根據(jù)這個藍圖編寫出實際的程序代碼。
5.1.1 Markdown 文件信息分析的實現(xiàn)
Markdown語言有自己的語法定義,簡要如下:
Markdown語言要素一般分為標題、粗體斜體、分割線、列表、超鏈接、圖片、代碼
以下著重講解代碼
語法:Markdown里語法只需要縮進4個空格或者1個Tab
示例:Normal Text Code Text Normal Text 對應Html中標簽
綜上,程序在將Markdown轉(zhuǎn)換成HTML時只需根據(jù)Markdown語法對應的HTML標簽進行生成。同時,我們需要在Markdown文件中包含博客信息。程序中定義的Markdown頭部寫法如下:title: 文章標題,date: 文章時間,格式Y(jié)YYY-MM-DD HH:MM:SS,tags: - 標簽1- 標簽 2,description: 簡介(用于顯示在首頁)
這樣,程序需要在調(diào)用分析Markdown語法函數(shù)之前先逐行讀入源文件,匹配title、date等信息,直到讀入‘---時一并讀入源文件剩余全部內(nèi)容,并對剩余內(nèi)容調(diào)用Markdown分析器。源代碼(readfile.php):
//讀取分析markdown文件
function readMdFile($sFilename,&$array) {
$sMdFileDirName = "post/".$sFilename.".md";$array['ta gs'] = "";
$a r r ay['t a g s a r r ay'] = a r r ay();$h a nd le =fopen($sMdFileDirName,"r");
while (!feof($handle)) {$line = fgets($handle);
if (trim($line) == "---") {$sOriMdText =fread($handle,800000);
$array['postbody'] = Markdown::defaultTransform($sOri MdText);}
else {$strinfo = trim($line);$strlength = strlen($strinfo);
if (substr($strinfo,0,6)=="title:") {$array['pagetitle'] = su bstr($strinfo,6,$strlength-6);}if (substr($strinfo,0,5)=="date:"){
$a r r a y['d a t e t i m e'] = s u b s t r($s t r i n f o,5,$strlength-5);}if (substr($strinfo,0,5)=="tags:") { }i f(substr($strinfo,0,2)=="- ") {
$taginfo = substr($strinfo,2,$strlength-2);
$array['tags'] = $array['tags']. ' '; array_push($array['tags array'],$taginfo);}
if (substr($strinfo,0,12)=="description:") {
$d e s = s u b s t r($s t r i n f o,1 2,$s t r l e n g t h-12);$array['description'] = $des;}}}
5.1.2 根據(jù)文檔創(chuàng)建時間對內(nèi)容數(shù)據(jù)排序的實現(xiàn)原理
排序是程序設計中重要知識點,排序系統(tǒng)選用了簡單的冒泡排序,冒泡排序(Bubble Sort),是一種計算機科學領域的較簡單的排序算法。
它重復地走訪過要排序的數(shù)列,一次比較兩個元素,如果他們的順序錯誤就把他們交換過來。走訪數(shù)列的工作是重復地進行直到?jīng)]有再需要交換,也就是說該數(shù)列已經(jīng)排序完成。
這個算法的名字由來是因為越大的元素會經(jīng)由交換慢慢“浮”到數(shù)列的頂端,故名。
在scanfolder.php中實現(xiàn)如下:
//內(nèi)容數(shù)組根據(jù)文章創(chuàng)建時間排序使用的交換函數(shù)
function swap(&$array1,&$array2) {
$arraytemp = $array1;$array1 = $array2;$array2 =$arraytemp;}
for ($i=0;$i<$cnt;$i++) {for ($j=$i+1;$j<$cnt;$j++) {
$datei = $content[$i]['datetime'];$datej = $content[$j]['datetime'];
if (strtotime($datei) > strtotime($datej)) swap($content[$i],$content[$j]);}}
5.1.3 生成HTML時替換模板的實現(xiàn)原理
在項目中,引導同學嘗試了兩種方法進行模板的預留字符串替換。一種是模板字符串中直接使用$變量名標志需要替換的部分(實現(xiàn)于首頁模板和關于/友情鏈接模板),PHP中,用雙引號括起來的字符串中的$變量名會自動替換為$變量名的值。所以我們可以直接先將$變量名從內(nèi)容數(shù)組中賦值好,然后再用require引入模板,模板中標識的變量名就會自動替換為值。
第二種是模板中用’@變量名’去標識,在使用時先導入模板字符串,然后使用php內(nèi)置函數(shù)str_replace。
str_replace的模型是mixed str_replace(mixed $search,mixed $replace),將’@變量名’直接替換為值。
博客構(gòu)建系統(tǒng)的入口文件是scanfolder.php,用戶只需要將Markdown文件放在Post目錄下,運行scanfolder.php,就可以在out文件夾下生成整套博客。用戶可以將out文件夾重命名并拷貝至任何地方,都可以直接運行。
5.2.1 文件復制的實現(xiàn)
在程序開始生成html之前,系統(tǒng)需要將模板所需的CSS和Javascript文件拷貝至out文件夾下給生成的html提供方便攜帶的CSS/Javascript。PHP自身支持的copy函數(shù)只能支持單個文件的拷貝,案例中寫了一個xCopy函數(shù),用于遞歸拷貝一個文件夾內(nèi)所有文件和子文件夾里所有文件。代碼如下所示:
function xCopy($source, $destination, $child){
if (!is_dir($destination)) mkdir ($destination);$handle=di r($source);
while($entry=$handle->read()) {if(($entry!=".")&&($ent ry!="..")){
if(is_dir($source."/".$entry)){if ($child)
xCopy($source."/".$entry,$destination."/".$entry,$child);}else{
copy($source."/".$entry,$destination."/".$entry);}}}return 1;}
5.2.2 目錄掃描的實現(xiàn)
程序需要掃描整個post目錄,并將目錄下除了about.md(用于生成關于頁面)和links.md(用于生成友情鏈接頁面)的所有markdown文件篩選出來,這部分代碼如下:
$dir = './post'; if (is_dir($dir)) { $handle =opendir($dir);while (($file = readdir($handle)) !== false) {if(pathinfo($file, PATHINFO_EXTENSION) == 'md'
&& basename($file,'.md')!= 'about' && basename($file,'.md')!='links') {
r e a d M d F i l e(b a s e n a m e($f i l e,".md"),$content[$cnt]);$cnt++;}}closedir($handle);}
5.2.3 博客文章頁面的實現(xiàn)
博客文章頁面需要套用pagemodule://scanfolder.php//循環(huán)生成每篇文章的html
for ($i=0;$i<$cnt;$i++) {$pagetitle = $content[$i]['pagetitle'];$datetime = $content[$i]['datetime'];$tags =$content[$i]['tags'];$postbody = $content[$i]['postbody'];
$contentpre = $content[$i]['contentpre'];$contentnext =$content[$i]['contentnext'];
$titlepre = $content[$i]['titlepre'];$titlenext = $content[$i]['titlenext'];
//$key = $i+1;//$url = $i.'.html';$thispagetagcnt =count($content[$i]['tagsarray']);
//e c h o $t h i s p a g e t a g c n t;f o r($j=0;$j<$thispagetagcnt;$j++) {
$tagname = $content[$i]['tagsarray'][$j];if (!array_key_exists($tagname,$tagarray)) {
$tagcnt++;$tagarray["$tagname"] = array();}array_push($tagarray["$tagname"],$i);}
require('pagemodule.php');$sHtmlDirName = "out/".(string)($i+1).".html";
$strout = fopen($sHtmlDirName,"w");fwrite($strout,$str);fclose($strout);//echo $str;}
//pagemodule.php<!DOCTYPE html>
$datetime $tags
5.2.4 主頁的生成
在生成主頁時,系統(tǒng)需要按照時間倒序提取固定個數(shù)文章放在第一頁,實訓中提醒學生將主頁文章個數(shù)設置為5。同時,主頁的生成和文章頁面不同,主頁需要一個翻頁按鈕,我采用了拼接字符串的方法完成。
主頁對每篇文章需要展示的信息和文章頁面不同點在于文章使用postbody,主頁上是description。代碼:
if ($cnt > 5) $pageindexcnt = 5;else $pageindexcnt= $cnt;$pagecnt = ceil($cnt/5);$indexcnt = $cnt;for($k=0;$k<$pagecnt;$k++) {if ($k+1 == $pagecnt){$pageindexcnt = $indexcnt;}
require('indexmodule.php');for ($i=$indexcnt,$j=0;$j<$p ageindexcnt;$i--,$j++) {require('itemmodule.php');
$itemstr = str_replace("@pagetitle",$content[$i-1]['pagetitle'],$itemstr);
$itemstr = str_replace("@datetime",$content[$i-1]['datetime'],$itemstr);
$itemstr = str_replace("@tags",$content[$i-1]['tags'],$itemstr);
$itemstr = str_replace("@description",$content[$i-1]['description'],$itemstr);
$itemstr = str_replace("@pagelink",$i.'.html',$itemstr);
$strindexhead = $strindexhead . $itemstr;}
if ($k==0) $strindexend = str_replace("@prepage",'index.html',$strindexend);
else $strindexend = str_replace("@prepage",'index'.($k).'.html',$strindexend);
if ($k+1 == $pagecnt) $strindexend = str_replace("@nextpage",'index'.($k+1).'.html',$strindexend);
else $strindexend = str_replace("@nextpage",'index'.($k+2).'.html',$strindexend);
$s t r i n d e x h e a d = $s t r i n d e x h e a d .$strindexend;$stroutindex = fopen('out/index'.($k+1).'.html',"w");fwrite($stroutindex,$strindexhead);fclose($stroutindex);if($k==0) {$stroutindex2 = fopen('out/index.html','w');fwrite($stroutindex2,$strindexhead);
f c l o s e($s t r o u t i n d e x 2);}$i n d e x c n t -=$pageindexcnt;}<!DOCTYPE html>
@d at et i me@tags
5.2.5 歸檔的生成
歸檔更像是一個簡略版的主頁,不需要翻頁,也不需要帶入postbody或者description。
require('archivemodule.php');for ($i=$cnt-1;$i>=0;$i--){
require('archiveitemmodule.php');$archiveitemstr = str_replace("@pagetitle",$content[$i]['pagetitle'],$archiveitemstr);
$archiveitemstr = str_replace("@datetime",$content[$i]['datetime'],$archiveitemstr);
$archiveitemstr = str_replace("@pagelink",($i+1).'.html',$archiveitemstr);
$archive = $archive . $archiveitemstr;}$archive =$archive . $archiveend;
$stroutarc = fopen('out/archive.html',"w");fwrite($strout arc,$archive);fclose($stroutarc);
//a r c h i v e m o d u l e.p h p