...` tags. * * While this syntax plugin captures the CSS content, it does NOT directly * output it to the HTML. The actual injection of this CSS into the * `` section of the DokuWiki page is handled by the `action.php` * component of this plugin (specifically, `action_plugin_pagecss`). * * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html * @author dWiGhT Mulcahy */ // Ensure DokuWiki is loaded and prevent direct access to the plugin file. // DOKU_INC is a constant defined by DokuWiki, representing its installation directory. // If DOKU_INC is not defined, it means the script is being accessed directly, // which is not allowed for DokuWiki plugins. if (!defined('DOKU_INC')) { die(); } /** * Class syntax_plugin_pagecss * * This class extends DokuWiki_Syntax_Plugin, providing the necessary * methods to define a custom syntax for embedding CSS within DokuWiki pages. * It's responsible for: * 1. Defining the type of syntax (container). * 2. Specifying the block-level nature of the syntax. * 3. Setting its processing priority. * 4. Connecting its entry and exit patterns to the DokuWiki lexer. * 5. Handling the data parsed by the lexer (capturing the CSS content). * 6. (Optionally) Rendering output, though for this plugin, rendering is minimal * as the CSS is passed to an action plugin for actual injection. */ class syntax_plugin_pagecss extends DokuWiki_Syntax_Plugin { /** * Defines the type of syntax plugin. * * 'container' means this plugin has distinct opening and closing tags, * and it encapsulates content between them (e.g., `...`). * Other common types include 'substition' (self-closing tags), 'protected' * (content not parsed by DokuWiki), 'formatting' (inline text formatting), etc. * * @return string 'container' */ public function getType() { return 'container'; } /** * Defines the paragraph type. * * 'block' indicates that this syntax element creates a block-level element. * This means it cannot be part of an existing paragraph and will typically * force a new line before and after its content in the parsed output. * This is appropriate for CSS blocks which are not meant to be inline text. * * @return string 'block' */ public function getPType() { return 'block'; } /** * Defines the sort order (priority) for syntax plugins. * * DokuWiki processes syntax plugins in ascending order of their sort value. * A higher number means the plugin is processed later. This plugin is given * a relatively high number (199). This ensures that it runs after most * other common DokuWiki syntax elements have been processed, allowing it * to capture raw text that might otherwise be interpreted by other plugins. * * @return int The sort order value (e.g., 199). */ public function getSort() { return 199; } /** * Connects the plugin's syntax patterns to the DokuWiki lexer. * * This method is crucial for telling DokuWiki how to identify the start * of this plugin's custom syntax within the wiki text. * * @param string $mode The current DokuWiki lexer mode (e.g., 'base', 'p_wiki'). * Plugins often connect to 'base' mode to be available everywhere. */ public function connectTo($mode) { // Adds an entry pattern for the '' opening tag. // The regular expression '(?=.*?)' is used: // - '': Matches the literal string "". // - (?=.*?): This is a positive lookahead assertion. // - `(?=...)`: Asserts that the characters immediately following the current position // match the pattern inside the lookahead, but these characters are NOT // consumed by this match. This means the lexer won't advance past `` // based on the lookahead part. // - `.*?`: Matches any character (`.`) zero or more times (`*`) in a non-greedy way (`?`). // This ensures it matches the shortest possible string until the next part. // - ``: Matches the literal closing tag. // This lookahead ensures that the '' tag is only recognized as a valid entry // pattern if it is eventually followed by a matching closing '' tag. // 'plugin_pagecss' is the name of the new lexer state (or mode) that DokuWiki enters // when this pattern is matched. All content until the exit pattern will be processed // within this 'plugin_pagecss' state. $this->Lexer->addEntryPattern('(?=.*?)',$mode,'plugin_pagecss'); } /** * Defines how the plugin's syntax pattern exits the current state. * * This method specifies the closing tag for this 'container' type plugin. * When the lexer is in the 'plugin_pagecss' state and encounters this pattern, * it will exit that state and return to the previous lexer mode. */ public function postConnect() { // Adds an exit pattern for ''. // When this pattern is encountered while the lexer is in the 'plugin_pagecss' state, // it signifies the end of the custom CSS block. $this->Lexer->addExitPattern('', 'plugin_pagecss'); } /** * Handles the matched syntax. * * This method is called by the DokuWiki parser when the lexer identifies * content related to this plugin's defined syntax patterns. Its primary * role is to process the raw matched text and transform it into a * structured data representation that can be used by the renderer or other * parts of the plugin (like the action plugin). * * @param string $match The raw text that was matched by the lexer (e.g., "", "body { color: red; }", ""). * @param int $state The current state of the lexer when the match occurred. * Possible states include: * - DOKU_LEXER_ENTER: The opening tag was matched (e.g., ''). * - DOKU_LEXER_UNMATCHED: Content between the entry and exit patterns (the actual CSS). * - DOKU_LEXER_EXIT: The closing tag was matched (e.g., ''). * @param int $pos The byte position of the match within the original text. * @param Doku_Handler $handler The DokuWiki handler object. This object is used to * manipulate the parser's instruction stream (e.g., adding instructions). * @return array|bool Returns an array containing the captured CSS content if the state is * DOKU_LEXER_UNMATCHED, otherwise returns true to indicate successful handling * of the enter/exit states (no specific data needed for those). */ public function handle($match, $state, $pos, Doku_Handler $handler){ // This condition checks if the lexer is processing the actual content // *between* the opening and closing tags. This is where the user's CSS code resides. if ($state === DOKU_LEXER_UNMATCHED) { // Return an associative array where the key 'css' holds the matched content. // This data will then be passed to the `render` method of this plugin. return ['css' => $match]; } // For the DOKU_LEXER_ENTER (opening tag) and DOKU_LEXER_EXIT (closing tag) states, // no specific data needs to be captured by the syntax plugin itself, // so we simply return `true` to acknowledge that the state transition was handled. return true; } /** * Renders the handled data into the DokuWiki output. * * This method is called by the DokuWiki renderer to generate the final HTML * or other output format (e.g., XHTML, ODT). * * For the 'pagecss' plugin, this `render` method primarily serves for * debugging purposes. The actual injection of the CSS into the page's * `` section is NOT done here. Instead, the CSS is captured by * the `handle()` method and then typically retrieved and processed by an * accompanying action plugin (defined in `action.php`) which listens to * DokuWiki events (e.g., `TPL_METAHEADER_OUTPUT`) to insert the CSS * at the correct location in the HTML document. * * @param string $mode The rendering mode (e.g., 'xhtml', 'odt'). * @param Doku_Renderer $renderer The DokuWiki renderer object, used to output HTML, etc. * @param mixed $data The data returned by the `handle()` method. For this plugin, * it's an array like `['css' => '...']` when processing the CSS content. * @return bool Always returns true, indicating that the rendering process for this * syntax element has completed successfully, even if no visible output is produced. */ public function render($mode, Doku_Renderer $renderer, $data) { // Check if the received data is an array, which signifies that it contains // the CSS content captured during the DOKU_LEXER_UNMATCHED state in `handle()`. if (is_array($data)) { // Log the captured CSS content to the DokuWiki debug log. // This is useful for verifying that the plugin correctly extracts the CSS. // `substr($data['css'], 0, 200)` truncates the CSS string to the first // 200 characters to prevent excessively long entries in the debug log. dbglog("pagecss plugin: Captured CSS (first 200 chars): " . substr($data['css'], 0, 200)); // IMPORTANT NOTE: This `render` method DOES NOT output the CSS directly // to the HTML page's ``. If it did, the CSS would not be applied // correctly and would likely be visible as text on the page. // The sole purpose of this `syntax.php` file is to identify, parse, // and capture the CSS content. The `action.php` file (the action plugin) // is responsible for retrieving this captured CSS and injecting it into // the `` section of the HTML. } // Always return true to signal that the rendering process for this syntax element // has finished successfully. return true; } }