]> _ Git - cubeextranet.git/commitdiff
wip #3634 @3
authorvincent@cubedesigners.com <vincent@cubedesigners.com@f5622870-0f3c-0410-866d-9cb505b7a8ef>
Tue, 2 Jun 2020 18:28:37 +0000 (18:28 +0000)
committervincent@cubedesigners.com <vincent@cubedesigners.com@f5622870-0f3c-0410-866d-9cb505b7a8ef>
Tue, 2 Jun 2020 18:28:37 +0000 (18:28 +0000)
inc/ws/Controlleur/class.ws.flash.php
inc/ws/Metier/class.ws.book.parametres.php
inc/ws/Util/html5/master/class.ws.html5.compiler.php
inc/ws/Util/html5/master/class.ws.html5.links.php

index 41d5e49d07966de6ec6ebaf75ed93f2a01da0208..344d2dce9b9080b8b66a065806e36e914fd35370 100644 (file)
@@ -618,7 +618,7 @@ class wsFlash extends cubeFlashGateway
 
         $types = array(1, 2, 3, 4, 5, 6, 7, 11, 13, 14, 15, 16, 17, 18, 19, 24, 25);
         if (wsDroits::revendeur()) {
-            $types = array(1, 2, 3, 4, 5, 6, 7, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 24, 25, 31, 33);
+            $types = array(1, 2, 3, 4, 5, 6, 7, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 24, 25, 31, 33,36);
         }
         if (wsDroits::admin()) {
             $types = range(1, 100);
index d4dd81ffd6606cc0c6aec22ebf9b8958c2f4e002..9a3f8f1133a6140152a5bc68545ddc25fdbca984 100644 (file)
@@ -463,10 +463,11 @@ class wsBookParametres extends wsParametres
         // Articles
         $this->fields['articlesFile'] = ['type' => 'freefile', 'default' => '', 'editable' => true,
             'label' => 'Articles', 'grade' => 3, 'fileFilter' => $xmlFilter];
-        $this->fields['articlesFont'] = ['type' => 'combo', 'label' => __('Police des articles'), 'default' => 'OpenSans', 'datas' => ['OpenSans' => 'Open Sans (police du Fluidbook)', 'Montserrat' => 'Monserrat'], 'editable' => 'true', 'grade' => 3];
-        $this->fields['articlesImages'] = ['type' => 'freefile', 'label' => __('Images des articles'), 'default' => '', 'hint' => __('Les noms des fichiers doivent être les même que ceux des balises <image> du XML'), 'editable' => true, 'grade' => 3];
+        $this->fields['articlesFont'] = ['type' => 'combo', 'label' => __('Police des articles'), 'default' => 'OpenSans', 'datas' => [
+            'Open Sans (police du Fluidbook)' => 'OpenSans', 'Montserrat' => 'Montserrat'], 'editable' => 'true', 'grade' => 3];
+        $this->fields['articlesImages'] = ['type' => 'freefile', 'label' => __('Images des articles'), 'default' => '', 'hint' => __('Les noms des fichiers doivent être les même que ceux des balises <image> du XML'), 'editable' => true, 'grade' => 3, 'dir' => 'articles'];
 
-        $this->forms['articles'] = ['label' => __('Articles'), 'fieldsnames' => ['articlesFile', 'articlesFont','articlesImages']];
+        $this->forms['articles'] = ['label' => __('Articles'), 'fieldsnames' => ['articlesFile', 'articlesFont', 'articlesImages']];
 
         //.
         $this->fields['externalArchives'] = array('type' => 'freefile', 'default' => '', 'editable' => true,
index 735e336f2ef57fd9f63fed7cda14928d0c0a5a8b..e5eff0a8b3c328fc3e3a489433f4f7383b6842d2 100644 (file)
@@ -208,6 +208,7 @@ class wsHTML5Compiler
     public $writeLinksData = false;
     public $content_lock = [];
     public $cssfont = [];
+    public $lessVariables = [];
     protected $_indexVars = null;
 
     public $_signature;
@@ -575,12 +576,12 @@ class wsHTML5Compiler
         $this->writeImages();
         $this->log('Images written');
         $this->writeCartConfig();
+        $this->writeArticles();
+        $this->log('Articles written');
         $linksCSS = $this->writeLinks();
         $this->log('Links written');
         $this->writeLangs();
         $this->log('Langs written');
-        $this->writeArticles();
-        $this->log('Articles written');
         $this->writeSEO();
         $this->log('SEO written');
         $this->writeWidget();
@@ -1857,10 +1858,9 @@ class wsHTML5Compiler
 
         $lessContents = '';
 
-        $lessVariables = array();
-        $lessVariables['css-scale'] = $this->cssScale;
-        $lessVariables['slider-display'] = $this->_lessBoolean($this->theme->parametres->pagesBar);
-        $lessVariables['slider-thumb-background'] = wsHTML5::colorToCSS($this->theme->parametres->pageBarThumbBack);
+        $this->lessVariables['css-scale'] = $this->cssScale;
+        $this->lessVariables['slider-display'] = $this->_lessBoolean($this->theme->parametres->pagesBar);
+        $this->lessVariables['slider-thumb-background'] = wsHTML5::colorToCSS($this->theme->parametres->pageBarThumbBack);
 
         // General theme
         $cssWidth = $this->cssWidth;
@@ -1880,27 +1880,27 @@ class wsHTML5Compiler
         $navTop = ($cssHeight - 40 - 100) / 2;
         $leftOfRightPage = (floor($cssWidth) - 1) . 'px';
 
-        $lessVariables['z'] = $this->z;
-        $lessVariables['book-page-width'] = $w;
+        $this->lessVariables['z'] = $this->z;
+        $this->lessVariables['book-page-width'] = $w;
         if ($this->book->parametres->correctCenter && !$this->isMobileFirst()) {
-            $lessVariables['book-page-correct-width'] = ceil($w) + 1;
-            $lessVariables['book-page-correct-height'] = ceil($h) + 1;
+            $this->lessVariables['book-page-correct-width'] = ceil($w) + 1;
+            $this->lessVariables['book-page-correct-height'] = ceil($h) + 1;
         } else {
-            $lessVariables['book-page-correct-width'] = $w;
-            $lessVariables['book-page-correct-height'] = $h;
+            $this->lessVariables['book-page-correct-width'] = $w;
+            $this->lessVariables['book-page-correct-height'] = $h;
         }
-        $lessVariables['book-page-height'] = $h;
-        $lessVariables['book-page-ratio'] = floatval($w) / floatval($h);
+        $this->lessVariables['book-page-height'] = $h;
+        $this->lessVariables['book-page-ratio'] = floatval($w) / floatval($h);
 
-        $lessVariables['shadow-opacity'] = wsHTML5::colorToArray($this->theme->parametres->bookShadeColor)['opacity'] * 1.2;
-        $lessVariables['edges-display'] = $this->_lessBoolean($this->theme->parametres->usePageEdges);
-        $lessVariables['edge-left-offset'] = $this->theme->parametres->pageEdgeLeftOffset;
-        $lessVariables['edge-right-offset'] = $this->theme->parametres->pageEdgeRightOffset;
-        $lessVariables['edges-opacity'] = $this->theme->parametres->pageEdgeOpacity / 100;
+        $this->lessVariables['shadow-opacity'] = wsHTML5::colorToArray($this->theme->parametres->bookShadeColor)['opacity'] * 1.2;
+        $this->lessVariables['edges-display'] = $this->_lessBoolean($this->theme->parametres->usePageEdges);
+        $this->lessVariables['edge-left-offset'] = $this->theme->parametres->pageEdgeLeftOffset;
+        $this->lessVariables['edge-right-offset'] = $this->theme->parametres->pageEdgeRightOffset;
+        $this->lessVariables['edges-opacity'] = $this->theme->parametres->pageEdgeOpacity / 100;
 
-        $lessVariables['page-number-color'] = wsHTML5::colorToCSS($this->theme->parametres->colorPageNumber);
-        $lessVariables['display-page-number'] = $this->_lessBoolean($this->theme->parametres->displayPageNumber);
-        $lessVariables['page-transition-duration'] = $this->book->parametres->mobileTransitionDuration . 's';
+        $this->lessVariables['page-number-color'] = wsHTML5::colorToCSS($this->theme->parametres->colorPageNumber);
+        $this->lessVariables['display-page-number'] = $this->_lessBoolean($this->theme->parametres->displayPageNumber);
+        $this->lessVariables['page-transition-duration'] = $this->book->parametres->mobileTransitionDuration . 's';
 
         $corrText = $this->isMobileFirst() ? 0 : 4;
 
@@ -1961,20 +1961,20 @@ class wsHTML5Compiler
         $res[] = 'footer,footer a{color:' . wsHTML5::colorToCSS($this->theme->parametres->creditsColor) . ';}';
 
         // Arrows
-        $lessVariables['arrows-background'] = wsHTML5::colorToCSS($this->theme->parametres->couleurA);
-        $lessVariables['arrows-color'] = wsHTML5::colorToCSS($this->theme->parametres->arrowsColor);
+        $this->lessVariables['arrows-background'] = wsHTML5::colorToCSS($this->theme->parametres->couleurA);
+        $this->lessVariables['arrows-color'] = wsHTML5::colorToCSS($this->theme->parametres->arrowsColor);
 
         // Loader
-        $lessVariables['loader-background-color'] = wsHTML5::colorToCSS($this->theme->parametres->couleurL);
-        $lessVariables['loader-foreground-color'] = wsHTML5::colorToCSS($this->theme->parametres->loadingSecColor);
+        $this->lessVariables['loader-background-color'] = wsHTML5::colorToCSS($this->theme->parametres->couleurL);
+        $this->lessVariables['loader-foreground-color'] = wsHTML5::colorToCSS($this->theme->parametres->loadingSecColor);
 
         // Audio description buttons
-        $lessVariables['audiodescription-background'] = wsHTML5::colorToCSS($this->theme->parametres->couleurA);
-        $lessVariables['audiodescription-color'] = wsHTML5::colorToCSS($this->theme->parametres->couleurA);
+        $this->lessVariables['audiodescription-background'] = wsHTML5::colorToCSS($this->theme->parametres->couleurA);
+        $this->lessVariables['audiodescription-color'] = wsHTML5::colorToCSS($this->theme->parametres->couleurA);
 
         // Links Styles
-        $lessVariables['links-color'] = wsHTML5::colorToCSS($this->theme->parametres->linksColor);
-        $lessVariables['inlineslideshow-transition-time'] = (floatval($this->book->parametres->inlineSlideshowTransitionDuration) * 1000) . 'ms';
+        $this->lessVariables['links-color'] = wsHTML5::colorToCSS($this->theme->parametres->linksColor);
+        $this->lessVariables['inlineslideshow-transition-time'] = (floatval($this->book->parametres->inlineSlideshowTransitionDuration) * 1000) . 'ms';
         $res = array_merge($res, $links);
 
         // Bookmarks
@@ -1982,11 +1982,11 @@ class wsHTML5Compiler
             $this->book->parametres->bookmarkCornerSize = 10;
         }
 
-        $lessVariables['bookmark-star-disabled-color'] = wsHTML5::colorToCSS($this->theme->parametres->bookmarkStarDisabledColor);
-        $lessVariables['bookmark-star-enabled-color'] = wsHTML5::colorToCSS($this->theme->parametres->bookmarkStarEnabledColor);
-        $lessVariables['bookmark-color'] = wsHTML5::colorToCSS($this->theme->parametres->bookmarkBackgroundColor);
-        $lessVariables['bookmark-corner-size'] = round($this->width * $this->book->parametres->bookmarkCornerSize * 0.0075 * $this->z) . 'px';
-        $lessVariables['bookmark-corner-offset'] = $this->book->parametres->bookmarkOffset . 'px';
+        $this->lessVariables['bookmark-star-disabled-color'] = wsHTML5::colorToCSS($this->theme->parametres->bookmarkStarDisabledColor);
+        $this->lessVariables['bookmark-star-enabled-color'] = wsHTML5::colorToCSS($this->theme->parametres->bookmarkStarEnabledColor);
+        $this->lessVariables['bookmark-color'] = wsHTML5::colorToCSS($this->theme->parametres->bookmarkBackgroundColor);
+        $this->lessVariables['bookmark-corner-size'] = round($this->width * $this->book->parametres->bookmarkCornerSize * 0.0075 * $this->z) . 'px';
+        $this->lessVariables['bookmark-corner-offset'] = $this->book->parametres->bookmarkOffset . 'px';
 
         // Menus
         $menuColor = new CubeIT_Graphics_Color($this->theme->parametres->couleurB);
@@ -1994,29 +1994,29 @@ class wsHTML5Compiler
         $menuTextColor = wsHTML5::colorToCSS($this->theme->parametres->subTextColor);
         $menuBreakpoint = empty($this->book->parametres->menuBreakpoint) ? '1023px' : $this->book->parametres->menuBreakpoint;
 
-        $lessVariables['menu-breakpoint'] = $menuBreakpoint;
-        $lessVariables['menu-background'] = $menuColor->toCSS();
+        $this->lessVariables['menu-breakpoint'] = $menuBreakpoint;
+        $this->lessVariables['menu-background'] = $menuColor->toCSS();
         if ($this->theme->parametres->subSecondaryColor) {
-            $lessVariables['menu-button-background'] = wsHTML5::colorToCSS($this->theme->parametres->subSecondaryColor);
+            $this->lessVariables['menu-button-background'] = wsHTML5::colorToCSS($this->theme->parametres->subSecondaryColor);
         } else {
-            $lessVariables['menu-background-green'] = 'max(45, min(255-45, green(@menu-background)))';
-            $lessVariables['menu-background-red'] = 'max(45, min(255-45, red(@menu-background)))';
-            $lessVariables['menu-background-blue'] = 'max(45, min(255-45, blue(@menu-background)))';
-            $lessVariables['menu-button-background'] = 'overlay(rgb(@menu-background-red, @menu-background-green, @menu-background-blue), #c0c0c0)';
+            $this->lessVariables['menu-background-green'] = 'max(45, min(255-45, green(@menu-background)))';
+            $this->lessVariables['menu-background-red'] = 'max(45, min(255-45, red(@menu-background)))';
+            $this->lessVariables['menu-background-blue'] = 'max(45, min(255-45, blue(@menu-background)))';
+            $this->lessVariables['menu-button-background'] = 'overlay(rgb(@menu-background-red, @menu-background-green, @menu-background-blue), #c0c0c0)';
         }
 
-        $lessVariables['menu-text'] = $menuTextColor;
-        $lessVariables['menu-field-background'] = wsHTML5::colorToCSS($this->theme->parametres->subFieldColor);
-        $lessVariables['menu-field-text'] = wsHTML5::colorToCSS($this->theme->parametres->subTextFieldColor);
-        $lessVariables['menu-select-background'] = wsHTML5::colorToCSS($this->theme->parametres->subSelectColor);
-        $lessVariables['menu-select-text'] = wsHTML5::colorToCSS($this->theme->parametres->subTextSelectColor);
-        $lessVariables['icon-color'] = wsHTML5::colorToCSS($this->theme->parametres->couleurI);
-        $lessVariables['menu-overlay'] = wsHTML5::colorToCSS($this->theme->parametres->popupVideoOverlay);
+        $this->lessVariables['menu-text'] = $menuTextColor;
+        $this->lessVariables['menu-field-background'] = wsHTML5::colorToCSS($this->theme->parametres->subFieldColor);
+        $this->lessVariables['menu-field-text'] = wsHTML5::colorToCSS($this->theme->parametres->subTextFieldColor);
+        $this->lessVariables['menu-select-background'] = wsHTML5::colorToCSS($this->theme->parametres->subSelectColor);
+        $this->lessVariables['menu-select-text'] = wsHTML5::colorToCSS($this->theme->parametres->subTextSelectColor);
+        $this->lessVariables['icon-color'] = wsHTML5::colorToCSS($this->theme->parametres->couleurI);
+        $this->lessVariables['menu-overlay'] = wsHTML5::colorToCSS($this->theme->parametres->popupVideoOverlay);
 
         // Chapters
-        $lessVariables['menu-chapters-columns-count'] = max(1, min(6, $this->book->parametres->chaptersColumns));
-        $lessVariables['menu-chapters-columns-width'] = $this->book->parametres->chaptersColMaxWidth;
-        $lessVariables['menu-chapters-font-size'] = $this->book->parametres->chaptersFontSize;
+        $this->lessVariables['menu-chapters-columns-count'] = max(1, min(6, $this->book->parametres->chaptersColumns));
+        $this->lessVariables['menu-chapters-columns-width'] = $this->book->parametres->chaptersColMaxWidth;
+        $this->lessVariables['menu-chapters-font-size'] = $this->book->parametres->chaptersFontSize;
 
         foreach ($this->book->chapters as $chapter) {
             if (substr($chapter->page, 0, 1) != '#') {
@@ -2039,12 +2039,12 @@ class wsHTML5Compiler
         $ratio = $this->width / $this->height;
         $thumbh = round(100 / $ratio);
         $this->config->thumbHeight = $thumbh;
-        $lessVariables['thumb-height'] = $thumbh . 'px';
+        $this->lessVariables['thumb-height'] = $thumbh . 'px';
 
         #tooltip
-        $lessVariables['tooltip-background'] = wsHTML5::colorToCSS($this->theme->parametres->tooltipBackColor);
-        $lessVariables['tooltip-color'] = wsHTML5::colorToCSS($this->theme->parametres->tooltipTextColor);
-        $lessVariables['tooltip-font-size'] = 14 * ($this->theme->parametres->tooltipTextSize / 100);
+        $this->lessVariables['tooltip-background'] = wsHTML5::colorToCSS($this->theme->parametres->tooltipBackColor);
+        $this->lessVariables['tooltip-color'] = wsHTML5::colorToCSS($this->theme->parametres->tooltipTextColor);
+        $this->lessVariables['tooltip-font-size'] = 14 * ($this->theme->parametres->tooltipTextSize / 100);
 
         #fonts
         foreach ($this->cssfont as $hash => $item) {
@@ -2055,7 +2055,7 @@ class wsHTML5Compiler
             $res[] = file_get_contents($this->wdir . '/' . $this->book->parametres->textPopupStylesheet);
         }
 
-        $this->_writeLess($lessVariables, $lessContents);
+        $this->_writeLess($this->lessVariables, $lessContents);
         $this->stylesheets[] = 'data/style/style.css';
         $this->vdir->file_put_contents('data/style/style.css', implode("\n", $res));
         $this->log('Write CSS');
@@ -2375,9 +2375,10 @@ class wsHTML5Compiler
 
     public function addFontKit($font)
     {
-        $path = 'style/fonts/Montserrat';
+        $path = 'style/fonts/' . $font;
         $this->stylesheets[] = $path . '/font.css';
         $this->vdir->copyDirectory($this->assets . '/' . $path, $path);
+        return $path . '/font.css';
     }
 
     public function writeArticles()
@@ -2394,28 +2395,52 @@ class wsHTML5Compiler
             return;
         }
 
+        $this->addLess('articles');
+
+        $this->lessVariables['articles-title-color'] = '#565657';
+        $this->lessVariables['articles-font'] = $this->book->parametres->articlesFont;
         if ($this->book->parametres->articlesFont !== 'OpenSans') {
-            $this->addFontKit($this->book->parametres->articlesFont);
+            $fontPath = $this->addFontKit($this->book->parametres->articlesFont);
         }
 
+        $svg = '<svg xmlns="http://www.w3.org/2000/svg" style="display: none;"><symbol id="nav-print" viewBox="0 0 512 512">
+        <path d="m424 186l-39 0 0-114c0-9-6-15-14-15l-230 0c-8 0-14 6-14 15l0 114-39 0c-22 0-41 19-41 41l0 121c0 23 19 41 41 41l39 0 0 49c0 8 6 15 14 15l230 0c8 0 14-7 14-15l0-49 39 0c22 0 41-18 41-41l0-121c0-22-19-41-41-41z m-268-100l200 0 0 100-200 0z m200 340l-200 0 0-88 200 0z m80-76c0 6-6 12-12 12l-39 0 0-38c0-9-6-15-14-15l-230 0c-8 0-14 6-14 15l0 38-39 0c-6 0-12-6-12-12l0-121c0-6 6-12 12-12l336 0c6 0 12 6 12 12z m-278-96l-33 0c-8 0-14 6-14 14 0 8 6 15 14 15l35 0c8 0 14-7 14-15 0-8-8-14-16-14z m32 139l132 0c8 0 14-6 14-14 0-8-6-14-14-14l-132 0c-8 0-14 6-14 14 0 8 6 14 14 14z"/>
+    </symbol></svg>';
+
         $markupMap = ['category' => 'h3', 'subtitle' => 'h2', 'title' => 'h1', 'lead' => 'div.chapo', 'paragraph' => 'p', 'note' => 'div.note', 'quote' => 'blockquote', 'signature' => 'div.author'];
 
         $x = simplexml_load_string(file_get_contents($f));
+        $prevurl = '';
         foreach ($x->xpath('/articles/article') as $k => $a) {
+            $url = (string)$a['url'];
             $article = ['id' => (string)$a['id'],
-                'url' => (string)$a['url'],
+                'url' => $url,
                 'color' => (string)$a['color'],
-                'contents' => ''];
+                'contents' => '',
+                'prev' => $prevurl,
+                'next' => ''];
 
-            $id = 'article_' . $k;
+            if ($prevurl !== '') {
+                $list[count($list) - 1]['next'] = $url;
+            } else {
+                $firsturl = $url;
+            }
+
+            $prevurl = $url;
 
-            $content = '<article id="' . $id . '">';
+            $specificStyles = '## h3, ## figure figcaption{background-color:' . $article['color'] . '}';
+            $specificStyles .= '## .chapo, ## blockquote{color:' . $article['color'] . ';}';
+
+            $inner = '<article data-id="' . $article['id'] . '" class="menu-article" id="article_' . $article['id'] . '">';
+            $inner .= '<style type="text/css">' . str_replace('##', '#article_' . $article['id'], $specificStyles) . '</style>';
+            $inner .= '<a href="#" class="print"><svg viewBox="0 0 512 512" class="nav-print nav-icon svg-icon"><use xlink:href="#nav-print"></use></svg></a>';
             foreach ($a->children() as $child) {
                 $tag = $child->getName();
                 if ($tag === 'image') {
                     $file = (string)$child['file'];
+                    $this->vdir->copy($this->wdir . '/articles/' . $file, 'data/articles/' . $file);
                     $legend = (string)$child;
-                    $content .= '<figure><img src="data/articles/' . $file . '" alt="' . $legend . '"><figcation>' . $legend . '</figcation></figure>';
+                    $inner .= '<figure><img src="data/articles/' . $file . '" alt="' . $legend . '"><figcaption>' . $legend . '</figcaption></figure>';
                 } else {
                     $m = $markupMap[$tag] ?? $tag;
                     $e = explode('.', $m);
@@ -2424,15 +2449,34 @@ class wsHTML5Compiler
                     if (count($e) === 2) {
                         $class = ' class="' . $e[1] . '"';
                     }
-                    $content .= '<' . $markup . $class . '>' . ((string)$child) . '</' . $markup . '>';
+                    $inner .= '<' . $markup . $class . '>' . ((string)$child) . '</' . $markup . '>';
                 }
             }
-            $content .= '</article>';
-            $article['contents'] = $content;
+            $inner .= '</article>';
+
+            $article['contents'] = $inner;
+            $content = '<html><head>';
+            $content .= '<link rel="stylesheet" type="text/css" href="' . $fontPath . '">';
+            $content .= '<link rel="stylesheet" type="text/css" href="style/articles.css">';
+            $content .= '<style type="text/css">';
+            $content .= str_replace('## ', '', $specificStyles);
+            $content .= '</style>';
+            $content .= '<style type="text/css" media="screen">*{visibility:hidden}</style>';
+            $content .= '</head><body>';
+            $content .= $svg;
+            $content .= $inner;
+            $content .= '</body></html>';
+            $article['print'] = $content;
             $list[] = $article;
         }
+        $list[0]['prev'] = $prevurl;
+        $list[count($list) - 1]['next'] = $firsturl;
 
-        $this->config->articlesList = $list;
+        $idlist = [];
+        foreach ($list as $item) {
+            $idlist[$item['id']] = $item;
+        }
+        $this->config->articlesList = $idlist;
     }
 
 }
index db80328a0b895897f9448b91a6dcb579cab3882d..817e8077924c67097beb083b2d94672e65aa580d 100644 (file)
@@ -187,6 +187,9 @@ class wsHTML5Link
             case 35:
                 return new textLink($id, $init, $compiler);
                 break;
+            case 36:
+                return new articleLink($id, $init, $compiler);
+                break;
             default:
                 return null;
         }
@@ -2114,6 +2117,23 @@ class iframeLink extends wsHTML5Link
     }
 }
 
+class articleLink extends normalLink
+{
+    protected $article;
+
+    public function init()
+    {
+        parent::init();
+        $this->compiler->config->articlesList[$this->to]['page'] = $this->page;
+        $this->article = $this->compiler->config->articlesList[$this->to];
+    }
+
+    public function getURL()
+    {
+        return '#/article/' . $this->article['url'];
+    }
+}
+
 class iframePopupLink extends normalLink
 {
     public function getURL()