-
- 1. 섹션 단위 수정
-
-
- 1.1. 구현하면서 신경쓴 부분
-
- 1.2. 사용법
-
- 1.3. 부작용
-
- 1.4. wiki.pl 수정
-
- 1.5. wiki.css 수정
-
- 1.6. translation/korean.pl 수정
-
- 1.7. 추가 업데이트 내역
-
- 1.8. 사용자 의견
-
1. 섹션 단위 수정
"== 섹션 제목 =="을 출력할 때 우측에 "편집" 링크를 띄우고, 그 섹션만 수정할 수 있도록 한다.
웬만하면 안 건드리려고 했는데, 페이지의 양이 조금만 늘어나도 당장 나부터 정신이 없어서 수정하기 너무 힘들기에, 다른 것에 앞서 이것부터... =.=;
1.1. 구현하면서 신경쓴 부분
- 모든 단계의 섹션에 대해 다 제공? 아니면 "==" 두개짜리 Headline 2 에 대해서만 제공?
- 모든 단계에 적용. 단 "=" 하나짜리 H1은 나오지 않게 하였다.
- 아래와 같은 구조에서, 섹션2를 편집하는 경우에 섹션2.1과 섹션2.2도 편집 화면에 나오게 할 것인가?
== 섹션1 ==
== 셕션2 ==
섹션2의 내용
=== 섹션2.1 ===
섹션2.1의 내용
=== 셕션2.2 ===
셕션2.2의 내용
== 셕션3 ==
- 위키페디아의 경우는 하위 섹션들의 내용까지 전부 수정하게 된다.
- 모니위키의 경우는 "섹션2의 내용"까지만 수정하게 된다.
- 여기서는 위키페디아처럼 동작하게 하였다.
- 서로 다른 두 사람이 한 페이지의 서로 같은 섹션을 수정하는 경우, 서로 다른 섹션을 수정하는 경우, 한 쪽에서 페이지 전체 수정을 하면서 섹션 순서에 변경을 가하는 경우 등등
- edit conflict가 발생하기 때문에 따로 신경쓸 것은 많지 않았다. 하지만 충돌 발생 시에는 섹션 단위 수정이 안 되어서 전체 페이지를 수정하게 된다.
- 위키페디아는 서로 다른 섹션을 편집하는 경우는 충돌 처리를 하지 않고 매끄럽게 적용된다. 부럽긴 한데, 우리도 그렇게 하기에는 고쳐야 될 게 너무 많다. 포기.
- "3장을 편집하라"라고 편집 모드로 들어갈 때, 어떻게 세번째 섹션을 찾을 것인가? 또 저장 버튼을 눌렀을 때, 어떻게 기존의 페이지 내용에 수정된 섹션을 삽입할 것인가?
- <html> </html> 쌍이나 {{{ }}} 등, 마크업되지 않는 영역 안에 헤드라인 서식이 우연히 들어가 있는 경우 문제가 된다. 이 때문에 섹션의 갯수와 순서가 페이지를 출력할 때와 편집할 때 서로 다를 수가 있다. 나름대로 처리한다고는 했는데, 빼먹은 부분이 있을지도 모름
- 이전 리비전의 문서를 보는 경우는?
- 위키페디아에서는 섹션별 편집 링크가 안 뜸
- 모니위키에서는 뜨며, 클릭을 하면 실제로는 가장 최근 리비전의 문서를 편집하게 된다.
- 위키페디아 쪽이 낫겠다 싶어서, revision 파라메터의 값이 없는 경우에만 편집 링크를 띄우도록 함.
- 다른 페이지를 include 한 경우는?
- Include 되는 페이지 내에 헤드라인 서식이 있을 경우 거기에는 편집하기 링크가 들어가면 안 된다.
- 이게 상당히 골치 아픈 부분. 깔끔하게 처리가 안 되고 땜질하듯 수정했다 =.=
당장 이 페이지만 봐도 알 수 있을테니 생략.
한 가지, 섹션 편집을 할 경우 변경사항요약 부분에 자동으로 "섹션 제목 - "의 형태로 값이 들어가게 하였다. 혹시 이게 맘에 안 든다면 아래 소스 수정에서 "# summary 를 해당 섹션 제목으로"라는 주석이 붙어 있는 단락을 주석 처리해 주면 됨.
위에서 언급했듯이, 페이지를 출력할 때는 헤드라인으로 처리되지 않는데, 수정하거나 저장할 때는 헤드라인으로 인식되어서 오류를 낼 가능성이 있다.
예를 들어 어떤 페이지의 소스가 아래와 같다면,
== 이건 진짜 헤드라인 (1) ==
{{{
== 이건 {{{ }}} 안에 있어서 그냥 출력되는 부분 (2) ==
}}}
== 이건 진짜 헤드라인 (3) ==
(1)과 (3)에는 편집하기 링크가 있고 (2)에는 없을 것이다. 그런데 (3)의 링크를 눌렀는데, 편집화면에는 (2)의 내용이 나온다던가, 편집화면에도 제대로 나왔는데 막상 저장 버튼을 눌렀더니 그 내용이 (2)의 자리가 바뀌어 있다던가 하는 경우가 있을 수 있다는 것.
그런 일이 발생하지 않도록 신경을 쓴다고는 썼는데, 빠뜨린 게 있을 지 모르니 발견하면 알려 주시면 감사하겠습니다.
섹션 단위로 편집을 하다가 "미리 보기" 버튼을 누르면, 페이지 전체가 아니라 해당 섹션 내용만 가지고 결과를 출력한다. 이것 자체로 큰 문제는 아닌데 (오히려 나은 것 같기도 하고), 해당 섹션 이외의 부분의 영향을 받는 부분은 이상하게 나올 수 있다. 예를 들어서 Diary/티스토리에서유즈모드로링크문제에서 제목 헤드라인의 편집을 눌러서 미리 보기를 해보면 footer 부분이 우측이 아니라 아래로 나오는 걸 볼 수 있다.
1.4. wiki.pl 수정
전역 변수 추가:
use vars qw(%RevisionTs $FS_lt $FS_gt $StartTime $Sec_Revision $Sec_Ts
...
$UseShortcut $UseShortcutPage
$SectionNumber);
다른 페이지를 include할 때 그 페이지 안에 있는 헤드라인 서식에는 "noedit"라는 마크를 붙여 둔다.
sub MacroInclude {
...
$txt =~ s/(<thread\()([-+]?\d+(,\d+)?)(\)>)/$1$name,$2$4/gi;
$txt =~ s/((^|\n)[\ \t\f]*\=+[\ \t\f]+[^\n]+)([\ \t\f]+\=+)/$1${FS}noedit$FS$3/go;
return $txt;
}
헤드라인 서식을 마크업할 때 편집하기 링크를 추가
sub WikiHeading {
my ($pre, $depth, $text) = @_;
$depth = length($depth);
$depth = 6 if ($depth > 6);
$text =~ s/^#\s+/&WikiHeadingNumber($depth,$')/e;
my $edit_section;
if ($text =~ s/${FS}noedit$FS//) {
} elsif (&GetParam('revision', '') eq '') {
$SectionNumber++;
$edit_section = '<SPAN class="editsection">['.
&ScriptLink("action=edit&id=$pageid§ion=$SectionNumber",&T("edit")).
']</SPAN>';
$edit_section = '' if ($depth == 1);
}
return $pre . "<H$depth>$edit_section$text</H$depth>\n";
}
페이지 편집 모드에서 section 파라메터가 있으면 해당 섹션의 내용만 불러옴
sub DoEdit {
...
$oldText = $Text{'text'};
if ($preview && !$isConflict) {
$oldText = $newText;
}
my $section = &GetParam('section', '');
if ($section >= 1) {
my $temp_text;
my (@h_depth, @h_pos);
my $num = 0;
$temp_text = $oldText;
%SaveUrl = ();
$SaveUrlIndex = 0;
$temp_text = &store_raw_codes($temp_text);
while ($temp_text =~ /(^[ \t]*(\=+)\s+[^\n]+\s+\=+\s*$)/gm) {
$num++;
$h_pos[$num] = pos($temp_text) - length($1);
$h_depth[$num] = length($2);
if ($num == $section) {
my $h_str = $1;
$h_str =~ /^[ \t]*\=+\s+(#\s+)?([^\n]+)\s+\=+\s*$/;
$h_str = $2;
$h_str =~ s/"/"/g;
$q->param("summary", "$h_str - ".&GetParam("summary", ""));
}
}
$num++;
$h_pos[$num] = length($temp_text);
$h_depth[$num] = 1;
my $next;
for ($next = $section+1; ($next <= $#h_depth) && ($h_depth[$section] < $h_depth[$next]); $next++) {}
my $offset = $h_pos[$section];
my $length = $h_pos[$next] - $offset;
$temp_text = substr($temp_text, $offset, $length);
$temp_text = &RestoreSavedText($temp_text);
%SaveUrl = ();
$SaveUrlIndex = 0;
$oldText = $temp_text;
$header .= " ". &T('(section)');
}
$editRows = &GetParam("editrows", 20);
$editCols = &GetParam("editcols", 65);
...
if ($revision ne "") {
print &GetHiddenValue("revision", $revision), "\n";
}
my $ecode = &simple_crypt(length($id).substr(&CalcDay($Now),5));
print &GetHiddenValue("ecode","$ecode")."\n";
if ($section >= 1) {
print &GetHiddenValue("section", $section)."\n";
}
print &GetTextArea('text', $oldText, $editRows, $editCols);
$summary = &GetParam("summary", "*");
...
}
페이지를 저장할 때, 사용자가 입력한 해당 섹션의 내용과 기존 페이지 내용 중 다른 섹션의 내용을 합쳐서 처리함
sub DoPostMain {
...
$old = $Text{'text'};
$oldrev = $Section{'revision'};
$pgtime = $Section{'ts'};
my $section = &GetParam('section', '');
if ($section >= 1) {
my $temp_text;
my (@h_depth, @h_pos);
my $num = 0;
$temp_text = $old;
%SaveUrl = ();
$SaveUrlIndex = 0;
$temp_text = &store_raw_codes($temp_text);
while ($temp_text =~ /(^[ \t]*(\=+)\s+[^\n]+\s+\=+\s*$)/gm) {
$num++;
$h_pos[$num] = pos($temp_text) - length($1);
$h_depth[$num] = length($2);
}
$num++;
$h_pos[$num] = length($temp_text);
$h_depth[$num] = 1;
my $next;
for ($next = $section+1; ($next <= $#h_depth) && ($h_depth[$section] < $h_depth[$next]); $next++) {}
$temp_text = substr($temp_text, 0, $h_pos[$section]).
$string.
substr($temp_text, $h_pos[$next]);
$temp_text = &RestoreSavedText($temp_text);
%SaveUrl = ();
$SaveUrlIndex = 0;
$string = $temp_text;
}
$preview = 0;
$preview = 1 if (&GetParam("Preview", "") ne "");
...
if (($oldrev > 0) && ($newAuthor && ($oldtime != $pgtime))) {
&ReleaseLock();
$q->param('section','');
if ($oldconflict>0) {
&DoEdit($id, 2, $pgtime, $string, $preview);
...
}
다음 함수 통채로 추가:
sub store_raw_codes {
my ($text) = @_;
$text =~ s/(<html>((.|\n)*?)<\/html>)/&StoreRaw($1)/ige;
$text =~ s/(^|\n)(\{\{\{[ \t\r\f]*\n((.|\n)*?)\n\}\}\}[ \t\r\f]*)\n/$1.&StoreRaw($2)."\n"/igem;
$text =~ s/(^|\n)(\{\{\{([a-zA-Z0-9+]+)(\|(n|\d*|n\d+|\d+n))?[ \t\r\f]*\n((.|\n)*?)\n\}\}\}[ \t\r\f]*)\n/$1.&StoreRaw($2)."\n"/igem;
$text =~ s/(^|\n)(\{\{\{#!((\w+)( .+)?)[ \t\r\f]*\n((.|\n)*?)\n\}\}\}[ \t\r\f]*)\n/$1.&StoreRaw($2)."\n"/igem;
$text =~ s/(<nowiki>(.|\n)*?\<\/nowiki>)/&StoreRaw($1)/ige;
$text =~ s/(<pre>(.|\n)*?\<\/pre>)/&StoreRaw($1)/ige;
$text =~ s/(<code>(.|\n)*?\<\/code>)/&StoreRaw($1)/ige;
return $text;
}
1.5. wiki.css 수정
헤드라인에 들어가는 편집 링크의 span 스타일 - [위키페디아의 스타일쉬트]를 참조했음
.editsection {
font-size: 90%;
float: right;
margin-right: 0.5em;
}
1.6. translation/korean.pl 수정
다음 항목 추가
(section)
(부분)
1.7. 추가 업데이트 내역
ext1.106a
- 헤드라인 내에 따옴표가 들어갔을 경우, summary 파라메터로 넣을 때 따옴표를 "으로 치환해서 넣는다. 안 그러면 편집 화면의 변경사항요약 필드에 따옴표 뒷부분이 잘린 채로 들어가 버림.
- 헤드라인 바로 다음 줄에 {{{ 가 왔을 때 뽑아내지 못하는 문제 수정
ext2.1e
- store_raw_codes 수정, {{{ }}} 블럭을 nowiki, pre, code 블럭보다 먼저 처리함
ext2.5c
- 헤드라인이 연달아 나오는 페이지를 include했을 때, 두 헤드라인을 하나로 취급하여 noedit 태그를 두 헤드라인 사이에 끼워넣는 문제 수정
아... 막상 만들어 보니, 진짜 페이지 편집할 때 편하긴 하군요. 특히 페이지 분량은 긴데 내가 고치려는 부분은 뒷부분에 있을 때... 왜 진작에 하지 않았을까 후회될 정도. ^_^
바벨의 도서관 같은 경우는 페이지의 diff를 볼 때 변경사항 부분도 마크업을 해버리기 때문에, 변경사항 중에 헤드라인이 있으면 거기서부터 번호를 매겨버립니다. 따라서 diff화면에서 바로 edit 링크를 누르면 자기가 의도한 섹션이 아니라 엇갈려 나올테니, 아예 diff 화면에서 edit 링크가 나오지 않게 바꿔버릴 수 있겠네요. 제 홈에서는 최근변경내역->페이지 diff->여기에서 바로 수정으로 갈 수 있는 게 좋아서 그냥 놔둡니다만, 필요하실 지 몰라서 적어둡니다.
sub WikiHeading {
...
$edit_section = '' if ($depth == 1);
$edit_section = '' if (&GetParam('diff', '') ne '');
}
return $pre . "<H$depth>$edit_section$text</H$depth>\n";
}
- 우와. 감사합니다.
Hi, Raymundo
possibly you thought about this, hint: edit by sections also in versions (only a suggestion, no waiting time for its implementation since I am working with that in localhost). Hope it helps, thanks for this great patch.
Regards, --JuanmaMP --
JustSameJuanmaMP
2009-8-28 2:01 am
- Good job :-)
I considered it when I was making this patch. But I wondered if there would be such need (edit sections in the past revisions ). And I refered Wikipedia and Moniwiki. Wikipedia doesn't support it. Moniwiki supports it but not correctly. Therefore, I decided not to support it, either, hehehe. :-D
Anyway, if someone need to edit a page of past revisions frequently, your work would be helpful.
Good Night over there, Raymundo.
I just don't understand what does it mean?
Where does it go the particle "noedit" to?
Moreover, there's nothing into parentheses.
Thanks for shed light, as far as you can.
if ($text =~ s/${FS}noedit$FS//) { # include 된 내용의 경우는 스킵
}
Sincerely.
Juanma
- Well, well, well... You asked me about "noedit"...?
Okay, Welcome to the world of ancient black magic :-)
It has some historical background.
- First, I made "include" macro.
- Next, I made "section edit" feature.
- Then, I realized that, if a user clicks "edit" link on a heading and (unluckily) the heading is in the "included page", all things would be spoiled, because there is not such section in the "including page"
So I needed to make the included contents not to have edit links, and I did it as following:
1) Insert a mark "${FS}noedit${FS}" into all the headings in the included content. This is done in MacroInclude().
2) In markup stage, if a heading contains the mark, skip that heading, that is, not insert the edit link. This is done in the elsif block in WikiHeading(), as you've seen.
3) There is one more thing to do. We need to remove the "noedit" mark before we print the page. This is done in... the code you wrote above :-) There's nothing in if block, but substitution is done in the parentheses. This removes the mark, replacing it with an empty string.
You can see the example in
- TestPage : this page includes a subpage
- TestPage/SubPage : this page is included
Good Evening, Raymundo.
Big thanks for clarification.
Could you maintain TestPage and TestPage/SubPage, let's say, until tomorrow (from now. It will be enough), in order to catching the idea?
Have a good Sunday!.
- Sure, they shall remain until next year, LOL
Thanks. Indeed, it is perfectly possible that I could to need an extension of the one-year deadline. (Sometimes, I feel myself as HAL when sings Daisy. Haha!).
Cheers!.
Your reasoning helps me to take awareness (remembering, best said) about kinds of these patches.
I use, sometimes, "print &GetHiddenValue('parameter', 1)"; for instance, into "IncludeRaw" (in this case).
Then, in "WikiHeading" I use the parameter value to discriminate scenarios. Hope it functional, too. I guess ...
Good morning over there.
This feature, also leaves the door to rawinclusions by section (other new feature) ... .
위키위키분류