DokuWiki

It's better when it's simple

ユーザ用ツール

サイト用ツール


ja:devel:syntax_plugins

差分

このページの2つのバージョン間の差分を表示します。

この比較画面へのリンク

両方とも前のリビジョン前のリビジョン
次のリビジョン
前のリビジョン
次のリビジョン両方とも次のリビジョン
ja:devel:syntax_plugins [2008-08-09 21:25] – fixed link references chija:devel:syntax_plugins [2009-12-23 09:34] wakuteka
行 1: 行 1:
 +====== Syntax Plugins ======
  
 +構文プラグインはDokuwikiの構文を拡張する為の[[:ja:plugins]]です。新しい構文をDokuwikiに登録するために何が必要かはを理解するには[[:Parser]]の処理を理解してください。
 +
 +自作の構文プラグインの為の詳細な情報は[[Syntax Plugins|syntax_tutorial]]を参照してください。
 +
 +===== Synopsis =====
 +
 +例えば構文プラグイン//example//は、''syntax_plugin_example''を定義しなければいけません。これは''DokuWiki_Syntax_Plugin''を拡張したものです。((''lib/plugins/syntax.php''に定義されています))。 クラスは''lib/plugins/example/syntax.php''に記述してください。プラグインとその他のファイルに関する情報は[[plugin file_structure]]を参照してください。
 +
 +最低でも下記の関数が実装されていなければなりません。: 
 +
 +  * **''getInfo()''** プラグイン情報のハッシュを返す。 [author, email, date, name, desc, url]
 +  * **''getType()''** このプラグインのsyntax typeを返す。 ([[#syntax_types|see below]])
 +  * **''getSort()''** Returns a number used to determine in which order modes are added, also see [[parser#order_of_adding_modes_important|parser, order of adding modes]] and [[parser:getSort list]]
 +  * **''connectTo($mode)''** Doku_Parser_Modeを継承したメソッド ((''inc/parser/parser.php''で定義されています)). あなたの自作構文にマッチする正規表現はここで登録してください。
 +  * **''handle($match, $state, $pos, &$handler)''** rendererメソッドでマッチした構文を使うための準備処理。
 +  * **''render($mode, &$renderer, $data)''** 文章を処理する
 +\\ 
 +
 +必要であれば下記のメソッドがオーバーライド可能です:
 +
 +  * **''getPType()''** Defines how this syntax is handled regarding paragraphs((See ''Doku_Handler_Block'')). Return:
 +    *  ''normal'' --- (default value, will be used if the method is not overridden) The plugin can be used inside paragraphs,
 +    * ''block'' --- Open paragraphs need to be closed before plugin output or
 +    * ''stack'' --- Special case. Plugin wraps other paragraphs
 +  * **''getAllowedTypes()''** (default value: ''array()'') Should return an array of [[#syntax_types|mode types]] that may be nested within the plugin's own markup.
 +  * **''accepts($mode)''** This function is used to tell the parser if the plugin accepts syntax mode $mode within its own markup.  The default behaviour is to test $mode against the array of modes held by the inherited property ''allowedModes''.
 +
 +Additional functions can be defined as needed. It is recommended to prepend an underscore to self defined functions to avoid possible nameclashes with future plugin specification enhancements.
 +
 +\\ 
 +継承されるプロパティ
 +
 +  * ''allowedModes'' --- initial value, an empty array, inherited from Doku_Parser_Mode ((defined in ''inc/parser/parser.php'')). Contains a list of other syntax modes which are allowed to occur within the plugin's own syntax mode (ie. the modes which belong to any other dokuwiki markup that can be nested inside the plugin's own markup).  Normally, it is automatically populated by the ''accepts()'' function using the results of ''getAllowedTypes()''.
 +
 +===== Syntax Types =====
 +
 +DokuWiki uses different syntax types to determine which syntax may be nested. Eg. you can have text formatting inside of tables. To integrate your Plugin into this system it needs to specify which type it is and which types can be nested within it. The following types are currently available:
 +
 +^ Type      ^ Used in ..                  ^ Description ^
 +| container | listblock, table, quote, hr | containers are complex modes that can contain many other modes hr breaks the principle but they shouldn't be used in tables / lists so they are put here |
 +| baseonly | header | some mode are allowed inside the base mode only |
 +| formatting | strong, emphasis, underline, monospace, subscript, superscript, deleted, footnote | modes for styling text -- footnote behaves similar to styling |
 +| substition((Yes this is spelled wrong, but we won't change it to avoid breaking existing plugins. Sometimes a typo becomes a standard - see the HTTP "referer" header for an example))| 'acronym','smiley','wordblock','entity', 'camelcaselink', 'internallink', 'media', 'externallink', 'linebreak', 'emaillink', 'windowssharelink', 'filelink', 'notoc', 'nocache', 'multiplyentity', 'quotes', 'rss' | modes where the token is simply replaced - they can not contain any other modes | 
 +| protected |'preformatted','code','file','php','html'|modes which have a start and end token but inside which no other modes should be applied |
 +| disabled | unformatted | inside this mode no wiki markup should be applied but lineendings and whitespace isn't preserved |
 +| paragraphs | eol | used to mark paragraph boundaries |
 +
 +For a description what each type means and which other formatting classes are registered in them read the comments in ''inc/parser/parser.php''.
 +
 +===== Discussion =====
 +It's not readily apparent that the folder name needs to match the class declaration in the //syntax.php//. Otherwise, you'll get a nasty error, like
 +<code>
 +Fatal error: Cannot instantiate non-existent class: syntax_plugin_xyz in <path>\inc\pluginutils.php on line 57
 +</code>
 +or
 +<code>
 +Fatal error: Cannot redeclare class xyz in <path\lib\plugins\<xyz\<xyz>.php on line 58
 +</code>
 +
 +====== Tutorial: Syntax Plugins Explained ======
 +
 +このチュートリアルの目的は[[:DokuWiki]] [[syntax plugins|syntax plugin]]のコンセプトを説明し、自作プラグイン作成を段階的に追っていく事です。
 +
 +すぐにでも作成を始めたい方は[[devel:syntax_plugin_skeleton]]をコピーしてください。
 +これはページに"''%%<TEST>%%''"を見つけたときに"//Hello World!//"を出力するシンプルなプラグインです。
 +
 +===== Quick Summary =====
 +
 +**modes**
 +
 +  * すべてのdokuwiki syntaxは、あなたの自作プラグインも含めて自分のmodeを持っています。
 +  * 同じようなmodesは [[#mode types]]にまとめられています.
 +  * modeの"allowedTypes"は自作のsyntaxの中にネストされた他のdokuwiki syntaxを見つけたときの振る舞いを定義します。AllowedTypesに関連づけられたすべてのmodeが許可されます。
 +  * modeの"type"は他のmodeにこのsyntaxを許可すべきかどうかを教えます。
 +
 +** handle **
 +  * ''[[#handle_method|handle()]]'' メソッドは、パーサーがあなたのsyntaxモードに属しているWikiページのコンテントに遭遇した場合に呼び出されます。
 +  * ''$state'' パラメータはどのパターンのタイプがあなたのモードのトリガーに登録されているかを表します。もし、それが普通のテキスト文字列だったら、stateパラメータは''DOKU_LEXER_UNMATCHED''に設定されます。
 +  * なるべく処理や設定はここで終わらせて、''[[#render_method|render()]]'' で実行される処理を少なくします。
 +
 +** render **
 +  * The ''[[#render_method|render()]]'' method processes the renderer instructions that apply to the plugin's syntax mode - and which were created by the plugin's ''[[#handle_method|handle()]]'' method.
 +  * 出力文字列を ''%%$renderer->doc .= 'content';%%'' に追加します
 +
 +  * プラグインから出力されるデータが安全であることを確認してください。- run raw wiki data through an entity conversion function. 
 +  * できるだけ短い処理にしてください。 ''[[#handle_method|handle()]]'' メソッドですべて完結していなければなりません。
 +
 +:!: ''[[#render_method|render()]]'' メソッドが ''[[#handle_method|handle()]]'' メソッドと同時に呼ばれる保証はありません。 The instructions generated by the handler are cached and can be used by the renderer at a future time. ''[[#handle_method|handle()]]'' から ''[[#render_method|render()]]'' へ確実にデータを渡す方法は配列を返すことです。すると ''[[#render_method|render()]]'' の''$data''に渡されます。.
 +
 +===== Key Concepts =====
 +
 +==== modes ====
 +
 +Modes (or more properly syntax modes) are the foundation on which the dokuwiki parser is based.  Every different bit of dokuwiki markup has its own syntax mode. 例えばstrong modeは**strong**を処理します。superscript modeは<sup>superscript</sup>を処理します。table modeはtablesを、他にもたくさんのmodeがあります。
 +
 +parserがパターンを見つけると、syntax modeに入ります。 プロパティとメソッドは、そのmodeの間parserがどのような処理を行うかを決定します。 :
 +  * 他にどのようなsyntax modesが許可されているか
 +  * what instructions to prepare for the renderer
 +\\ 
 +自作プラグインはparserに自分のsyntax modeを追加します。これはDokuwikiによって、プラグインのロード時に自動的になされます。名前は ''plugin_''+ ディレクトリ (これはプラグインのクラス名から"''syntax_''"を除いたものでもあります)になります。 そしてparserが自作プラグインのmarkupを見つけるとsyntax modeに入ります。  While it is in that mode your plugin controls what the parser can do.
 +
 +==== mode types ====
 +
 +簡単に言うと、mode typesによってグループ化されたsyntax modesは同じように振る舞います。一覧は[[syntax plugins#syntax_types|syntax plugin]]にあります。
 +
 +Each mode type corresponds to a key in the ''$PARSER_MODES'' array. The entry for each mode type is itself an array which holds all the syntax modes which belong to that type. e.g. In vanilla dokuwiki with no plugins installed, ''$PARSER_MODES['formatting']'' holds an array containing: 'strong', 'emphasis', 'underline', 'superscript', 'subscript', 'monospace', 'deleted' & 'footnote'.
 +
 +When each plugin is loaded into the parser it is queried, via ''getType()'', to discover which mode type it will belong to.  The syntax mode associated with the plugin is then added to the appropriate ''$PARSER_MODES'' array.
 +
 +:!: The mode type your plugin reports governs where in a Dokuwiki page the parser will recognise your plugin's markup.  Other Dokuwiki (and plugin) syntax modes won't know about your plugin, but they do know about the different mode types. If they allow a particular mode type, they will allow all the modes which belong to that type, including any plugins that have returned that mode type.
 +
 +Select the mode type for your plugin by comparing the behaviour of your plugin to that of the standard dokuwiki syntax modes.  Choose the type that the most similar modes belong to. 
 +
 +==== allowed modes ====
 +
 +ネストされた他のmodeが現在のmode中に出現することがあります。
 +
 +
 +Each syntax mode has its own array of allowed modes which tells the parser what other syntax modes will be recognised whilst its processing the mode.  
 +もしあなたのプラグインを "%%**strong**%%" markup中で使用可能にしたいのであればstrong modeはあなたのプラグインのmodeをallowedModes配列内に持っていなければなりません。そしてあなたがstrong markupをあなたのプラグインのmarkup内で許可したいのであれば''%%'strong'%%''がallowModes配列内に存在していなければなりません。
 +
 +:!: Your plugin gets in the allowedModes array of other syntax modes through the mode type it reports using the ''getType()'' method.
 +
 +:!: Your plugin tells the parser which other syntax modes it permits by reporting the mode types it allows via the ''getAllowedTypes()'' method.
 +
 +==== PType ====
 +
 +PTypeはparserがあなたのsyntax mode内でhtmlの %%<p>%% タグをどのように扱うのかを管理します。
 +
 +parserが何かmarkupを発見した時、そこにはhtml表記での開始タグがあるかもしれません。parserはあなたのsyntax modeに入る前にそれが閉じられるべきか、そして処理後に新たに新しい開始タグを出力すべきか判断する必要があります。これが''%%PType='block'%%''です。もしタグを放っておいていいのであれば''%%PType='normal'%%''です。最後に''%%PType='stack'%%''というのがありますがこれは良く分かっていないので今は置いておきます。 (FIXME).
 +
 +For those that know CSS, returning ''%%PType='block'%%'' means the html generated by your plugin will be similar to ''display:block'' and returning ''%%PType='normal'%%''means the html generated will be similar to ''display:inline''.
 +
 +<del>There is one gotcha with ''%%PType='block'%%''. If your plugin allows other syntax modes, the parser will generate %%</p>%% & %%<p>%% tags when entering and exiting any nested syntax modes.  If that causes problems, choose ''%%PType='normal'%%'' and start the html your render method generates with a ''</p>'' and finish it with a ''<p>''.</del> --- [corrected in DW2006-11-06 version (and preceding release candidates)]
 +
 +==== Sort Number ====
 +
 +lexer((parserの一部で生のwiki pageを解析する))によって使われる番号で、生のWikiデータがsyntax modeのパターンに応じて処理される順番をコントロールします。これはパターンが同じデータ中で複数のModeに属している場合のみ重要です。もっとも小さい番号から処理されます。
 +
 +You can make use of this behaviour to write a plugin which will replace or extend a native dokuwiki handler for the same syntax.  An example is the [[plugin:code]] plugin.
 +
 +Details of existing sort numbers are available for both the [[parser]] ([[.:parser:getsort_list|sort list]]) ...
 +
 +==== Patterns ====
 +
 +parserはPHPのpreg((perl compatible regular expressions \\ ref: www.php.net/manual/en/ref.pcre.php)) と互換の関数を使用します。 A detailed explanation of regular expressions and their syntax is beyond the scope of this tutorial.  There are many good sources on the web. 
 +
 +The complete preg syntax is not available for use in constructing syntax plugin patterns. Below is a list of the known differences:
 +
 +  * don't surround the pattern with delimiters
 +  * to use a pipe "''|''" for multiple alternatives, make them a non-captured group, e.g. "''(?:cat|dog)''"
 +  * be very wary of look behind assertions. The parser only attempts to match patterns on the next piece of "not yet matched" data.  If you need to look behind to characters that have been involved in a previous pattern match, those characters will never be there.
 +  * option flagsはインラインオプションのみ使用可能です。例 ''(?i)'', ''(?-i)''
 +\\
 +
 +The parser provides four functions for a plugin to register the patterns it needs.  Each function corresponds to a pattern with a different meaning.
 +
 +  * **special patterns** --- ''addSpecialPattern()'' --- these are the patterns used when one pattern is all that is required.  In the parser's terms, these patterns represent entry in the the plugin's syntax mode and exit from that syntax mode all in the one match. Typically these are used by ''substition'' plugins.
 +  * **entry patterns** --- ''addEntryPattern()'' --- the pattern which indicates the start of data to be handled by the plugin.  Typically these patterns should include a look-ahead to ensure there is also an exit pattern.  Any plugin which registers an entry pattern should also register an exit pattern.
 +  * **exit patterns** --- ''addExitPattern()'' --- the pattern which indicates the end of the data to be handled by the plugin. This pattern can only be matched if text matching the entry pattern has been found.
 +  * **internal patterns** --- ''addPattern()'' --- these represent special syntax applicable to the plugin that may occur between the entry and exit patterns.  Generally these are only required by the more complex structures, e.g. lists and tables.
 +\\
 +
 +One plugin may add several patterns to the parser, including more than one pattern of the same type.
 +
 +**Tips**
 +
 +  * 最短マッチを使ってください。例 ''+?'' or ''*?'' 悪い例 ''+'' or ''*''.
 +  * be wary of using multiple exit patterns. The first exit pattern encountered will most likely trigger the parser to exit your syntax mode - even if that wasn't the pattern the entry pattern looked ahead for. Needing multiple exit patterns probably indicates a need for multiple plugins.
 +  * early versions of the Dokuwiki lexer had a bug which prevented use of "<" or ">" in look ahead patterns.  This bug has been fixed and angle brackets can now be used.  Some plugins will still contain the hex codes for angle brackets ("\x3C", "\x3E") which was the workaround to overcome the effects of this bug.
 +
 +==== handle() method ====
 +
 +ここですべての処理を行ってください。 Before Dokuwiki renders the wiki page it creates a list of instructions for the renderer.  プラグインの''handle()''メソッドは、自分のsyntax modeのためのrender instructionsを作成します。 しばらくしてこれはプラグインの''render()'' によって解析されます。instruction listはキャッシュされ、何度も使用されます。これはできるだけの処理をここで行い、''render()''の処理をできるだけ少なくするためです。
 +
 +**$state** parameter --- The type of pattern which triggered this call to handle().
 +  * **''DOKU_LEXER_ENTER''** --- a pattern set by addEntryPattern()
 +  * **''DOKU_LEXER_MATCHED''** --- a pattern set by addPattern()
 +  * **''DOKU_LEXER_EXIT''** --- a pattern set by addExitPattern()
 +  * **''DOKU_LEXER_SPECIAL''** --- a pattern set by addSpecialPattern()
 +  * **''DOKU_LEXER_UNMATCHED''** --- ordinary text encountered within the plugin's syntax mode which doesn't match any pattern.
 +
 +**$match** parameter --- The text which matched the pattern, or in the case of **''DOKU_LEXER_UNMATCHED''** the contiguous piece of ordinary text which didn't match any pattern.
 +
 +==== render() method ====
 +
 +最終的なWEBページの出力を提供します。プラグインはその出力を、すでにrendererによって作られたものに追加します。それは例えばrendererの''doc''プロパティに追加することによって行われます。
 +
 +<code>
 +$renderer->doc .= "some plugin output...";
 +</code>
 +
 +:!: すべての''render()''に渡される生wikiデータは、html entitiesに変換された特殊文字を持っています。以下のphp関数を使うことができます。 ''[[http://uk.php.net/manual/en/function.htmlspecialchars.php|htmlspecialchars()]]'', ''[[http://uk.php.net/manual/en/function.htmlentities.php|htmlentities()]]'' またはrendererが持っている ''xmlEntities()'' が利用可能です。 例<code>$renderer->doc .= $renderer->_xmlEntities($text);</code>  
 +
 +**$mode** パラメータ --- rendererによって最終出力されたformat modeの名前です。今のところDokuwikiがサポートしているのは''xhtml''だけです。 ((There is also the special mode ''metadata'' that doesn't output anything but collects metadata for the page. Use it to insert values into the metadata array. See the translation plugin for an example.)). New modes can be introduced by [[renderer plugins]].  The plugin should only produce output for those formats which it supports - which means this function should be structured ...
 +<code>
 +if ($mode == 'xhtml') {  // supported mode
 +  // code to generate xhtml output from instruction $data
 +}
 +</code>
 +
 +**$data** パラメータ --- instructionsを含む、自プラグインの''handle()''メソッドによって準備された配列です。関数はinstructionsを解析して適切な出力をしなければなりません。
 +
 +==== Safety & Security ====
 +
 +Raw wiki page data which reaches your plugin has not been processed at all.  No further processing is done on the output after it leaves your plugin.  At an absolute minimum the plugin should ensure any raw data output has all html special characters converted to html entities. Also any wiki data extracted and used internally should be treated with suspicion. See also [[security]].
 +
 +==== Localization ====
 +
 +FIXME
 +
 +For now refer to [[common plugin functions#localisation]] & [[plugin file structure]]
 +
 +==== Configuration ====
 +
 +FIXME
 +
 +Also, refer [[common plugin functions#configuration]] & [[plugin file structure]]
 +
 +The plugin interface provides some basic functions for accessing plugin specific configuration settings.  To make use of these functions and also to allow Wiki Admins to change the settings with the [[plugin:config|Configuration Plugin]], the settings themselves and associated details need to be kept in particular files:
 +
 +^ file in ''<plugin directory>/'' ^ description ^ example ^
 +|''conf/default.php'' |default settings for the plugin |''lib/plugins/config/settings/default.php''
 +|''conf/metadata.php'' |meta data describing the settings and their possible values |''lib/plugins/config/settings/metadata.php'' |
 +|''lang/xx/settings.php'' |localised prompts for the settings and any selection values |''lib/plugins/config/lang/xx/settings.php'' |
 +
 +A plugin can access its own setting values by using the ''getConf(<setting>)'' method.
 +
 +The [[plugin:config|Configuration Plugin]] provides several different classes for settings.  The classes control the display, validation and output plugin values.  If none of the provided classes are suitable for a particular setting the plugin can include its own class in the file ''conf/settings.class.php'' Details of the standard settings classes can be found in [[configuration metadata|plugin configuration metadata]] and in the source files ''lib/plugins/config/settings/config.class.php'' and ''lib/plugins/config/settings/extra.class.php''.
 +
 +
 +==== Using Styles and Javascript ====
 +
 +FIXME
 +
 +For now refer to [[plugin file structure]]
 +
 +
 +==== Adding a Toolbar Button ====
 +
 +To make it easy on the users of wikis which install your plugin, you should add a button for its syntax to the editor toolbar.
 +
 +FIXME
 +
 +For now refer to [[devel:toolbar]]
 +
 +===== プラグインを自作するために =====
 +
 +Ok, so you have decided you want to extend Dokuwiki's syntax with your own plugin.  You have worked out what that syntax will be and how it should be rendered on the user's browser.  Now you need to write the plugin.
 +
 +  - Decide on a name for the plugin.  You may want to check the list of [[:plugins|available plugins]] to make sure you aren't choosing a name that is already in use.
 +  - In your own Dokuwiki installation create a new sub directory in the ''lib/plugins/'' directory.  That directory will have the same name as your plugin.
 +  - Create the file ''syntax.php'' in the new directory.  As a starting point, use a copy of the [[devel:syntax plugin skeleton|skeleton plugin]].
 +  - Edit that file to make it yours.
 +    * change the class name to be ''syntax_plugin_<your plugin name>''.
 +    * change the ''getInfo()'' to report information about your plugin.
 +    * change the ''getType()'' method to report the mode type your plugin will belong to.
 +    * add a ''getAllowedTypes()'' method to report any mode types your plugin will allow to be nested within its own syntax.  If your plugin won't allow any other mode then this can be left out.
 +    * change the ''getPType()'' method to report the PType that will apply for your plugin.  If its ''%%'normal'%%'' you can remove this method.
 +    * change the ''getSort()'' method to report a unique number after checking the list of [[:plugins]].
 +    * alter the ''connectTo()'' method to register the pattern to match your syntax.
 +    * add a ''postConnect()'' method if your syntax has an second pattern to say when the parser is leaving your syntax mode.
 +  - Thats the easy part done, you now have a plugin that will say "Hello World!" when it encounters your syntax pattern.  Time to test it and make sure the pattern works as expected - visit your wiki and make up a page with the syntax for your plugin, save it and make sure "Hello World!" shows up.
 +  - Write your ''handle()'' & ''render()'' methods.
 +    * if you have entry and exit patterns remember to handle the unmatched data.
 +    * treat raw wiki data with suspicion and remember to ensure all special characters go to an entity converter.
 +  - Test and post your completed plugin on the Dokuwiki [[:plugins|plugin page]].
 +
 +===== Sample Plugin 1 - Now =====
 +
 +When its syntax, ''%%[NOW]%%'', is encountered in a wiki page the current date and time will be inserted in [[http://www.faqs.org/rfcs/rfc2822|RFC2822]] format.
 +
 +  * type is ''%%'substition'%%''. We are substituting a time stamp for the ''%%[NOW]%%'' token, similar to the way smileys and acronyms are handled.  They belong to the mode type ''%%'substition'%%'' so we will too. 
 +  * allowedTypes are not required, no other dokuwiki syntax can occur within our ''%%[NOW]%%'' syntax.  Therefore we don't need the ''getAllowedTypes()'' method.
 +  * PType is ''normal'', thats the default value, so we don't need the ''getPType()'' method.
 +  * there is no need for an entry and exit pattern, just a special pattern to detect ''%%[NOW]%%'' The only thing we need to be careful of is "[" and "]" have special meanings in regular expressions, so we will need to //escape// them, making our pattern - ''%%'\[NOW\]'%%''.
 +  * in this case the ''handler()'' method doesn't need to do anything.  We have no special states to take care of or extra parameters in our syntax.  We just return an empty array to ensure a render instruction for our plugin is stored.
 +  * all the ''render()'' method needs to do is add the time stamp to the current wiki page --- ''%%$renderer->doc .= date('r');%%''
 +
 +And that's our plugin finished.
 +
 +<code php syntax.php>
 +<?php
 +/**
 + * Plugin Now: Inserts a timestamp.
 + 
 + * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
 + * @author     Christopher Smith <chris@jalakai.co.uk>
 + */
 +
 +// must be run within Dokuwiki
 +if(!defined('DOKU_INC')) die();
 +
 +if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
 +require_once(DOKU_PLUGIN.'syntax.php');
 +
 +/**
 + * All DokuWiki plugins to extend the parser/rendering mechanism
 + * need to inherit from this class
 + */
 +class syntax_plugin_now extends DokuWiki_Syntax_Plugin {
 +
 +    function getInfo(){
 +      return array(
 +        'author' => 'me',
 +        'email'  => 'me@someplace.com',
 +        'date'   => '2005-07-28',
 +        'name'   => 'Now Plugin',
 +        'desc'   => 'Include the current date and time',
 +        'url'    => 'http://www.dokuwiki.org/plugin:tutorial',
 +      );
 +    }
 +
 +    function getType() { return 'substition'; }
 +    function getSort() { return 32; }
 +    function connectTo($mode) { $this->Lexer->addSpecialPattern('\[NOW\]',$mode,'plugin_now'); }
 +    function handle($match, $state, $pos, &$handler){ return array($match, $state, $pos); }
 +    function render($mode, &$renderer, $data) {
 +    
 +      if($mode == 'xhtml'){
 +          $renderer->doc .= date('r');
 +          return true;
 +      }
 +      return false;
 +    }
 +}
 +?></code>
 +
 +Note: due to the way Dokuwiki caches pages this plugin will report the date/time at which the cached version was created.  You would need to add ''%%~~NOCACHE~~%%'' to the page to ensure the date was current every time the page was requested.
 +
 +===== Sample Plugin 2 - Color =====
 +
 +When its syntax, ''%%<color somecolour/somebackgroundcolour>%%'', is encountered in a wiki page the text colour will be changed to somecolour, the background will be changed to somebackgroundcolour and both will remain that way until ''%%</color>%%'' is encountered.
 +
 +  * what we are doing is similar to the strong mode, its type is 'formatting' so we should use that type too.
 +  * allowedTypes should be the inline modes - ''substition'', ''formatting'' & ''disabled''.
 +  * PType is ''normal'', thats the default value, so again we don't need a ''getPType()'' method.
 +  * we need to use an entry and exit pattern.  The entry pattern should check to make sure there is an exit pattern, which means ''%%'<color.*>(?=.*?</color>)'%%''. The exit pattern is simpler, ''%%</color>%%''.
 +  * the ''handle()'' method will need to deal with three states matching our entry and exit patterns and unmatched for the text which occurs between them.
 +    * ''DOKU_LEXER_ENTER'' state requires some processing to extract the colour and background colour values, they make up our render instruction.
 +    * ''DOKU_LEXER_UNMATCHED'' state doesn't require any processing, but we have to pass the unmatched text (in ''$match'') to ''render()'' so that goes into our render instruction.
 +    * ''DOKU_LEXER_EXIT'' state doesn't require any processing or have any special data, we simply need to generate an exit instruction for ''render()''.
 +  * the ''render()'' method will need to deal with the same three states as ''handle()''.
 +    * ''DOKU_LEXER_ENTER'', open a span with a style using the colour and/or background colour values.
 +    * ''DOKU_LEXER_UNMATCHED'', add the unmatched text to the output document.
 +    * ''DOKU_LEXER_EXIT'', close the span
 +
 +Again, all fairly straightforward - and here it is.
 +
 +<code php syntax.php>
 +<?php
 +/**
 + * Plugin Color: Sets new colors for text and background.
 + 
 + * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
 + * @author     Christopher Smith <chris@jalakai.co.uk>
 + */
 +
 +// must be run within Dokuwiki
 +if(!defined('DOKU_INC')) die();
 +
 +if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
 +require_once(DOKU_PLUGIN.'syntax.php');
 +
 +/**
 + * All DokuWiki plugins to extend the parser/rendering mechanism
 + * need to inherit from this class
 + */
 +class syntax_plugin_color extends DokuWiki_Syntax_Plugin {
 +
 +    /**
 +     * return some info
 +     */
 +    function getInfo(){
 +        return array(
 +            'author' => 'Christopher Smith',
 +            'email'  => 'chris@jalakai.co.uk',
 +            'date'   => '2008-02-06',
 +            'name'   => 'Color Plugin',
 +            'desc'   => 'Changes text colour and background',
 +            'url'    => 'http://www.dokuwiki.org/plugin:tutorial',
 +        );
 +    }
 +
 +    function getType(){ return 'formatting'; }
 +    function getAllowedTypes() { return array('formatting', 'substition', 'disabled'); }   
 +    function getSort(){ return 158; }
 +    function connectTo($mode) { $this->Lexer->addEntryPattern('<color.*?>(?=.*?</color>)',$mode,'plugin_color'); }
 +    function postConnect() { $this->Lexer->addExitPattern('</color>','plugin_color'); }
 +
 +
 +    /**
 +     * Handle the match
 +     */
 +    function handle($match, $state, $pos, &$handler){
 +        switch ($state) {
 +          case DOKU_LEXER_ENTER :
 +                list($color, $background) = preg_split("/\//u", substr($match, 6, -1), 2);
 +                if ($color = $this->_isValid($color)) $color = "color:$color;";
 +                if ($background = $this->_isValid($background)) $background = "background-color:$background;";
 +                return array($state, array($color, $background));
 +
 +          case DOKU_LEXER_UNMATCHED :  return array($state, $match);
 +          case DOKU_LEXER_EXIT :       return array($state, '');
 +        }
 +        return array();
 +    }
 +
 +    /**
 +     * Create output
 +     */
 +    function render($mode, &$renderer, $data) {
 +        if($mode == 'xhtml'){
 +            list($state, $match) = $data;
 +            switch ($state) {
 +              case DOKU_LEXER_ENTER :      
 +                list($color, $background) = $match;
 +                $renderer->doc .= "<span style='$color $background'>"; 
 +                break;
 +                
 +              case DOKU_LEXER_UNMATCHED :  $renderer->doc .= $renderer->_xmlEntities($match); break;
 +              case DOKU_LEXER_EXIT :       $renderer->doc .= "</span>"; break;
 +            }
 +            return true;
 +        }
 +        return false;
 +    }
 +    
 +    // validate color value $c
 +    // this is cut price validation - only to ensure the basic format is correct and there is nothing harmful
 +    // three basic formats  "colorname", "#fff[fff]", "rgb(255[%],255[%],255[%])"
 +    function _isValid($c) {
 +        $c = trim($c);
 +        
 +        $pattern = "/^\s*(
 +            ([a-zA-z]+)|                                #colorname - not verified
 +            (\#([0-9a-fA-F]{3}|[0-9a-fA-F]{6}))|        #colorvalue
 +            (rgb\(([0-9]{1,3}%?,){2}[0-9]{1,3}%?\))     #rgb triplet
 +            )\s*$/x";
 +        
 +        if (preg_match($pattern, $c)) return trim($c);
 +        
 +        return "";
 +    }
 +}
 +?>
 +</code>
 +
 +Note: No checking is done to ensure colour names are valid or rgb values are within correct ranges.
 +
 +==== Discussion ====
 +
 +I try to create a plugin witch contains 2 block syntax in one plugin. I would like to put all my syntax codes in one plugin instead to split them in to many.
 +
 +for example:
 +<code>
 +<color green>Text</color>
 +<box note>Note</box>
 +</code>
 +
 +The problem, one should create a "span" and the other a "div" tag.
 +
 +Result example:
 +<code>
 +<span green>Text</span>
 +<div note>Note</div>
 +</code>
 +
 +So I need to detect the head tag "<color" "</color" "<box" "</box" in the method "render($mode, &$renderer, $data)" to be able to generate different results.
 +How I find out in "render" if "color" or "box" is used :?:G
ja/devel/syntax_plugins.txt · 最終更新: 2023-08-17 19:29 by Klap-in

特に明示されていない限り、本Wikiの内容は次のライセンスに従います: CC Attribution-Share Alike 4.0 International
CC Attribution-Share Alike 4.0 International Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki