diff --git a/assets/main.css b/assets/main.css index 25463aa..f59bc00 100644 --- a/assets/main.css +++ b/assets/main.css @@ -371,6 +371,15 @@ body { flex-grow: 1; } +#sidebar > .menu-container > .menu hr { + width: calc(0.66 * calc(var(--sidebar-menu-container-padding-width) + 100%)); + margin: 0.55rem auto; + transform: translate(calc(0px - var(--sidebar-menu-container-padding-width)/2), 0px); + height: var(--sidebar-menu-list-seperator-width); + border-radius: calc(var(--sidebar-menu-list-seperator-width) / 2); + background: var(--color-menu-list-separator); +} + #sidebar > .menu-container > .menu .menu-item { display: block; padding: 0.55rem 0; diff --git a/assets/xsd/book.xsd b/assets/xsd/book.xsd index f4a2225..d8b0550 100644 --- a/assets/xsd/book.xsd +++ b/assets/xsd/book.xsd @@ -1,46 +1,63 @@ - + + + + + + + + + + + + - - - - - - - + + + + + + + + - - + + - - - - - - - - - + - - - - - - - + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/assets/xsd/bookshelf.xsd b/assets/xsd/bookshelf.xsd index 4d0cacd..275fa22 100644 --- a/assets/xsd/bookshelf.xsd +++ b/assets/xsd/bookshelf.xsd @@ -1,8 +1,8 @@ @@ -13,63 +13,77 @@ + + - + + + + + - + + + + + - + - + - - + + - - + + + + + - - - - - + + + + - + - - + + - - + + + + + - - - - - + + + + - + \ No newline at end of file diff --git a/assets/xsd/configurations.xsd b/assets/xsd/configurations.xsd index aac2504..9b4597e 100644 --- a/assets/xsd/configurations.xsd +++ b/assets/xsd/configurations.xsd @@ -1,30 +1,29 @@ - - - - - - - - - - - - - + + + + + + + + + + + + + - diff --git a/constant.php b/constant.php index 33d702d..d7eecce 100644 --- a/constant.php +++ b/constant.php @@ -2,6 +2,6 @@ const APP_NAME = "ph-Bookshelf"; -const VERSION = "0.4.0"; +const VERSION = "0.5.0-alpha1"; const CHANNEL = "suk-ws"; const BRANCH = "master"; diff --git a/src/Element/Book.php b/src/Element/Book.php index f4d9847..d9b2e7d 100644 --- a/src/Element/Book.php +++ b/src/Element/Book.php @@ -20,26 +20,28 @@ class Book { } /** - * @param DOMNode $xmlData + * @param DOMNode $bookNode * @param BookCollection $parent * @return Book * @throws Exception */ - public static function parse (DOMNode $xmlData, BookCollection $parent): Book { - if ($xmlData->hasAttributes()) { - $attrName = $xmlData->attributes->getNamedItem("name"); - $attrId = $xmlData->attributes->getNamedItem("id"); - if ($attrName == null) - if ($attrId == null) throw new Exception("Book xml data missing attribute \"name\""); - else throw new Exception("Book xml data with id \"$attrId->nodeValue\" missing attribute \"name\""); - else $name = $attrName->nodeValue; - if ($attrId == null) throw new Exception("Book xml data named \"$name\" missing attribute \"id\""); + public static function parse (DOMNode $bookNode, BookCollection $parent): Book { + if ($bookNode->hasAttributes()) { + $attrId = $bookNode->attributes->getNamedItem("id"); + if ($attrId == null) throw new Exception("an Book xml data named missing attribute \"id\""); else $id = $attrId->nodeValue; } else throw new Exception("Book xml data missing attributes"); - if ($xmlData->hasChildNodes()) - throw new Exception("Book xml with id \"$id\" have some children which are not supported"); - return new Book($id, $name, $parent); + $valueName = $bookNode->nodeValue; +// if ($bookNode->hasChildNodes()) { +// for ($child = $bookNode->firstChild; $child; $child = $child->nextSibling) { +// $valueName .= match ($child->nodeName) { +// "#text", "#cdata-section" => $child->nodeValue, +// default => throw new Exception("Unsupported element type \"$child->nodeName\" in parsing configuration $bookNode->nodeName") +// }; +// } +// } // todo warn if no link name + return new Book($id, $valueName, $parent); } public function getId (): string { diff --git a/src/Element/BookCollection.php b/src/Element/BookCollection.php index 0da485f..e710580 100644 --- a/src/Element/BookCollection.php +++ b/src/Element/BookCollection.php @@ -23,23 +23,33 @@ class BookCollection { } /** - * @param DOMNode $root + * @param DOMNode $collectionNode * @param ?BookCollection $parent * @param bool $isRoot * @return BookCollection * @throws Exception */ - public static function parse (DOMNode $root, ?BookCollection $parent, bool $isRoot = false): BookCollection { - $name = BookCollection::ROOT; + public static function parse (DOMNode $collectionNode, ?BookCollection $parent, bool $isRoot = false): BookCollection { + $collectionName = LinkCollection::ROOT; + $child = $collectionNode->firstChild; + if ($child == null) throw new Exception("an BookCollection is NULL!"); if (!$isRoot) { - if ($root->hasAttributes()) { - $attrName = $root->attributes->getNamedItem("name"); - if ($attrName == null) throw new Exception("BookCollection (not root) xml data missing attribute \"name\""); - else $name = $attrName->nodeValue; - } else throw new Exception("BookCollection (not root) xml data missing attributes"); + while ($child->nodeName != "caption") { + switch ($child->nodeName) { + case "#comment": + break; + case "#text": + if (empty(trim($child->nodeValue))) break; + default: + throw new Exception("BookCollection need a \"caption\" as first child but \"$child->nodeName\" found"); + } + $child = $child->nextSibling; + } + $collectionName = $child->nodeValue; + $child = $child->nextSibling; } - $node = new BookCollection($name, $parent); - for ($child = $root->firstChild; $child != null; $child = $child->nextSibling) { + $node = new BookCollection($collectionName, $parent); + for (; $child != null; $child = $child->nextSibling) { switch ($child->nodeName) { case "Book": $node->array[] = Book::parse($child, $node); @@ -51,9 +61,9 @@ class BookCollection { break; case "#text": if (empty(trim($child->nodeValue))) break; - throw new Exception("Unsupported element type \"$child->nodeName\" in BookCollection named \"$name\""); + throw new Exception("Unsupported element type \"$child->nodeName\" in BookCollection named \"$collectionName\""); default: - throw new Exception("Unsupported element type \"$child->nodeName\" in BookCollection named \"$name\""); + throw new Exception("Unsupported element type \"$child->nodeName\" in BookCollection named \"$collectionName\""); } } return $node; diff --git a/src/Element/BookContent/BookContented.php b/src/Element/BookContent/BookContented.php index 91da22b..2722bb6 100644 --- a/src/Element/BookContent/BookContented.php +++ b/src/Element/BookContent/BookContented.php @@ -44,6 +44,17 @@ class BookContented { return $node; } + /** + * @param DOMNode $rootBookNode + * @return BookContented + * @throws Exception + */ + public static function parseRootBook (DOMNode $rootBookNode): BookContented { + $return = new BookContented("%root", ""); + $return->childs = Chapter::parse($rootBookNode, null); + return $return; + } + /** * @param string $xmlContent * @return BookContented diff --git a/src/Element/BookContent/Chapter.php b/src/Element/BookContent/Chapter.php index 10171cd..f0bb3a7 100644 --- a/src/Element/BookContent/Chapter.php +++ b/src/Element/BookContent/Chapter.php @@ -28,12 +28,23 @@ class Chapter { * @throws Exception */ public static function parse (DOMNode $xmlData, ?Chapter $parent): Chapter { - if ($xmlData->hasAttributes()) { - $attrName = $xmlData->attributes->getNamedItem("name"); - if ($attrName == null) throw new Exception("Chapter xml data missing attribute \"name\""); - else $node = new Chapter($xmlData->attributes->getNamedItem("name")->nodeValue, array(), $parent); - } else throw new Exception("Chapter xml data missing attributes"); - for ($child = $xmlData->firstChild;$child != null ; $child = $child->nextSibling) { + $child = $xmlData->firstChild; + if ($parent != null) { + while ($child->nodeName != "caption") { + switch ($child->nodeName) { + case "#comment": + break; + case "#text": + if (empty(trim($child->nodeValue))) break; + default: + throw new Exception("Chapter need a \"caption\" as first child but \"$child->nodeName\" found"); + } + $child = $child->nextSibling; + } + $node = new Chapter($child->nodeValue, array(), $parent); + $child = $child->nextSibling; + } else $node = new Chapter("", array(), $parent); + for (;$child != null ; $child = $child->nextSibling) { switch ($child->nodeName) { case "Page": $node->children[] = Page::parse($child, $node); @@ -41,6 +52,9 @@ class Chapter { case "Chapter": $node->children[] = self::parse($child, $node); break; + case "Separator": + $node->children[] = Separator::parse($child, $node); + break; case "#comment": break; case "#text": diff --git a/src/Element/BookContent/Page.php b/src/Element/BookContent/Page.php index d2118e0..c29ee0d 100644 --- a/src/Element/BookContent/Page.php +++ b/src/Element/BookContent/Page.php @@ -23,33 +23,19 @@ class Page { } /** - * @param DOMNode $xmlData + * @param DOMNode $pageNode * @param Chapter $parent * @return Page * @throws Exception */ - public static function parse (DOMNode $xmlData, Chapter $parent): Page { - if ($xmlData->hasAttributes()) { - $attrName = $xmlData->attributes->getNamedItem("name"); - $attrId = $xmlData->attributes->getNamedItem("id"); - if ($attrName == null) - if ($attrId == null) throw new Exception("Page xml data missing attribute \"name\""); - else throw new Exception("Page xml data with id \"$attrId->nodeValue\" missing attribute \"name\""); - else $name = $attrName->nodeValue; - if ($attrId == null) throw new Exception("Page xml data named \"$name\" missing attribute \"id\""); + public static function parse (DOMNode $pageNode, Chapter $parent): Page { + if ($pageNode->hasAttributes()) { + $attrId = $pageNode->attributes->getNamedItem("id"); + if ($attrId == null) throw new Exception("an Page xml data missing attribute \"id\""); else $id = $attrId->nodeValue; - $node = new Page($id, $name, $parent); - Bookshelf::parseConfigurationAttr($xmlData->attributes, $node->configurations, array("name", "id")); } else throw new Exception("Book xml data missing attributes"); - for ($child = $xmlData->firstChild; $child != null; $child = $child->nextSibling) { - switch ($child->nodeName) { - case "#text": - default: - throw new Exception("Unsupported element type \"$child->nodeName\" in Page with id $id"); - } - } - return $node; + return new Page($id, $pageNode->nodeValue, $parent); } public function getId (): string { diff --git a/src/Element/BookContent/Separator.php b/src/Element/BookContent/Separator.php new file mode 100644 index 0000000..00303c0 --- /dev/null +++ b/src/Element/BookContent/Separator.php @@ -0,0 +1,38 @@ +parent = $parent; + } + + /** + * @throws Exception + */ + public static function parse (DOMNode $xmlData, ?Chapter $parent): Separator { + if ($xmlData->hasAttributes() || $xmlData->hasChildNodes()) + throw new Exception("Separator need be clean with no any attr/children"); + if ($parent->getParent() != null) + throw new Exception("Separator must in root contents path"); + return new Separator($parent); + } + + /** + * @return Chapter + */ + public function getParent (): Chapter { + return $this->parent; + } + + public function getSummaryHtml (): string { + return "
"; + } + +} \ No newline at end of file diff --git a/src/Element/Bookshelf.php b/src/Element/Bookshelf.php index c02a232..afe5c6f 100644 --- a/src/Element/Bookshelf.php +++ b/src/Element/Bookshelf.php @@ -10,6 +10,8 @@ use Exception; class Bookshelf { + private string $configureVersion; + private string $siteName; private LinkCollection $links; @@ -32,9 +34,9 @@ class Bookshelf { if ($dom->hasAttributes() && $dom->hasChildNodes()) { // Bookshelf 属性 - $attrSiteName = $dom->attributes->getNamedItem("siteName"); - if ($attrSiteName == null) throw new Exception("Bookshelf xml data missing attribute \"siteName\""); - $return->siteName = $attrSiteName->nodeValue; + $attrConfigVersion = $dom->attributes->getNamedItem("version"); + // todo no version warning + $return->configureVersion = $attrConfigVersion->nodeValue; // 对根节点的子节点进行遍历 for ($rc = $dom->firstChild; $rc != null; $rc = $rc->nextSibling) { @@ -45,12 +47,15 @@ class Bookshelf { case "books": $return->books = BookCollection::parse($rc, null, true); break; - case "rootBook": - $return->rootBook = BookContented::parse($rc); + case "root_book": + $return->rootBook = BookContented::parseRootBook($rc); break; case "configurations": self::parseConfiguration($rc, $return->configurations); break; + case "site_name": + $return->siteName = self::parseSiteName($rc); + break; case "#comment": break; case "#text": @@ -100,6 +105,19 @@ class Bookshelf { } } + private static function parseSiteName (DOMNode $siteNameNode): string { + $siteNameValue = ""; + for ($child = $siteNameNode->firstChild; $child != null; $child = $child->nextSibling) { + $siteNameValue .= match ($child->nodeName) { + "#text", "#cdata-section" => $child->nodeValue, + default => throw new Exception( + "Unsupported element type \"$child->nodeName\" in parsing configuration $siteNameNode->nodeName" + ), + }; + } + return $siteNameValue; + } + public function getSiteName (): string { return $this->siteName; } diff --git a/src/Element/Link.php b/src/Element/Link.php index 11588c5..be7e056 100644 --- a/src/Element/Link.php +++ b/src/Element/Link.php @@ -18,26 +18,28 @@ class Link { } /** - * @param DOMNode $xmlData + * @param DOMNode $linkNode * @param LinkCollection $parent * @return Link * @throws Exception */ - public static function parse (DOMNode $xmlData, LinkCollection $parent): Link { - if ($xmlData->hasAttributes()) { - $attrName = $xmlData->attributes->getNamedItem("name"); - $attrHref = $xmlData->attributes->getNamedItem("href"); - if ($attrName == null) - if ($attrHref == null) throw new Exception("Link xml data missing attribute \"name\""); - else throw new Exception("Link xml data which href is \"$attrHref->nodeValue\" missing attribute \"name\""); - else $name = $attrName->nodeValue; - if ($attrHref == null) throw new Exception("Link xml data named \"$name\" missing attribute \"href\""); + public static function parse (DOMNode $linkNode, LinkCollection $parent): Link { + if ($linkNode->hasAttributes()) { + $attrHref = $linkNode->attributes->getNamedItem("href"); + if ($attrHref == null) throw new Exception("an Link data missing attribute \"href\""); else $href = $attrHref->nodeValue; } else - throw new Exception("Link xml data missing attributes"); - if ($xmlData->hasChildNodes()) - throw new Exception("Link xml named \"$name\" have some children which are not supported"); - return new Link($name, $href, $parent); + throw new Exception("an Link data missing attributes"); + $valueName = $linkNode->nodeValue; +// if ($linkNode->hasChildNodes()) { +// for ($child = $linkNode->firstChild; $child; $child = $child->nextSibling) { +// $valueName .= match ($child->nodeName) { +// "#text", "#cdata-section" => $child->nodeValue, +// default => throw new Exception("Unsupported element type \"$child->nodeName\" in parsing configuration $linkNode->nodeName") +// }; +// } +// } // todo warn if no link name + return new Link($valueName, $href, $parent); } public function getName (): string { diff --git a/src/Element/LinkCollection.php b/src/Element/LinkCollection.php index a49ce7d..f4c6411 100644 --- a/src/Element/LinkCollection.php +++ b/src/Element/LinkCollection.php @@ -22,23 +22,33 @@ class LinkCollection { } /** - * @param DOMNode $root + * @param DOMNode $collectionNode * @param ?LinkCollection $parent * @param bool $isRoot * @return LinkCollection * @throws Exception */ - public static function parse (DOMNode $root, ?LinkCollection $parent, bool $isRoot = false): LinkCollection { - $name = LinkCollection::ROOT; + public static function parse (DOMNode $collectionNode, ?LinkCollection $parent, bool $isRoot = false): LinkCollection { + $collectionName = LinkCollection::ROOT; + $child = $collectionNode->firstChild; + if ($child == null) throw new Exception("an LinkCollection is NULL!"); if (!$isRoot) { - if ($root->hasAttributes()) { - $attrName = $root->attributes->getNamedItem("name"); - if ($attrName == null) throw new Exception("LinkCollection (not root) xml data missing attribute \"name\""); - else $name = $attrName->nodeValue; - } else throw new Exception("LinkCollection (not root) xml data missing attributes"); + while ($child->nodeName != "caption") { + switch ($child->nodeName) { + case "#comment": + break; + case "#text": + if (empty(trim($child->nodeValue))) break; + default: + throw new Exception("LinkCollection need a \"caption\" as first child but \"$child->nodeName\" found"); + } + $child = $child->nextSibling; + } + $collectionName = $child->nodeValue; + $child = $child->nextSibling; } - $node = new LinkCollection($name, $parent); - for ($child = $root->firstChild; $child != null; $child = $child->nextSibling) { + $node = new LinkCollection($collectionName, $parent); + for (; $child != null; $child = $child->nextSibling) { switch ($child->nodeName) { case "Link": $node->array[] = Link::parse($child, $node); @@ -50,9 +60,9 @@ class LinkCollection { break; case "#text": if (empty(trim($child->nodeValue))) break; - throw new Exception("Unsupported element type \"$child->nodeName\" in LinkCollection named \"$name\""); + throw new Exception("Unsupported element type \"$child->nodeName\" in LinkCollection named \"$collectionName\""); default: - throw new Exception("Unsupported element type \"$child->nodeName\" in LinkCollection named \"$name\""); + throw new Exception("Unsupported element type \"$child->nodeName\" in LinkCollection named \"$collectionName\""); } } return $node; diff --git a/template/main.php b/template/main.php index df8c179..6d49a5c 100644 --- a/template/main.php +++ b/template/main.php @@ -6,7 +6,7 @@
- +