Infobox



The highligters and wrappers were parsed in the wacko_preprocess() of the WackoFormatter.


<?php
/*
* WackoFormatter
*
* Formats text with wacko-formatting.
* Links and actions aren't processed. Its processed by PostWacko formatter
*/

// . . .

$result = $wacko->_format($code, 'highlight/' . $formatter, $params);

// add wrapper
if (isset($params['wrapper']) && ($params['wrapper'] != 'none'))
{
    $wrapper            = 'wrapper_' . $params['wrapper'];
    $params['wrapper']    = ''; // no recursion
    $result                = $wacko->_format(trim($result), 'highlight/' . $wrapper, $params);
}

  1. extend the wrappers box and shade
  2. add formatter for callout
  3. arguments for formatter and wrapper
    1. type
    2. title
    3. icon
    4. col
  4. add prefix wrapper_ for wrapper arguments

Wrappers were parsed after the highlighter...


Formatter

  1. %%(info type="warning" title="Warning") Formatter info.%%

Wrapper

  1. %%(wacko wrapper="shade" wrapper_type="warning" wrapper_title="Warning") Formatter wacko with shade wrapper.%%

1. Issues

  1. nesting
    • Nested formatters / wrappers are currently not feasible, that means you cant wrap a page or a section of o page in a wrapper, if it already contains a formatter (see exception below)
    • As character markup for text formatters, you can use percent signs %%, %% or grave accents ``, ``. Both characters are equal. Grave accents can be useful if the text already contains percent signs, which may be mistakenly considered markup.

Beyond that this allows you to wrap a formatter in a formatter, e.g. wrapping a CSS highlighter in a details formatter.


  1. CSS for print and wordprocessor
  2. Reset body_r after changing CSS class for wrapper to .wrapper and .wrapper-content
  3. SVG: set only viewbox
    • all SVG background images require a change, so we can set the icon size in the CSS file, e.g. <span>text</span> and .success span::before{}.
    • added CSS class msg: <div class="msg note">
  4. CSS: define min-height for both containers
  5. use type to assign style only to paragraph <p class="type-warning">
  6. Unicode icon versus SVG icon
  7. Paragrafica & Formatters: <ignore> terminator versus auto-paragraphs
  8. it is too colorful, reduce and simplify color usage
  9. make icon optional in container and wrapper title

2. Formatter

Formatter Examples

Test here...

2.1. Callout


%%(info type="warning" title="Warning") Formatter info.%%

Warning

Formatter info.

formatter/highlight/info.php

<?php

/*
    %%(info
        [type="default | error | example | important | note | question | quote | success | warning"]
        [title="Title"]
        [icon=0|1]
        [style="no use"]
        )
    content
    %%
*/

$types            = ['default', 'error', 'example', 'important', 'note', 'question', 'quote', 'success', 'warning'];

// defaults
$options['type']    ??= 'default';
$options['title']    ??= '';
$options['icon']    ??= 1;
$options['style']    ??= false;

$options['tpl']        = true;

if (in_array($options['type'], $types))
{
    // info type-* in wacko.css
    $tpl->type = ' type-' . $options['type'];
}

if ($options['icon'])
{
    $tpl->icon    = true;
    $tpl->eicon    = true;
}

$tpl->style        = 'info';
$tpl->t_title    = $options['title'] ?? null;
$tpl->include    = include Ut::join_path(FORMATTER_DIR, 'wiki.php');

formatter/highlight/template/info.tpl

[ === main === ]
<ignore>
	<div class="[ ' style ' ][ ' type ' ]">
	[= icon _ =
		[ ' nonstatic ' ]
		<div class="info-content">
	=]
	[= t _ =
		<p class="info-title">[ ' title | e ' ]</p>
	=]
[ ' include  // <-- no indention for embeded pre ' ]
	[= eicon _ =
		[ ' nonstatic ' ]
		</div>
	=]
	</div>
</ignore>	

2.2. Pre-configured formatter


formatter/highlight/customized.php

<?php
// set wrapper options
$options['wrapper'] = 'box';
$options['wrapper_align'] = $options['align'];
$options['wrapper_width'] = $options['width'];

// add / include highlighter / formatter ...

echo Ut::html($text);

3. Color scheme

type background color border
default rgb(147, 154, 69,.1) #939A45
important rgba(255,23,68,.1) #ff1744
note rgba(68,138,255,.1) #448aff
warning rgba(255,145,0,.1) #ff9100
success rgba(0,200,83,.1) #00c853
question rgba(100,221,23,.1) #64dd17
error rgba(255,82,82,.1) #ff5252
example rgba(101,31,255,.1) #651fff
quote hsla(0,0%,62%,.1) #9e9e9e
summary rgba(224, 203, 82,.1) #e0cb52


Color picker tool

4. Types

  1. note, tip, hint, nota bene *
  2. abstract, summary
  3. error, failure, fail
  4. important, attention
  5. success
  6. question, help, faq
  7. warning, caution, attention, danger
  8. issue, bug
  9. example, snippet
  10. quote, cite

* info is used as a meta term for the formatter.

5. Layout

  • info

<ignore>
<div class="info type-note">
  <div class="info-content">
    <p class="info-title">Info</p>
  </div>
</div>
</ignore>	

  • <div>
  • <aside>
  • <p>

<ignore> is terminator tag for Paragrafica, gets parsed away in the process

5.1. Icon

5.1.1. background:

span.icon{
/*     background-size: 16px 16px;*/
    /* ! required for span width -> inline element */
    display: inline-block;
    height: 16px;
    width: 0;
    vertical-align: text-bottom; /* middle */
}
 
a.external-link .icon {
    background: rgba(0, 0, 0, 0) url('./../icon/web.svg') no-repeat scroll left center;
    padding-left: 17px;
}

5.1.2. before::

span.icon {
    position: relative;
    padding: 0 1rem 0 0;
    vertical-align: middle; /* text-bottom */
}
.icon::before{
    position: absolute;
    height: 1rem;
    width: 1rem;
}
 
a.external-link .icon::before {
    content: url('./../icon/web.svg') " ";
}

6. CSS


color
background
border
icon


# type hl class icon svg syntax
1 default β„Ή
2 error βœ•
3 example πŸ’‘
4
5 important !
6 note ✎
7 question ?
8 quote ❝
9 success βœ“
10 warning ⚠
custom

6.1. Icons

6.1.1. Unicode

.callout.type-fail > .callout-title::before {
    color: #ff5252;
    content: "βœ•"
}

πŸ–‰βœŽ βœοΈβš™βš πŸš«β­•βŒπŸž
πŒ†β˜ β˜‘β˜’βœ…πŸ‘€πŸ’₯πŸ‘πŸ”§
β“β—πŸ“ŒπŸ“πŸ’‘β”β•πŸ—‘οΈβ°πŸΎ
β„ΉπŸ“‹πŸ“πŸ”₯βš‘βœ”οΈβœ“βœ”βœ•βœ–


❝❞¢ πŸ·βš™οΈπŸš§


6.1.2. SVG

.callout.type-fail > .callout-title::before {
    content: url('./../icon/report-bug.svg') " ";
    height: 1rem;
    width: 1rem;
}

6.2. wacko.css

/* Callouts: SYNTAX % %(callout type="warning" title="Warning")text% % */
 
/* 1. default */
.info,
.wrapper {
    /* box-shadow: 0 2px 2px 0 rgba(0,0,0,.14),0 1px 5px 0 rgba(0,0,0,.12),0 3px 1px -2px rgba(0,0,0,.2); */
    position: relative;
    margin: 1em 0;
    padding: .4rem .6rem;
    border: .05rem solid rgb(147, 154, 69,.1);
    border-left: .2rem solid #939a45;
    border-radius: .1rem;
    min-height: 5em;
    overflow: auto;
}
 
