diff --git a/CHANGELOG.textile b/CHANGELOG.textile index e26b6aa5..dd55530c 100644 --- a/CHANGELOG.textile +++ b/CHANGELOG.textile @@ -2,8 +2,6 @@ h1. Changelog Here's a summary of changes in each release. The list doesn't include some small changes or updates to test cases. -h2. Version 3.7.5 - upcoming - h2. "Version 3.7.4 - 2019/12/15":https://github.com/textile/php-textile/releases/tag/v3.7.4 * Fix issue where an inline tag preceding the last character, that is a glyph, is not rendered if the block tags are disabled with @Parser::setBlockTags@ (closes "#198":https://github.com/textile/php-textile/issues/198). diff --git a/composer.json b/composer.json index fffdc3c1..4727d8bd 100644 --- a/composer.json +++ b/composer.json @@ -12,12 +12,12 @@ }, "autoload": { "psr-4": { - "Netcarver\\Textile\\": "src/Netcarver/Textile/" + "Netcarver\\Textile\\": "src/" } }, "autoload-dev": { "psr-4": { - "Netcarver\\Textile\\Test\\": "test/Netcarver/Textile/Test/" + "Netcarver\\Textile\\Test\\": "test/" } }, "require": { @@ -36,8 +36,6 @@ }, "scripts": { "test": "./vendor/bin/phpunit", - "cs": "./vendor/bin/phpcs", - "bump": "@php ./scripts/release.php", - "bump-dev": "@php ./scripts/release.php --dev" + "cs": "./vendor/bin/phpcs" } } diff --git a/phpunit.xml b/phpunit.xml index 852a959c..65c093b1 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -2,7 +2,7 @@ - ./test/Netcarver/Textile/Test/ + ./test/ diff --git a/scripts/release.php b/scripts/release.php deleted file mode 100644 index 18c505b6..00000000 --- a/scripts/release.php +++ /dev/null @@ -1,111 +0,0 @@ - [ - '/(protected \$ver = \')([^\']+)(\';)/' => function ($m) use ($version) { - return $m[1] . $version . $m[3]; - }, - ], - 'composer.json' => [ - '/("dev-master": ")([^"])(")/' => function ($m) use ($minor) { - return $m[1] . $dev . $m[2]; - } - ] -]; - -if ($release) { - $update['README.textile'] = [ - '/(\/textile[ :])(\d+\.\d+\.\*)/' => function ($m) use ($install) { - return $m[1] . $install; - } - ]; - - $update['CHANGELOG.textile'] = [ - '/(h2. )([\s\S]+)(upcoming)/' => function ($m) use ($date, $url, $version) { - return $m[1] . '"' . $m[2] . $date . '":' . $url . $version; - } - ]; -} - -foreach ($update as $file => $replacements) { - echo "· $file\n"; - - $content = file_get_contents($file); - - foreach ($replacements as $from => $to) { - $content = preg_replace_callback($from, $to, (string) $content); - } - - if ($dry) { - continue; - } - - if (file_put_contents($file, $content) === false) { - exit(1); - } -} diff --git a/src/Api/ConfigInterface.php b/src/Api/ConfigInterface.php new file mode 100644 index 00000000..2b1244e3 --- /dev/null +++ b/src/Api/ConfigInterface.php @@ -0,0 +1,526 @@ +setDocumentType('html5') + * ->parse('HTML(HyperText Markup Language)"); + * + * @param string $doctype Either 'xhtml' or 'html5' + * @return Parser This instance + * @since 3.6.0 + * @see Parser::getDocumentType() + */ + public function setDocumentType(string $doctype): self; + + /** + * Gets the current output document type. + * + * bc. $parser = new \Netcarver\Textile\Parser(); + * echo $parser->getDocumentType(); + * + * @return string The document type + * @since 3.6.0 + * @see Parser::setDocumentType() + */ + public function getDocumentType(): string; + + /** + * Sets the document root directory path. + * + * This method sets the path that is used to resolve relative file paths + * within local filesystem. This is used to fetch image dimensions, for + * instance. + * + * bc. $parser = new \Netcarver\Textile\Parser(); + * $parser->setDocumentRootDirectory('/path/to/document/root/dir'); + * + * If not set, document root defaults to the current working directory if + * PHP-Textile is used via CLI. On server environment, DOCUMENT_ROOT or + * PATH_TRANSLATED server variable is used based on which ever is available. + * + * @param string $path The root path + * @return Parser This instance + * @since 3.6.0 + * @see Parser::getDocumentRootDirectory() + */ + public function setDocumentRootDirectory(string $path): self; + + /** + * Gets the current document root directory path. + * + * bc. $parser = new \Netcarver\Textile\Parser(); + * echo $parser->getDocumentRootDirectory(); + * + * @return string Path to the document root directory + * @since 3.6.0 + * @see Parser::setDocumentRootDirectory() + */ + public function getDocumentRootDirectory(): string; + + /** + * Enables lite mode. + * + * If enabled, allowed tags are limited. Parser will prevent the use extra + * Textile formatting, accepting only paragraphs and blockquotes as valid + * block tags. + * + * bc. $parser = new \Netcarver\Textile\Parser(); + * $parser + * ->setLite(true) + * ->parse('h1. Headings are disabled too'); + * + * Generates: + * + * bc.

h1. Headings are disabled too

+ * + * This doesn't prevent unsafe input values. If you wish to parse untrusted + * user-given Textile input, also enable the restricted parser mode with + * Parser::setRestricted(). + * + * bc. $parser = new \Netcarver\Textile\Parser(); + * echo $parser + * ->setRestricted(true) + * ->setLite(true) + * ->parse('h1. Hello World!'); + * + * @param bool $lite TRUE to enable + * @return Parser This instance + * @since 3.6.0 + * @see Parser::isLiteModeEnabled() + * @see Parser::setRestricted() + */ + public function setLite(bool $lite): self; + + /** + * Gets the lite mode status. + * + * bc. $parser = new \Netcarver\Textile\Parser(); + * if ($parser->isLiteModeEnabled() === true) { + * echo 'Lite mode is enabled.'; + * } + * + * @return bool TRUE if enabled, FALSE otherwise + * @since 3.6.0 + * @see Parser::setLite() + */ + public function isLiteModeEnabled(): bool; + + /** + * Disables and enables images. + * + * If disabled, image tags are not generated. This option is ideal for + * minimalist output such as text-only comments. + * + * bc. $parser = new \Netcarver\Textile\Parser(); + * echo $parser + * ->setImages(true) + * ->parse('!image.png!'); + * + * Generates: + * + * bc.

!image.png!

+ * + * @param bool $enabled TRUE to enable, FALSE to disable + * @return Parser This instance + * @since 3.6.0 + * @see Parser::isImageTagEnabled() + */ + public function setImages(bool $enabled): self; + + /** + * Whether images are enabled. + * + * bc. $parser = new \Netcarver\Textile\Parser(); + * if ($parser->isImageTagEnabled() === true) { + * echo 'Images are enabled.'; + * } + * + * @return bool TRUE if enabled, FALSE otherwise + * @since 3.6.0 + * @see Parser::setImages() + */ + public function isImageTagEnabled(): bool; + + /** + * Sets link relationship status value. + * + * This method sets the HTML relationship tokens that are applied to links + * generated by PHP-Textile. + * + * bc. $parser = new \Netcarver\Textile\Parser(); + * echo $parser + * ->setLinkRelationShip('nofollow') + * ->parse('"Link":http://example.com/'); + * + * Generates: + * + * bc.

Link

+ * + * @param string|array $relationship The HTML rel attribute value + * @return Parser This instance + * @since 3.6.0 + * @see Parser::getLinkRelationShip() + */ + public function setLinkRelationShip($relationship): self; + + /** + * Gets the link relationship status value. + * + * bc. $parser = new \Netcarver\Textile\Parser(); + * echo $parse + * ->setLinkRelationShip('nofollow') + * ->getLinkRelationShip(); + * + * The above outputs "nofollow". + * + * @return string The value + * @since 3.6.0 + * @see Parser::setLinkRelationShip() + */ + public function getLinkRelationShip(): string; + + /** + * Enables restricted parser mode. + * + * This option should be enabled when parsing untrusted user input, + * including comments or forum posts. When enabled, the parser escapes any + * raw HTML input, ignores unsafe attributes and links only whitelisted URL + * schemes. + * + * For instance the following malicious input: + * + * bc. $parser = new \Netcarver\Textile\Parser(); + * echo $parser + * ->setRestricted(true) + * ->parse('Innocent _looking_ "link":javacript:window.alert().'); + * + * Returns safe, sanitized HTML with valid Textile input still parsed: + * + * bc.

Innocent looking “link”:javacript:window.alert().

+ * + * If left disabled, the parser allows users to mix raw HTML and Textile. + * Using the parser in non-restricted on untrusted input, like comments + * and forum posts, will lead to XSS issues, as users will be able to use + * any HTML code, JavaScript links and Textile attributes in their input. + * + * @param bool $enabled TRUE to enable, FALSE to disable + * @return Parser This instance + * @since 3.6.0 + * @see Parser::isRestrictedModeEnabled() + */ + public function setRestricted(bool $enabled): self; + + /** + * Whether restricted parser mode is enabled. + * + * bc. $parser = new \Netcarver\Textile\Parser(); + * if ($parser->isRestrictedModeEnabled() === true) { + * echo 'PHP-Textile is in restricted mode.'; + * } + * + * @return bool TRUE if enabled, FALSE otherwise + * @since 3.6.0 + * @see Parser::setRestricted() + */ + public function isRestrictedModeEnabled(): bool; + + /** + * Enables and disables raw blocks. + * + * When raw blocks are enabled, any paragraph blocks wrapped in a tag + * not matching Parser::$blockContent or Parser::$phrasingContent will not + * be parsed, and instead is left as is. + * + * bc. $parser = new \Netcarver\Textile\Parser(); + * echo $parser + * ->setRawBlocks(true) + * ->parse('
A *raw* block.
'); + * + * The above generates: + * + * bc.
A *raw* block.
+ * + * @param bool $enabled TRUE to enable, FALSE to disable + * @return Parser This instance + * @since 3.7.0 + * @see Parser::isRawBlocksEnabled() + * @see Parser::isRawBlock() + */ + public function setRawBlocks(bool $enabled): self; + + /** + * Whether raw blocks are enabled. + * + * bc. $parser = new \Netcarver\Textile\Parser(); + * if ($parser->isRawBlocksEnabled() === true) { + * echo 'Raw blocks are enabled'; + * } + * + * @return bool TRUE if enabled, FALSE otherwise + * @since 3.7.0 + * @see Parser::setRawBlocks() + */ + public function isRawBlocksEnabled(): bool; + + /** + * Enables and disables block-level tags and formatting features. + * + * When disabled, block-level tags aren't rendered. This allows PHP-Textile + * to operate on a single line of text, rather than blocks of text and does + * not wrap the output in paragraph tags. + * + * bc. $parser = new \Netcarving\Textile\Parser(); + * echo $parser + * ->setBlockTags(false) + * ->parse('h1. Hello *strong* world!'); + * + * The above generates: + * + * bc. h1. Hello strong world! + * + * @param bool $enabled TRUE to enable, FALSE to disable + * @return Parser This instance + * @since 3.6.0 + * @see Parser::isBlockTagEnabled() + */ + public function setBlockTags(bool $enabled): self; + + /** + * Whether block-level tags are enabled and parsed. + * + * bc. $parser = new \Netcarving\Textile\Parser(); + * if ($parser->isBlockTagAllowed() === true) { + * echo 'Block tags are enabled.'; + * } + * + * @return bool TRUE if enabled, FALSE otherwise + * @since 3.6.0 + * @see Parser::setBlockTags() + */ + public function isBlockTagEnabled(): bool; + + /** + * Enables and disables line-wrapping. + * + * If enabled, line-breaks are replaced by target document's break tag. If + * disabled, input document's line-breaks are ignored. This setting can be + * used if the the input document's lines are pre-wrapped. For instance, + * in case the input is from CLI content, or source code documentation. + * + * bc. $parser = new \Netcarving\Textile\Parser(); + * echo $parser + * ->setLineWrap(false) + * ->parse("Hello\nworld!"); + * + * The above generates: + * + * bc.

Hello world!

+ * + * @param bool $enabled TRUE to enable, FALSE to disable + * @return Parser This instance + * @since 3.6.0 + * @see Parser::isLineWrapEnabled() + */ + public function setLineWrap(bool $enabled): self; + + /** + * Whether line-wrapping is enabled. + * + * bc. $parser = new \Netcarving\Textile\Parser(); + * if ($parser->isLineWrapEnabled() === true) { + * echo 'Line-wrapping is enabled.'; + * } + * + * @return bool TRUE if enabled, FALSE otherwise + * @see Parser::setLineWrap() + * @since 3.6.0 + */ + public function isLineWrapEnabled(): bool; + + /** + * Sets a substitution symbol. + * + * This method lets you to redefine a substitution symbol. The following + * sets the 'half' glyph: + * + * bc. $parser = new \Netcarver\Textile\Parser(); + * echo $parser + * ->setSymbol('half', '1⁄2') + * ->parse('Hello [1/2] World!'); + * + * Generates: + * + * bc.

Hello 1&#⁄2 World!

+ * + * Symbol can be set to FALSE to disable it: + * + * bc. $parser = new \Netcarver\Textile\Parser(); + * $parser->setSymbol('dimension', false); + * + * See Parser::getSymbol() to find out all available symbols. + * + * @param string $name Name of the symbol to assign a new value to + * @param string|bool $value New value for the symbol, or FALSE to disable + * @return Parser This instance + * @see Parser::getSymbol() + */ + public function setSymbol(string $name, $value): self; + + /** + * Gets a symbol definitions. + * + * This method gets a symbol definition by name, or the full symbol table + * as an array. + * + * bc. $parser = new \Netcarver\Textile\Parser(); + * echo $parser->getSymbol('dimension'); + * + * To get all available symbol definitions: + * + * bc. $parser = new \Netcarver\Textile\Parser(); + * print_r($parser->getSymbol()); + * + * @param string|null $name The name of the symbol, or NULL if requesting the symbol table + * @return array|string The symbol table or the requested symbol + * @throws \InvalidArgumentException + * @see Parser::setSymbol() + */ + public function getSymbol(?string $name = null); + + /** + * Sets base relative image prefix. + * + * The given string is used to prefix relative image paths, usually an + * absolute HTTP address pointing a the site's image, or upload, directory. + * PHP-Textile to convert relative paths to absolute, or prefixed paths. + * + * bc. $parser = new \Netcarver\Textile\Parser(); + * $parser->setImagePrefix('https://static.example.com/images/'); + * + * @param string $prefix The prefix + * @return Parser This instance + * @since 3.7.0 + * @see Parser::getImagePrefix() + */ + public function setImagePrefix(string $prefix): self; + + /** + * Gets base relative image prefix. + * + * bc. $parser = new \Netcarver\Textile\Parser(); + * echo $parser->getImagePrefix(); + * + * @return string The prefix + * @since 3.7.0 + * @see Parser::setImagePrefix() + */ + public function getImagePrefix(): string; + + /** + * Sets base relative link prefix. + * + * The given string is used to prefix relative link paths. This allows + * PHP-Textile convert relative paths to absolute, or prefixed, links. + * + * bc. $parser = new \Netcarver\Textile\Parser(); + * $parser->setLinkPrefix('https://example.com/'); + * + * @param string $prefix The prefix + * @return Parser This instance + * @since 3.7.0 + * @see Parser::getLinkPrefix() + */ + public function setLinkPrefix(string $prefix): self; + + /** + * Gets base relative link prefix. + * + * bc. $parser = new \Netcarver\Textile\Parser(); + * echo $parser->getLinkPrefix(); + * + * @return string The prefix + * @since 3.7.0 + * @see Parser::setLinkPrefix() + */ + public function getLinkPrefix(): string; + + /** + * Enables dimensionless images. + * + * If enabled, image width and height attributes will not be included in + * rendered image tags. Normally, PHP-Textile will add width and height + * to images linked with a local relative path, as long as the image file + * can be accessed. + * + * bc. $parser = new \Netcarver\Textile\Parser(); + * echo $parser + * ->setDimensionlessImages(true) + * ->parse('!image.jpg!'); + * + * @param bool $dimensionless TRUE to disable image dimensions, FALSE to enable + * @return Parser This instance + * @see Parser::getDimensionlessImages() + */ + public function setDimensionlessImages(bool $dimensionless = true): self; + + /** + * Whether dimensionless images are enabled. + * + * bc. $parser = new \Netcarver\Textile\Parser(); + * if ($parser->getDimensionlessImages() === true) { + * echo 'Images do not get dimensions.'; + * } + * + * @return bool TRUE if images will not get dimensions, FALSE otherwise + * @see Parser::setDimensionlessImages() + */ + public function getDimensionlessImages(): bool; +} diff --git a/test/Netcarver/Textile/Test/Parser/MaxLinkIndex.php b/src/Api/EncoderInterface.php similarity index 78% rename from test/Netcarver/Textile/Test/Parser/MaxLinkIndex.php rename to src/Api/EncoderInterface.php index 787a0dd4..8e9f0954 100644 --- a/test/Netcarver/Textile/Test/Parser/MaxLinkIndex.php +++ b/src/Api/EncoderInterface.php @@ -1,15 +1,15 @@ textileEncode('Some content to encode.'); + * + * @param string $text The text to be encoded + * @return string The encoded text */ - - protected function getMaxLinkIndex() - { - return 0; - } + public function textileEncode(string $text): string; } diff --git a/test/Netcarver/Textile/Test/Parser/NoMultiByteStrings.php b/src/Api/ParserInterface.php similarity index 53% rename from test/Netcarver/Textile/Test/Parser/NoMultiByteStrings.php rename to src/Api/ParserInterface.php index fbc7fc7e..b2f727ef 100644 --- a/test/Netcarver/Textile/Test/Parser/NoMultiByteStrings.php +++ b/src/Api/ParserInterface.php @@ -1,15 +1,15 @@ parse('h1. Hello World!'); + * + * The above parses trusted input in full-feature mode, generating: + * + * bc.

Hello World!

+ * + * Additionally the parser can be run in safe, restricted mode using the + * Parser::setRestricted() method. + * + * bc. $parser = new \Netcarver\Textile\Parser(); + * echo $parser + * ->setRestricted(true) + * ->parse('h1. Hello World!'); + * + * This enables restricted mode and allows safe parsing of untrusted input. + * PHP-Textile will disable unsafe attributes, links and escapes any raw + * HTML input. This option should be enabled when parsing untrusted user + * input. + * + * If restricted mode is disabled, the parser allows users to mix raw HTML + * and Textile. + * + * @param string $text The Textile input to parse + * @return string Parsed Textile input + * @since 3.6.0 + * @api */ - - protected function isMultiByteStringSupported() - { - return false; - } + public function parse(string $text): string; } diff --git a/src/Netcarver/Textile/DataBag.php b/src/DataBag.php similarity index 95% rename from src/Netcarver/Textile/DataBag.php rename to src/DataBag.php index 9cb491fa..97c50d10 100644 --- a/src/Netcarver/Textile/DataBag.php +++ b/src/DataBag.php @@ -1,5 +1,7 @@ data = (array) $data; } @@ -86,8 +85,7 @@ public function __construct(array $data = null) * @param array $params Arguments * @return DataBag */ - - public function __call($name, array $params) + public function __call(string $name, array $params): self { if (!empty($params[1]) || !empty($params[0])) { $this->data[$name] = $params[0]; diff --git a/src/Netcarver/Textile/Parser.php b/src/Parser.php similarity index 72% rename from src/Netcarver/Textile/Parser.php rename to src/Parser.php index cca3d680..aa06ae9e 100644 --- a/src/Netcarver/Textile/Parser.php +++ b/src/Parser.php @@ -1,5 +1,7 @@

Header...

- - Paragraph: p. (also applied by default) - Example: p. Text ->

Text

- - Blockquote: bq. - Example: bq. Block quotation... ->
Block quotation...
- - Blockquote with citation: bq.:http://citation.url - Example: bq.:http://example.com/ Text... - ->
Text...
- - Footnote: fn(1-100). - Example: fn1. Footnote... ->

Footnote...

- - Numeric list: #, ## - Consecutive paragraphs beginning with # are wrapped in ordered list tags. - Example:
  1. ordered list
- - Bulleted list: *, ** - Consecutive paragraphs beginning with * are wrapped in unordered list tags. - Example: - - Definition list: - Terms ;, ;; - Definitions :, :: - Consecutive paragraphs beginning with ; or : are wrapped in definition list tags. - Example:
term
definition
- - Redcloth-style Definition list: - - Term1 := Definition1 - - Term2 := Extended - definition =: - -Phrase modifier syntax: - - _emphasis_ -> emphasis - __italic__ -> italic - *strong* -> strong - **bold** -> bold - ??citation?? -> citation - -deleted text- -> deleted - +inserted text+ -> inserted - ^superscript^ -> superscript - ~subscript~ -> subscript - @code@ -> computer code - %(bob)span% -> span - - ==notextile== -> leave text alone (do not format) - - "linktext":url -> linktext -"linktext(title)":url -> linktext - "$":url -> url - "$(title)":url -> url - - !imageurl! -> - !imageurl(alt text)! -> alt text - !imageurl!:linkurl -> - -ABC(Always Be Closing) -> ABC - -Linked Notes: - - Allows the generation of an automated list of notes with links. - - Linked notes are composed of three parts, a set of named _definitions_, a set of - _references_ to those definitions and one or more _placeholders_ indicating where - the consolidated list of notes is to be placed in your document. - - Definitions: - - Each note definition must occur in its own paragraph and should look like this... - - note#mynotelabel. Your definition text here. - - You are free to use whatever label you wish after the # as long as it is made up - of letters, numbers, colon(:) or dash(-). - - References: - - Each note reference is marked in your text like this[#mynotelabel] and - it will be replaced with a superscript reference that links into the list of - note definitions. - - List placeholder(s): - - The note list can go anywhere in your document. You have to indicate where - like this: - - notelist. - - notelist can take attributes (class#id) like this: notelist(class#id). - - By default, the note list will show each definition in the order that they - are referenced in the text by the _references_. It will show each definition with - a full list of backlinks to each reference. If you do not want this, you can choose - to override the backlinks like this... - - notelist(class#id)!. Produces a list with no backlinks. - notelist(class#id)^. Produces a list with only the first backlink. - - Should you wish to have a specific definition display backlinks differently to this - then you can override the backlink method by appending a link override to the - _definition_ you wish to customise. - - note#label. Uses the citelist's setting for backlinks. - note#label!. Causes that definition to have no backlinks. - note#label^. Causes that definition to have one backlink (to the first ref.) - note#label*. Causes that definition to have all backlinks. - - Any unreferenced notes will be left out of the list unless you explicitly state - you want them by adding a '+'. Like this... - - notelist(class#id)!+. Giving a list of all notes without any backlinks. - - You can mix and match the list backlink control and unreferenced links controls - but the backlink control (if any) must go first. Like so: notelist^+. , not - like this: notelist+^. - - Example... - Scientists say[#lavader] the moon is small. - - note#other. An unreferenced note. - - note#lavader(myliclass). "Proof":http://example.com of a small moon. - - notelist(myclass#myid)+. - - Would output (the actual IDs used would be randomised)... - -

Scientists say1 the moon is small.

- -
    -
  1. a - Proof of a small moon.
  2. -
  3. An unreferenced note.
  4. -
- - The 'a b c' backlink characters can be altered too. - For example if you wanted the notes to have numeric backlinks starting from 1: - - notelist:1. - -Table syntax: - - Simple tables: - - |a|simple|table|row| - |And|Another|table|row| - |With an||empty|cell| - - |=. My table caption goes here - |_. A|_. table|_. header|_.row| - |A|simple|table|row| - - Note: Table captions *must* be the first line of the table else treated as a center-aligned cell. - - Tables with attributes: - - table{border:1px solid black}. My table summary here - {background:#ddd;color:red}. |{}| | | | - - To specify thead / tfoot / tbody groups, add one of these on its own line - above the row(s) you wish to wrap (you may specify attributes before the dot): - - |^. # thead - |-. # tbody - |~. # tfoot - - Column groups: - - |:\3. 100| - - Becomes: - - - You can omit either or both of the \N or width values. You may also - add cells after the colgroup definition to specify col elements with - span, width, or standard Textile attributes: - - |:. 50|(firstcol). |\2. 250||300| - - Becomes: - - - - - - - - (Note that, per the HTML specification, you should not add span - to the colgroup if specifying col elements.) - -Applying Attributes: - - Most anywhere Textile code is used, attributes such as arbitrary css style, - css classes, and ids can be applied. The syntax is fairly consistent. - - The following characters quickly alter the alignment of block elements: - - < -> left align ex. p<. left-aligned para - > -> right align h3>. right-aligned header 3 - = -> centred h4=. centred header 4 - <> -> justified p<>. justified paragraph - - These will change vertical alignment in table cells: - - ^ -> top ex. |^. top-aligned table cell| - - -> middle |-. middle aligned| - ~ -> bottom |~. bottom aligned cell| - - Plain (parentheses) inserted between block syntax and the closing dot-space - indicate classes and ids: - - p(hector). paragraph ->

paragraph

- - p(#fluid). paragraph ->

paragraph

- - (classes and ids can be combined) - p(hector#fluid). paragraph ->

paragraph

- - Curly {brackets} insert arbitrary css style - - p{line-height:18px}. paragraph ->

paragraph

- - h3{color:red}. header 3 ->

header 3

- - Square [brackets] insert language attributes - - p[no]. paragraph ->

paragraph

- - %[fr]phrase% -> phrase - - Usually Textile block element syntax requires a dot and space before the block - begins, but since lists don't, they can be styled just using braces - - #{color:blue} one ->
    - # big
  1. one
  2. - # list
  3. big
  4. -
  5. list
  6. -
- - Using the span tag to style a phrase - - It goes like this, %{color:red}the fourth the fifth% - -> It goes like this, the fourth the fifth - -Ordered list start and continuation: - - You can control the start attribute of an ordered list like so; - - #5 Item 5 - # Item 6 - - You can resume numbering list items after some intervening anonymous block like so... - - #_ Item 7 - # Item 8 -*/ - namespace Netcarver\Textile; +use Netcarver\Textile\Api\ConfigInterface; +use Netcarver\Textile\Api\EncoderInterface; +use Netcarver\Textile\Api\ParserInterface; + /** * Textile parser. * @@ -348,54 +87,37 @@ * * class CommentParser extends Parser * { - * protected function configure() + * private function configure() * { * $this->setImages(false)->setRestricted(true)->setLite(true); * } * } * - * p. Keep in mind that the classes' protected methods and properties should be - * considered part of the private API and depending on them should be avoided. - * Instead try to only use the public methods marked as being part of the - * public API. - * * @see Parser::__construct() * @see Parser::parse() */ - -class Parser +class Parser implements ConfigInterface, EncoderInterface, ParserInterface { - /** - * Version number. - * - * @var string - */ - - protected $ver = '3.7.5-dev'; - /** * Regular expression snippets. * * @var array */ - - protected $regex_snippets; + private $regex_snippets; /** * Pattern for horizontal align. * * @var string */ - - protected $hlgn = "(?:\<(?!>)|<>|>|<|(?|\<\>|\=|[()]+(?! ))"; + private $hlgn = "(?:\<(?!>)|<>|>|<|(?|\<\>|\=|[()]+(?! ))"; /** * Pattern for vertical align. * * @var string */ - - protected $vlgn = "[\-^~]"; + private $vlgn = "[\-^~]"; /** * Pattern for HTML classes and IDs. @@ -405,40 +127,35 @@ class Parser * * @var string */ - - protected $clas = "(?:\([^)\n]+\))"; + private $clas = "(?:\([^)\n]+\))"; /** * Pattern for language attribute. * * @var string */ - - protected $lnge = "(?:\[[^]\n]+\])"; + private $lnge = "(?:\[[^]\n]+\])"; /** * Pattern for style attribute. * * @var string */ - - protected $styl = "(?:\{[^}\n]+\})"; + private $styl = "(?:\{[^}\n]+\})"; /** * Regular expression pattern for column spans in tables. * * @var string */ - - protected $cspn = "(?:\\\\[0-9]+)"; + private $cspn = "(?:\\\\[0-9]+)"; /** * Regular expression for row spans in tables. * * @var string */ - - protected $rspn = "(?:\/[0-9]+)"; + private $rspn = "(?:\/[0-9]+)"; /** * Regular expression for horizontal or vertical alignment. @@ -446,7 +163,7 @@ class Parser * @var string */ - protected $a; + private $a; /** * Regular expression for column or row spans in tables. @@ -454,15 +171,14 @@ class Parser * @var string */ - protected $s; + private $s; /** * Pattern that matches a class, style, language and horizontal alignment attributes. * * @var string */ - - protected $c; + private $c; /** * Pattern that matches class, style and language attributes. @@ -472,16 +188,14 @@ class Parser * * @var string */ - - protected $cls; + private $cls; /** * Whitelisted block tags. * - * @var array + * @var string[] */ - - protected $blocktag_whitelist = array(); + private $blocktag_whitelist = []; /** * Whether raw blocks are enabled. @@ -489,8 +203,7 @@ class Parser * @var bool * @since 3.7.0 */ - - protected $rawBlocksEnabled = false; + private $rawBlocksEnabled = false; /** * An array of patterns used for matching phrasing tags. @@ -498,11 +211,10 @@ class Parser * Phrasing tags, unline others, are wrapped in a paragraph even if they * already wrap the block. * - * @var array + * @var string[] * @since 3.7.0 */ - - protected $phrasingContent = array( + private $phrasingContent = [ 'a', 'abbr', 'acronym', @@ -556,7 +268,7 @@ class Parser 'var', 'video', 'wbr', - ); + ]; /** * An array of patterns used to match divider tags. @@ -564,15 +276,14 @@ class Parser * Blocks containing only self-closing divider tags are not wrapped in * paragraph tags. * - * @var array + * @var string[] * @since 3.7.0 */ - - protected $dividerContent = array( + private $dividerContent = [ 'br', 'hr', 'img', - ); + ]; /** * An array of patterns used to match unwrappable block tags. @@ -580,11 +291,10 @@ class Parser * Blocks containing any of these unwrappable tags will not be wrapped in * paragraphs. * - * @var array + * @var string[] * @since 3.7.0 */ - - protected $blockContent = array( + private $blockContent = [ 'address', 'article', 'aside', @@ -615,16 +325,15 @@ class Parser 'table', 'template', 'ul', - ); + ]; /** * An array of built patterns. * - * @var array + * @var string[] * @since 3.7.0 */ - - protected $patterns; + private $patterns; /** * Whether block tags are enabled. @@ -632,8 +341,7 @@ class Parser * @var bool * @since 3.6.0 */ - - protected $blockTagsEnabled = true; + private $blockTagsEnabled = true; /** * Whether lines are wrapped. @@ -641,48 +349,42 @@ class Parser * @var bool * @since 3.6.0 */ - - protected $lineWrapEnabled = true; + private $lineWrapEnabled = true; /** * Pattern for punctation. * * @var string */ - - protected $pnct = '[\!"#\$%&\'()\*\+,\-\./:;<=>\?@\[\\\]\^_`{\|}\~]'; + private $pnct = '[\!"#\$%&\'()\*\+,\-\./:;<=>\?@\[\\\]\^_`{\|}\~]'; /** * Pattern for URL. * * @var string */ - - protected $urlch; + private $urlch; /** * Matched marker symbols. * * @var string */ - - protected $syms = '¤§µ¶†‡•∗∴◊♠♣♥♦'; + private $syms = '¤§µ¶†‡•∗∴◊♠♣♥♦'; /** * HTML rel attribute used for links. * * @var string */ - - protected $rel = ''; + private $rel = ''; /** * Array of footnotes. * * @var array */ - - protected $fn; + private $fn; /** * Shelved content. @@ -692,61 +394,54 @@ class Parser * * @var array */ - - protected $shelf = array(); + private $shelf = []; /** * Restricted mode. * * @var bool */ - - protected $restricted = false; + private $restricted = false; /** * Disallow images. * * @var bool */ - - protected $noimage = false; + private $noimage = false; /** * Lite mode. * * @var bool */ - - protected $lite = false; + private $lite = false; /** * Accepted link protocols. * * @var array */ - - protected $url_schemes = array(); + private $url_schemes = []; /** * Restricted link protocols. * - * @var array + * @var string[] */ - - protected $restricted_url_schemes = array( + private $restricted_url_schemes = [ 'http', 'https', 'ftp', 'mailto', - ); + ]; /** * Unrestricted link protocols. * - * @var array + * @var string[] */ - - protected $unrestricted_url_schemes = array( + private $unrestricted_url_schemes = [ 'http', 'https', 'ftp', @@ -755,15 +450,14 @@ class Parser 'tel', 'callto', 'sftp', - ); + ]; /** * Span tags. * - * @var array + * @var string[] */ - - protected $span_tags = array( + private $span_tags = [ '*' => 'strong', '**' => 'b', '??' => 'cite', @@ -774,18 +468,17 @@ class Parser '+' => 'ins', '~' => 'sub', '^' => 'sup', - ); + ]; /** * Span wrappers. * - * @var array + * @var string[] * @since 3.7.2 */ - - protected $spanWrappers = array( + private $spanWrappers = [ '[' => ']', - ); + ]; /** * Patterns for finding glyphs. @@ -798,8 +491,7 @@ class Parser * @var array * @see Parser::$glyph_replace */ - - protected $glyph_search = array(); + private $glyph_search = []; /** * Glyph replacements. @@ -809,11 +501,10 @@ class Parser * the $glyph_search array and may refer to values captured in * the corresponding search regex. * - * @var array + * @var string[] * @see Parser::$glyph_search */ - - protected $glyph_replace = array(); + private $glyph_replace = []; /** * Indicates whether glyph substitution is required. @@ -824,19 +515,7 @@ class Parser * @var bool * @see Parser::setSymbol() */ - - protected $rebuild_glyphs = true; - - /** - * Relative image path. - * - * @var string - * @deprecated in 3.7.0 - * @see Parser::$relImagePrefix - * @see Parser::$relLinkPrefix - */ - - protected $relativeImagePrefix; + private $rebuild_glyphs = true; /** * Relative link prefix. @@ -844,8 +523,7 @@ class Parser * @var string * @since 3.7.0 */ - - protected $relLinkPrefix = ''; + private $relLinkPrefix = ''; /** * Prefix applied to relative images. @@ -853,44 +531,39 @@ class Parser * @var string * @since 3.7.0 */ - - protected $relImagePrefix = ''; + private $relImagePrefix = ''; /** * Maximum nesting level for inline elements. * * @var int */ - - protected $max_span_depth = 5; + private $max_span_depth = 5; /** * Server document root. * * @var string */ - - protected $doc_root; + private $doc_root; /** * Target document type. * * @var string */ - - protected $doctype; + private $doctype; /** * An array of supported doctypes. * - * @var array + * @var string[] * @since 3.6.0 */ - - protected $doctypes = array( + private $doctypes = [ 'xhtml', 'html5', - ); + ]; /** * Substitution symbols. @@ -898,12 +571,11 @@ class Parser * Basic symbols used in textile glyph replacements. To override these, call * setSymbol method before calling Parser::parse(). * - * @var array + * @var string[]|null[] * @see Parser::setSymbol() * @see Parser::parse() */ - - protected $symbols = array( + private $symbols = [ 'quote_single_open' => '‘', 'quote_single_close' => '’', 'quote_double_open' => '“', @@ -928,119 +600,110 @@ class Parser 'nl_ref_pattern' => '{marker}', 'caps' => '{content}', 'acronym' => null, - ); + ]; /** * Dimensionless images flag. * * @var bool */ - - protected $dimensionless_images = false; + private $dimensionless_images = false; /** * Directory separator. * * @var string */ - - protected $ds = '/'; + private $ds = '/'; /** * Whether mbstring extension is installed. * * @var bool */ - - protected $mb; + private $mb; /** * Multi-byte conversion map. * * @var array */ - - protected $cmap = array(0x0080, 0xffff, 0, 0xffff); + private $cmap = [ + 0x0080, + 0xffff, + 0, + 0xffff, + ]; /** * Stores note index. * * @var int */ - - protected $note_index = 1; + private $note_index = 1; /** * Stores unreferenced notes. * - * @var array + * @var string[] */ - - protected $unreferencedNotes = array(); + private $unreferencedNotes = []; /** * Stores note lists. * - * @var array + * @var string[] */ - - protected $notelist_cache = array(); + private $notelist_cache = []; /** * Stores notes. * - * @var array + * @var string[] */ - - protected $notes = array(); + private $notes = []; /** * Stores URL references. * - * @var array + * @var string[] */ - - protected $urlrefs = array(); + private $urlrefs = []; /** * Stores span depth. * * @var int */ - - protected $span_depth = 0; + private $span_depth = 0; /** * Unique ID used for reference tokens. * * @var string */ - - protected $uid; + private $uid; /** * Token reference index. * * @var int */ - - protected $refIndex = 1; + private $refIndex = 1; /** * Stores references values. * - * @var array + * @var string[] */ - - protected $refCache = array(); + private $refCache = []; /** * Matched open and closed quotes. * - * @var array + * @var string[] */ - - protected $quotes = array( + private $quotes = [ '"' => '"', "'" => "'", '(' => ')', @@ -1054,39 +717,35 @@ class Parser '‚' => '‘', '‘' => '’', '”' => '“', - ); + ]; /** * Regular expression that matches starting quotes. * * @var string */ - - protected $quote_starts; + private $quote_starts; /** * Ordered list starts. * - * @var array + * @var string[] */ - - protected $olstarts = array(); + private $olstarts = []; /** * Link prefix. * * @var string */ - - protected $linkPrefix; + private $linkPrefix; /** * Link index. * * @var int */ - - protected $linkIndex = 1; + private $linkIndex = 1; /** * Constructor. @@ -1105,11 +764,10 @@ class Parser * @see Parser::setDocumentType() * @api */ - - public function __construct($doctype = 'xhtml') + public function __construct(string $doctype = 'xhtml') { $this->setDocumentType($doctype)->setRestricted(false); - $uid = uniqid(rand()); + $uid = \uniqid((string) \rand()); $this->uid = 'textileRef:'.$uid.':'; $this->linkPrefix = $uid.'-'; $this->a = "(?:$this->hlgn|$this->vlgn)*"; @@ -1183,7 +841,7 @@ public function __construct($doctype = 'xhtml') * * use Netcarver\Textile\Parser; * - * class CommentParser extends Parser + * final class CommentParser extends Parser * { * protected function configure() * { @@ -1193,29 +851,15 @@ public function __construct($doctype = 'xhtml') * * @since 3.7.0 * @return void Return value is ignored - * @api */ - protected function configure() { } /** - * Sets the output document type. - * - * bc. $parser = new \Netcarver\Textile\Parser(); - * echo $parser - * ->setDocumentType('html5') - * ->parse('HTML(HyperText Markup Language)"); - * - * @param string $doctype Either 'xhtml' or 'html5' - * @return Parser This instance - * @since 3.6.0 - * @see Parser::getDocumentType() - * @api + * {@inheritdoc} */ - - public function setDocumentType($doctype) + public function setDocumentType(string $doctype): ConfigInterface { if (in_array($doctype, $this->doctypes, true)) { if ($this->getDocumentType() !== $doctype) { @@ -1230,253 +874,91 @@ public function setDocumentType($doctype) } /** - * Gets the current output document type. - * - * bc. $parser = new \Netcarver\Textile\Parser(); - * echo $parser->getDocumentType(); - * - * @return string The document type - * @since 3.6.0 - * @see Parser::setDocumentType() - * @api + * {@inheritdoc} */ - - public function getDocumentType() + public function getDocumentType(): string { - return $this->doctype; + return (string) $this->doctype; } /** - * Sets the document root directory path. - * - * This method sets the path that is used to resolve relative file paths - * within local filesystem. This is used to fetch image dimensions, for - * instance. - * - * bc. $parser = new \Netcarver\Textile\Parser(); - * $parser->setDocumentRootDirectory('/path/to/document/root/dir'); - * - * If not set, document root defaults to the current working directory if - * PHP-Textile is used via CLI. On server environment, DOCUMENT_ROOT or - * PATH_TRANSLATED server variable is used based on which ever is available. - * - * @param string $path The root path - * @return Parser This instance - * @since 3.6.0 - * @see Parser::getDocumentRootDirectory() - * @api + * {@inheritdoc} */ - - public function setDocumentRootDirectory($path) + public function setDocumentRootDirectory(string $path): ConfigInterface { - $this->doc_root = rtrim($path, '\\/').$this->ds; + $this->doc_root = rtrim($path, '\\/') . $this->ds; + return $this; } /** - * Gets the current document root directory path. - * - * bc. $parser = new \Netcarver\Textile\Parser(); - * echo $parser->getDocumentRootDirectory(); - * - * @return string Path to the document root directory - * @since 3.6.0 - * @see Parser::setDocumentRootDirectory() - * @api + * {@inheritdoc} */ - - public function getDocumentRootDirectory() + public function getDocumentRootDirectory(): string { - return $this->doc_root; + return (string) $this->doc_root; } /** - * Enables lite mode. - * - * If enabled, allowed tags are limited. Parser will prevent the use extra - * Textile formatting, accepting only paragraphs and blockquotes as valid - * block tags. - * - * bc. $parser = new \Netcarver\Textile\Parser(); - * $parser - * ->setLite(true) - * ->parse('h1. Headings are disabled too'); - * - * Generates: - * - * bc.

h1. Headings are disabled too

- * - * This doesn't prevent unsafe input values. If you wish to parse untrusted - * user-given Textile input, also enable the restricted parser mode with - * Parser::setRestricted(). - * - * bc. $parser = new \Netcarver\Textile\Parser(); - * echo $parser - * ->setRestricted(true) - * ->setLite(true) - * ->parse('h1. Hello World!'); - * - * @param bool $lite TRUE to enable - * @return Parser This instance - * @since 3.6.0 - * @see Parser::isLiteModeEnabled() - * @see Parser::setRestricted() - * @api + * {@inheritdoc} */ - - public function setLite($lite) + public function setLite(bool $lite): ConfigInterface { - $this->lite = (bool) $lite; + $this->lite = $lite; + return $this; } /** - * Gets the lite mode status. - * - * bc. $parser = new \Netcarver\Textile\Parser(); - * if ($parser->isLiteModeEnabled() === true) { - * echo 'Lite mode is enabled.'; - * } - * - * @return bool TRUE if enabled, FALSE otherwise - * @since 3.6.0 - * @see Parser::setLite() - * @api + * {@inheritdoc} */ - - public function isLiteModeEnabled() + public function isLiteModeEnabled(): bool { return (bool) $this->lite; } /** - * Disables and enables images. - * - * If disabled, image tags are not generated. This option is ideal for - * minimalist output such as text-only comments. - * - * bc. $parser = new \Netcarver\Textile\Parser(); - * echo $parser - * ->setImages(true) - * ->parse('!image.png!'); - * - * Generates: - * - * bc.

!image.png!

- * - * @param bool $enabled TRUE to enable, FALSE to disable - * @return Parser This instance - * @since 3.6.0 - * @see Parser::isImageTagEnabled() - * @api + * {@inheritdoc} */ - - public function setImages($enabled) + public function setImages($enabled): ConfigInterface { $this->noimage = !$enabled; + return $this; } /** - * Whether images are enabled. - * - * bc. $parser = new \Netcarver\Textile\Parser(); - * if ($parser->isImageTagEnabled() === true) { - * echo 'Images are enabled.'; - * } - * - * @return bool TRUE if enabled, FALSE otherwise - * @since 3.6.0 - * @see Parser::setImages() - * @api + * {@inheritdoc} */ - public function isImageTagEnabled() + public function isImageTagEnabled(): bool { return !$this->noimage; } /** - * Sets link relationship status value. - * - * This method sets the HTML relationship tokens that are applied to links - * generated by PHP-Textile. - * - * bc. $parser = new \Netcarver\Textile\Parser(); - * echo $parser - * ->setLinkRelationShip('nofollow') - * ->parse('"Link":http://example.com/'); - * - * Generates: - * - * bc.

Link

- * - * @param string|array $relationship The HTML rel attribute value - * @return Parser This instance - * @since 3.6.0 - * @see Parser::getLinkRelationShip() - * @api + * {@inheritdoc} */ - public function setLinkRelationShip($relationship) + public function setLinkRelationShip($relationship): ConfigInterface { $this->rel = (string) implode(' ', (array) $relationship); + return $this; } /** - * Gets the link relationship status value. - * - * bc. $parser = new \Netcarver\Textile\Parser(); - * echo $parse - * ->setLinkRelationShip('nofollow') - * ->getLinkRelationShip(); - * - * The above outputs "nofollow". - * - * @return string The value - * @since 3.6.0 - * @see Parser::setLinkRelationShip() - * @api + * {@inheritdoc} */ - - public function getLinkRelationShip() + public function getLinkRelationShip(): string { - return $this->rel; + return (string) $this->rel; } /** - * Enables restricted parser mode. - * - * This option should be enabled when parsing untrusted user input, - * including comments or forum posts. When enabled, the parser escapes any - * raw HTML input, ignores unsafe attributes and links only whitelisted URL - * schemes. - * - * For instance the following malicious input: - * - * bc. $parser = new \Netcarver\Textile\Parser(); - * echo $parser - * ->setRestricted(true) - * ->parse('Innocent _looking_ "link":javacript:window.alert().'); - * - * Returns safe, sanitized HTML with valid Textile input still parsed: - * - * bc.

Innocent looking “link”:javacript:window.alert().

- * - * If left disabled, the parser allows users to mix raw HTML and Textile. - * Using the parser in non-restricted on untrusted input, like comments - * and forum posts, will lead to XSS issues, as users will be able to use - * any HTML code, JavaScript links and Textile attributes in their input. - * - * @param bool $enabled TRUE to enable, FALSE to disable - * @return Parser This instance - * @since 3.6.0 - * @see Parser::isRestrictedModeEnabled() - * @api + * {@inheritdoc} */ - - public function setRestricted($enabled) + public function setRestricted(bool $enabled): ConfigInterface { if ($enabled) { $this->url_schemes = $this->restricted_url_schemes; @@ -1490,200 +972,72 @@ public function setRestricted($enabled) } /** - * Whether restricted parser mode is enabled. - * - * bc. $parser = new \Netcarver\Textile\Parser(); - * if ($parser->isRestrictedModeEnabled() === true) { - * echo 'PHP-Textile is in restricted mode.'; - * } - * - * @return bool TRUE if enabled, FALSE otherwise - * @since 3.6.0 - * @see Parser::setRestricted() - * @api + * {@inheritdoc} */ - public function isRestrictedModeEnabled() + public function isRestrictedModeEnabled(): bool { return (bool) $this->restricted; } /** - * Enables and disables raw blocks. - * - * When raw blocks are enabled, any paragraph blocks wrapped in a tag - * not matching Parser::$blockContent or Parser::$phrasingContent will not - * be parsed, and instead is left as is. - * - * bc. $parser = new \Netcarver\Textile\Parser(); - * echo $parser - * ->setRawBlocks(true) - * ->parse('
A *raw* block.
'); - * - * The above generates: - * - * bc.
A *raw* block.
- * - * @param bool $enabled TRUE to enable, FALSE to disable - * @return Parser This instance - * @since 3.7.0 - * @see Parser::isRawBlocksEnabled() - * @see Parser::isRawBlock() - * @api + * {@inheritdoc} */ - - public function setRawBlocks($enabled) + public function setRawBlocks(bool $enabled): ConfigInterface { - $this->rawBlocksEnabled = (bool) $enabled; - return $this; - } + $this->rawBlocksEnabled = $enabled; - /** - * Whether raw blocks are enabled. - * - * bc. $parser = new \Netcarver\Textile\Parser(); - * if ($parser->isRawBlocksEnabled() === true) { - * echo 'Raw blocks are enabled'; - * } - * - * @return bool TRUE if enabled, FALSE otherwise - * @since 3.7.0 - * @see Parser::setRawBlocks() - * @api - */ + return $this; + } - public function isRawBlocksEnabled() + /** + * {@inheritdoc} + */ + public function isRawBlocksEnabled(): bool { return (bool) $this->rawBlocksEnabled; } /** - * Enables and disables block-level tags and formatting features. - * - * When disabled, block-level tags aren't rendered. This allows PHP-Textile - * to operate on a single line of text, rather than blocks of text and does - * not wrap the output in paragraph tags. - * - * bc. $parser = new \Netcarving\Textile\Parser(); - * echo $parser - * ->setBlockTags(false) - * ->parse('h1. Hello *strong* world!'); - * - * The above generates: - * - * bc. h1. Hello strong world! - * - * @param bool $enabled TRUE to enable, FALSE to disable - * @return Parser This instance - * @since 3.6.0 - * @see Parser::isBlockTagEnabled() - * @api + * {@inheritdoc} */ - - public function setBlockTags($enabled) + public function setBlockTags(bool $enabled): ConfigInterface { - $this->blockTagsEnabled = (bool) $enabled; + $this->blockTagsEnabled = $enabled; + return $this; } /** - * Whether block-level tags are enabled and parsed. - * - * bc. $parser = new \Netcarving\Textile\Parser(); - * if ($parser->isBlockTagAllowed() === true) { - * echo 'Block tags are enabled.'; - * } - * - * @return bool TRUE if enabled, FALSE otherwise - * @since 3.6.0 - * @see Parser::setBlockTags() - * @api + * {@inheritdoc} */ - - public function isBlockTagEnabled() + public function isBlockTagEnabled(): bool { return (bool) $this->blockTagsEnabled; } /** - * Enables and disables line-wrapping. - * - * If enabled, line-breaks are replaced by target document's break tag. If - * disabled, input document's line-breaks are ignored. This setting can be - * used if the the input document's lines are pre-wrapped. For instance, - * in case the input is from CLI content, or source code documentation. - * - * bc. $parser = new \Netcarving\Textile\Parser(); - * echo $parser - * ->setLineWrap(false) - * ->parse("Hello\nworld!"); - * - * The above generates: - * - * bc.

Hello world!

- * - * @param bool $enabled TRUE to enable, FALSE to disable - * @return Parser This instance - * @since 3.6.0 - * @see Parser::isLineWrapEnabled() - * @api + * {@inheritdoc} */ - - public function setLineWrap($enabled) + public function setLineWrap(bool $enabled): ConfigInterface { $this->lineWrapEnabled = (bool) $enabled; + return $this; } /** - * Whether line-wrapping is enabled. - * - * bc. $parser = new \Netcarving\Textile\Parser(); - * if ($parser->isLineWrapEnabled() === true) { - * echo 'Line-wrapping is enabled.'; - * } - * - * @return bool TRUE if enabled, FALSE otherwise - * @see Parser::setLineWrap() - * @since 3.6.0 - * @api + * {@inheritdoc} */ - - public function isLineWrapEnabled() + public function isLineWrapEnabled(): bool { return (bool) $this->lineWrapEnabled; } /** - * Sets a substitution symbol. - * - * This method lets you to redefine a substitution symbol. The following - * sets the 'half' glyph: - * - * bc. $parser = new \Netcarver\Textile\Parser(); - * echo $parser - * ->setSymbol('half', '1⁄2') - * ->parse('Hello [1/2] World!'); - * - * Generates: - * - * bc.

Hello 1&#⁄2 World!

- * - * Symbol can be set to FALSE to disable it: - * - * bc. $parser = new \Netcarver\Textile\Parser(); - * $parser->setSymbol('dimension', false); - * - * See Parser::getSymbol() to find out all available symbols. - * - * @param string $name Name of the symbol to assign a new value to - * @param string|bool $value New value for the symbol, or FALSE to disable - * @return Parser This instance - * @see Parser::getSymbol() - * @api + * {@inheritdoc} */ - - public function setSymbol($name, $value) + public function setSymbol(string $name, $value): ConfigInterface { if ($value !== false) { $value = (string) $value; @@ -1691,31 +1045,14 @@ public function setSymbol($name, $value) $this->symbols[(string) $name] = $value; $this->rebuild_glyphs = true; + return $this; } /** - * Gets a symbol definitions. - * - * This method gets a symbol definition by name, or the full symbol table - * as an array. - * - * bc. $parser = new \Netcarver\Textile\Parser(); - * echo $parser->getSymbol('dimension'); - * - * To get all available symbol definitions: - * - * bc. $parser = new \Netcarver\Textile\Parser(); - * print_r($parser->getSymbol()); - * - * @param string|null $name The name of the symbol, or NULL if requesting the symbol table - * @return array|string The symbol table or the requested symbol - * @throws \InvalidArgumentException - * @see Parser::setSymbol() - * @api + * {@inheritdoc} */ - - public function getSymbol($name = null) + public function getSymbol(?string $name = null) { if ($name !== null) { if (isset($this->symbols[$name])) { @@ -1729,226 +1066,70 @@ public function getSymbol($name = null) } /** - * Sets base relative image prefix. - * - * The given string is used to prefix relative image paths, usually an - * absolute HTTP address pointing a the site's image, or upload, directory. - * PHP-Textile to convert relative paths to absolute, or prefixed paths. - * - * bc. $parser = new \Netcarver\Textile\Parser(); - * $parser->setImagePrefix('https://static.example.com/images/'); - * - * @param string $prefix The prefix - * @return Parser This instance - * @since 3.7.0 - * @see Parser::getImagePrefix() - * @api + * {@inheritdoc} */ - - public function setImagePrefix($prefix) + public function setImagePrefix(string $prefix): ConfigInterface { - $this->relImagePrefix = (string) $prefix; + $this->relImagePrefix = $prefix; + return $this; } /** - * Gets base relative image prefix. - * - * bc. $parser = new \Netcarver\Textile\Parser(); - * echo $parser->getImagePrefix(); - * - * @return string The prefix - * @since 3.7.0 - * @see Parser::setImagePrefix() - * @api + * {@inheritdoc} */ - - public function getImagePrefix() + public function getImagePrefix(): string { return (string) $this->relImagePrefix; } /** - * Sets base relative link prefix. - * - * The given string is used to prefix relative link paths. This allows - * PHP-Textile convert relative paths to absolute, or prefixed, links. - * - * bc. $parser = new \Netcarver\Textile\Parser(); - * $parser->setLinkPrefix('https://example.com/'); - * - * @param string $prefix The prefix - * @return Parser This instance - * @since 3.7.0 - * @see Parser::getLinkPrefix() - * @api + * {@inheritdoc} */ - - public function setLinkPrefix($prefix) + public function setLinkPrefix(string $prefix): ConfigInterface { - $this->relLinkPrefix = (string) $prefix; + $this->relLinkPrefix = $prefix; + return $this; } /** - * Gets base relative link prefix. - * - * bc. $parser = new \Netcarver\Textile\Parser(); - * echo $parser->getLinkPrefix(); - * - * @return string The prefix - * @since 3.7.0 - * @see Parser::setLinkPrefix() - * @api + * {@inheritdoc} */ - - public function getLinkPrefix() + public function getLinkPrefix(): string { return (string) $this->relLinkPrefix; } /** - * Sets base relative image and link directory path. - * - * This is used when Textile is supplied with a relative image or link path. - * Allows client systems to have PHP-Textile convert relative paths to - * absolute or prefixed paths. This method is used to set that base path, - * usually an absolute HTTP address pointing to a directory. Note that - * despite its name it applies to both links and images. - * - * bc. $parser = new \Netcarver\Textile\Parser(); - * $parser->setRelativeImagePrefix('https://example.com/'); - * - * @param string $prefix The string to prefix all relative image paths with - * @return Parser This instance - * @deprecated in 3.7.0 - * @see Parser::setImagePrefix - * @see Parser::setLinkPrefix - * @api - */ - - public function setRelativeImagePrefix($prefix = '') - { - trigger_error( - 'Parser::setRelativeImagePrefix() is deprecated.'. - 'Use Parser::setImagePrefix() and Parser::setLinkPrefix() instead.', - E_USER_DEPRECATED - ); - - $this->relativeImagePrefix = $prefix; - return $this; - } - - /** - * Enables dimensionless images. - * - * If enabled, image width and height attributes will not be included in - * rendered image tags. Normally, PHP-Textile will add width and height - * to images linked with a local relative path, as long as the image file - * can be accessed. - * - * bc. $parser = new \Netcarver\Textile\Parser(); - * echo $parser - * ->setDimensionlessImages(true) - * ->parse('!image.jpg!'); - * - * @param bool $dimensionless TRUE to disable image dimensions, FALSE to enable - * @return Parser This instance - * @see Parser::getDimensionlessImages() - * @api + * {@inheritdoc} */ - - public function setDimensionlessImages($dimensionless = true) + public function setDimensionlessImages(bool $dimensionless = true): ConfigInterface { - $this->dimensionless_images = (bool) $dimensionless; + $this->dimensionless_images = $dimensionless; return $this; } /** - * Whether dimensionless images are enabled. - * - * bc. $parser = new \Netcarver\Textile\Parser(); - * if ($parser->getDimensionlessImages() === true) { - * echo 'Images do not get dimensions.'; - * } - * - * @return bool TRUE if images will not get dimensions, FALSE otherwise - * @see Parser::setDimensionlessImages() - * @api + * {@inheritdoc} */ - - public function getDimensionlessImages() + public function getDimensionlessImages(): bool { return (bool) $this->dimensionless_images; } /** - * Gets PHP-Textile version number. - * - * bc. $parser = new \Netcarver\Textile\Parser(); - * echo $parser->getVersion(); - * - * @return string Version number - * @api - */ - - public function getVersion() - { - return $this->ver; - } - - /** - * Encodes the given text. - * - * bc. $parser = new \Netcarver\Textile\Parser(); - * $parser->textileEncode('Some content to encode.'); - * - * @param string $text The text to be encoded - * @return string The encoded text - * @api + * {@inheritdoc} */ - - public function textileEncode($text) + public function textileEncode(string $text): string { return (string)preg_replace('/&(?!(?:[a-z][a-z\d]*|#(?:\d+|x[a-f\d]+));)/i', '&', $text); } /** - * Parses the given Textile input according to the previously set options. - * - * The parser's features can be changed by using the various public setter - * methods this class has. The most basic use case is: - * - * bc. $parser = new \Netcarver\Textile\Parser(); - * echo $parser->parse('h1. Hello World!'); - * - * The above parses trusted input in full-feature mode, generating: - * - * bc.

Hello World!

- * - * Additionally the parser can be run in safe, restricted mode using the - * Parser::setRestricted() method. - * - * bc. $parser = new \Netcarver\Textile\Parser(); - * echo $parser - * ->setRestricted(true) - * ->parse('h1. Hello World!'); - * - * This enables restricted mode and allows safe parsing of untrusted input. - * PHP-Textile will disable unsafe attributes, links and escapes any raw - * HTML input. This option should be enabled when parsing untrusted user - * input. - * - * If restricted mode is disabled, the parser allows users to mix raw HTML - * and Textile. - * - * @param string $text The Textile input to parse - * @return string Parsed Textile input - * @since 3.6.0 - * @api + * {@inheritdoc} */ - - public function parse($text) + public function parse(string $text): string { $this->prepare(); $text = (string) $text; @@ -2002,128 +1183,6 @@ public function parse($text) return $text; } - /** - * Parses the given Textile input in un-restricted mode. - * - * This method is deprecated, use Parser::parse() method instead. - * This method is equilavent of: - * - * bc. $parser = new \Netcarver\Textile\Parser(); - * echo $parser->parse('h1. Hello World!'); - * - * Additinal arguments can be passed with setter methods: - * - * bc. $parser = new \Netcarver\Textile\Parser(); - * echo $parser - * ->setLite(true) - * ->setImages(true) - * ->setLinkRelationShip('nofollow') - * ->parse('h1. Hello World!'); - * - * @param string $text The Textile input to parse - * @param bool $lite Switch to lite mode - * @param bool $encode Encode input and return - * @param bool $noimage Disables images - * @param bool $strict This argument is ignored - * @param string $rel Relationship attribute applied to generated links - * @return string Parsed $text - * @see Parser::parse() - * @deprecated in 3.6.0 - * @api - */ - - public function textileThis($text, $lite = false, $encode = false, $noimage = false, $strict = false, $rel = '') - { - if ($encode) { - trigger_error( - '$encode argument is deprecated. Use Parser::textileEncode() instead.', - E_USER_DEPRECATED - ); - - return $this->textileEncode($text); - } - - trigger_error( - 'Parser::textileThis() is deprecated. Use Parser::parse() instead.', - E_USER_DEPRECATED - ); - - return $this - ->setRestricted(false) - ->setLite($lite) - ->setBlockTags(true) - ->setImages(!$noimage) - ->setLinkRelationShip($rel) - ->parse($text); - } - - /** - * Parses the given Textile input in restricted mode. - * - * This method is deprecated, use Parser::parse() method with - * Parser::setRestricted() and Parser::setLite() enabled, and - * Parser::setImages() disabled. - * - * This method's defaults are identical to: - * - * bc. $parser = new \Netcarver\Textile\Parser(); - * echo $parser - * ->setRestricted(true) - * ->setLite(true) - * ->setImages(false) - * ->setLinkRelationShip('nofollow') - * ->parse('h1. Hello World!'); - * - * As in the above, restricted mode should be used when parsing any - * untrusted user input, including comments or forum posts. - * - * @param string $text The Textile input to parse - * @param bool $lite Controls lite mode, allowing extra formatting - * @param bool $noimage Allow images - * @param string $rel Relationship attribute applied to generated links - * @return string Parsed input - * @see Parser::setRestricted() - * @see Parser::setLite() - * @see Parser::setImages() - * @see Parser::setLinkRelationShip() - * @see Parser::parse() - * @deprecated in 3.6.0 - * @api - */ - - public function textileRestricted($text, $lite = true, $noimage = true, $rel = 'nofollow') - { - trigger_error( - 'Parser::textileRestricted() is deprecated. Use Parser::parse() with Parser::setRestricted() instead.', - E_USER_DEPRECATED - ); - - return $this - ->setRestricted(true) - ->setLite($lite) - ->setBlockTags(true) - ->setImages(!$noimage) - ->setLinkRelationShip($rel) - ->parse($text); - } - - /** - * Parses Textile syntax. - * - * This method performs common parse actions. - * - * @param string $text The input to parse - * @param bool $lite Enables lite mode - * @return string Parsed input - * @deprecated in 3.6.0 - */ - - protected function textileCommon($text, $lite) - { - trigger_error('Parser::textileCommon() is deprecated.', E_USER_DEPRECATED); - return $this->setLite($lite)->parse($text); - } - /** * Prepares the glyph patterns from the symbol table. * @@ -2131,7 +1190,7 @@ protected function textileCommon($text, $lite) * @see Parser::getSymbol() */ - protected function prepGlyphs() + private function prepGlyphs() { if ($this->rebuild_glyphs === false) { return; @@ -2144,8 +1203,8 @@ protected function prepGlyphs() $cur = '(?:['.$this->regex_snippets['cur'].']'.$this->regex_snippets['space'].'*)?'; } - $this->glyph_search = array(); - $this->glyph_replace = array(); + $this->glyph_search = []; + $this->glyph_replace = []; // Dimension sign if ($this->symbols['dimension'] !== false) { @@ -2317,7 +1376,7 @@ protected function prepGlyphs() * @since 3.5.5 */ - protected function getMaxLinkIndex() + private function getMaxLinkIndex() { return 1000000; } @@ -2327,57 +1386,25 @@ protected function getMaxLinkIndex() * * This method prepares the transient internal state of * Textile parser in preparation for parsing a new document. - * - * @param bool|null $lite Controls lite mode - * @param bool|null $noimage Disallow images - * @param string|null $rel A relationship attribute applied to links */ - - protected function prepare($lite = null, $noimage = null, $rel = null) + private function prepare() { if ($this->linkIndex >= $this->getMaxLinkIndex()) { $this->linkPrefix .= '-'; $this->linkIndex = 1; } - $this->unreferencedNotes = array(); - $this->notelist_cache = array(); - $this->notes = array(); - $this->urlrefs = array(); - $this->shelf = array(); - $this->fn = array(); + $this->unreferencedNotes = []; + $this->notelist_cache = []; + $this->notes = []; + $this->urlrefs = []; + $this->shelf = []; + $this->fn = []; $this->span_depth = 0; $this->refIndex = 1; - $this->refCache = array(); + $this->refCache = []; $this->note_index = 1; - if ($lite !== null) { - trigger_error( - '$lite argument is deprecated. Use Parser::setLite() instead.', - E_USER_DEPRECATED - ); - - $this->setLite($lite); - } - - if ($noimage !== null) { - trigger_error( - '$noimage argument is deprecated. Use Parser::setImages() instead.', - E_USER_DEPRECATED - ); - - $this->setImages(!$noimage); - } - - if ($rel !== null) { - trigger_error( - '$rel argument is deprecated. Use Parser::setRelative() instead.', - E_USER_DEPRECATED - ); - - $this->setLinkRelationShip($rel); - } - if ($this->patterns === null) { $block = implode('|', $this->blockContent); $divider = implode('|', $this->dividerContent); @@ -2411,8 +1438,7 @@ protected function prepare($lite = null, $noimage = null, $rel = null) * @param string $in The input string * @return string Cleaned string */ - - protected function cleanAttribs($in) + private function cleanAttribs($in) { $tmp = $in; $before = -1; @@ -2449,7 +1475,7 @@ protected function cleanAttribs($in) * @return Tag */ - protected function newTag($name, $atts, $selfclosing = true) + private function newTag($name, $atts, $selfclosing = true) { return new Tag($name, $atts, $selfclosing); } @@ -2462,10 +1488,9 @@ protected function newTag($name, $atts, $selfclosing = true) * @param bool $include_id If FALSE, IDs are not included in the attribute list * @param string $autoclass An additional classes applied to the output * @return string HTML attribute list - * @see Parser::parseAttribsToArray() + * @see Parser::parseAttribsTo[] */ - - protected function parseAttribs($in, $element = '', $include_id = true, $autoclass = '') + private function parseAttribs($in, $element = '', $include_id = true, $autoclass = '') { $o = $this->parseAttribsToArray($in, $element, $include_id, $autoclass); @@ -2478,8 +1503,7 @@ protected function parseAttribs($in, $element = '', $include_id = true, $autocla * @param array $attribute_array * @return string */ - - protected function formatAttributeString(array $attribute_array) + private function formatAttributeString(array $attribute_array) { $out = ''; @@ -2502,10 +1526,9 @@ protected function formatAttributeString(array $attribute_array) * @return array HTML attributes as key => value mappings * @see Parser::parseAttribs() */ - - protected function parseAttribsToArray($in, $element = '', $include_id = true, $autoclass = '') + private function parseAttribsToArray($in, $element = '', $include_id = true, $autoclass = '') { - $style = array(); + $style = []; $class = ''; $lang = ''; $colspan = ''; @@ -2599,7 +1622,7 @@ protected function parseAttribsToArray($in, $element = '', $include_id = true, $ } if ($this->isRestrictedModeEnabled()) { - $o = array(); + $o = []; $class = trim($autoclass); if ($class) { @@ -2616,7 +1639,7 @@ protected function parseAttribsToArray($in, $element = '', $include_id = true, $ $class = trim($class . ' ' . $autoclass); } - $o = array(); + $o = []; if ($class) { $o['class'] = $this->cleanAttribs($class); @@ -2644,7 +1667,7 @@ protected function parseAttribsToArray($in, $element = '', $include_id = true, $ if (!empty($style)) { $so = ''; - $tmps = array(); + $tmps = []; foreach ($style as $s) { $parts = explode(';', $s); @@ -2681,8 +1704,7 @@ protected function parseAttribsToArray($in, $element = '', $include_id = true, $ * @param string $text The input string * @return bool TRUE if the text can be wrapped, FALSE otherwise */ - - protected function hasRawText($text) + private function hasRawText($text) { if (preg_match($this->patterns['unwrappable'], $text)) { return false; @@ -2709,8 +1731,7 @@ protected function hasRawText($text) * @param string $text The textile input * @return string The parsed text */ - - protected function tables($text) + private function tables($text) { $text = $text . "\n\n"; return (string)preg_replace_callback( @@ -2731,8 +1752,7 @@ protected function tables($text) * @return string HTML table * @see Parser::tables() */ - - protected function fTable($matches) + private function fTable($matches) { $tatts = $this->parseAttribs($matches['tatts'], 'table'); $space = $this->regex_snippets['space']; @@ -2742,7 +1762,7 @@ protected function fTable($matches) $last_rgrp = ''; $c_row = 1; $sum = ''; - $rows = array(); + $rows = []; $summary = trim($matches['summary']); @@ -2827,7 +1847,7 @@ protected function fTable($matches) $ratts = ''; } - $cells = array(); + $cells = []; $cellctr = 0; foreach (explode("|", $row) as $cell) { @@ -2845,7 +1865,7 @@ protected function fTable($matches) } if (!$this->isLiteModeEnabled()) { - $a = array(); + $a = []; if (preg_match('/(?'.$this->regex_snippets['space'].'*)(?P.*)/s', $cell, $a)) { $cell = $this->redclothLists($a['cell']); @@ -2893,8 +1913,7 @@ protected function fTable($matches) * @param string $text The textile input * @return string The parsed text */ - - protected function redclothLists($text) + private function redclothLists($text) { return (string)preg_replace_callback( "/^([-]+$this->cls[ .].*:=.*)$(?![^-])/smU", @@ -2913,15 +1932,14 @@ protected function redclothLists($text) * @return string HTML definition list * @see Parser::redclothLists() */ - - protected function fRedclothList($m) + private function fRedclothList($m) { $in = $m[0]; - $out = array(); + $out = []; $text = preg_split('/\n(?=[-])/m', $in); foreach ($text as $line) { - $m = array(); + $m = []; if (preg_match("/^[-]+(?P$this->cls)\.? (?P.*)$/s", $line, $m)) { $content = trim($m['content']); @@ -2990,8 +2008,7 @@ protected function fRedclothList($m) * @param string $text The input * @return string The parsed text */ - - protected function textileLists($text) + private function textileLists($text) { return (string)preg_replace_callback( "/^((?:[*;:]+|[*;:#]*#(?:_|\d+)?)$this->cls[ .].*)$(?![^#*;:])/smU", @@ -3010,15 +2027,14 @@ protected function textileLists($text) * @return string HTML list * @see Parser::textileLists() */ - - protected function fTextileList($m) + private function fTextileList($m) { $text = $m[0]; $lines = preg_split('/\n(?=[*#;:])/m', $m[0]); - $list = array(); + $list = []; $prev = false; - $out = array(); - $lists = array(); + $out = []; + $lists = []; $litem = ''; if ($lines === false) { @@ -3088,11 +2104,11 @@ protected function fTextileList($m) } } - if (strpos($prev['tl'], ';') !== false && strpos($m['tl'], ':') !== false) { + if ($prev['tl'] && \strpos($prev['tl'], ';') !== false && \strpos($m['tl'], ':') !== false) { $lists[$m['tl']] = 2; } - $tabs = str_repeat("\t", $m['level'] - 1); + $tabs = \str_repeat("\t", $m['level'] - 1); $atts = $this->parseAttribs($m['atts']); if (!isset($lists[$m['tl']])) { @@ -3113,7 +2129,7 @@ protected function fTextileList($m) } foreach (array_reverse($lists) as $k => $v) { - $indent = strlen($k); + $indent = \strlen($k); if (!$next || $indent > $next['level']) { if ($v !== 2) { @@ -3142,10 +2158,9 @@ protected function fTextileList($m) * @param string $in Textile input containing the possible list marker * @return string Either 'd', 'o', 'u' */ - - protected function liType($in) + private function liType($in) { - $m = array(); + $m = []; $type = 'd'; if (preg_match('/^(?P[#*]+)/', $in, $m)) { $type = ('#' === substr($m['type'], -1)) ? 'o' : 'u'; @@ -3160,8 +2175,7 @@ protected function liType($in) * @param string $in The input * @return string */ - - protected function doTagBr($tag, $in) + private function doTagBr($tag, $in) { return (string)preg_replace_callback( '@<(?P'.preg_quote($tag).')(?P[^>]*?)>(?P.*)(?P)@s', @@ -3176,8 +2190,7 @@ protected function doTagBr($tag, $in) * @param string $in The input * @return string */ - - protected function doPBr($in) + private function doPBr($in) { return (string)preg_replace_callback( '@<(?Pp|h[1-6])(?P[^>]*?)>(?P.*)(?P)@s', @@ -3196,8 +2209,7 @@ protected function doPBr($in) * @param array $m The input * @return string */ - - protected function fPBr($m) + private function fPBr($m) { if ($this->isLineWrapEnabled()) { // Replaces
\n instances that are not followed by white-space, @@ -3225,8 +2237,7 @@ protected function fPBr($m) * @param array $m The input * @return string */ - - protected function fBr($m) + private function fBr($m) { $content = preg_replace( "@(.+)(?|
|||)\n(?![\s|])@", @@ -3246,14 +2257,13 @@ protected function fBr($m) * @param string $text Textile source text * @return string Input text with blocks processed */ - - protected function blocks($text) + private function blocks($text) { - $regex = '/^(?P'.join('|', $this->blocktag_whitelist).')'. + $regex = '/^(?P'.\implode('|', $this->blocktag_whitelist).')'. '(?P'.$this->a.$this->cls.$this->a.')\.(?P\.?)(?::(?P\S+))? (?P.*)$/Ss'. $this->regex_snippets['mod']; - $textblocks = preg_split('/(\n{2,})/', $text, null, PREG_SPLIT_DELIM_CAPTURE); + $textblocks = \preg_split('/(\n{2,})/', $text, -1, \PREG_SPLIT_DELIM_CAPTURE); if ($textblocks === false) { return ''; @@ -3262,11 +2272,11 @@ protected function blocks($text) $eatWhitespace = false; $whitespace = ''; $ext = ''; - $out = array(); + $out = []; foreach ($textblocks as $block) { // Line is just whitespace, keep it for the next block. - if (trim($block) === '') { + if (\trim($block) === '') { if ($eatWhitespace === false) { $whitespace .= $block; } @@ -3281,16 +2291,16 @@ protected function blocks($text) } $eatWhitespace = false; - $anonymous_block = !preg_match($regex, $block, $m); + $anonymous_block = !\preg_match($regex, $block, $m); if (!$anonymous_block) { // Last block was extended, so close it if ($ext) { - $out[count($out)-1] .= $c1; + $out[\count($out)-1] .= $c1; } // Extract the new block's parts - extract($m); + \extract($m); list($o1, $o2, $content, $c2, $c1, $eat) = $this->fBlock($m); // Leave off c1 if this block is extended, we'll close it at the start of the next block @@ -3299,10 +2309,10 @@ protected function blocks($text) $block .= $c1; } } else { - $rawBlock = preg_match($this->patterns['divider'], $block) || + $rawBlock = \preg_match($this->patterns['divider'], $block) || ($this->isRawBlocksEnabled() && $this->isRawBlock($block)); - if ($ext || (strpos($block, ' ') !== 0 && !$rawBlock)) { + if ($ext || (\strpos($block, ' ') !== 0 && !$rawBlock)) { list($o1, $o2, $content, $c2, $c1, $eat) = $this->fBlock(array( 0, $tag, @@ -3328,10 +2338,10 @@ protected function blocks($text) } $block = $this->doPBr($block); - $block = $whitespace. str_replace('
', '
', $block); + $block = $whitespace . \str_replace('
', '
', $block); if ($ext && $anonymous_block) { - $out[count($out)-1] .= $block; + $out[\count($out)-1] .= $block; } elseif (!$eat) { $out[] = $block; } @@ -3344,10 +2354,10 @@ protected function blocks($text) } if ($ext) { - $out[count($out)-1] .= $c1; + $out[\count($out)-1] .= $c1; } - return join('', $out); + return \implode('', $out); } /** @@ -3359,8 +2369,7 @@ protected function blocks($text) * @param array $m The block content to format * @return array */ - - protected function fBlock($m) + private function fBlock($m) { list(, $tag, $att, $ext, $cite, $content) = $m; $atts = $this->parseAttribs($att); @@ -3470,8 +2479,7 @@ protected function fBlock($m) * @return bool TRUE if the block is raw, FALSE otherwise * @since 3.7.0 */ - - protected function isRawBlock($text) + private function isRawBlock($text) { if (preg_match($this->patterns['contained'], $text, $m)) { if (preg_match($this->patterns['phrasing'], $m['open'])) { @@ -3496,8 +2504,7 @@ protected function isRawBlock($text) * @param bool $anchor TRUE, if its a reference link * @return string Processed footnote */ - - protected function formatFootnote($marker, $atts = '', $anchor = true) + private function formatFootnote($marker, $atts = '', $anchor = true) { $pattern = ($anchor) ? $this->symbols['fn_foot_pattern'] : $this->symbols['fn_ref_pattern']; return $this->replaceMarkers($pattern, array('atts' => $atts, 'marker' => $marker)); @@ -3510,10 +2517,9 @@ protected function formatFootnote($marker, $atts = '', $anchor = true) * @param array $replacements Marker replacement pairs * @return string */ - - protected function replaceMarkers($text, $replacements) + private function replaceMarkers($text, $replacements) { - $map = array(); + $map = []; foreach ($replacements as $from => $to) { $map['{'.$from.'}'] = $to; @@ -3531,8 +2537,7 @@ protected function replaceMarkers($text, $replacements) * @param string $text Textile input * @return string $text Processed input */ - - protected function getHTMLComments($text) + private function getHTMLComments($text) { return (string)preg_replace_callback( "/\/sx", @@ -3550,8 +2555,7 @@ protected function getHTMLComments($text) * @param array $m Options * @return string Reference token wrapped to a HTML comment tags */ - - protected function fParseHTMLComments($m) + private function fParseHTMLComments($m) { return ''; } @@ -3562,8 +2566,7 @@ protected function fParseHTMLComments($m) * @param string $text Textile input * @return string Processed input */ - - protected function graf($text) + private function graf($text) { // Handle normal paragraph text if (!$this->isLiteModeEnabled()) { @@ -3621,8 +2624,7 @@ protected function graf($text) * @param string $text The Textile document to perform the replacements in * @return string The Textile document with spans replaced by their HTML inline equivalents */ - - protected function spans($text) + private function spans($text) { $span_tags = array_keys($this->span_tags); $pnct = ".,\"'?!;:‹›«»„“”‚‘’"; @@ -3659,8 +2661,7 @@ protected function spans($text) * @return string Content wrapped to reference tokens * @see Parser::spans() */ - - protected function fSpan($m) + private function fSpan($m) { $m = $this->getSpecialOptions($m); $tag = $this->span_tags[$m['tag']]; @@ -3688,10 +2689,9 @@ protected function fSpan($m) * @param string $closetag Closing tag * @return array Reference tokens for both opening and closing tag */ - - protected function storeTags($opentag, $closetag = '') + private function storeTags($opentag, $closetag = '') { - $tags = array(); + $tags = []; $this->refCache[$this->refIndex] = $opentag; $tags['open'] = $this->uid.$this->refIndex.':ospan '; @@ -3714,8 +2714,7 @@ protected function storeTags($opentag, $closetag = '') * @return string Processed text * @see Parser::storeTags() */ - - protected function retrieveTags($text) + private function retrieveTags($text) { $text = (string)preg_replace_callback( '/'.$this->uid.'(?P[0-9]+):ospan /', @@ -3739,8 +2738,7 @@ protected function retrieveTags($text) * @return string * @see Parser::retrieveTags() */ - - protected function fRetrieveTags($m) + private function fRetrieveTags($m) { return $this->refCache[$m['token']]; } @@ -3755,12 +2753,11 @@ protected function fRetrieveTags($m) * @param string $text Textile input * @return string Processed input */ - - protected function placeNoteLists($text) + private function placeNoteLists($text) { // Sequence all referenced definitions. if ($this->notes) { - $o = array(); + $o = []; foreach ($this->notes as $label => $info) { if (!empty($info['seq'])) { $o[$info['seq']] = $info; @@ -3796,8 +2793,7 @@ protected function placeNoteLists($text) * @param array $m Options * @return string Processed note list */ - - protected function fNoteLists($m) + private function fNoteLists($m) { if (!$m['startchar']) { $m['startchar'] = 'a'; @@ -3807,7 +2803,7 @@ protected function fNoteLists($m) if (empty($this->notelist_cache[$index])) { // If not in cache, build the entry... - $out = array(); + $out = []; if ($this->notes) { foreach ($this->notes as $seq => $info) { @@ -3852,8 +2848,7 @@ protected function fNoteLists($m) * @param string $i Instance count * @return string Processed input */ - - protected function makeBackrefLink($info, $g_links, $i) + private function makeBackrefLink($info, $g_links, $i) { $backlink_type = !empty($info['def']) && $info['def']['link'] ? $info['def']['link'] : $g_links; $allow_inc = (false === strpos($this->syms, $i)); @@ -3866,7 +2861,7 @@ protected function makeBackrefLink($info, $g_links, $i) } elseif ($backlink_type === '^') { return ''.$i.''; } else { - $out = array(); + $out = []; foreach ($info['refids'] as $id) { $out[] = ''. (($decode) ? $this->decodeHigh($i_) : $i_) .''; @@ -3889,8 +2884,7 @@ protected function makeBackrefLink($info, $g_links, $i) * @param array $m Options * @return string Empty string */ - - protected function fParseNoteDefs($m) + private function fParseNoteDefs($m) { $label = $m['label']; $link = $m['link']; @@ -3922,8 +2916,7 @@ protected function fParseNoteDefs($m) * @param string $text Textile input * @return string */ - - protected function noteRefs($text) + private function noteRefs($text) { return (string)preg_replace_callback( "/\[(?P{$this->c})\#(?P