diff options
Diffstat (limited to 'platform/www/lib/plugins/refnotes/syntax/references.php')
-rw-r--r-- | platform/www/lib/plugins/refnotes/syntax/references.php | 348 |
1 files changed, 348 insertions, 0 deletions
diff --git a/platform/www/lib/plugins/refnotes/syntax/references.php b/platform/www/lib/plugins/refnotes/syntax/references.php new file mode 100644 index 0000000..d4f8931 --- /dev/null +++ b/platform/www/lib/plugins/refnotes/syntax/references.php @@ -0,0 +1,348 @@ +<?php + +/** + * Plugin RefNotes: Reference collector/renderer + * + * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) + * @author Mykola Ostrovskyy <dwpforge@gmail.com> + */ + +require_once(DOKU_PLUGIN . 'refnotes/core.php'); +require_once(DOKU_PLUGIN . 'refnotes/bibtex.php'); + +//////////////////////////////////////////////////////////////////////////////////////////////////// +class syntax_plugin_refnotes_references extends DokuWiki_Syntax_Plugin { + use refnotes_localization_plugin; + + private $mode; + private $entryPattern; + private $exitPattern; + private $handlePattern; + private $noteCapture; + + /** + * Constructor + */ + public function __construct() { + refnotes_localization::initialize($this); + + $this->mode = substr(get_class($this), 7); + $this->noteCapture = new refnotes_note_capture(); + + $this->initializePatterns(); + } + + /** + * + */ + private function initializePatterns() { + /* Introduces changes to achive the format. Yet not perfect but similar to Pandoc (https://pandoc.org/MANUAL.html#footnotes): + + This is the text[^n01]. + + [^n01:] this is the note.] + + */ + if (refnotes_configuration::getSetting('replace-footnotes')) { + $entry = '(?:\(\(|\[\()'; + $exit = '(?:\)\)|\)\])'; + $id = '@@FNT\d+|#\d+'; + } + else { + $entry = '\[\^'; + $exit = '\]'; + $exit2 = '\.'; + $id = '#\d+'; + } + + $strictName = refnotes_note::getNamePattern('strict'); + $extendedName = refnotes_note::getNamePattern('extended'); + $namespace = refnotes_namespace::getNamePattern('optional'); + + $text = '.*?'; + + $strictName = '(?:' . $id . '|' . $strictName . ')'; + $fullName = '\s*(?:' . $namespace . $strictName . '|:' . $namespace . $extendedName . ')\s*'; + $lookaheadExit = '(?=' . $exit . ')'; + $nameEntry = $fullName . $lookaheadExit; + + $extendedName = '(?:' . $id . '|' . $extendedName . ')'; + $optionalFullName = $extendedName . '?'; + $structuredEntry = '\s*' . $optionalFullName . '\s*>>' . $text . $lookaheadExit; + + $define = '\s*' . $optionalFullName . '\s*:]\s*'; + $optionalDefine = '(?:' . $define . ')?'; + $lookaheadExit = '(?=' . $text . $exit . ')'; + $defineEntry = $optionalDefine . $lookaheadExit; + + $this->entryPattern = $entry . '(?:' . $nameEntry . '|' . $structuredEntry . '|' . $defineEntry . ')'; + $this->exitPattern = $exit; + $this->handlePattern = '/' . $entry . '\s*(' . $optionalFullName . ')\s*(?:>>(.*))?(.*)/s'; + } + + + /** + * What kind of syntax are we? + */ + public function getType() { + return 'formatting'; + } + + /** + * What modes are allowed within our mode? + */ + public function getAllowedTypes() { + return array ( + 'formatting', + 'substition', + 'protected', + 'disabled' + ); + } + + /** + * Where to sort in? + */ + public function getSort() { + return 145; + } + + public function connectTo($mode) { + refnotes_parser_core::getInstance()->registerLexer($this->Lexer); + + $this->Lexer->addEntryPattern($this->entryPattern, $mode, $this->mode); + } + + public function postConnect() { + $this->Lexer->addExitPattern($this->exitPattern, $this->mode); + } + + /** + * Handle the match + */ + public function handle($match, $state, $pos, Doku_Handler $handler) { + $result = refnotes_parser_core::getInstance()->canHandle($state); + + if ($result) { + switch ($state) { + case DOKU_LEXER_ENTER: + $result = $this->handleEnter($match); + break; + + case DOKU_LEXER_EXIT: + $result = $this->handleExit(); + break; + } + } + + if ($result === false) { + $handler->addCall('cdata', array($match), $pos); + } + + return $result; + } + + /** + * Create output + */ + public function render($mode, Doku_Renderer $renderer, $data) { + $result = false; + + try { + switch ($mode) { + case 'xhtml': + case 'odt': + $result = $this->renderReferences($mode, $renderer, $data); + break; + + case 'metadata': + $result = $this->renderMetadata($renderer, $data); + break; + } + } + catch (Exception $error) { + msg($error->getMessage(), -1); + } + + return $result; + } + + /** + * + */ + private function handleEnter($syntax) { + if (preg_match($this->handlePattern, $syntax, $match) == 0) { + return false; + } + + refnotes_parser_core::getInstance()->enterReference($match[1], $match[2]); + + return array('start'); + } + + /** + * + */ + private function handleExit() { + $reference = refnotes_parser_core::getInstance()->exitReference(); + + if ($reference->hasData()) { + return array('render', $reference->getAttributes(), $reference->getData()); + } + else { + return array('render', $reference->getAttributes()); + } + } + + /** + * + */ + public function renderReferences($mode, $renderer, $data) { + switch ($data[0]) { + case 'start': + $this->noteCapture->start($renderer); + break; + + case 'render': + $this->renderReference($mode, $renderer, $data[1], (count($data) > 2) ? $data[2] : array()); + break; + } + + return true; + } + + /** + * Stops renderer output capture and renders the reference link + */ + private function renderReference($mode, $renderer, $attributes, $data) { + $reference = refnotes_renderer_core::getInstance()->addReference($attributes, $data); + $text = $this->noteCapture->stop(); + + if ($text != '') { + $reference->getNote()->setText($text); + } + + $renderer->doc .= $reference->render($mode); + } + + /** + * + */ + public function renderMetadata($renderer, $data) { + if ($data[0] == 'render') { + $source = ''; + + if (array_key_exists('source', $data[1])) { + $source = $data[1]['source']; + } + + if (($source != '') && ($source != '{configuration}')) { + $renderer->meta['plugin']['refnotes']['dbref'][wikiFN($source)] = true; + } + } + + return true; + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +class refnotes_note_capture { + + private $renderer; + private $note; + private $doc; + + /** + * Constructor + */ + public function __construct() { + $this->initialize(); + } + + /** + * + */ + private function initialize() { + $this->renderer = NULL; + $this->doc = ''; + } + + /** + * + */ + private function resetCapture() { + $this->renderer->doc = ''; + } + + /** + * + */ + public function start($renderer) { + $this->renderer = $renderer; + $this->doc = $renderer->doc; + + $this->resetCapture(); + } + + /** + * + */ + public function restart() { + $text = trim($this->renderer->doc); + + $this->resetCapture(); + + return $text; + } + + /** + * + */ + public function stop() { + $text = trim($this->renderer->doc); + + $this->renderer->doc = $this->doc; + + $this->initialize(); + + return $text; + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +class refnotes_nested_call_writer extends \dokuwiki\Parsing\Handler\Nest { + + private $handler; + private $callWriterBackup; + + /** + * Constructor + * + * HACK: Fix compatibility with PHP versions before 7.2 by passing handler as second optional + * argument. This makes constructor signature compatible with one defined in ReWriterInterface. + * Starting from PHP 7.2 this is not needed because arguments without type hint are compatible + * with any type since they have a wider type (any type). + * https://wiki.php.net/rfc/parameter-no-type-variance + */ + public function __construct(\dokuwiki\Parsing\Handler\CallWriterInterface $callWriter, $handler = NULL) { + $this->handler = $handler; + + parent::__construct($this->handler->getCallWriter()); + } + + /** + * + */ + public function connect() { + $this->callWriterBackup = $this->handler->getCallWriter(); + + $this->handler->setCallWriter($this); + } + + /** + * + */ + public function disconnect() { + $this->handler->setCallWriter($this->callWriterBackup); + } +} |