38 번째 수정본
-
- 1. 기능 추가 또는 개선
-
-
- 1.1. 데이타 디렉토리와 설정 화일 위치 변경 (optional)
-
- 1.2. Index 의 페이지 목록을 제목의 첫글자별로 구분
-
- 1.3. 상단 메뉴바에 사용자 정의 링크 추가 (optional)
-
- 1.4. 외부 URL 옆에 "새 창으로 열기" 아이콘 표시 (optional)
-
- 1.5. 상단 메뉴에 상위페이지 아이콘 표시 (optional)
-
- 1.6. {{{ }}} 태그 추가
-
- 1.7. 이모티콘 도움말 추가
-
- 1.8. UseModWiki번역화일 사용
-
- 1.9. 페이지 목록에서 잠겨 있는 페이지 표시
-
- 1.10. 페이지 하단에 수정금지 여부와 설정/해제 표시 (optional)
-
- 1.11. 이미지에 마우스를 갖다 대면 URL 보임 (optional)
-
- 1.12. 편집을 취소하고 원래 페이지로 돌아가는 링크 추가
-
- 1.13. 페이지 수정 불가 메시지에, 사이트 제목 대신 페이지명이 나오도록 수정 (optional)
-
- 1.14. 탐색을 편하게 하기 위한 단축키 추가 (optional)
-
-
- 1.14.1. 검색란에 Alt+S 단축키 할당
-
- 1.14.2. 사이트 로고 이미지에 Alt+W 할당
-
- 1.14.3. 페이지 상단에 Alt+Z 할당
-
- 1.14.4. 페이지 하단에 Alt+X 할당
-
- 1.14.5. 텍스트 편집영역에 Alt+I 할당
-
1.15. 페이지 수정하기로 들어갔을 때 커서가 편집 영역에 놓이게 함
-
- 1.16. 로그인 화면에서 커서가 아이디 입력 필드에 놓이게 함
-
- 1.17. 페이지 정보 출력 양식 변경
-
- 1.18. {{{ }}} 태그 개선 및 SyntaxHighlighting 지원
-
- 1.19. 페이지를 저장할 때 수행되는 매크로 도입
-
-
- 1.19.1. <mysign> 매크로 도입
-
1.20. <mysign(name,time)> 매크로 도입
-
- 1.21. <include> 매크로 출력을 html 변환
-
- 1.22. 테이블 정렬 방식 개선 및 rowspan 기능 추가
-
- 1.23. <calendar> 매크로 추가
-
- 1.24. <wikiversion> 매크로 추가 (optional)
-
- 1.25. <vote(count[,scale])> 매크로 추가
-
- 1.26. 존재하지 않는 페이지의 링크를 WikiX 스타일로 출력
-
- 1.27. GetFullLinkList 함수에 파라메터 사용을 가능하게 함
-
- 1.28. 페이지 제목을 클릭했을때 진정한 의미의 역링크 출력
-
- 1.29. RemoveLink() 함수 추가
-
- 1.30. allpagesto 매크로 추가
-
- 1.31. allpagesfrom 매크로 추가
-
- 1.32. orphanedpages 매크로 추가
-
- 1.33. wantedpages 매크로 추가
-
- 1.34. includenotoc 매크로 추가
-
- 1.35. #EXTERN 명령어 추가
-
- 1.36. InterWiki 로 된 이미지 화일 처리
-
- 1.37. mms 프로토콜 인식
-
- 1.38. IMG: 태그 개선
-
- 1.39. 존재하지 않는 페이지의 링크 스타일을 사용자가 결정할 수 있게 함
-
- 1.40. userlist 매크로 추가
-
- 1.41. titleindex action 추가
-
- 1.42. form 을 생성할 때 form 의 이름을 부여할 수 있도록 함
-
1. 기능 추가 또는 개선
1.1. 데이타 디렉토리와 설정 화일 위치 변경 (optional)
- 웹브라우저에서 데이타 디렉토리 내의 내용을 직접 억세스 할 수 있기 때문에, 특히나 user 디렉토리 밑에 있는 사용자 정보를 읽을 수 있었다.
- wiki.pl 을 수정하여, 데이타 디렉토리와 config 화일의 이름을 바꾸고, (사실 이름만 그럴싸하게 바꿔도 밖에서 들여다보기는 힘들겠지만) public_html 디렉토리 밖으로 이동시켰다.
- 부작용 : 알려진 것 없음
- 화일 경로명을 바꿨을 뿐이니, 부작용이 생길 여지가 보이지 않는다
-
# == Configuration =====================================================
# $DataDir = "data"; # Main wiki directory
# 자기가 사용할 데이타 디렉토리와 설정화일명을 아래에 적어준다
$DataDir = "newdata"; # Main wiki directory
$ConfigFile = "newconfig.pl"; # path of config file
-
sub DoWikiRequest {
# if 구문을 다음과 같이 고친다
# if ($UseConfig && (-f "config.pl")) {
# do "config.pl"; # Later consider error checking?
# }
if ($UseConfig && (-f $ConfigFile)) {
do "$ConfigFile";
}
...
}
- 간단하게는, 데이타 디렉토리 안에 .htaccess 화일을 만들어서 그 안에 "deny from all" (따옴표 제외) 라고만 적어줘도 아파치 서버에서는 브라우저를 통해서 들여다 볼 수 없게 할 수 있다.
1.2. Index 의 페이지 목록을 제목의 첫글자별로 구분
- 상단 메뉴의 index 를 클릭했을때 기존에 페이지들이 알파벳 순으로 출력되는 것을 개선하여, 첫글자에 따라 A,B,...,가,나,... 등으로 색인을 나눔.
- [jof4002님의 패치]를 적용함
- 여기에 다시 추가로, 목록 상단에 각 머리글자로 한 번에 이동할 수 있도록 링크를 추가함
- 주인장이 직접 고침. perl 에 대해 전혀 모른 상태에서 기존 소스만 보고 고친 탓에 지저분하다.
-
# 다음의 함수를 통채로 바꿈
sub PrintPageList {
my ($pagename);
my $count = 0;
my $titleIsPrinted = 0;
my @han = qw(가 나 다 라 마 바 사 아 자 차 카 타 파 하);
my @indexTitle = (0, "A".."Z");
push (@indexTitle, @han, "기타");
my @indexSearch=("A".."Z");
push (@indexSearch, @han, "豈");
print "<h2>", Ts('페이지 수: %s', ($#_ + 1)), "</h2>\n";
my $count2 = 0;
print("\n|");
while ( $count2 <= $#indexTitle ) {
if ($count2 == 27) {
print("<br>\n|");
}
print("<a href=\"#H_$indexTitle[$count2]\"><b>");
print(" $indexTitle[$count2] ");
print("</b></a>|");
$count2++;
}
print "<br><br>";
$count2 = 0;
foreach $pagename(@_) {
until (
$pagename lt @indexSearch[$count]
&& ($count == 0 || $pagename gt @indexSearch[$count-1])
) {
$count++;
$titleIsPrinted = 0;
last if $count > 40;
}
if (!$titleIsPrinted) {
while ( $count2 <= ($count - 1) ) {
print "\n<a name=\"H_$indexTitle[$count2]\">";
print "</a>";
$count2++;
}
print "\n<a name=\"H_$indexTitle[$count]\">";
print $q->h3($indexTitle[$count]);
print "</a>";
$count2 = $count + 1;
$titleIsPrinted=1;
}
print ".... " if ($pagename =~ m|/|);
print &GetPageLink($pagename);
if (&UserIsAdmin()) {
print " | " . &ScriptLink("action=pagelock&set=1&id=" .$pagename, T('lock'));
print " | " . &ScriptLink("action=pagelock&set=0&id=" .$pagename, T('unlock'));
}
print $q->br;
print "\n";
}
}
1.3. 상단 메뉴바에 사용자 정의 링크 추가 (optional)
- 기존 소스에서 UserGotoBar 라는 변수를 사용해서 사용자 메뉴 항목을 상단 메뉴 오른쪽 끝에 표시한다.
- UserGotoBar2~UserGotoBar4 세 개의 변수를 추가하여 상단 메뉴에 포함
- 부작용 : 알려진 것 없음
- 단순한 출력 변경이라, 전혀 없을 것이라 짐작함
-
### 제일 끝에 UserGotoBar2~4 추가
use vars qw(@RcDays @HtmlPairs @HtmlSingle
$TempDir $LockDir $DataDir $HtmlDir $UserDir $KeepDir $PageDir
...
$UserGotoBar $UserGotoBar2 $UserGotoBar3 $UserGotoBar4);
...
-
sub GetGotoBar {
...
$bartext .= ' </td><td> ' . &GetSearchForm();
if ($UserGotoBar ne '') {
$bartext .= " </td><td> " . $UserGotoBar;
}
### 다음 단락을 추가. UserGotoBar3 와 4 도 원하는 위치에 삽입하면 됨
if ($UserGotoBar2 ne '') {
$bartext .= " </td><td> " . $UserGotoBar2;
}
### 여기까지
$bartext .= "</td></tr>";
$bartext .= $q->endform;
$bartext .= "</table><hr>\n";
return $bartext;
}
...
1.4. 외부 URL 옆에 "새 창으로 열기" 아이콘 표시 (optional)
- 외부 URL 또는 인터위키 링크 옆에 있는
아이콘을 클릭하면 새 창이 뜬다.
- [jof4002님의 패치]를 적용함
- 아이콘은 친구 danny가 자신의 홈페이지에서 사용하려고 만든 것을 가져다가 좀 더 날씬하게 바꿨음. :-)
- 부작용 : 알려진 것 없음
- 단순한 출력 변경이라, 전혀 없을 것이라 짐작함
-
sub InterPageLink {
...
# return ("<a href=\"$url\">$name</a>", $punct);
return ("<a href=\"$url\">$name</a><a href=\"$url\" target=\"_blank\"><img src=\"아이콘경로\" border=\"0\" alt=\"새 창으로 열기\" align=\" absbottom\"></a>", $punct);
}
-
sub StoreBracketInterPage {
...
# return &StoreRaw("<a href=\"$url\">[$text]</a>");
return &StoreRaw("<a href=\"$url\">[$text]</a><a href=\"$url\" target=\"_blank\"><img src=\"아이콘경로\" border=\"0\" alt=\"새 창으로 열기\" align=\"absbottom\"></a>");
}
-
sub UrlLink {
...
# return ("<a href=\"$name\">$name</a>", $punct);
return ("<a href=\"$name\">$name</a><a href=\"$name\" target=\"_blank\"><img src=\"아이콘경로\" border=\"0\" alt=\"새 창으로 열기\" align=\"absbottom\"></a>", $punct);
}
-
sub StoreBracketUrl {
...
# return &StoreRaw("<a href=\"$url\">[$text]</a>");
return &StoreRaw("<a href=\"$url\">[$text]</a><a href=\"$url\" target=\"_blank\"><img src=\"아이콘경로\" border=\"0\" alt=\"새 창으로 열기\" align=\"absbottom\"></a>");
}
1.5. 상단 메뉴에 상위페이지 아이콘 표시 (optional)
- 하위페이지의 경우, 상단 메뉴에 상위페이지로 가는 링크가 추가되는데, 이 링크가 다른 링크 사이에 묻혀 잘 눈에 띄지 않는다.
- 상위페이지 이름 앞에
아이콘을 표시하게 함
- 부작용 : 알려진 것 없음
- 단순한 출력 변경이라, 전혀 없을 것이라 짐작함
-
...
sub GetGotoBar {
...
if ($id =~ m|/|) {
$main = $id;
$main =~ s|/.*||; # Only the main page name (remove subpage)
# $bartext .= " </td><td> " . &GetPageLink($main); 이 줄을 아래와 같이 바꾼다
$bartext .= " </td><td> <img src=\"./emoticon/parentpage.gif\" border=\"0\" alt=\"상위페이지: $main\" align=\"absmiddle\">" . &GetPageLink($main);
}
...
}
...
1.6. {{{ }}} 태그 추가
- 아래에 있는 "{{{ }}} 태그 개선 및 SyntaxHighlighting 지원" 항목에서 다시 코드가 수정되었기 때문에, 이 항목은 더 이상 유효하지 않다.
1.7. 이모티콘 도움말 추가
- 페이지 수정 모드에서, 상단 메뉴 아래에 있는 도움말에 "이모티콘" 항목을 추가
- danny의 패치를 약간 수정하여 적용
- $UseEmoticon 값에 따라 출력 내용이 달라진다.
- 부작용 : 알려진 것 없음
-
sub DoHelp {
...
<goto(바보)>
|;
}
### 여기서부터 추가
elsif ($idx eq 5) {
if ($UseEmoticon eq 0) {
$text = q|
'''현재 이 홈페이지에서는 이모티콘을 사용하지 않도록 설정되어 있습니다.'''
'''따라서 아래의 도움말은 적용되지 않습니다.'''
|;
}
$text .= q|
== 이모티콘 ==
이모티콘은 감정표현에 사용되는 작은 그림입니다. <br>
다음과 같은 문자열 중 하나를 입력하시면 왼쪽의 그림이 자동으로 삽입됩니다.
* ^^ <nowiki>^^ ^-^ ^_^ ^o^ ^O^ ^^; ^-^; ^_^; ^o^ ^O^ :-D :D</nowiki>
* :-) <nowiki>:-)</nowiki>
* -_- <nowiki>-_- -_-; =.= =.=; :-s :-S</nowiki>
* o.O <nowiki>o.O *.* :-o :-O :o :O</nowiki>
* :-( <nowiki>:-( :(</nowiki>
* :-p <nowiki>:-p :-P :p :P</nowiki>
* ;-) <nowiki>;-) ;)</nowiki>
|;
}
### 여기까지
$ClickEdit = 0;
print &GetHttpHeader();
...
}
-
sub DoEdit {
...
print &HelpLink(3, "링크와 이미지") . " | ";
# print &HelpLink(4, "매크로") . "<br>"; 이 줄을 아래 두 줄로 바꿈
print &HelpLink(4, "매크로") . " | ";
print &HelpLink(5, "이모티콘") . "<br>";
print &GetFormStart();
...
}
- wiki.pl 을 수정하여, Luke 님이 한글로 바꾸어 적었던 것들을 원래의 영문 메시지로 전부 바꿈
- korean.pl 이라는 이름의 UseModWiki번역화일을 작성하여, 이 안에 Translate 해쉬변수의 값을 정의하였다.
- 현재, 오리지널 UseModWiki 에서 지정되어 있는 205개와, 여기에 별도로 추가되고 있는 40여개의 메시지 엔트리가 있다. 이 중 몇�m 메시지는 어떤 상황에서 출력되는지를 파악하지 못하여 그대로 영문으로 둠
- config.pl 또는 wiki.pl 내에 다음과 같이 적어주면 UseModWiki번역화일을 사용하게 된다.
-
do "./translations/korean.pl"; # 번역 화일의 경로
- wiki.pl 에서 변경된 부분이 너무 많아서 여기에 적을 수가 없습니다. (소스에 주석처리도 하지 않았습니다) 기존에 사용하고 있는 소스를 바꾸고 싶지 않다면, korean.pl 화일을 가져가고 위에 적은 한 줄만 추가하여서 그냥 사용하셔도 될 겁니다. 이 경우, Luke 님이 고쳐둔 한글메시지는 언어팩 설정의 영향을 받지 않고 무조건 한글로 나오게 되겠죠.
1.9. 페이지 목록에서 잠겨 있는 페이지 표시
- 관리자로 로긴했을 때, 페이지 목록을 보면 각 페이지 제목 옆에 lock 과 unlock 두 가지 기능이 있는데, 정작 각 페이지가 현재 잠겨 있는지 그렇지 않은지를 알려면 쉘에서 lock 화일을 찾는 수 밖에 없다. (아니면 로그아웃해서 각각의 페이지를 확인하던가..)
- wiki.pl 을 수정하여, 관리자로 로긴하여 index 화면에 들어갈 경우, 잠긴 화일 옆에는 "(locked)" 라는 표시가 추가로 보이게 하였음
- 관리자 아닌 경우에도 표시되게 하고 싶다면, if (&UserIsAdmin()) { 라인 위쪽에 적어주면 될 터이다. 그렇지만 방문자들이 index 를 볼 때마다 lock 화일을 찾는 과정을 거쳐야 하므로, 페이지 수가 많고 방문객도 많은 사이트에서는 시스템을 혹사시킬 듯 하다.
- 부작용:
- 페이지 수가 많을 경우, 각 페이지에 대한 lock 화일을 찾아야 하므로 시스템 성능 저하가 예상됨 - lock 화일이 있는 페이지의 목록을 미리 만들어 두었다가 비교하는 방법이 더 낫지 않을까 함
-
sub PrintPageList {
...
if (&UserIsAdmin()) {
### 아래의 if { } 문 삽입
if (-f &GetLockedPageFile($pagename)) {
print " " . T('(locked)');
}
### 여기까지
print " | " . &ScriptLink("action=pagelock&set=1&id=" . $pagename, T('lock'));
print " | " . &ScriptLink("action=pagelock&set=0&id=" . $pagename, T('unlock'));
}
...
}
1.10. 페이지 하단에 수정금지 여부와 설정/해제 표시 (optional)
- 관리자 권한이 있는 경우는, 페이지 내용을 볼 때 그 페이지가 수정금지 설정이 되어 있는지 여부와, 설정/해제 기능을 하는 링크를 화면 하단에 표시하도록 하였다
- 매번 index 화면에 가서 하자니 귀찮아서... :-)
- 부작용 : 알려진 것 없음
-
sub GetEditGuide {
my ($id, $rev) = @_;
my $result = "<div align=right>";
### 다음 코드를 삽입.
if (&UserIsAdmin()) {
if (-f &GetLockedPageFile($id)) {
$result .= T('(locked)') . " | ";
}
$result .= &ScriptLink("action=pagelock&set=1&id=" . $id, T('lock'));
$result .= " | " . &ScriptLink("action=pagelock&set=0&id=" . $id, T('unlock'));
$result .= "<br>";
}
### 여기까지
if (&UserCanEdit($id, 0)) {
if ($rev ne '') {
...
}
1.11. 이미지에 마우스를 갖다 대면 URL 보임 (optional)
- 애초 의도는 이모티콘 그림에 마우스를 갖다대면 원래 입력했던 문자 이모티콘이 보이게 하려는 것이었으나.. 그러자면 너무 많은 부분을 뜯어고쳐야 된다는 것을 깨닫고 관뒀음.
- 부작용: 생길 여지가 없는 듯 함
-
sub UrlLink {
...
if ($useImage && ($name =~ /^(http:|https:|ftp:).+\.$ImageExtensions$/)) {
$name = $1 if ($name =~ /^https?:(.*)/ && $1 !~ /^\/\//);
### 다음 라인을 수정
# return ("<img $ImageTag src=\"$name\">", $punct);
return ("<img $ImageTag src=\"$name\" alt=\"$name\">", $punct);
###
}
...
}
1.12. 편집을 취소하고 원래 페이지로 돌아가는 링크 추가
-
sub DoEdit {
....
print "<h2>", T('Preview only, not yet saved'), "</h2>\n";
}
### 다음 라인을 추가
print Ts('Return to %s' , &GetPageLink($id)) . " | ";
###
print &GetHistoryLink($id, T('View other revisions')) . "<br>\n";
...
}
1.13. 페이지 수정 불가 메시지에, 사이트 제목 대신 페이지명이 나오도록 수정 (optional)
- 수정 권한이 없는 사용자가 페이지를 수정하려고 할 때, 수정할 수 없다는 메세지가 나오는데, 그 메시지에 홈페이지 이름이 나오는 것을 해당 페이지 이름이 나오도록 수정
- 이 홈페이지에서는 개별 페이지에 따라 락이 걸린 상태라서 그게 더 합당한데, 만일 사이트 전체에 락을 거는 경우라면 고치지 않는게 더 나을 듯도 하다.
-
sub DoEdit {
...
if (!&UserCanEdit($id, 1)) {
...
} else {
### 다음 라인을 수정
# print Ts('Editing not allowed: %s is read-only.', $SiteName);
print Ts('Editing not allowed: %s is read-only.', $id);
###
}
print &GetCommonFooter();
return;
}
# Consider sending a new user-ID cookie if user does not have one
...
}
1.14. 탐색을 편하게 하기 위한 단축키 추가 (optional)
- 마우스를 최대한 사용하지 않고 탭키와 엔터키를 사용하여 서핑을 할 수 있도록 UseModWiki단축키들을 추가함
- 부작용:
- 딱히 문제가 생기지는 않으나, 소스 코드 내에서 제공하는 링크 생성 함수들(GetSearchLink, ScriptLink, GetPageLink, GetEditLink 등)을 사용하지 않고 직접 html 코드를 뿌리기 때문에, 일관성을 떨어뜨리고, 차후에 소스 코드를 다시 수정할 때 복잡해질 우려가 있다.
1.14.1. 검색란에 Alt+S 단축키 할당
- Alt+S 를 누르면 상단메뉴 검색란에 커서가 옮겨가도록 수정
- 겸사겸사, 검색란 왼쪽에 있는 "Search:" 라는 문자열도 UseModWiki번역화일의 적용을 받도록 하였다.
-
sub GetSearchForm {
my ($result);
### 다음 부분을 변경
# $result = "Search: <input class=text type=text name='search' size=10>"
# . $q->textfield(-name=>'search', -size=>12)
# . &GetHiddenValue("dosearch", 1);
$result = T('Search:') . " <input accesskey=\"s\"class=text type=text name='search' size=10>"
. &GetHiddenValue("dosearch", 1);
###
return $result;
}
1.14.2. 사이트 로고 이미지에 Alt+W 할당
- Alt+W 를 누르면 로고 이미지가 선택되고, 그 상태에서 엔터키를 누르면 홈페이지 대문으로 이동한다.
-
sub GetHeader {
...
if ((!$embed) && ($LogoUrl ne "")) {
$logoImage = "img src=\"$LogoUrl\" alt=\"$altText\" border=0";
if (!$LogoLeft) {
$logoImage .= " align=\"right\"";
}
### 다음 라인을 아래와 같이 바꾼다
# $header = &ScriptLink($HomePage, "<$logoImage>");
$header = "<a accesskey=\"w\" href=\"$ScriptName?$HomePage\"><$logoImage></a>";
###
}
if ($id ne '') {
...
}
1.14.3. 페이지 상단에 Alt+Z 할당
- 상단에 "Bottom" 이라는 링크를 추가
- Alt+Z 를 누르면 그 링크로 이동하고, 엔터키를 누르면 페이지 제일 마지막에 있는 "Top" 링크로 이동
- 로고 이미지로 가는 단축키가 있으니 굳이 이 링크가 필요할까 싶긴 한데, 반대로 마우스로만 서핑하는 경우 클릭 한 번에 페이지 끝으로 이동할 방법이 있어야겠기에 추가하였다. 썩 좋은 미관은 아니군.
-
sub GetHeader {
...
$result .= $q->h1($header . $title);
}
### 다음 라인 추가
$result .= "\n<div align=\"right\"><a accesskey=\"z\" name=\"#PAGE_TOP\" href=\"#PAGE_BOTTOM\">". T('Bottom') . "</a></div>\n";
###
if (&GetParam("toplinkbar", 1)) {
# Later consider smaller size?
...
}
1.14.4. 페이지 하단에 Alt+X 할당
- 하단에 "Top" 이라는 링크를 추가
- Alt+X 를 누르면 이 링크로 이동하고, 엔터키를 누르면 페이지 상단의 "Bottom" 링크로 이동한다.
- Bab2 님의 제보로 (감사합니다), $FooterNote 를 사용자가 따로 설정해 둔 경우 제대로 동작하지 않는 문제가 있다는 것을 발견하고 수정했음.
- $FooterNote 에 align=right 속성을 가진 이미지 등이 올 경우 Top 링크가 이미지와 같은 라인에 포함되어 버릴 수 있다. $FooterNote 의 내용을 <p align=right>내용</p> 와 같이 적어넣으면 해결된다.
-
sub GetMinimumFooter {
# 함수의 본문을 통채로 바꾼다.
# if ($FooterNote ne '') {
# return T($FooterNote) . $q->end_html; # Allow local translations
# }
# return $q->end_html;
my $result = '';
if ($FooterNote ne '') {
$result .= T($FooterNote); # Allow local translations
}
$result .= "\n<div align=\"right\"><a accesskey=\"x\" name=\"#PAGE_BOTTOM\" href=\"#PAGE_TOP\">" . T('Top') . "</a></div>\n" . $q->end_html;
return $result;
}
1.14.5. 텍스트 편집영역에 Alt+I 할당
- 페이지를 수정할 때나, 관리자 모드에서 링크관리 등을 할 때 Alt+I 를 누르면 텍스트 편집영역으로 커서가 이동한다.
- edit conflict 가 발생할 때는, 편집영역이 두 개가 나타난다. (저장될 텍스트, 자신이 입력한 텍스트) 이 때 두 편집 영역에 동시에 같은 단축키가 할당되는 문제가 있다. 그런데 Internet Explorer 에서 테스트해봤더니, Alt+I 를 누를 때마다 커서가 양쪽 창을 번갈아가며 이동하길래, 차라리 잘 됐다..고 생각하고 넘어가기로 했다. :-)
-
sub GetTextArea {
my ($name, $text, $rows, $cols) = @_;
### 이건 부등호 처리문제 패치에서 적용한 라인
$text =~ s/(\&)/\&/g;
### 아래의 두 return 문에 accesskey 값을 추가한다.
# if (&GetParam("editwide", 1)) {
# return $q->textarea(-name=>$name, -default=>$text,
# -rows=>$rows, -columns=>$cols, -override=>1,
# -style=>'width:100%', -wrap=>'virtual');
# }
# return $q->textarea(-name=>$name, -default=>$text,
# -rows=>$rows, -columns=>$cols, -override=>1,
# -wrap=>'virtual');
if (&GetParam("editwide", 1)) {
return $q->textarea(-accesskey=>'i', -name=>$name, -default=>$text,
-rows=>$rows, -columns=>$cols, -override=>1,
-style=>'width:100%', -wrap=>'virtual');
}
return $q->textarea(-accesskey=>'i', -name=>$name, -default=>$text,
-rows=>$rows, -columns=>$cols, -override=>1,
-wrap=>'virtual');
###
}
1.15. 페이지 수정하기로 들어갔을 때 커서가 편집 영역에 놓이게 함
- 페이지 수정하기로 들어간 직후에 편집을 하기 위해서 마우스로 편집 영역을 클릭해야 되는 것이 귀찮아서..
- Perl 도 모르고 JavaScript는 더더욱 모르는 채로 JavaScript를 출력하도록 perl 코드를 수정하다.. -.-;
- 아래에 있는 "form 을 생성할 때 form 의 이름을 부여할 수 있도록 함" 패치가 적용되어 있어야 한다.
- 부작용: 알려진 것 없음
-
sub DoEdit {
...
print &HelpLink(5, "이모티콘") . "<br>\n";
### 다음 라인 교체
# print &GetFormStart();
print &GetFormStart("form_edit"); # 예전 패치에 없던 부분
###
print &GetHiddenValue("title", $id), "\n",
...
print $q->endform;
### 다음 코드를 추가
print "\n<script language=\"JavaScript\" type=\"text/javascript\">\n"
. "<!--\n"
. "document.form_edit.text.focus();\n" # 예전 패치에서 재수정
. "//-->\n"
. "</script>\n";
### 여기까지
print &GetMinimumFooter();
}
1.16. 로그인 화면에서 커서가 아이디 입력 필드에 놓이게 함
- 로그인할 때 커서가 자동으로 아이디 입력 필드에 위치하도록 함
- 아래에 있는 "form 을 생성할 때 form 의 이름을 부여할 수 있도록 함" 패치가 적용되어 있어야 한다.
-
sub DoEnterLogin {
print &GetHeader('', T('Login'), "");
### 다음 라인 교체
# print &GetFormStart();
print &GetFormStart("form_login"); # 예전 패치에 없던 부분
###
print &ScriptLink("action=newlogin", T('Create new UserName') . "<br>");
...
print $q->endform;
### 다음 단락 추가
print "\n<script language=\"JavaScript\" type=\"text/javascript\">\n"
. "<!--\n"
. "document.form_login.p_userid.focus();\n" # 예전 패치에서 재수정
. "//-->\n"
. "</script>\n";
###
print &GetMinimumFooter();
}
1.17. 페이지 정보 출력 양식 변경
- 각 페이지 아래에 있는 변경내역보기, 수정하기 등의 링크들의 순서를 바꿨다.
- 딱히 이유가 있는 것은 아니고, Alt+X 를 누른후 Shift+Tab 을 한 번만 눌러서 "이 페이지를 수정" 링크로 이동할 수 있도록 하기 위함이다. :-)
- GetEditGuide 함수 뒷부분의 if 구문들의 순서를 바꾸고, 중간에 <br> 을 출력하는 라인을 삽입한다
-
sub GetEditGuide {
...
# if (&UserCanEdit($id, 0)) { 여기서부터
# if ($rev ne '') {
# ...
#
# $result .= "</div>"; 여기까지를 다음과 같이 변경
if ($Section{'revision'} > 0) {
$result .= '<br>';
if ($rev eq '') { # Only for most current rev
$result .= T('Last edited');
} else {
$result .= T('Edited');
}
$result .= ' ' . &TimeToText($Section{ts});
}
if ($UseDiff) {
$result .= ' ' . &ScriptLinkDiff(4, $id, T('(diff)'), $rev);
}
$result .= '<br>';
$result .= &GetHistoryLink($id, T('History'));
if ($rev ne '') {
$result .= ' | ';
$result .= &GetPageLinkText($id, T('View current revision'));
}
$result .= ' | ';
if (&UserCanEdit($id, 0)) {
if ($rev ne '') {
$result .= &GetOldPageLink('edit', $id, $rev,
Ts('Edit revision %s of this page', $rev));
} else {
$result .= &GetEditLink($id, T('Edit text of this page'));
}
} else {
$result .= T('This page is read-only');
}
$result .= "</div>";
### 여기까지
return $result;
}
1.18. {{{ }}} 태그 개선 및 SyntaxHighlighting 지원
- 숙원 사업 하나를 풀다. 만세.
- 기존에 있던 "{{{ }}} 태그 추가" 항목은 더 이상 유효하지 않다.
- 내용이 길어서 사용자입력을그대로출력하기에 따로 기술하겠음
- 부작용: 매우 많음 ^^
- 기존에 {{{ }}} 태그를 사용했던 페이지들이 제대로 출력되지 않을 수 있으니 점검할 것
- SyntaxHighlighting 을 많이 사용한 페이지는 경우 로딩 속도가 현저하게 느려진다.
- 데이타를 html 로 변환하는 주요 루틴을 뜯어 고쳤기 때문에, 이 외에 어떤 문제가 생길지 모른다. :-)
- {{{ }}} 내부에 있는 위키네임이나 이중 대괄호쌍이 있을 경우, 본문 출력시에는 이들을 링크로 간주하지 않으나 역링크 검색이나 전체 링크 목록 출력 화면에서는 링크로 간주한다. 이것을 막으려면 다음을 수정한다.
-
sub GetPageLinks {
...
$text =~ s/<code>(.|\n)*?\<\/code>/ /ig;
### 다음 두 줄 추가
$text =~ s/(^|\n)\{\{\{[ \t\r\f]*\n((.|\n)*?)\n\}\}\}[ \t\r\f]*\n/ \n/igm;
$text =~ s/(^|\n)\{\{\{([a-zA-Z0-9+]+)(\|(n|\d*|n\d+|\d+n))?[ \t\r\f]*\n((.|\n)*?)\n\}\}\}[ \t\r\f]*\n/ \n/igm;
### 여기까지
if ($interlink) {
$text =~ s/''+/ /g; # Quotes can adjacent to inter-site links
...
}
1.19. 페이지를 저장할 때 수행되는 매크로 도입
- 현재 UseModWiki 에서 지원하는 모든 매크로나 태그들은, 사용자가 입력한 그대로 저장이 되었다가, 화면에 출력할 때 매번 wiki.pl 이 내용을 적절히 치환하여 출력한다. 따라서 매크로의 출력 결과는, 페이지를 열람하는 순간의 상태에 좌우된다.
- 아래에 나오는 <mysign> 과 같이, 페이지를 "작성하는" 순간의 상태에 의존하는 출력을 얻을 수 있었으면..하여 뚝딱거려보았다.
- 부작용:
- 아래에 언급되는 매크로들은 출력시 변환되는 게 아니라 입력시 변환되어 저장된다.
- 따라서, 한 번 저장하고 나면 원래의 매크로가 아닌 치환된 문자열만이 남아 있게 된다. 페이지 수정하기로 들어가 보면 알 수 있다.
- 기존에 동작하는 모든 태깅, 치환 등보다 앞서서 적용되어 버린다. 대표적으로, {{{ }}} 안에 적어도 치환되어 버리니 주의할 것. 게다가 {{{ }}} 안에서는 < 등의 escape 도 통하지 않으므로, "<mysign>" 을 문자 그대로 출력되게 할 방법이 없다.
- 변환하는 시점이 타당한지 확신이 서지를 않는다. 테스트하는 동안은 잘 동작했는데, 예기치 않은 곳에서 엉뚱하게 동작할 우려가 있다.
- 다음과 같이 DoPost 함수 내에 ProcessPostMacro() 함수를 삽입한다.
sub DoPost {
...
# Remove "\r"-s (0x0d) from the string
$string =~ s/\r//g;
### 다음 라인 추가
$string = &ProcessPostMacro($string);
###
# Lock before getting old page to prevent races
&RequestLock() or die(T('Could not get editing lock'));
...
- 그 다음, 적당한 위치에 ProcessPostMacro() 함수를 통채로 작성한다.
sub ProcessPostMacro {
my ($string) = @_;
### 여기에 사용할 매크로들을 나열한다
$string = &PostMacroMySign($string);
return $string;
}
- 이제 "작성시 변환되는 매크로"를 도입하고 싶다면, 적절한 변환 함수를 작성하고, 그 함수를 위의 ProcessPostMacro 안에서 다음과 같이 호출해준다.
$string = &내가추가한함수($string);
- 또한, 미리보기 창에서도 이런 매크로가 정의되게 하기 위해서, DoPreview() 함수도 마찬가지로 수정한다.
sub DoPreview {
$ClickEdit = 0;
print &GetHttpHeader();
print &GetHtmlHeader("$SiteName: " . T('Preview'), "Preview");
### 다음 라인을 아래 두 줄로 교체
# print &WikiToHTML(&GetParam("text", undef));
my ($textPreview) = &GetParam("text", undef);
print &WikiToHTML(&ProcessPostMacro($textPreview));
###
}
1.19.1. <mysign> 매크로 도입
- WikiX에 있는 기능이 너무 맘에 들어서 흉내를 내보았다. ^^;
- 게시판 등의 페이지에서 글을 쓴 후에, 끝에 <mysign> 이라고 적고 "저장" 버튼을 누르면 <mysign(편집자ID,편집시각)>으로 치환되어 저장된다. 로그인하지 않았을 경우는 편집자id 대신에 IP 주소가 저장된다.
- 이렇게 저장된 매크로는 다시 페이지 열람시에 적절하게 변환된다.
- 다음 함수를 적당한 위치에 추가하고, 위에서 언급한 ProcessPostMacro() 함수내에서 호출하도록 한다.
sub PostMacroMySign {
my ($string) = @_;
my ($authorAddr) = $ENV{REMOTE_ADDR};
my ($timestamp) = CalcDay($Now) . " " . CalcTime($Now);
my ($author) = &GetParam('username');
if ($author ne "") {
# 이 시점에서 [[ ]] 를 붙이는 것이 옳은가 확인할 것
$author = "[[$author]]";
} else {
$author = $authorAddr;
# 아래의 주석을 해제하면 ip 끝자리를 xxx 로 표시한다
# $author =~ s/\d+$/xxx/;
}
# 아래에 <mysign > 의 n 과 우측부등호 사이에 공백이 없게 할 것.
$string =~ s/<mysign >/<mysign($author,$timestamp)>/g;
return $string;
}
1.20. <mysign(name,time)> 매크로 도입
- 게시판 등에서 <mysign(name,time)> 의 형태로 적으면, 우측으로 정렬되는 서명을 출력한다.
- name 과 time 자리에 들어갈 수 있는 값에 대해 조건이 복잡하다. 잘못된 값을 넣어 예상하지 못한 출력이 나오는 것을 막아보고자 함이니, 이 매크로를 직접 사용하지 말고 <mysign> 를 사용하는 것을 권장한다.
- 이런, mysign(name,time) 을 임의로 작성하는 것을 최대한 막으려고 엄격하게 검사를 시켰더니만, $UseAmPm 변수가 0일 경우 (am, pm 을 쓰지 않고 24시간제로 표시) 제대로 치환이 되지 않는 문제가 있었다. 정규표현식을 수정하여 해결.
-
sub MacroSubst {
...
# 원래 소스 코드에는 < 와 > 로 적혀 있는 것을, {{{ }}} 태그 사용을 위하여
# &__LT__; 와 &__GT__; 로 수정했다. 자세한 내용은 {{{ }}} 태그 도입 항목을 참조
$txt =~ s/\&__LT__;goto\((.*)\)\&__GT__;/&MacroGoto($1)/gei;
$txt =~ s/\&__LT__;history\((.*)\)\&__GT__;/&MacroHistory($1)/gei;
### 다음 라인을 추가
$txt =~ s/\&__LT__;mysign\(([^,]+),(\d+-\d+-\d+ \d+:\d+.*)\)\&__GT__;/&MacroMySign($1, $2)/gei;
###
return $txt;
}
- 적당한 위치에 MacroMySign 함수 전체를 삽입한다
sub MacroMySign {
my ($author, $timestamp) = @_;
return "\n<div align=\"right\">-- $author <small>$timestamp</small></div>\n";
}
1.21. <include> 매크로 출력을 html 변환
- <include(A)> 로 A 페이지의 내용을 불러올 때, A 페이지의 내용은 위키에서 처리하지 않고 소스 그대로 출력되는 것을 개선.
- "문제 해결"이 아니라 "개선" 항목으로 취급하는 이유는, 원래의 방식과 장단점이 있어서 반드시 수정해야 할 필요는 없다고 보기 때문이다.
-
프로그래밍팁/Wiki 에 있는 지양님의 패치를 적용.
- 포함되는 페이지 안에 있는 include 태그는 처리되지 않는다. (처리되면 곤란하다. 무한루프에 빠질 수 있기 때문이다)
- 부작용:
- 원래의 페이지와 포함되는 페이지들 안에 각각 # 으로 시작하는 헤드라인이 있을 경우 <toc> 태그의 변환이 정상적이지 않다. 모든 헤드라인을 전부 아울러 목차를 만든다.
- include 매크로의 처리 순서를 다른 매크로들과는 달리 하였기 때문에, 소스의 일관성이 떨어진다.
-
sub WikiToHTML {
...
$SaveNumUrlIndex = 0;
$pageText =~ s/$FS//g; # Remove separators (paranoia)
### 다름 라인 추가
$pageText = &MacroIncludeSubst($pageText);
###
if ($RawHtml) {
...
}
-
sub MacroSubst {
...
$txt =~ s/\&__LT__;RandomPage\((.*)\)\&__GT__;/&MacroRandom($1)/gei;
### 다음 라인 주석 처리
# $txt =~ s/\&__LT__;Include\((.*)\)\&__GT__;/&MacroInclude($1)/gei;
...
-
### 다음 함수를 통채로 추가
sub MacroIncludeSubst {
my ($txt) = @_;
$txt =~ s/<Include\((.*)\)>/&MacroInclude($1)/gei;
return $txt;
}
1.22. 테이블 정렬 방식 개선 및 rowspan 기능 추가
- || 를 사용하여 테이블을 만들 때, 테이블 안의 텍스트가 항상 가운데 정렬만 되었다.
- 테이블 내의 셀마다 별도로 정렬 방식을 지정할 수 있게 하고, rowspan 을 원하는 값을 지정할 수 있게 했다.
- 사용법 - |(| 또는 < 또는 >)[v[숫자]]
** 자세한 내용은 [[표만들기]]를 참조하라.
* 기존에 수정했던 패치가, 비슷한 코드가 세 번씩 반복되는 터라 다시 수정할 때 상당히 번거로왔다. 2002년11월27일 새로 수정
** <nowiki>|v 는 사용할 수 없게 되었다.
- 부작용:
- 테이블 내에 들어가는 텍스트에 부등호 등이 들어가면 제대로 출력되지 않을 수 있으니, || 등의 구분자와 셀에 들어가는 텍스트 사이에 공백을 두라.
- 웹브라우저가 복잡한 표를 표시하지 못한다면 예상치 못한 출력이 나타날 수 있다.
-
sub CommonMarkup {
...
if ($doLines) { # 0 = no line-oriented, 1 or 2 = do line-oriented
...
if ($UseHeadings) {
s/(^|\n)\s*(\=+)\s+([^\n]+)\s+\=+/&WikiHeading($1, $2, $3)/geo;
### 다음 줄을 주석처리하고 그 아래의 내용을 추가한다.
# s/((\|\|)+)/"<\/TD><TD COLSPAN=\"" . (length($1)\/2) . "\">"/ge if $TableMode;
my %td_align = ("&__LT__;", "left", "&__GT__;", "right", "|", "center");
s/((\|\|)*)(\|(&__LT__;|&__GT__;|\|)((v(\d*))?))/"<\/TD><TD align=\"$td_align{$4}\" COLSPAN=\""
. ((length($1)\/2)+1) . ((length($5))?"\" ROWSPAN=\"" . ((length($7))?"$7":"2"):"") . "\">"/ge if $TableMode;
### 여기까지
}
}
...
}
-
sub WikiLinesToHtml {
my ($pageText) = @_;
my ($pageHtml, @htmlStack, $code, $depth, $oldCode);
my ($tag);
### 다음 라인 추가
my %td_align = ("&__LT__;", "left", "&__GT__;", "right", "|", "center");
###
...
foreach (split(/\n/, $pageText)) { # Process lines one-at-a-time
...
} elsif (/^[ \t].*\S/) {
$code = "PRE";
$depth = 1;
### 다음 단락은 주석처리하고 그 아래의 내용을 추가한다
# } elsif (s/^((\|\|)+)(.*)\|\|\s*$/"<TR VALIGN='CENTER' ALIGN='CENTER'><TD colspan='" . (length($1)\/2) . "'>$3<\/TD><\/TR>\n"/e) {
# $code = 'TABLE';
# $TableMode = 1;
# $depth = 1;
} elsif (s/^((\|\|)*)(\|(&__LT__;|&__GT__;|\|)((v(\d*))?))(.*)\|\|\s*$/"<TR VALIGN='CENTER' ALIGN='CENTER'>"
. "<TD align=\"$td_align{$4}\" colspan=\""
. ((length($1)\/2)+1) . ((length($5))?"\" ROWSPAN=\"" . ((length($7))?"$7":"2"):"") . "\">"
. $8 . "<\/TD><\/TR>\n"/e) {
$code = 'TABLE';
$TableMode = 1;
$depth = 1;
### 여기까지
} elsif (/^IMG:(.*)$/) { # luke added
StoreImageTag($1);
...
}
...
}
- 위에서 등장하는 "&__LT__;" 와 "&__GT__;" 는 {{{ }}} 태그, 즉 사용자입력을그대로출력하기를 지원하기 위하여 도입된 문자열이다. 저 문자열을 처음 본다면, 또는 자신이 가지고 있는 wiki.pl 내에 저런 문자열이 없다면, 저 문자열 대신에 각각 "<" 와 ">" 를 넣어야 된다.
1.23. <calendar> 매크로 추가
- WikiX 에 있는 Calendar 매크로가 너무 부러워서... UseModWiki 에서 구현해 보았음.
- PHP 소스는 도저히 봐도 모르겠는터라.. ^^ 겉모양은 비슷하게 꾸몄지만 실제 코딩은 백지에서 시작했기 때문에, complexity 라던가 퍼포먼스에 자신이 없지만.. 그래도 그럭저럭 쓸만할 듯
- 일종의 subcalendar 를 지원할 수 있게 수정하였다.
- 사용법 - <calendar([페이지이름,] [+/-]년,[+/-]월)>
- 자세한 내용은 Calendar매크로 를 참조하라.
- 2002년11월27일자로 인터페이스가 변경되었다. 원래는 페이지이름이 제일 마지막이었는데, 제일 앞에 두는 것이 직관적이라는 생각으로 옮겼다. (조프님께 감사)
- 부작용: 모름 (없다고 장담을 못하겠다)
- 이 홈페이지에서 보기 좋도록 적당히 꾸몄기 때문에, 이 홈페이지와 다른 스타일쉬트 화일을 사용하는 곳에서는 흉칙하게 보일 수 있다. html 문서를 꾸밀 때 스타일쉬트로 줄 수 있는 옵션과 태그 자체에 있는 옵션들이 제각각이라 주인장도 뭐가 뭔지 모른다. 좀 더 일관성 있게 (이왕이면 스타일쉬트를 쓰는 쪽으로 통일하는 것이 나을 듯) 태그 옵션을 주는 방향으로 고치는 게 좋겠다. 제보 환영. :-)
- "페이지이름"에 제일 뒤에 오는 기존의 패치를 이미 적용한 경우는 다음 라인만 바꿔주면 된다.
-
MacroSubst 안에서
< $txt =~ s/\&__LT__;calendar\(([-+]?\d+),([-+]?\d+)(,[^\n)]+)?\)\&__GT__;/&MacroCalendar($1, $2, $3)/gei;
> $txt =~ s/\&__LT__;calendar\(([^,\n]+,)?([-+]?\d+),([-+]?\d+)\)\&__GT__;/&MacroCalendar($1, $2, $3)/gei;
MacroCalendar 안에서
< my ($cal_year, $cal_month, $cal_mainpage) = @_;
> my ($cal_mainpage, $cal_year, $cal_month) = @_;
< return "<calendar($cal_year,$cal_month$cal_mainpage)>";
> return "<calendar($cal_mainpage$cal_year,$cal_month)>";
< $temp =~ s/^,//;
> $temp =~ s/,$//;
< return "<calendar($cal_year,$cal_month$cal_mainpage)>";
> return "<calendar($cal_mainpage$cal_year,$cal_month)>";
- 전체 소스
sub MacroSubst {
...
### 다음 라인 추가
$txt =~ s/\&__LT__;calendar\(([^,\n]+,)?([-+]?\d+),([-+]?\d+)\)\&__GT__;/&MacroCalendar($1, $2, $3)/gei;
###
return $txt;
}
-
### 다음 함수를 적당한 곳에 추가
sub MacroCalendar {
use Time::Local;
my ($cal_mainpage, $cal_year, $cal_month) = @_;
my $result='';
my $cal_result='';
my $cal_page;
my @cal_color = ("red", "black", "black", "black", "black", "black", "blue", "green");
my @cal_dow = (T('Su'), T('Mo'), T('Tu'), T('We'), T('Th'), T('Fr'), T('Sa'));
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($Now);
my ($this_year, $this_month, $this_day) = ($year, $mon, $mday);
my $cal_time;
my $cal_tdstyle;
my $temp;
# 달의 값이 13 이상이면 무효
if (!($cal_month =~ /[-+]/) && ($cal_month > 12)) {
return "<calendar($cal_mainpage$cal_year,$cal_month)>";
}
# prefix 처리
if (length($cal_mainpage) != 0) {
$temp = $cal_mainpage;
$temp =~ s/,$//;
$temp = &RemoveLink($temp);
$temp = &FreeToNormal($temp);
if (&ValidId($temp) ne "") {
return "<calendar($cal_mainpage$cal_year,$cal_month)>";
}
$temp =~ s/\/.*$//;
$cal_mainpage = "$temp/";
}
# 년도나 달에 0 을 인자로 받으면 올해 또는 이번 달
$cal_year = $this_year+1900 if ($cal_year == 0);
$cal_month = $this_month+1 if ($cal_month == 0);
# 년도에 + 또는 - 가 있으면 올해로부터 변위 계산
if ($cal_year =~ /\+(\d+)/ ) {
$cal_year = $this_year+1900 + $1;
} elsif ($cal_year =~ /-(\d+)/ ) {
$cal_year = $this_year+1900 - $1;
}
# 달에 + 또는 - 가 있으면 이번 달로부터 변위 계산
if ($cal_month =~ /\+(\d+)/ ) {
$cal_month = $this_month+1 + $1;
while ($cal_month > 12) {
$cal_month -= 12;
$cal_year++;
}
} elsif ($cal_month =~ /-(\d+)/ ) {
$cal_month = $this_month+1 - $1;
while ($cal_month < 1) {
$cal_month += 12;
$cal_year--;
}
}
# 1902년부터 2037년 사이만 지원함. 그 범위를 벗어나면 1902년과 2037년으로 계산
$cal_year = 2037 if ($cal_year > 2037);
$cal_year = 1902 if ($cal_year < 1902);
# 달력 제목 출력
$result .= "<table style=\"border:1 solid lightgrey;\">";
$result .= "<caption style=\"padding:0; font-size:9pt; text-decoration:none;\">"
."<a href=\"$ScriptName?$cal_mainpage$cal_year-$cal_month\">"
."<font color=\"black\"><b>"
.(length($cal_mainpage)?"$cal_mainpage<br>":"")
."$cal_year-$cal_month"
."</b></font>"
."</a>"
."</caption>";
# 상단의 요일 출력
$result .= "<tr>";
for (0..6) {
$result .= "<th style=\"line-height:100%; border:none;\" align=\"center\">"
. "<font color=\"$cal_color[$_]\">$cal_dow[$_]</font></th>";
}
$result .= "</tr>";
# 인자로 주어진 달의 1일날을 찾음
$cal_time = timelocal(0,0,0,1,$cal_month-1,$cal_year);
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($cal_time);
# 달력의 첫번째 날 찾음
$cal_time -= $wday * (60 * 60 * 24);
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($cal_time);
# 달력 그림
for (1..6) {
$result .= "<tr>";
for (0..6) {
$cal_page = ($year + 1900) . "-" . ($mon+1) ."-$mday";
$cal_result = $mday;
$cal_tdstyle = "line-height:100%;";
if (($year == $this_year) && ($mon == $this_month) && ($mday == $this_day)) {
$cal_tdstyle .= " border:1 solid lightgrey; background:yellow;";
} else {
$cal_tdstyle .= " border:none;";
}
if (-f &GetPageFile($cal_mainpage . $cal_page)) {
$cal_tdstyle .= " text-decoration:underline; ";
$cal_result = "<b>$cal_result</b>";
$wday = 7;
}
if ($cal_month != ($mon+1)) {
$cal_result = "<small>$cal_result</small>";
}
$result .= "<td style=\"$cal_tdstyle\" align=\"right\">"
."<a href=\"$ScriptName?$cal_mainpage$cal_page\">"
."<font color=\"$cal_color[$wday]\">"
.$cal_result
."</font></a></td>";
$cal_time += (60 * 60 * 24);
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($cal_time);
}
$result .= "</tr>";
# 4 또는 5 줄로 끝낼 수 있으면 끝냄
last if (($mon+1 > $cal_month) || ($year+1900 > $cal_year));
}
$result .= "</table>";
return $result;
}
- Time::Local 모듈이 설치되어 있어야 한다. 아마 설치되어 있을 것이다. 만일 모듈이 없다고 에러가 난다면.. 재주껏 설치하도록.. 어떻게 설치하는지 본인도 모름. :-)
- 위에 보면 &RemoveLink 라는 함수가 있다. 이 함수를 새로 만들어 주어야 한다. 별도의 섹션에서 다루겠다.
1.24. <wikiversion> 매크로 추가 (optional)
- wiki.pl?action=version 으로 위키소스의 버전을 볼 수 있는데, 이 때 나오는 버전 정보가 hard coding 되어 있는 게 보기 싫어서... 버전 정보를 담고 있는 변수를 따로 사용하도록 함
- 겸사겸사, 현재 소스 버전을 출력할 수 있는 매크로 <wikiversion> 도 추가함.
-
...
package UseModWiki;
use strict;
### 소스 제일 첫부분에 다음 라인들을 추가
use vars qw($WikiVersion $WikiRelease);
$WikiVersion = "0.92K3-ext1";
$WikiRelease = "2002-11-24";
###
local $| = 1; # Do not buffer output (localized for mod_perl)
...
- 버전명이 딱히 생각나지 않아서... 1'st extended 를 뜻하는 ext1 을 뒤에 붙였다. -_-;
-
sub MacroSubst {
...
### 다음 라인 추가
$txt =~ s/\&__LT__;wikiversion&__GT__;/&MacroWikiVersion()/gei;
###
return $txt;
}
-
### 다음 함수를 적절한 곳에 추가
sub MacroWikiVersion {
return &ScriptLink("action=version", $WikiVersion);
}
-
sub DoShowVersion {
print &GetHeader("", T('Displaying Wiki Version'), "");
### 다음 라인을 교체
# print "<p>UseModWiki version 0.92K2<p>\n";
print "<p>UseModWiki version $WikiVersion ($WikiRelease)<p>\n";
###
print &GetCommonFooter();
}
1.25. <vote(count[,scale])> 매크로 추가
- WikiX 에 있는 매크로를 흉내내다. (왜 창작은 못할까... -.-;)
- 사용법 - <vote(count[,scale])>
- count * scale 의 길이(픽셀 단위)의 막대가 그려진다
- scale 을 생략하면 기본값은 10이다.
- /TestVote 참조
-
sub MacroSubst {
...
### 다음 라인 추가
$txt =~ s/\&__LT__;vote\((\d+)(,(\d+))?\)&__GT__;/&MacroVote($1,$3)/gei;
###
return $txt;
}
-
# 다음 함수를 통채로 추가
sub MacroVote {
my ($count, $scale) = @_;
my $maximum = 1000;
$scale = 10 if ($scale eq '');
my $width = $count * $scale;
$width = $maximum if ($width > $maximum);
return "<table ".(($width)?"bgcolor=\"lightgrey\" ":"")
."width=\"$width\" style=\"border:1 solid gray;\">"
."<tr><td style=\"padding:0; border:none; font-size:8pt;\">$count"
."</td></tr></table>";
}
1.26. 존재하지 않는 페이지의 링크를 WikiX 스타일로 출력
- "페이지명?" 의 형태로 출력되는 기존의 방법이, 다른 곳으로 Copy & Paste 할 때 물음표가 붙어버리는 게 불편한 점을 해소
- WikiX 처럼 "페이지명"의 첫글자에 edit 할 수 있는 링크가 달리도록 수정
- $LinkFirstChar 라는 환경설정변수 도입. 값이 1이면 새로운 스타일, 0이면 기존의 물음표 스타일이다. config 화일 또는 wiki.pl 소스내에
$LinkFirstChar = 1;
등으로 정의해 준다.
-
# $LinkFirstChar 추가
use vars qw(@RcDays @HtmlPairs @HtmlSingle
...
$ConfigFile $SOURCEHIGHLIGHT %SRCHIGHLANG $LinkFirstChar);
-
sub GetPageOrEditAnchoredLink {
...
### 다음 라인을 아래와 같이 수정
# return $name . &GetEditLink($id,"?");
if (($LinkFirstChar) && ($name =~ /(\[)?([^\/]*\/)?([a-zA-Z0-9\/]|[\x80-\xff][\x80-\xff])([^\]]*)(\])?/)) {
return $2 . &GetEditLink($id,"<b>$3</b>") . $4;
} else {
return $name . &GetEditLink($id,"?");
}
###
}
1.27. GetFullLinkList 함수에 파라메터 사용을 가능하게 함
- 역링크를 구현하는 과정에 파생된 부산물
- 이 패치만 가지고는 아무런 변화도 일어나지 않는다.
- 기존에는 wiki.pl?action=links 화면에서, 추가로 몇 가지 옵션을 주소 입력창에서 넣어줄 수 있었다.
- unique, sort, page, inter, url, exists, empty, search 등
- 예: wiki.pl?action=links&sort=0&url=1
- 위키 소스 내부에서 이 함수를 호출할 때도, 함수 파라메터로 위의 옵션을 받을 수 있게 수정했다. 옵션을 명시하는 방법은 주소 입력창에서와 동일하게, "옵션항목=값"의 쌍을 & 로 붙이면 된다.
- 예: &GetFullLinkList("sort=0&url=1");
- 위키소스를 수정하여 운영하는 과정에서, 이 함수에 어떤 옵션(예:sort=0)을 주어 호출하는데, 사용자가 브라우저 주소창에서 같은 옵션 항목에 다른 값(예:sort=1)을 지정하는 경우가 발생할 수 있다. 이런 경우 후자에게 우선권이 주어진다. (sort=1이 된다)
-
sub GetFullLinkList {
### 다음 라인들을 추가
my ($opt) = @_;
my $opt_item;
my %args = ( # default 값
"unique" , 1,
"sort", 1,
"page", 1,
"inter", 0,
"url", 0,
"exists", 2,
"empty", 0,
"search", "",
"reverse", ""
);
foreach $opt_item (split('&',$opt)) {
if ($opt_item =~ /^(.+)=(.+)$/) {
$args{$1} = $2;
}
}
###
...
my ($pagelink, $interlink, $urllink);
my (@found, @links, @newlinks, @pglist, %pgExists, %seen);
### 다음 라인들을 교체
# $unique = &GetParam("unique", 1);
# $sort = &GetParam("sort", 1);
# $pagelink = &GetParam("page", 1);
# $interlink = &GetParam("inter", 0);
# $urllink = &GetParam("url", 0);
# $exists = &GetParam("exists", 2);
# $empty = &GetParam("empty", 0);
# $search = &GetParam("search", "");
$unique = &GetParam("unique", $args{"unique"});
$sort = &GetParam("sort", $args{"sort"});
$pagelink = &GetParam("page", $args{"page"});
$interlink = &GetParam("inter", $args{"inter"});
$urllink = &GetParam("url", $args{"url"});
$exists = &GetParam("exists", $args{"exists"});
$empty = &GetParam("empty", $args{"empty"});
$search = &GetParam("search", $args{"search"});
###
1.28. 페이지 제목을 클릭했을때 진정한 의미의 역링크 출력
- 페이지 제목을 클릭하는 경우, 기존에는 단지 해당 페이지 이름이 포함된 페이지들의 목록이 출력되었다.
- 역링크, 즉 해당 페이지를 "링크"하고 있는 페이지들만이 출력되도록 하였다.
- 테스트해야 할 경우의 수가 워낙 많아서 제대로 동작한다고 보장할 수는 없으나, 주인장이 수행한 테스트해서는 완벽하게 동작하였다. 잘못된 동작을 보이는 것을 목격하면 /사용자의견에 제보해 주기 바란다.
- "GetFullLinkList 함수에 파라메터 사용을 가능하게 함" 패치가 적용되어 있어야 한다.
-
### 다음 함수를 통채로 추가
sub GetReverseLink {
my ($id) = @_;
my $name = $id;
if ($FreeLinks) {
$name =~ s/_/ /g; # Display with spaces
}
return &ScriptLink("reverse=$id", $name);
}
-
sub GetHeader {
...
### 다음 라인을 교체
# $result .= $q->h1(&GetSearchLink($id)); # 원래 코드
# $result .= $q->h1($header . &GetSearchLink($id)); # "사이트 로고" 관련해서 패치했던 코드
$result .= $q->h1($header . &GetReverseLink($id)); # 이것이 최종 코드
###
...
}
-
sub DoOtherRequest {
...
$search = &GetParam("search", "");
if (($search ne "") || (&GetParam("dosearch", "") ne "")) {
&DoSearch($search);
return;
}
### 다음 단락 추가
$search = &GetParam("reverse", "");
if ($search ne "") {
&DoReverse($search);
return;
}
### 여기까지
# Handle posted pages
if (&GetParam("oldtime", "") ne "") {
...
}
-
# 다음 함수를 통채로 추가
sub DoReverse {
my ($string) = @_;
my @x = ();
my $pagelines;
if ($string eq '') {
&DoIndex();
return;
}
print &GetHeader('', &QuoteHtml(Ts('Links to %s', $string)), '');
print '<br>';
foreach $pagelines (&GetFullLinkList("sort=1&reverse=$string")) {
my @pages = split(' ', $pagelines);
@x = (@x, shift(@pages));
}
&PrintPageList(@x);
if ($#x eq -1) {
print T('No reverse link.') . "<br>";
}
print "<hr size=\"1\">" . Ts('Return to %s' , &GetPageLink($string)) . "<br>";
print &GetCommonFooter();
}
-
# 다시 한 번 말하지만, 위의 "GetFullLinkList 함수에 파라메터 사용을 가능하게 함" 패치가 적용된 상태여야 한다.
sub GetFullLinkList {
...
### 다음 라인 교체
# my ($name, $unique, $sort, $exists, $empty, $link, $search);
my ($name, $unique, $sort, $exists, $empty, $link, $search, $reverse);
###
my ($pagelink, $interlink, $urllink);
...
$search = &GetParam("search", $args{"search"});
### 다음 라인 추가
$reverse = &GetParam("reverse", $args{"reverse"});
###
...
if (($search ne "") && !($link =~ /$search/)) {
next;
}
### 다음 단락 추가
if ($reverse ne "") {
my ($mainpage, $subpage) = ("", "");
if ($reverse =~ /(.+)\/(.+)/) {
($mainpage, $subpage) = ($1, $2);
}
if (!((split('/',$name))[0] eq $mainpage && $link eq "\/$subpage") && !($link eq $reverse)) {
next;
}
}
### 여기까지
push(@newlinks, $link);
...
}
1.29. RemoveLink() 함수 추가
- <allpagesto> 매크로를 만드는 과정에서 생긴 부산물
- 페이지 이름을 인자로 받는 매크로의 경우, 페이지 이름이 위키네임일 경우 먼저 해당 페이지에 대한 링크로 변환된 후 매크로 치환이 일어나기 때문에 엉뚱한 인자가 넘어가게 된다.
- 이 함수가 하는 일은 문자열을 받아서 그 안에 있는 a href 태그 및 기타 페이지링크의 특성 (존재하지 않는 페이지의 경우 물음표가 붙거나 첫글자가 볼드체인 것 등) 을 제거하고 사용자가 입력한 그대로 넘기는 것이다. 다만 사용자가 [[ ]] 를 명시적으로 넣어버리는 경우는 처리해주지 못한다.
- 만약에 위키네임에 대한 처리를 다르게 하도록 고쳤다면, 여기서도 적절히 그 역변환 과정을 넣어주어야 한다.
-
# 다음 함수를 통채로 추가
sub RemoveLink {
my ($string) = @_;
$string =~ s/<a href[^>]*>(\?<\/a>)?//ig;
$string =~ s/<\/?b>//ig;
$string =~ s/<\/a>//ig;
return $string;
}
1.30. allpagesto 매크로 추가
- 특정한 페이지의 역링크 목록을 출력하는 매크로
- 매크로 이름은 애초에 "Links To" 로 하려고 했으나.. WikiX 에서 이미 같은 용도의 매크로가 있기에 같은 이름이 나을 것 같아 "All Pages To"로 정했다.
- 사용법 - <allpagesto(페이지이름)>
-
sub MacroSubst {
...
### 추가
$txt =~ s/\&__LT__;allpagesto\(([^\n]+)\)\&__GT__;/&MacroAllPagesTo($1)/gei;
###
return $txt;
}
-
### 함수를 통채로 추가
sub MacroAllPagesTo {
my ($string) = @_;
my @x = ();
my ($pagelines, $pagename, $txt);
my $pagename;
$string = &RemoveLink($string);
$string = &FreeToNormal($string);
if (&ValidId($string) ne "") {
return "<allpagesto($string)>";
}
foreach $pagelines (&GetFullLinkList("sort=1&reverse=$string")) {
my @pages = split(' ', $pagelines);
@x = (@x, shift(@pages));
}
foreach $pagename (@x) {
$txt .= ".... " if ($pagename =~ m|/|);
$txt .= &GetPageLink($pagename) . "<br>";
}
return $txt;
}
- "RemoveLink() 함수 추가" 패치가 적용되어 있어야 한다.
1.31. allpagesfrom 매크로 추가
- 특정한 페이지 안에 있는 링크의 목록을 출력하는 매크로. <allpagesto> 와 반대의 개념.
- 사용법 - <allpagesfrom(페이지이름[,옵션])>
- 페이지이름은 "페이지" 또는 "상위페이지/하위페이지"의 형식이다. "/하위페이지"는 지원하지 않는다.
- 옵션은 0,1,2 중의 하나. 생략하면 기본값은 2 이다.
- 0 - 현재 존재하지 않는 페이지에 대한 링크만 출력
- 1 - 현재 존재하는 페이지에 대한 링크만 출력
- 2 - 모든 링크를 출력
-
sub MacroSubst {
...
### 다음라인 추가
$txt =~ s/\&__LT__;allpagesfrom\(([^,\n]+)(,\d)?\)\&__GT__;/&MacroAllPagesFrom($1, $2)/gei;
###
return $txt;
}
-
### 다음 함수를 통채로 추가
sub MacroAllPagesFrom {
my ($string, $exists) = @_;
my (@x, @links, $pagename, %seen, %pgExists);
my $txt;
$string = &RemoveLink($string);
$string = &FreeToNormal($string);
if (&ValidId($string) ne "") {
return "<allpagesfrom($string)>";
}
if ($exists =~ /,(\d)/) {
$exists = $1;
} else {
$exists = 2;
}
%pgExists = ();
foreach $pagename (&AllPagesList()) {
$pgExists{$pagename} = 1;
}
@x = &GetPageLinks($string, 1, 0, 0);
foreach $pagename (@x) {
$pagename = (split('/',$string))[0]."$pagename" if ($pagename =~ /^\//);
if ($seen{$pagename} != 0) {
next;
}
if (($exists == 0) && ($pgExists{$pagename} == 1)) {
next;
}
if (($exists == 1) && ($pgExists{$pagename} != 1)) {
next;
}
$seen{$pagename}++;
push (@links, $pagename);
}
@links = sort(@links);
foreach $pagename (@links) {
$txt .= ".... " if ($pagename =~ m|/|);
$txt .= &GetPageOrEditLink($pagename) . "<br>";
}
return $txt;
}
1.32. orphanedpages 매크로 추가
- OrphanedPages 를 찾기 위한 매크로
- 사용법 - <orphanedpages([+,-]숫자)>
- 역링크 페이지 수가 "숫자"개인 페이지들의 목록이 출력된다. 따라서 인자로 0 을 주면 역링크의 갯수가 0 인 OrphanedPages 들이 출력된다.
- 이 때, 자기 자신을 링크하고 있는 것은 포함하지 않는다. 즉, <orphanedpages(3)> 이라고 했을때 A 라는 페이지가 출력되었다면, 실제 A 페이지의 역링크는 3개일 수도 있고 4개(A 내에 A 가 링크되어 있을 경우)일 수도 있다.
- 숫자 앞에 별도로 + 또는 - 를 붙일 수 있다. -3 은 "역링크의 갯수가 3개 이하", +4 는 "역링크의 갯수가 4개 이상"인 페이지들의 목록을 출력한다.
- 부작용
- 매크로 치환을 한 번 할 때마다 전체 페이지 목록을 읽어야 한다. 한 페이지 내에 저 매크로를 두 번 이상 사용하는 것은 바람직하지 못하다. 페이지 수가 1000개 단위로 늘어날 경우 얼마나 느려질지 알 수 없다.
- "GetFullLinkList 함수에 파라메터 사용을 가능하게 함" 패치가 적용되어 있어야 한다.
-
sub MacroSubst {
...
### 다음 라인 추가
$txt =~ s/\&__LT__;orphanedpages\(([-+])?(\d+)\)\&__GT__;/&MacroOrphanedPages($1, $2)/gei;
###
return $txt;
}
-
### 다음 함수를 통채로 추가
sub MacroOrphanedPages {
my ($less_or_more, $criterion) = @_;
my (@allPages, $page, $pageline, @pages, $id, @x);
my %numOfReverse;
my $txt;
@allPages = &AllPagesList();
foreach $page (@allPages) {
$numOfReverse{$page} = 0;
}
foreach $pageline (&GetFullLinkList("exists=1&sort=0")) {
my @links = split(' ', $pageline);
my $id = shift(@links);
my $link;
foreach $link (@links) {
$link = (split('/',$id))[0]."$link" if ($link =~ /^\//);
next if ($id eq $link);
$numOfReverse{$link}++;
}
}
foreach $page (@allPages) {
next if (($less_or_more eq "-") && ($numOfReverse{$page} > $criterion));
next if (($less_or_more eq "+") && ($numOfReverse{$page} < $criterion));
next if (($less_or_more eq "") && ($numOfReverse{$page} != $criterion));
$txt .= ".... " if ($page =~ m|/|);
$txt .= &GetPageLink($page) . "<br>";
}
return $txt;
}
1.33. wantedpages 매크로 추가
- 링크만 있고 내용은 아직 없는 WantedPages 를 찾기 위한 매크로
- 사용법 - <wantedpages>
- 목록의 각 라인에는 페이지 이름이 나오고, 이름 오른쪽에는 괄호 안에 숫자가 나온다. 이 숫자는 그 페이지가 몇 개의 페이지에서 링크를 하고 있는지를 나타낸다. 숫자를 클릭하면 그 페이지들의 목록을 볼 수 있다.
-
sub MacroSubst {
...
### 다음 라인 추가
$txt =~ s/\&__LT__;wantedpages\&__GT__;/&MacroWantedPages()/gei;
###
return $txt;
}
-
### 다음 함수를 통채로 추가
sub MacroWantedPages {
my ($pageline, @found, $page);
my %numOfReverse;
my $txt;
foreach $pageline (&GetFullLinkList("exists=0&sort=0")) {
my @links = split(' ', $pageline);
my $id = shift(@links);
foreach $page (@links) {
$page = (split('/',$id))[0]."$page" if ($page =~ /^\//);
push(@found, $page) if ($numOfReverse{$page} == 0);
$numOfReverse{$page}++;
}
}
@found = sort(@found);
foreach $page (@found) {
$txt .= ".... " if ($page =~ m|/|);
$txt .= &GetPageOrEditLink($page, $page) . " ("
. &ScriptLink("action=links&editlink=1&reverse=$page", $numOfReverse{$page})
. ")<br>";
}
return $txt;
}
1.34. includenotoc 매크로 추가
- 이 UserModWiki소스수정 페이지를 여러 하위 페이지로 나누고 include 할 때, 하위페이지 쪽에 <toc> 를 쓸 수 없는 불편함을 개선하고저 함
- include 매크로를 사용하여 어떤 페이지를 내부에 포함하는 경우, 포함되는 페이지 내에 <toc> 태그가 있으면 그 자리 역시 목차로 바뀌어 버리는 문제를 미흡하게나마 해결
- 사용법 - <includenotoc(페이지이름)>
- include 태그와 사용법은 동일
- 포함되는 페이지 내에 있는 <toc> 는, 마치 원래 데이타가 <toc> 였던 것처럼 간주된다. 결국 최종 출력물은 "<toc>" 자체가 된다.
- 아예 포함되는 페이지 내에 있는 toc 태그를 제거해 버리는 것을 고려했으나, 이 경우 {{{ }}} 안에 있는 문자열 "<toc>" 마저도 사라져 버린다. 또한, include 매크로가 재귀적으로 실행되지 않고 그냥 출력되듯이 toc 도 마찬가지로 그냥 출력되는 것이 합당하다고 생각했다. 다만, include 를 사용하는 쪽에서는 중간에 보이는 "<toc>" 가 눈에 거슬릴 것이다. :-/
- "include 매크로 출력을 html 변환" 패치가 적용된 상태여야 한다.
- 2002-12-17 조프님이 수정한 것을 다시 적용함. (MacroInclude 의 버그 수정)
-
...
use vars qw(@RcDays @HtmlPairs @HtmlSingle
...
$ConfigFile $SOURCEHIGHLIGHT %SRCHIGHLANG $LinkFirstChar $FS_lt $FS_gt); # 끝에 $FS_lt $FS_gt 추가
...
-
sub InitLinkPatterns {
...
$FS3 = $FS . "3"; # The FS character is not allowed in user data.
### 다음 두 줄 추가
$FS_lt = $FS . "lt";
$FS_gt = $FS . "gt";
###
...
}
-
sub WikiToHTML {
...
### 다음 두 라인 추가
$pageText =~ s/$FS_lt/</g;
$pageText =~ s/$FS_gt/>/g;
###
return &RestoreSavedText($pageText);
}
-
sub MacroIncludeSubst {
my ($txt) = @_;
$txt =~ s/<include\((.*)\)>/&MacroInclude($1)/gei;
### 다음 라인 추가
$txt =~ s/<includenotoc\((.*)\)>/&MacroInclude($1, "notoc")/gei;
###
return $txt;
}
-
### 다음 함수를 새로 작성
sub MacroInclude {
my ($name, $opt) = @_;
if ($OpenPageName eq $name) { # Recursive Include 방지
return "";
}
my $fname = &GetPageFile($name); # 존재하지 않는 파일이면 그냥 리턴
if (!(-f $fname)) {
return "";
}
my $data = &ReadFileOrDie($fname);
my %SubPage = split(/$FS1/, $data, -1); # -1 keeps trailing null fields
if (!defined($SubPage{"text_default"})) {
return "";
}
my %SubSection = split(/$FS2/, $SubPage{"text_default"}, -1);
my %TextInclude = split(/$FS3/, $SubSection{'data'}, -1);
# includenotoc 의 경우
$TextInclude{'text'} =~ s/<toc>/$FS_lt."toc".$FS_gt/gei if ($opt eq "notoc");
return $TextInclude{'text'};
}
1.35. #EXTERN 명령어 추가
- 하나의 페이지 내부에 외부의 웹페이지를 그대로 가져오는 명령어
- 사용법 - #EXTERN URL
- 페이지 제일 처음에 적어야 한다.
- URL 은 일반적인 형식 (프로토콜://주소) 에 맞춰 적는다.
- 2단 프레임을 만들어 상단 프레임에는 페이지 제목과 메뉴바가, 하단 프레임에는 URL 에 해당하는 웹 페이지가 출력된다.
- 환경변수
- $EditGuideInExtern - EXTERN 을 사용한 페이지 하단에 편집 가이드를 출력할 것인지를 지정한다.
- 1 - 하단에 별도의 프레임을 두어 편집 가이드를 출력한다.
- 0 - 출력하지 않는다.
- 출력할 경우, 상단과 하단을 합쳐서 300 pixel 정도를 차지하게 되므로, 해상도가 낮은 화면에서 볼 때 불편할 수 있다. 0 을 권장
- 사이트마다 로고 이미지의 크기나 스타일쉬트의 차이 때문에 아래의 두 변수를 적절히 조절해 주어야 한다.
- $SizeTopFrame - 첫번째 프레임의 높이, pixel 단위
- $SizeBottomFrame - 세번째 프레임 (편집 가이드를 출력할 경우) 의 높이, pixel 단위
- 부작용
- 프레임을 사용하게 된다. 프레임을 지원하지 않는 브라우저에서는 보이지 않는다.
- 지저분한 소스코드 :-/
- 2002.12.5 - 상,하단 프레임에 들어가는 html 소스가 제대로 </body></html> 가 붙지 않는 것을 수정
-
use vars qw(@RcDays @HtmlPairs @HtmlSingle
...
### 환경변수 추가
$EditGuideInExtern $SizeTopFrame $SizeBottomFrame);
-
### wiki.pl 에 기본값을 적어주고, config.pl 에서 별도로 설정한다.
$EditGuideInExtern = 0; # 1 = show edit guide in bottom frame, 0 = don't show
$SizeTopFrame = 160;
$SizeBottomFrame = 110;
-
sub BrowsePage {
...
} else { # Not a valid target, so continue as normal page
$id = $oldId;
$oldId = '';
}
}
### 다음 단락 추가
if (substr($Text{'text'}, 0, 8) eq '#EXTERN ') {
$oldId = &GetParam('oldid', '');
my ($externURL) = ($Text{'text'} =~ /\#EXTERN\s+([^\s]+)/);
if ($externURL =~ /^$UrlPattern$/) {
&BrowseExternUrl($id, $oldId, $externURL);
return;
}
}
### 여기까지
$MainPage = $id;
$MainPage =~ s|/.*||; # Only the main page name (remove subpage)
...
}
-
### 다음 함수를 통채로 추가
sub BrowseExternUrl {
my ($id, $oldId, $url) = @_;
my $sizeBottomFrame = $SizeBottomFrame * $EditGuideInExtern;
if (&GetParam('InFrame','') eq '1') {
print &GetHeader($id, "$id [InTopFrame]",$oldId);
print &GetMinimumFooter();
return;
} elsif ((&GetParam('InFrame','') eq '2') && ($EditGuideInExtern)) {
print &GetHeader($id, "$id [InBottomFrame]",$oldId);
print "<hr>\n";
print &GetEditGuide($id, '');
print &GetMinimumFooter();
return;
} else {
print &GetHttpHeader();
print "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Frameset//EN\">\n";
print "<html><</html>html<html>></html>\n";
print "<title>$SiteName: $id</title>\n";
print "<frameset rows=\"$SizeTopFrame,*,$sizeBottomFrame\" cols=\"1\" frameborder=\"0\">\n";
print " <frame src=\"$ScriptName?action=browse&InFrame=1&id=$id&oldid=$oldId\" noresize>\n";
print " <frame src=\"$url\" noresize>\n";
print " <frame src=\"$ScriptName?action=browse&InFrame=2&id=$id&oldid=$oldId\" noresize>\n" if ($EditGuideInExtern);
print " <noframes>\n";
print " <body>\n";
print " <p>".T('You need the web browser which supports frame tag.')."\n";
print " </body>\n";
print " </noframes>\n";
print "</frameset>\n";
print "<html><</html>/html<html>></html>\n";
return;
}
}
-
sub GetHeader {
...
return $result if ($embed);
### 다음 라인 추가
return $result if (&GetParam('InFrame','') eq '2');
### 여기까지
### 다음 단락 수정
# if ($oldId ne '') {
# $result .= $q->h3('(' . Ts('redirected from %s',
# &GetEditLink($oldId, $oldId)) . ')');
# }
my $topMsg = "";
if ($oldId ne '') {
$topMsg .= '('.Ts('redirected from %s',&GetEditLink($oldId, $oldId)).') ';
}
if (&GetParam('InFrame','') eq '1') {
$topMsg .= '('.Ts('%s includes external page',&GetEditLink($id,$id)).')';
}
$result .= $q->h3($topMsg) if (($oldId ne '') || (&GetParam('InFrame','') eq '1'));
### 여기까지
if ((!$embed) && ($LogoUrl ne "")) {
...
} else {
$result .= $q->h1($header . $title);
}
### 아래는 "페이지 상단에 Alt+Z 할당" 패치에서 추가한 부분이다.
### 그 패치를 적용하지 않았다면 아래 단락은 무시해도 된다.
if (&GetParam('InFrame','') eq '') {
$result .= "\n<div align=\"right\"><a accesskey=\"z\" name=\"#PAGE_TOP\" href=\"#PAGE_BOTTOM\">".T('Bottom') . "</a></div>\n";
}
### 여기까지
if (&GetParam("toplinkbar", 1)) {
...
}
-
sub GetHtmlHeader {
...
### 다음 단락 교체
# added luke
# if ($ClickEdit) {
# if ($FreeLinks) {
# $id = &FreeToNormal($id);
# }
# $bodyExtra .= qq(ondblclick="location.href='$ScriptName?action=edit&id=$id'");
# }
# end
if (&GetParam('InFrame','') ne '') {
$html .= qq(<base target="_parent">\n);
} else {
if ($ClickEdit) {
if ($FreeLinks) {
$id = &FreeToNormal($id);
}
$bodyExtra .= qq(ondblclick="location.href='$ScriptName?action=edit&id=$id'");
}
}
### 여기까지
...
}
-
sub GetMinimumFooter {
### 다음 단락 추가
if (&GetParam('InFrame','') ne '') {
return $q->end_html;
}
###
...
}
- InterWiki 의 개념을 생각해 볼 때.. 이미지 화일을 인터위키로 적는다는 것 자체가 편법이긴 하지만... 어쨌거나... :-)
- "인터위키이름:그림.jpg" 형식으로 적을 경우, 자동으로 그림이 출력되지 않는 문제가 있었다.
- 조프님의 패치를 적용
-
sub InterPageLink {
### 다음 라인 수정
# my ($id) = @_;
my ($id, $useImage) = @_;
###
my ($name, $site, $remotePage, $url, $punct);
($id, $punct) = &SplitUrlPunct($id);
$name = $id;
($site, $remotePage) = split(/:/, $id, 2);
$url = &GetSiteUrl($site);
return ("", $id . $punct) if ($url eq "");
$remotePage =~ s/&/&/g; # Unquote common URL HTML
$url .= $remotePage;
### 다음 단락 추가
if ($useImage && ($url =~ /^(http:|https:|ftp:).+\.$ImageExtensions$/)) {
$url = $1 if ($url =~ /^https?:(.*)/ && $1 !~ /^\/\//);
return ("<img $ImageTag src=\"$url\" alt=\"$id\">", $punct);
}
### 여기까지
return ("<a href=\"$url\">$name</a><a href=\"$url\" target=\"_blank\"><img src=\"./emoticon/newwindow.gif\" border=\"0\" alt=\"" . T('Open in a New Window') . "\" align=\"absbottom\"></a>", $punct);
}
- 위에서 볼 수 있듯이 InterPageLink 에 두번째 파라메터가 추가되었다. 호출해주는 곳 각각을 적절히 수정해주어야 한다.
-
sub CommonMarkup {
...
### 다름 라인 수정
# s/$InterLinkPattern/&StoreInterPage($1)/geo;
s/$InterLinkPattern/&StoreInterPage($1, $useImage)/geo;
###
...
}
-
sub StoreInterPage {
### 다음 라인 수정
# my ($id) = @_;
my ($id, $useImage) = @_;
###
my ($link, $extra);
### 다음 라인 수정
# ($link, $extra) = &InterPageLink($id);
($link, $extra) = &InterPageLink($id, $useImage);
###
# Next line ensures no empty links are stored
$link = &StoreRaw($link) if ($link ne "");
return $link . $extra;
}
1.37. mms 프로토콜 인식
$UrlProtocols = "http|https|ftp|afs|news|nntp|mid|cid|mailto|wais|mms|" # 뒤에 "mms|" 를 추가
. "prospero|telnet|gopher";
1.38. IMG: 태그 개선
- K3 버전에 있는 (오리지널에는 없음) IMG: 태그의 경우, 한 페이지에서 단 한 번 밖에 사용할 수 없었다. 여러 번 사용해도 마지막에 선언된 것이 모든 이미지에 적용된다. 게다가 이 extended 버전에서는 작동하지 않는다.
- 각 이미지마다 별도로 옵션을 줄 수 있도록 수정
- 사용법:
-
IMG:옵션 이미지경로
또는
IMG:옵션
이미지경로
- 위와 같이 적으면, <img 옵션 src="이미지경로" alt="이미지경로"> 로 치환된다.
- "IMG:옵션" 구문만 단독으로 사용되는 것은 아무런 효과가 없다. (기존 K3 소스에 의해서 NULL 로 치환만 된다)
-
sub CommonMarkup {
...
s/\[$InterLinkPattern\]/&StoreBracketInterPage($1, "")/geo;
### 다음 라인 추가.
s/IMG:([^<>\n]*)\n?$UrlPattern/&StoreImgUrl($1, $2, $useImage)/geo;
###
s/$UrlPattern/&StoreUrl($1, $useImage)/geo;
...
}
-
### 다음 함수를 통채로 추가
sub StoreImgUrl {
my ($imgTag, $name, $useImage) = @_;
my ($link, $extra);
$ImageTag = $imgTag;
($link, $extra) = &UrlLink($name, $useImage);
# Next line ensures no empty links are stored
$link = &StoreRaw($link) if ($link ne "");
$ImageTag = "";
return $link . $extra;
}
1.39. 존재하지 않는 페이지의 링크 스타일을 사용자가 결정할 수 있게 함
- 위의 "존재하지 않는 페이지의 링크를 WikiX 스타일로 출력" 항목을 참조할 것
- 각 사용자마다 "환경설정" 페이지에서 자신이 선호하는 스타일을 택할 수 있다.
- Bab2 님의 패치 적용
- "존재하지 않는 페이지의 링크를 WikiX 스타일로 출력" 패치를 적용한 상태여야 한다. 그렇지 않으면 LinkFirstChar 변수가 선언되어 있지 않다고 에러를 낼 것이다. 위 패치를 같이 적용하던가, 그게 귀찮으면 아래 코드에서 $LinkFirstChar 대신에 0 또는 1 중 맘에 드는 값을 넣어라.
-
sub GetPageOrEditAnchoredLink {
...
# 다음 줄 이하를 재수정
# if (($LinkFirstChar) && ($name =~ ... /)) {;
if ((&GetParam('linkstyle', $LinkFirstChar))
&& ($name =~ /(\[)?([^\/]*\/)?([a-zA-Z0-9\/]|[\x80-\xff][\x80-\xff])([^\]]*)(\])?/)) {
return $2 . &GetEditLink($id,"<b>$3</b>") . $4;
} else {
return $name . &GetEditLink($id,"?");
}
### 여기까지
}
-
sub DoEditPrefs {
...
print '<br>', &GetFormCheck('toplinkbar', 1,
T('Show link bar on top'));
### 다음 단락 추가
print '<br>', &GetFormCheck('linkstyle', $LinkFirstChar,
T('Use wikiX style for the links to empty pages'));
###
print '<br>', &GetFormCheck('linkrandom', 0,
T('Add "Random Page" link to link bar'));
...
}
-
sub DoUpdatePrefs {
...
&UpdatePrefCheckbox("toplinkbar");
### 다음 라인 추가
&UpdatePrefCheckbox("linkstyle");
###
&UpdatePrefCheckbox("linkrandom");
...
}
1.40. userlist 매크로 추가
- 현재 존재하는 아이디 목록을 출력한다.
- 사용법 - <userlist>
- Bab2 님의 패치를 함수 이름만 바꿔서 적용
-
sub MacroSubst {
### 다음 라인 추가
$txt =~ s/\&__LT__;userlist\&__GT__;/&MacroUserList()/gei;
###
return $txt;
}
-
### 다음 함수를 통채로 추가
sub MacroUserList {
my (@userlist, $result);
my $usernumber;
opendir(USERLIST, $UserDir);
@userlist = readdir(USERLIST);
close(USERLIST);
shift @userlist;
shift @userlist;
@userlist = sort @userlist;
foreach $usernumber (0..(@userlist-1)) {
@userlist[$usernumber] =~ s/(.*)\.db/($1)/gei;
@userlist[$usernumber] = &StorePageOrEditLink("@userlist[$usernumber]", "@userlist[$usernumber]") . "<br>";
}
$result = "@userlist";
return $result;
}
1.41. titleindex action 추가
- 모든 페이지 목록을 단순한 텍스트로 출력함
- 사용법 - 주소창에서, http...wiki.pl?action=titleindex
-
sub DoOtherRequest {
...
} elsif ($action eq "index") {
&DoIndex();
### 다음 단락 추가
} elsif ($action eq "titleindex") {
&DoTitleIndex();
###
} elsif ($action eq "help") { # luke added
&DoHelp();
...
}
-
### 다음 함수를 통채로 추가
sub DoTitleIndex {
my (@list);
my $index;
print "Content-type: text/plain\n\n";
@list = &AllPagesList();
foreach $index (@list) {
print $index."\r\n";
}
}
1.42. form 을 생성할 때 form 의 이름을 부여할 수 있도록 함
- 다른 패치들을 위한 패치
- 이 패치만 적용한 것으로는 아무런 변화가 일어나지 않는다.
- GetFormStart() 함수의 인터페이스를 변경하여, 문자열을 인자로 받을 경우 그 문자열을 form 의 name 속성으로 지정하도록 하였다.
- 부작용: 아직 모름
- 애초에 perl 의 CGI 관련 함수인 startform() 에는 method, action, enctype 만을 인자로 받을 수 있게 되어 있다. 이것을 맘대로 이렇게 고쳐도 모든 플랫폼에서 다 지원 가능할지는 의문이다.
-
sub GetFormStart {
### 다음 라인을 아래 단락으로 교체
# return $q->startform("POST", "$ScriptName", "application/x-www-form-urlencoded");
my ($name) = @_;
if ($name eq '') {
return $q->startform("POST", "$ScriptName", "application/x-www-form-urlencoded");
} else {
return $q->startform(-method=>"POST", -action=>"$ScriptName", -enctype=>"application/x-www-form-urlencoded" ,-name=>"$name") ;
}
###
}
이미지 화일 확장자 대문자 인식
sub InitLinkPatterns {
....
$ImageExtensions = "(GIF|JPG|PNG|BMP|JPEG|gif|jpg|png|bmp|jpeg)"; #### 바꿔준다.
}