.wrapper-title {
    margin: -.4rem -.6rem .4rem -.6rem;
    padding: .4rem .6rem .4rem 2rem;
/*     border-bottom: .05rem solid rgba(68,138,255,.1);
    background-color: rgba(68,138,255,.1); */
    font-weight: 700;
}
.info.type-default,
.wrapper.type-default,
.wrapper-title {
    border-bottom: .05rem solid rgb(147, 154, 69,.1);
    background-color: rgb(147, 154, 69,.1);
}
.wrapper > .wrapper-title::before {
    position: absolute;
    left: .6rem;
    color: #939a45;
    font-size: 1rem;
    content: "i";
    height: 1rem;
    width: 1rem;
    font-family: "Times New Roman", Times, serif;
}
 
/* 2. note */
.info.type-note {
    border-color: rgba(68,138,255,.1);
    border-left-color: #448aff;
}
.info.type-note,
.wrapper.type-note,
.wrapper.type-note > .wrapper-title {
    background-color: rgba(68,138,255,.1);
}
.wrapper.type-note > .wrapper-title {
    border-bottom-color: rgba(68,138,255,.1);
}
.info.type-note > .info-content::before,
.wrapper.type-note > .wrapper-title::before {
    color: #448aff;
    content: "✎";
}
 
/* 3. warning */
.info.type-warning {
    border-color: rgba(255,145,0,.1);
    border-left-color: #ff9100;
}
.info.type-warning,
.wrapper.type-warning,
.wrapper.type-warning > .wrapper-title {
    background-color: rgba(255,145,0,.1);
}
.wrapper.type-warning > .wrapper-title {
    border-bottom-color: rgba(255,145,0,.1);
}
.info.type-warning > .info-content::before,
.wrapper.type-warning > .wrapper-title::before {
    color: #ff9100;
    content: "⚠";
    /* content: url('./../icon/warning.svg') " "; */
}
 
/* 4. success */
.info.type-success {
    border-color: rgba(100,221,23,.1);
    border-left-color: #64dd17;
}
.info.type-success,
.wrapper.type-success,
.wrapper.type-success > .wrapper-title {
    background-color: rgba(100,221,23,.1);
}
.wrapper.type-success > .wrapper-title {
    border-bottom-color: rgba(100,221,23,.1);
}
.info.type-success > .info-content::before,
.wrapper.type-success > .wrapper-title::before {
    color: #64dd17;
    content: "βœ“";
}
 
/* 5. question */
.info.type-question {
    border-color: rgba(224, 203, 82,.1);
    border-left-color: #e0cb52;
}
.info.type-question,
.wrapper.type-question,
.wrapper.type-question > .wrapper-title {
    background-color: rgba(224, 203, 82,.1);
}
.wrapper.type-question > .wrapper-title {
    border-bottom-color: rgba(224, 203, 82,.1);
}
.info.type-question > .info-content::before,
.wrapper.type-question > .wrapper-title::before {
    color: #e0cb52;
    content: "?";
}
 
/* 6. error */
.info.type-error {
    border-color: rgba(255,82,82,.1);
    border-left-color: #ff5252;
}
.info.type-error,
.wrapper.type-error,
.wrapper.type-error > .wrapper-title {
    background-color: rgba(255,82,82,.1);
}
.wrapper.type-error > .wrapper-title {
    border-bottom-color: rgba(255,82,82,.1);
}
.info.type-error > .info-content::before,
.wrapper.type-error > .wrapper-title::before {
    color: #ff5252;
    content: "βœ•";
    /* content: url('./../icon/cross.svg') " ";
    height: 1rem;
    width: 1rem; */
}
 
/* 7. example */
.info.type-example {
    border-left-color: #651fff;
}
.info.type-example,
.wrapper.type-example,
.wrapper.type-example > .wrapper-title {
    background-color: rgba(101,31,255,.1);
}
.wrapper.type-example > .wrapper-title {
    border-bottom-color: rgba(101,31,255,.1);
}
.info.type-example > .info-content::before,
.wrapper.type-example > .wrapper-title::before {
    color: #651fff;
    content: "πŸ’‘";
}
 
