-
- 1. 외부 PlugIn 확장
-
-
- 1.1. 사용법
-
- 1.2. wiki.pl 수정
-
- 1.3. 추가 업데이트 내역
-
- 1.4. 사용자 의견
-
1. 외부 PlugIn 확장
외부 프로그램을 실행시켜 텍스트를 처리하게 하는 확장 기능. 이 확장 기능은 /매크로모듈화처럼 사용자가 각각의 PlugIn 파일을 추가, 삭제, 수정하여 쉽게 덮어 쓸 수 있다.
- 필수 요구 사항:
- /LaTeX에 있는 UnquoteHtmlForPageContent() 함수가 있을 것
- 선택 요구 사항: 딱히 없다.
- 사용법: {{{#!플러그인이름 [옵션들] 내용 }}}
{{{#!gnuplot [옵션들...] <-- 한 줄에 오직 이 라인만 있을 것. 플러그인이름은 알파벳,숫자,_ 로만 이뤄짐. 옵션은 공백으로 구분
텍스트 <-- 플러그인이 처리할 텍스트
}}} <-- 역시 한 줄에 이 라인만 있을 것
- 동작
- 위키는 먼저 ./myplugin/ 디렉토리에서 "플러그인이름.pl"파일(여기서는 gnuplot.pl)을 찾는다. 여기는 사용자가 추가, 수정한 플러그인이 들어간다.
- 없으면 ./plugin/ 디렉토리에서 찾는다. 여기는 ext버전에서 제공하는 플러그인이 들어간다.
- gnuplot.pl 이 있으면, 그 파일을 require 로 부르고, plugin_gnuplot(옵션,텍스트)를 호출한다.
- gnuplot.pl 의 기본 뼈대는 아래와 같다.
sub plugin_gnuplot {
my ($content, @opt) = @_;
return "html코드";
}
1;
- 위키는 반환된 html을 StoreRaw()를 거쳐 원문에서 치환한다.
- 에러 처리
- 해당되는 플러그인 파일이 없으면 - "No such plugin found"에러를 내고 원래의 텍스트를 출력
- 플러그인 파일을 불러오는 데 실패하면 - "Failed to load plugin""에러를 내고 원래의 텍스트를 출력
- 플러그인이 불렸는데 플러그인 내에서 에러를 처리하는 경우
- 플러그인이 undef 를 반환하면 - "Error occurred while processing"에러를 내고 원래의 텍스트를 출력
- 그 외의 값을 반환하면 - 성공한 경우와 마찬가지로 반환된 스트링을 StoreRaw()를 거쳐 출력한다. 즉 제대로 외부 프로그램이 수행되었는지 아닌지를 구분할 수는 없다. 이런 처리는 각각의 플러그인이 알아서 해 줘야 한다.
- 플러그인을 만들 때 주의할 점들
- plugin의 이름과 외부 프로그램의 이름이 같을 필요는 없다. 플러그인 이름은 플러그인 pl 파일을 만드는 사람 맘.
- 외부 프로그램을 호출하므로, 이 외부 프로그램이 쉘 명령을 실행한다던가 기타 위험한 동작을 하지 않는지 꼼꼼히 확인할 것.
- 사용자가 넣은 "텍스트"부분의 코드 중에 위험한 부분을 제거해야 한다. (예: gnuplot 에서 "!"으로 시작하면 쉘 명령을 실행한다)
- wiki.pl은 오직 텍스트와 옵션 배열을 넘겨주는 것으로 끝이다. 어떤 옵션을 제공할지, 그림을 생성하는 경우 캐쉬를 사용할지 등등은 각각의 플러그인이 알아서 해야 한다.
1.2. wiki.pl 수정
use vars qw(
...
$PluginDir $MyPluginDir # 추가
...
);
sub CommonMarkup {
my ($text, $useImage, $doLines) = @_;
local $_ = $text;
if ($doLines < 2) {
s/(^|\n)\{\{\{[ \t\r\f]*\n((.|\n)*?)\n\}\}\}[ \t\r\f]*\n/&StoreRaw("\n<PRE class=\"code\">") . &StoreCodeRaw($2) . &StoreRaw("\n<\/PRE>") . "\n"/igem;
s/(^|\n)\{\{\{#!((\w+)( .+)?)[ \t\r\f]*\n((.|\n)*?)\n\}\}\}[ \t\r\f]*\n/$1.&StorePlugin($2,$5)."\n"/igem;
s/(^|\n)\{\{\{([a-zA-Z0-9+]+)(\|(n|\d*|n\d+|\d+n))?[ \t\r\f]*\n((.|\n)*?)\n\}\}\}[ \t\r\f]*\n/&StoreRaw("<PRE class=\"syntax\">") . &StoreSyntaxHighlight($2, $4, $5) . &StoreRaw("<\/PRE>") . "\n"/igem;
다음 함수 통채로 추가
sub StorePlugin {
my ($command, $content) = @_;
my $name;
my @opt;
my $plugin_file = "";;
$command = &UnquoteHtmlForPageContent($command);
@opt = split (/\s/, $command);
$name = shift @opt;
my ($PluginDir, $MyPluginDir) = ("./plugin/", "./myplugin/");
if (-f "$MyPluginDir/$name.pl") {
$plugin_file = "$MyPluginDir/$name.pl";
} elsif (-f "$PluginDir/$name.pl") {
$plugin_file = "$PluginDir/$name.pl";
}
if ($plugin_file eq "") {
return &StoreRaw("\n<PRE class='code'>").
&StoreRaw("\n<font color='red'>No such plugin found: $name</font>\n").
&StoreCodeRaw($content).
&StoreRaw("\n<\/PRE>") . "\n";
}
my $loadplugin = eval "require '$plugin_file'";
if (not $loadplugin) {
return &StoreRaw("\n<PRE class='code'>").
&StoreRaw("\n<font color='red'>Failed to load plugin: $name</font>\n").
&StoreCodeRaw($content).
&StoreRaw("\n<\/PRE>") . "\n";
}
my $func = "plugin_$name";
my $content_unquoted = &UnquoteHtmlForPageContent($content);
my $txt = &{\&$func}($content_unquoted, @opt);
if (not defined $txt) {
return &StoreRaw("\n<PRE class='code'>").
&StoreRaw("\n<font color='red'>Error occurred while processing: $name</font>\n").
&StoreCodeRaw($content).
&StoreRaw("\n<\/PRE>") . "\n";
}
return &StoreRaw($txt);
}
sub GetPageLinks {
...
$text =~ s/<code>(.|\n)*?\<\/code>/ /ig;
$text =~ s/(^|\n)(\{\{\{[ \t\r\f]*\n((.|\n)*?)\n\}\}\}[ \t\r\f]*)\n/$1 \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/$1 \n/igm;
$text =~ s/(^|\n)(\{\{\{#!((\w+)( .+)?)[ \t\r\f]*\n((.|\n)*?)\n\}\}\}[ \t\r\f]*)\n/$1 \n/igm;
if ($interlink) {
...
}
관리자가 페이지 내의 링크를 일괄 변경할 때도 plugin 영역의 내용은 변경하지 않게 한다.
sub SubstituteTextLinks {
...
$text =~ s/(<code>((.|\n)*?)<\/code>)/&StoreRaw($1)/ige;
$text =~ s/(<nowiki>((.|\n)*?)<\/nowiki>)/&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;
...
}
1.3. 추가 업데이트 내역
ext1.72a - 플러그인호출시의 에러처리 개선
ext1.73b - 플러그인이 에러가 나서 원래 텍스트를 보여 줄 때 부등호 등이 치환되어 버리는 문제를 수정
ext1.74a - 미리보기에서 플러그인이 동작하지 않는 문제 수정 (저장된 텍스트를 읽을 때는 줄바꿈이 \n이지만 textarea에 있는 텍스트를 미리보기에 넘겨줄 때는 줄바꿈이 \r\n임)
ext1.75 - 굳이 사용자가 바꿀 일이 없다고 판단되어서, 플러그인 파일이 들어가는 디렉토리 설정을 config 파일에서 제거함.
ext1.95a - {{{#!...}}} 안의 내용 중에 위키네임이나 이중대괄호쌍이 있더라도 그것을 링크로 취급하지 않게 함. (즉, 역링크 검색이나 전체 링크 출력시 표시되지 않게 함)
ext1.110 - ext1.95a와 같은 맥락으로, 관리자 기능 중 링크 일괄 변경을 할 때도 플러그인 안의 내용은 건드리지 않게 함
다양한 플러그인이 나오기를 기대합니다~ :-)
위키위키분류