summaryrefslogtreecommitdiff
path: root/platform/www/lib/plugins/refnotes/syntax/references.php
diff options
context:
space:
mode:
Diffstat (limited to 'platform/www/lib/plugins/refnotes/syntax/references.php')
-rw-r--r--platform/www/lib/plugins/refnotes/syntax/references.php348
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);
+ }
+}