/* 8. quote */
.info.type-quote {
    border-left-color: #9e9e9e;
}
.info.type-quote,
.wrapper.type-quote,
.wrapper.type-quote > .wrapper-title {
    background-color: hsla(0,0%,62%,.1);
}
.wrapper.type-quote > .wrapper-title {
    border-bottom-color: hsla(0,0%,62%,.1);
}
.info.type-quote > .info-content::before,
.wrapper.type-quote > .wrapper-title::before {
    color: #9e9e9e;
    content: "❝";
}
/* 9. important */
.info.type-important {
    border-color: rgba(255,23,68,.1);
    border-left-color: #ff1744;
}
.info.type-important,
.wrapper.type-important,
.wrapper.type-important > .wrapper-title {
    background-color: rgba(255,23,68,.1);
}
.wrapper.type-important > .wrapper-title {
    border-bottom-color: rgba(255,23,68,.1);
}
.info.type-important > .info-content::before,
.wrapper.type-important > .wrapper-title::before {
    color: #ff1744;
    content: "!";
}
 
/* Info container */
.info-title {
    margin: -.4rem -.6rem .4rem -.6rem;
    padding: .4rem .6rem .4rem .6rem;
    font-weight: 700;
}
.info-content {
    margin: 0;
    padding: .4rem .6rem .4rem 4.4rem;
    /* font-weight: 700; */
}
.info > .info-content::before {
    position: absolute;
    left: 1rem;
    top: .4rem;
    color: #939a45;
    /* font-weight: bold; */
    font-size: 3rem;
    content: "i";
    height: 3rem;
    width: 3rem;
    text-align: center;
    line-height: normal;
    font-family: "Times New Roman", Times, serif;
    /* opacity: 0.4; */
}
}

7. Sanitization

<?php

