1<?php 2/** 3 * DokuWiki Plugin pagecss 4 * 5 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html 6 * @author dWiGhT Mulcahy <dWiGhT.Codes@gmail.com> 7 */ 8 9// Ensure DokuWiki is loaded and prevent direct access to the plugin file. 10// DOKU_INC is a constant defined by DokuWiki, representing its installation directory. 11if (!defined('DOKU_INC')) { 12 die(); 13} 14 15/** 16 * Class syntax_plugin_pagecss 17 * 18 * This class defines the syntax for the 'pagecss' DokuWiki plugin. 19 * It allows users to embed custom CSS directly within a DokuWiki page 20 * using <pagecss> tags. The plugin captures the content within these 21 * tags but doesn't directly render it into the HTML output in the 'render' method. 22 * Instead, it's expected that another part of the plugin (e.g., an event handler) 23 * would retrieve and process this captured CSS to inject it into the page's 24 * <head> section or similar. 25 */ 26class syntax_plugin_pagecss extends DokuWiki_Syntax_Plugin { 27 28 /** 29 * Defines the type of syntax plugin. 30 * 31 * 'container' means this plugin has opening and closing tags (e.g., <pagecss>...</pagecss>). 32 * Other common types include 'substition' (self-closing tags), 'protected' (content not parsed), etc. 33 * 34 * @return string 'container' 35 */ 36 public function getType() { 37 return 'container'; 38 } 39 40 /** 41 * Defines the paragraph type. 42 * 43 * 'block' indicates that this syntax element creates a block-level element, 44 * meaning it cannot be part of an existing paragraph and will typically start 45 * on a new line. 46 * 47 * @return string 'block' 48 */ 49 public function getPType() { 50 return 'block'; 51 } 52 53 /** 54 * Defines the sort order for syntax plugins. 55 * 56 * Plugins are processed in ascending order of their sort value. 57 * A higher number means it's processed later. This plugin is given 58 * a relatively high number (199), suggesting it should be processed 59 * after many other common DokuWiki syntax elements. 60 * 61 * @return int The sort order. 62 */ 63 public function getSort() { 64 return 199; 65 } 66 67 /** 68 * Connects the plugin's syntax patterns to the DokuWiki lexer. 69 * 70 * This method defines how the DokuWiki parser identifies the start of 71 * this plugin's syntax. 72 * 73 * @param string $mode The current DokuWiki lexer mode (e.g., 'base', 'p_wiki'). 74 */ 75 public function connectTo($mode) { 76 // Adds an entry pattern for '<pagecss>' tag. 77 // '<pagecss>(?=.*?</pagecss>)' is a regular expression: 78 // - '<pagecss>': Matches the literal string "<pagecss>". 79 // - (?=.*?</pagecss>): This is a positive lookahead assertion. 80 // - (?=...): Asserts that the following characters match the pattern inside, but 81 // do not consume them. 82 // - .*: Matches any character (except newline) zero or more times. 83 // - ?: Makes the `.*` non-greedy, so it matches the shortest possible string. 84 // - </pagecss>: Matches the literal closing tag. 85 // This ensures that the '<pagecss>' tag is only recognized as an entry pattern 86 // if it is followed by a closing '</pagecss>' tag somewhere later in the text, 87 // making it a valid container. 88 // 'plugin_pagecss' is the name of the state (or mode) that the lexer enters 89 // when this pattern is matched. 90 $this->Lexer->addEntryPattern('<pagecss>(?=.*?</pagecss>)',$mode,'plugin_pagecss'); 91 } 92 93 /** 94 * Defines how the plugin's syntax pattern exits the current state. 95 * 96 * This method specifies the closing tag for the 'container' type plugin. 97 */ 98 public function postConnect() { 99 // Adds an exit pattern for '</pagecss>'. 100 // When this pattern is encountered while in the 'plugin_pagecss' state, 101 // the lexer exits that state. 102 $this->Lexer->addExitPattern('</pagecss>', 'plugin_pagecss'); 103 } 104 105 /** 106 * Handles the matched syntax. 107 * 108 * This method is called by the DokuWiki parser when the lexer encounters 109 * content related to this plugin's syntax. It processes the raw matched 110 * text and returns a structured data representation. 111 * 112 * @param string $match The text that was matched by the lexer. 113 * @param int $state The current state of the lexer (e.g., DOKU_LEXER_UNMATCHED, 114 * DOKU_LEXER_ENTER, DOKU_LEXER_MATCHED, DOKU_LEXER_EXIT). 115 * @param int $pos The byte position of the match within the original text. 116 * @param Doku_Handler $handler The DokuWiki handler object, used to pass data through the parser. 117 * @return array|bool Returns an array containing the captured CSS if the state is DOKU_LEXER_UNMATCHED, 118 * otherwise returns true to indicate successful handling of enter/exit states. 119 */ 120 public function handle($match, $state, $pos, Doku_Handler $handler){ 121 // DOKU_LEXER_UNMATCHED state indicates that the content *between* the 122 // entry and exit patterns is being processed. This is where the actual 123 // CSS code is captured. 124 if ($state === DOKU_LEXER_UNMATCHED) { 125 // Return an associative array with the key 'css' holding the matched CSS content. 126 return ['css' => $match]; 127 } 128 // For DOKU_LEXER_ENTER and DOKU_LEXER_EXIT states, we just return true 129 // as no specific data needs to be captured for these states beyond marking 130 // the start/end of the container. 131 return true; 132 } 133 134 /** 135 * Renders the handled data into the DokuWiki output. 136 * 137 * This method is called by the DokuWiki renderer to generate the final HTML. 138 * For this plugin, the 'render' method primarily serves for debugging. 139 * The actual injection of CSS into the page is typically handled by an 140 * action plugin that listens to DokuWiki events (e.g., 'TPL_METAHEADERS'). 141 * 142 * @param string $mode The rendering mode (e.g., 'xhtml', 'odt'). 143 * @param Doku_Renderer $renderer The DokuWiki renderer object. 144 * @param mixed $data The data returned by the `handle()` method. 145 * @return bool Always returns true, indicating that the rendering process for this element is complete. 146 */ 147 public function render($mode, Doku_Renderer $renderer, $data) { 148 // Check if the data received is an array, which means it contains the 149 // CSS content captured in the `handle` method (state DOKU_LEXER_UNMATCHED). 150 if (is_array($data)) { 151 // Log the captured CSS to the DokuWiki debug log. 152 // substr($data['css'], 0, 200) truncates the CSS string to the first 200 characters 153 // for brevity in the log, preventing very long log entries. 154 dbglog("Captured CSS: " . substr($data['css'], 0, 200)); 155 156 // It's important to note that this `render` method *does not* output 157 // the CSS directly to the HTML. If it did, the CSS would appear 158 // in the page body, which is not the desired behavior for CSS. 159 // The purpose of this plugin is to *capture* the CSS, and then a 160 // separate part of the plugin (likely an `action.php` file 161 // listening to `TPL_METAHEADERS` or similar events) would 162 // retrieve this captured CSS from a global variable or cache 163 // and insert it into the appropriate section of the HTML <head>. 164 } 165 // Always return true to indicate successful rendering (even if nothing is output). 166 return true; 167 } 168} 169