====== Description ====== ---- plugin ---- description: Shorthand for HTML divs and spans. author : Joe Lapp email : http://www.spiderjoe.com type : syntax lastupdate : 2007-06-05 compatible : depends : conflicts : similar : tags : div, span, html ---- This page provides two related [[plugins]]: **Span Shorthand** and **Div Shorthand**. Span Shorthand is a shorthand syntax for embedding HTML spans: %your_class{words}% ==> words Div Shorthand is a shorthand syntax for embedding HTML divs: #your_class[words]# ==>
....
*
* syntax: %your_class{...}%
*
* You may embed any syntax between the shorthand opening and closing tags
* that you can embed in (for example) the DokuWiki **...** bold syntax,
* except that you can't nest a span shorthand within a span shorthand. If
* anyone knows how to allow nesting, please let me know.
*
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
* @author Joe Lapp
*/
if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/');
if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
require_once(DOKU_PLUGIN.'syntax.php');
class syntax_plugin_span_shorthand extends DokuWiki_Syntax_Plugin
{
function getInfo()
{
return array(
'author' => 'Joe Lapp',
'email' => '',
'date' => '2005-08-21',
'name' => 'Span Shorthand',
'desc' => 'Shorthand for ...',
'url' => 'http://www.dokuwiki.org/plugin:div_span_shorthand',
);
}
function getType()
{ return 'formatting'; }
function getAllowedTypes()
{ return array('substition','protected','disabled','formatting'); }
function getSort()
{ return 500; } // I'm not sure what's appropriate
// override default accepts() method to allow nesting
// - ie, to get the plugin accepts its own entry syntax
function accepts($mode)
{
if ($mode == substr(get_class($this), 7)) return true;
return parent::accepts($mode);
}
function connectTo($mode)
{
$this->Lexer->addEntryPattern('\%[a-zA-Z0-9_-]+\{(?=.*\x7D\x25)',
$mode, 'plugin_span_shorthand');
}
function postConnect()
{
$this->Lexer->addExitPattern('\}\%', 'plugin_span_shorthand');
}
function handle($match, $state, $pos, &$handler)
{
switch($state)
{
case DOKU_LEXER_ENTER:
return array($state, substr($match, 1, -1));
case DOKU_LEXER_UNMATCHED:
return array($state, $match);
case DOKU_LEXER_EXIT:
return array($state, '');
}
return array();
}
function render($mode, &$renderer, $data)
{
if($mode == 'xhtml')
{
list($state, $match) = $data;
switch($state)
{
case DOKU_LEXER_ENTER:
//toc is lost when we use $renderer->nest so we back it up here
//$this->toc = $renderer->toc;
$renderer->doc .= '';
break;
case DOKU_LEXER_UNMATCHED:
$renderer->doc .= htmlspecialchars($match);
// if you want to render instructions placed inside the tag :
// $renderer->doc .= $renderer->nest(p_get_instructions($match));
break;
case DOKU_LEXER_EXIT:
$renderer->doc .= '';
//toc restore
//$renderer->toc = $this->toc;
break;
}
return true;
}
return false;
}
}
?>
===== Div Plugin Code =====
....
*
* syntax: #your_class[...]#
*
* The text you include between the shorthand opening and closing tags is not
* parsed in any way. It's special characters are all escaped. I'd like to
* allow embedded syntax, but paragraph generation behaves too strangely to
* make this useful. For example, embedding the word "ain't" would produce
* three separate paragraphs for each of "ain", "'", and "t". If you know
* how to fix this, please let me know.
*
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
* @author Joe Lapp
*/
if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/');
if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
require_once(DOKU_PLUGIN.'syntax.php');
class syntax_plugin_div_shorthand extends DokuWiki_Syntax_Plugin
{
function getInfo()
{
return array(
'author' => 'Joe Lapp',
'email' => '',
'date' => '2005-08-21',
'name' => 'Div Shorthand',
'desc' => 'Shorthand for ...',
'url' => 'http://www.dokuwiki.org/plugin:div_span_shorthand',
);
}
function getType()
{ return 'container'; }
function getAllowedTypes()
{
// I'd like to allow all types, but the autogen behavior makes them troublesome.
return array(/*'container','substition','protected','disabled','formatting'*/);
}
function getPType()
{ return 'block'; }
function getSort()
{ return 500; } // I'm not sure what's appropriate
function connectTo($mode)
{
$this->Lexer->addEntryPattern('\#[a-zA-Z0-9_-]+\[(?=.*\x5D\x23)',
$mode, 'plugin_div_shorthand');
}
// override default accepts() method to allow nesting
// - ie, to get the plugin accepts its own entry syntax
function accepts($mode)
{
if ($mode == substr(get_class($this), 7)) return true;
return parent::accepts($mode);
}
function postConnect()
{
$this->Lexer->addExitPattern('\]\#', 'plugin_div_shorthand');
}
function handle($match, $state, $pos, &$handler)
{
switch($state)
{
case DOKU_LEXER_ENTER:
return array($state, substr($match, 1, -1));
case DOKU_LEXER_UNMATCHED:
return array($state, $match);
case DOKU_LEXER_EXIT:
return array($state, '');
}
return array();
}
function render($mode, &$renderer, $data)
{
if($mode == 'xhtml')
{
list($state, $match) = $data;
switch($state)
{
case DOKU_LEXER_ENTER:
//toc is lost when we use $renderer->nest so we back it up here
//$this->toc = $renderer->toc;
$renderer->doc .= '
';
break;
case DOKU_LEXER_UNMATCHED:
$renderer->doc .= htmlspecialchars($match);
// if you want to render instructions placed inside the tag :
// $renderer->doc .= $renderer->nest(p_get_instructions($match));
break;
case DOKU_LEXER_EXIT:
$renderer->doc .= '';
//toc restore
//$renderer->toc = $this->toc;
break;
}
return true;
}
return false;
}
}
?>
===== Discussion =====
Some points:
* A getSort() value of 500 should be fine. You only need to worry about this value if your entry/exit patterns clash with other Dokuwiki syntax modes. Your chosen pattern does --- ''//on enter
// on exit
--- //[[chris@jalakai.co.uk|Christopher Smith]] 2005-08-23 09:40//
>I played around with it a bit. Given that I'm using PType 'block', it seems that I don't need the initial or final . >It might actually be useful for people to put a paragraph inside the div, but what if someone doesn't want them? I was using this plugin to display a date right under my page title header, and because I have a "div.level1 p:first-child", I'd end up acting on the
in the date div -- not what I wanted. (I have since come up with another way to do dates, as you'll see in my next plugin.) >I was hoping someone would show me how to include arbitrary syntax inside the div, in which case I shouldn't need to add the
tags via the plugin. Maybe as an interim fix I can have the plugin implement a special token, say "##", for wrapping text in paragraphs. That way you could have multiple paragraphs inside the div. For example:
#prettybox[
## Paragraph 1.
## Paragraph 2.
## Etc.
]#
>I'd have the handle() method take care of this -- there'd be no special substition plugin for it. What do you think?
>BTW, I added a special thank you to the description for providing a [[devel:Syntax Plugins|plugin tutorial]].
>[[http://www.spiderjoe.com|Spider Joe]]
>I thought of an even better way to embed paragraphs. If the content contains at least one blank line (whitespace only), then the entire content is partitioned into paragraphs delimited by blank lines. In particular, to get just one paragraph, you'd do this:
#prettybox[
This is the only paragraph.
]#
>The blank line occurs on the same line as ''#prettybox['', immediately following this opening tag.
>But I'd really rather be able to embed any syntax. Is it possible to call the DokuWiki parser recursively?
>[[http://www.spiderjoe.com|Spider Joe]]
>> Yes, its possible, probably not wise. // where $text is a string containing dokuwiki markup to be rendered
// and $info is an array to receive information from the renderer
$xhtml_output = p_render('xhtml', p_get_instructions($text),$info=array()); Its not very efficient. There is a large overhead in setting up the parser. If you use a type of ''formatting'' you can just embed about any syntax. --- //[[chris@jalakai.co.uk|Christopher Smith]] 2005-08-23 23:49//
>>>Maybe a future rev of the parser could factor out the static configuration so that nested invocations could share that configuration without rebuilding it? You might also have to pass in an inheritable state. Dunno. \\ \\ I tried changing Div Shorthand to use type formatting, allowing nesting types, but I ended up with the same problem as using type container and allowing nesting types -- wierd paragraph generation. It looks like the problem is with PType block -- it's dictating what happens between a syntax mode's opening and closing tags.\\ \\ BTW, how are you embedding the date/time in your responses? Is there an easy way to do this? I can't find it on the syntax page or the FAQ. Thanks! \\ \\ [[http://www.spiderjoe.com|Spider Joe]]
>>>> Don't use ''block'', use ''normal'' with the paragraph formatting I suggested. With ''block'' the parser will open and close paragraphs before and after any nested formatting, with ''normal'' it doesn't do that. \\ \\ If you are logged in, you will have a signature button amongst all the other editing buttons, you also get your login name added to the changes log. --- //[[chris@jalakai.co.uk|Christopher Smith]] 2005-08-24 23:34//
I'm unable to get the shorthand/syntax/span.php + syntax_plugin_shorthand_span directory organization to work. PHP isn't logging any error messages either. My next plugin sort of requires this directory structure because there are include files shared among the variations, and I'd like a logical home for those files. Any ideas? I'm using a recent devel version. Thanks! [[http://www.spiderjoe.com|Spider Joe]]
Uh, never mind. It works. The problem was with my new plugin (yet to be posted). An error was causing the parser to bomb out no matter what I did. My plugin PHP errors don't seem to be making it to the PHP error log.
BTW, I think I'd like to leave div_shorthand and span_shorthand in different directories. Other people might come up with other shorthand, and I don't want to confuse people by already have the shorthand directory taken. Besides, the only thing shorthand plugins will have in common is the conceptual idea of being shorthand, not any logic. [[http://www.spiderjoe.com|Spider Joe]]
> Your comment about PHP not logging error messages. To error check your plugin, edit ''inc/pluginutils.php'' and remove the "@" from in front of the two includes in the ''plugin_load()'' function. Note this will likely mean Dokuwiki generates lots of warnings when it first attempts to load any plugins using subfolders via ''pluginname/syntax.php''. You could get arround this by changing the error level to ignore warnings outside your plugin, and if you wish setting a tighter error level inside the plugin (remember to reset the error level before exiting). \\ \\ The two plugins might not share any code, but conceptually they are two sides of the one coin, doing the same thing just at different places within the wiki page. I think it could be reasonably assumed that a user of one of the plugins would be a user of the other. Of course its up to you about the name and structure - but would you consider a name like "custom_class"? :-) --- //[[chris@jalakai.co.uk|Christopher Smith]] 2005-08-25 20:56//
That's good to know about the error logging. Thanks. I wish I knew about that before starting the [[plugin:command|Command Plugin]].
There seems to be four possible ways to use
. If no inline text precedes or follows, you get
in that place. I don't know how to do (2) with the parser, unless I call it recursively. That leaves (1) as the most likely most doable solution. What behavior would be most helpful to people? In any case, I prefer to allow syntax within the div, and this is not currently allowed. BTW, if I end up creating yet another variant of this syntax, I'll probably throw it all into the same plugin. Maybe the potential should be enough to incline me to do so. [[http://www.spiderjoe.com|Spider Joe]] > ''%%$renderer->document%%'' is the whole output document up to that point. You can always look back at the characters immediately before the end to see if they are '''' and remove them if they are. Though to be fair, it would make sense for the renderer to check for empty
tags as its probably a fairly frequently occurring issue. --- //[[chris@jalakai.co.uk|Christopher Smith]] 2005-08-27 01:48//
>>Hey, that's a clever hack. ;-) It does allows me to remove a preceding one, but not a following one. The best I can do with the following paragraph is to always give it an absolute position off screen via the HTML style attribute. This might keep people from putting text in the same paragraph, but it might incline some people to put sneaky text in there that a search engine or a filtering client might see, but that people browsing and maintaining the site would not.
>>Were I to go ahead with that solution, I'm thinking of having four syntaxes instead of two. ''%'' and ''#'' would indicate whether the contents goes into an outer paragraph or not, while curly-braces and square-brackets would signify the use of a span or div, respectively.
>>Inside a ''#'' you would have the option of having paragraphs auto-generated. The plugin would put a special marker in ''%%$renderer->document%%'' at the beginning of the content and it would monitor unmatched text. If ever a blank line appears --- according to the unmatched text --- then the entire content would be repartitioned into paragraphs. I'm thinking that I could leave the marker in there (as an HTML comment) if repartitioning is not required, to save a few clock cycles.
>>Ideally, a future version of the parser would encapsulate page concatenation and then write each contribution to an output buffer. You can do this by capturing the output buffer before parsing, parsing to collect a new output buffer, capturing the parser's output buffer, and then restoring the original output buffer. Buffered output would be far more efficient than string cat'ing, which requires creating huge numbers of objects, reallocating the heap and copying growing strings. Higher peak load, you know. You could do this without breaking existing plugins by monitoring ''%%$renderer->document%%'', which would then serve as just an output variable for old-style plugins. (Of course, this plugin, as proposed, would break. But it could be fixed.)
>>Anyway, can you think of a better way to deal with the paragraph that follows the ''#''-style shorthand? If I can monitor unmatched text as described, hidden text is the only thing keeping me from doing it. --- [[http://www.spiderjoe.com|Spider Joe]]
----
So here's what I'm thinking. I'm going to rewrite these two plugins and add a third:
- ''%% %spanclass{words}% %%'' produces a embedded in a paragraph.
- ''%% %divclass[words]% %%'' produces a is invalid...martin
In addition:
- Syntax will be permitted and interpreted in both s as well as other HTML such as links, lists.
>The syntax indicates that there should also be ''%%#divid[words]#%%'', attaching an id. As an alternative how about this ''%%#div?id=words&class=words#%%''...martin
I thought of adding another syntax for clearing empty paragraphs from the preceding portion of the page, but I didn't want to burden people by making them have to do this.
Please speak up if you can think of a better approach. Thanks! --- [[http://www.spiderjoe.com|Spider Joe]]
> Is it possible to modify div plugin to put div class "your_class" into another class that's in main.php. That is:
text autogen behavior makes them troublesome.
return array('container','substition','protected','disabled','formatting','paragraphs');
}
function getPType()
{ return 'normal'; }
function getSort()
{ return 500; } // I'm not sure what's appropriate
function connectTo($mode)
{
$this->Lexer->addEntryPattern('\#[a-zA-Z0-9_-]+\[(?=.*\x5D\x23)',
$mode, 'plugin_div_shorthand');
}
// override default accepts() method to allow nesting
// - ie, to get the plugin accepts its own entry syntax
function accepts($mode)
{
if ($mode == substr(get_class($this), 7)) return true;
return parent::accepts($mode);
}
function postConnect()
{
$this->Lexer->addExitPattern('\]\#', 'plugin_div_shorthand');
}
function handle($match, $state, $pos, &$handler)
{
switch($state)
{
case DOKU_LEXER_ENTER:
return array($state, substr($match, 1, -1));
case DOKU_LEXER_UNMATCHED:
return array($state, $match);
default:
return array($state);
}
}
function render($mode, &$renderer, $indata) {
if($mode == 'xhtml'){
list($state, $data) = $indata;
switch ($state) {
case DOKU_LEXER_ENTER :
$renderer->doc .= "\n ';
break;
case DOKU_LEXER_UNMATCHED :
$renderer->doc .= $renderer->_xmlEntities($data);
break;
case DOKU_LEXER_EXIT :
$renderer->doc .= "\n ";
break;
}
return true;
}
// unsupported $mode
return false;
}
}
//Setup VIM: ex: et ts=4 enc=utf-8 :
?>
--- Wolfgang 2007/09/06
[[http://wcpedia.com|WCpedia]]'s Monkhouse
Hi; I posted to the plugin requests forum about a plugin for being able to have two columns, and someone replied sending me here. Unfortunately, I don't know what "div" and "span" do. In my days of html-ing they didn't exist. Would this plugin allow me to do that? If so, could you show me an example? This is the [[http://wcpedia.com/dw/doku.php/wc_info/index|WCpedia index page]]; just a table of links. I'd like to put the second set on a second column. Thanks in advance.
my_class[words][container_class]
with second argument were optional (page is default)
* Find "
...