$sanitize = function($value, $filter)
{
    switch ($filter)
    {
        case 'color':
            if (preg_match('/^(
                (\#([0-9a-fA-F]{3}|[0-9a-fA-F]{6}))|        # color value
                (rgb\(([0-9]{1,3}%?,){2}[0-9]{1,3}%?\))        # rgb triplet
                )$/x', $value))
            {
                return $value;
            }
            break;
        case 'width':
            if (preg_match('/^\d*\.?\d+(%|px|em|ex|pt|cm|mm|pi|in)$/', $value))
            {
                return $value;
            }
            break;
        case 'class':
            if (preg_match('/[^A-Za-z0-9_-]/', $value))
            {
                return $value;
            }
            break;
    }
};

8. Wrapper

text
shade
box


box shade page text
type + + – -
title + + – -
alignment + –1 –2 +
clear + + – –
width + –1 + –3
column – + – +
frame + + – –
automatic line feed + + + –

1 This option does not make sense, because the width of the block is always equal to the width of the page.
2 Only to the left.
3 If you don't put the line feeds yourself, the block width is fixed by the engine at approximately 90% of the page width.


What exactly is the purpose of the page wrapper in comparison to the text wrapper?

  • visualize

8.1. box

<?php

/*
    %%(Formatter
        wrapper="box"
        [wrapper_align="left | center | right"]
        [wrapper_width="pixel"]
        [wrapper_title="Title"]
        [wrapper_type="default | error | example | important | note | question | quote | success | warning"]
        [col=2|3|4|5]
        [clear])
    content
    %%
*/

$align_class    = '';
$type_class        = '';
$types            = ['default', 'error', 'example', 'important', 'note', 'question', 'quote', 'success', 'warning'];

// defaults
$options['wrapper_type']    ??= 'default';
$options['wrapper_title']    ??= null;
$options['wrapper_align']    ??= 'right';
$options['wrapper_width']    ??= 250;
$options['clear']            ??= false;
$options['col']                ??= false;

if (in_array($options['wrapper_align'], ['center', 'left', 'right']))
{
    // wrapper-* align in wacko.css
    $align_class = ' wrapper-' . $options['wrapper_align'];
}

if (in_array($options['wrapper_type'], $types))
{
    // wrapper type-* in wacko.css
    $type_class = ' type-' . $options['wrapper_type'];
}

$col_class    = $options['col'] ? ' wrapper-col' . (int) $options['col'] : '';

// output wrapper
$tpl->type        = $type_class;
$tpl->align        = $align_class;
$tpl->col        = $col_class;
$tpl->width        = (int) $options['wrapper_width'];
$tpl->t_title    = $options['wrapper_title'] ?? null;
$tpl->text        = $text;

if ($options['clear'])
{
    $tpl->clear = true;
}

[ === main === ]
<ignore>
	<aside class="wrapper[ ' type ' ][ ' align ' ][ ' col ' ]" style="width: [ ' width ' ]px;">
		[= t _ =
			<p class="wrapper-title">[ ' title | e ' ]</p>
		=]
		<div class="wrapper-content">
[ ' text  // <-- no indention for embeded pre ']
		</div>
	</aside>
	[= clear _ =
		[ ' nonstatic ' ]
		<span class="clearfix"></span>
	=]
</ignore>	

8.2. shade

<?php

/*
    %%(Formatter
        wrapper="shade"
        [wrapper_title="Title"]
        [wrapper_type="default | error | example | important | note | question | quote | success | warning"]
        [col=2|3|4|5])
    content
    %%
*/

$type_class        = '';
$types            = ['default', 'error', 'example', 'important', 'note', 'question', 'quote', 'success', 'warning'];

// defaults
$options['wrapper_type']    ??= 'default';
$options['wrapper_title']    ??= null;
$options['col']                ??= false;

if (in_array($options['wrapper_type'], $types))
{
    // wrapper type-* in wacko.css
    $type_class = ' type-' . $options['wrapper_type'];
}

$col_class    = $options['col'] ? ' wrapper-col' . (int) $options['col'] : '';

// output wrapper
$tpl->type        = $type_class;
$tpl->col        = $col_class;
$tpl->t_title    = $options['wrapper_title'] ?? null;
$tpl->text        = $text;

[ === main === ]
<ignore>
	<div class="wrapper[ ' type ' ]">
		[= t _ =
			<p class="wrapper-title">[ ' title | e ' ]</p>
		=]
		<div class="wrapper-content[ ' col ' ]">
[ ' text  // <-- no indention for embeded pre ']
		</div>
	</div>
</ignore>	

8.3. page

<?php

/*
    %%(Formatter
        wrapper="page"
        [wrapper_width=200])
    content
    %%
*/

// defaults
$options['wrapper_width']    ??= '800';

// output wrapper
$tpl->width        = (int) $options['wrapper_width'];
$tpl->text        = $text;

[ === main === ]
<ignore>
	<div style="width: [ ' width ' ]px;">
[ ' text  // <-- no indention for embeded pre ']
	</div>
</ignore>	

8.4. text

<?php

/*
    %%(Formatter
        wrapper="text"
        [wrapper_align="left | center | right | justify"]
        [col=2|3|4|5]
        [clear])
    content
    %%
*/

$align_class = '';

// defaults
$options['wrapper_align']    ??= 'left';
$options['clear']            ??= false;
$options['col']                ??= false;

if (in_array($options['wrapper_align'], ['center', 'justify', 'left', 'right']))
{
    if ($options['wrapper_align'] != 'justify')
    {
        // wrapper-* align in wacko.css
        $align_class = 'wrapper-' . $options['wrapper_align'];
    }

    $text_align        = ' style="text-align: ' . $options['wrapper_align'] . ';"';
}

$col_class    = $options['col'] ? ' wrapper-col' . (int) $options['col'] : '';

// output wrapper
$tpl->align        = $align_class;
$tpl->txtalign    = $text_align;
$tpl->col        = $col_class;
$tpl->text        = $text;

if ($options['clear'])
{
    $tpl->clear = true;
}

[ === main === ]
<ignore>
	<div class="[ ' align ' ][ ' col ' ]"[ ' txtalign ' ]>
[ ' text  // <-- no indention for embeded pre ']
	</div>
	[= clear _ =
		[ ' nonstatic ' ]
		<span class="clearfix"></span>
	=]
</ignore>	

9. Links

  1. Forum: Callouts