add contents

This commit is contained in:
Trevor Batley
2025-10-09 15:04:29 +11:00
parent 170362eec1
commit bce7dd054a
2537 changed files with 301282 additions and 0 deletions

View File

@@ -0,0 +1,436 @@
<?php
/**
* Class to fake a document tree for CSS matching.
*
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
* @author LarsDW223
*/
/** Include ecm_interface */
require_once DOKU_INC.'lib/plugins/odt/helper/ecm_interface.php';
/**
* Class css_doc_element
*
* @package CSS\CSSDocElement
*/
class css_doc_element implements iElementCSSMatchable {
/** var Reference to corresponding cssdocument */
public $doc = NULL;
/** var Index of this element in the corresponding cssdocument */
public $index = 0;
/**
* Get the name of this element.
*
* @return string
*/
public function iECSSM_getName() {
return $this->doc->entries [$this->index]['element'];
}
/**
* Get the attributes of this element.
*
* @return array
*/
public function iECSSM_getAttributes() {
return $this->doc->entries [$this->index]['attributes_array'];
}
/**
* Get the parent of this element.
*
* @return css_doc_element
*/
public function iECSSM_getParent() {
$index = $this->doc->findParent($this->index);
if ($index == -1 ) {
return NULL;
}
$element = new css_doc_element();
$element->doc = $this->doc;
$element->index = $index;
return $element;
}
/**
* Get the preceding sibling of this element.
*
* @return css_doc_element
*/
public function iECSSM_getPrecedingSibling() {
$index = $this->doc->getPrecedingSibling($this->index);
if ($index == -1 ) {
return NULL;
}
$element = new css_doc_element();
$element->doc = $this->doc;
$element->index = $index;
return $element;
}
/**
* Does this element belong to pseudo class $class?
*
* @param string $class
* @return boolean
*/
public function iECSSM_has_pseudo_class($class) {
if ($this->doc->entries [$this->index]['pseudo_classes'] == NULL) {
return false;
}
$result = array_search($class,
$this->doc->entries [$this->index]['pseudo_classes']);
if ($result === false) {
return false;
}
return true;
}
/**
* Does this element match the pseudo element $element?
*
* @param string $element
* @return boolean
*/
public function iECSSM_has_pseudo_element($element) {
if ($this->doc->entries [$this->index]['pseudo_elements'] == NULL) {
return false;
}
$result = array_search($element,
$this->doc->entries [$this->index]['pseudo_elements']);
if ($result === false) {
return false;
}
return true;
}
/**
* Return the CSS properties assigned to this element.
* (from extern via setProperties())
*
* @return array
*/
public function getProperties () {
return $this->doc->entries [$this->index]['properties'];
}
/**
* Set/assign the CSS properties for this element.
*
* @param array $properties
*/
public function setProperties (array &$properties) {
$this->doc->entries [$this->index]['properties'] = $properties;
}
}
/**
* Class cssdocument.
*
* @package CSS\CSSDocument
*/
class cssdocument {
/** var Current size, Index for next entry */
public $size = 0;
/** var Current nesting level */
public $level = 0;
/** var Array of entries, see open() */
public $entries = array ();
/** var Root index, see saveRootIndex() */
protected $rootIndex = 0;
/** var Root level, see saveRootIndex() */
protected $rootLevel = 0;
/**
* Internal function to get the value of an attribute.
*
* @param string $value Value of the attribute
* @param string $input Code to parse
* @param integer $pos Current position in $input
* @param integer $max End of $input
* @return integer Position at which the attribute ends
*/
protected function collect_attribute_value (&$value, $input, $pos, $max) {
$value = '';
$in_quotes = false;
$quote = '';
while ($pos < $max) {
$sign = $input [$pos];
$pos++;
if ($in_quotes == false) {
if ($sign == '"' || $sign == "'") {
$quote = $sign;
$in_quotes = true;
}
} else {
if ($sign == $quote) {
break;
}
$value .= $sign;
}
}
if ($in_quotes == false || $sign != $quote) {
// No proper quotes, delete value
$value = NULL;
}
return $pos;
}
/**
* Internal function to parse $attributes for key="value" pairs
* and store the result in an array.
*
* @param string $attributes Code to parse
* @return array Array of attributes
*/
protected function get_attributes_array ($attributes) {
if ($attributes == NULL) {
return NULL;
}
$result = array();
$pos = 0;
$max = strlen($attributes);
while ($pos < $max) {
$equal_sign = strpos ($attributes, '=', $pos);
if ($equal_sign === false) {
break;
}
$att_name = substr ($attributes, $pos, $equal_sign-$pos);
$att_name = trim ($att_name, ' ');
$att_end = $this->collect_attribute_value($att_value, $attributes, $equal_sign+1, $max);
// Add a attribute to array
$result [$att_name] = $att_value;
$pos = $att_end + 1;
}
return $result;
}
/**
* Save the current position as the root index of the document.
* It is guaranteed that elements below the root index will not be
* discarded from the cssdocument.
*/
public function saveRootIndex () {
$this->rootIndex = $this->getIndexLastOpened ();
$this->rootLevel = $this->level-1;
}
/**
* Shrinks/cuts the cssdocument down to its root index.
*/
public function restoreToRoot () {
for ($index = $this->size-1 ; $index > $this->rootIndex ; $index--) {
$this->entries [$index] = NULL;
}
$this->size = $this->rootIndex + 1;
$this->level = $this->rootLevel + 1;
}
/**
* Get the current state of the cssdocument.
*
* @param array $state Returned state information
*/
public function getState (array &$state) {
$state ['index'] = $this->size-1;
$state ['level'] = $this->level;
}
/**
* Shrinks/cuts the cssdocument down to the given $state.
* ($state must be retrieved by calling getState())
*
* @param array $state State information
*/
public function restoreState (array $state) {
for ($index = $this->size-1 ; $index > $state ['index'] ; $index--) {
$this->entries [$index] = NULL;
}
$this->size = $state ['index'] + 1;
$this->level = $state ['level'];
}
/**
* Open a new element in the cssdocument.
*
* @param string $element The element's name
* @param string $attributes The element's attributes
* @param string $pseudo_classes The element's pseudo classes
* @param string $pseudo_elements The element's pseudo elements
*/
public function open ($element, $attributes=NULL, $pseudo_classes=NULL, $pseudo_elements=NULL) {
$this->entries [$this->size]['level'] = $this->level;
$this->entries [$this->size]['state'] = 'open';
$this->entries [$this->size]['element'] = $element;
$this->entries [$this->size]['attributes'] = $attributes;
if (!empty($pseudo_classes)) {
$this->entries [$this->size]['pseudo_classes'] = explode(' ', $pseudo_classes);
}
if (!empty($pseudo_elements)) {
$this->entries [$this->size]['pseudo_elements'] = explode(' ', $pseudo_elements);
}
// Build attribute array/parse attributes
if ($attributes != NULL) {
$this->entries [$this->size]['attributes_array'] =
$this->get_attributes_array ($attributes);
}
$this->size++;
$this->level++;
}
/**
* Close $element in the cssdocument.
*
* @param string $element The element's name
*/
public function close ($element) {
$this->level--;
$this->entries [$this->size]['level'] = $this->level;
$this->entries [$this->size]['state'] = 'close';
$this->entries [$this->size]['element'] = $element;
$this->size++;
}
/**
* Get the current element.
*
* @return css_doc_element
*/
public function getCurrentElement() {
$index = $this->getIndexLastOpened ();
if ($index == -1) {
return NULL;
}
$element = new css_doc_element();
$element->doc = $this;
$element->index = $index;
return $element;
}
/**
* Get the entry of internal array $entries at $index.
*
* @param integer $index
* @return array
*/
public function getEntry ($index) {
if ($index >= $this->size ) {
return NULL;
}
return $this->entries [$index];
}
/**
* Get the current entry of internal array $entries.
*
* @return array
*/
public function getCurrentEntry () {
if ($this->size == 0) {
return NULL;
}
return $this->entries [$this->size-1];
}
/**
* Get the index of the 'open' entry of the latest opened element.
*
* @return integer
*/
public function getIndexLastOpened () {
if ($this->size == 0) {
return -1;
}
for ($index = $this->size-1 ; $index >= 0 ; $index--) {
if ($this->entries [$index]['state'] == 'open') {
return $index;
}
}
return -1;
}
/**
* Find the parent for the entry at index $start.
*
* @param integer $start Starting point
*/
public function findParent ($start) {
if ($this->size == 0 || $start >= $this->size) {
return -1;
}
$start_level = $this->entries [$start]['level'];
if ($start_level == 0) {
return -1;
}
for ($index = $start-1 ; $index >= 0 ; $index--) {
if ($this->entries [$index]['state'] == 'open'
&&
$this->entries [$index]['level'] == $start_level-1) {
return $index;
}
}
return -1;
}
/**
* Find the preceding sibling for the entry at index $current.
*
* @param integer $current Starting point
*/
public function getPrecedingSibling ($current) {
if ($this->size == 0 || $current >= $this->size || $current == 0) {
return -1;
}
$current_level = $this->entries [$current]['level'];
if ($this->entries [$current-1]['level'] == $current_level) {
return ($current-1);
}
return -1;
}
/**
* Dump the current elements/entries in this cssdocument.
* Only for debugging purposes.
*/
public function getDump () {
$dump = '';
$dump .= 'RootLevel: '.$this->rootLevel.', RootIndex: '.$this->rootIndex."\n";
for ($index = 0 ; $index < $this->size ; $index++) {
$element = $this->entries [$index];
$dump .= str_repeat(' ', $element ['level'] * 2);
if ($this->entries [$index]['state'] == 'open') {
$dump .= '<'.$element ['element'];
$dump .= ' '.$element ['attributes'].'>';
} else {
$dump .= '</'.$element ['element'].'>';
}
$dump .= ' (Level: '.$element ['level'].')';
$dump .= "\n";
}
return $dump;
}
/**
* Remove the current entry.
*/
public function removeCurrent () {
$index = $this->size-1;
if ($index <= $this->rootIndex) {
// Do not remove root elements!
return;
}
$this->level = $this->entries [$index]['level'];
$this->entries [$index] = NULL;
$this->size--;
}
}