Просмотр исходного кода

Merge branch 'master' of https://github.com/unaio/una

RomanL 4 лет назад
Родитель
Сommit
bf64118902

+ 7 - 1
inc/classes/BxDolTemplate.php

@@ -2919,7 +2919,13 @@ class BxDolTemplate extends BxDolFactory implements iBxDolSingleton
             $sReturn = substr($sReturn, 0, -1);
         }
 
-        return '<script language="javascript">var aDolLang = {' . $sReturn . '};</script>';
+        return '
+<script language="javascript">
+    if (\'undefined\' === typeof(aDolLang)) 
+        var aDolLang = {' . $sReturn . '};
+    else
+        $.extend(aDolLang, {' . $sReturn . '});
+</script>';
     }
     /**
      * Process all added options and return them as a string.

+ 76 - 0
inc/classes/BxDolWiki.php

@@ -277,6 +277,10 @@ class BxDolWiki extends BxDolFactory implements iBxDolFactoryObject
      */
     public function isAllowed ($sType, $iProfileId = false)
     {
+        if ('convert-links' == $sType) {
+            return isLogged();
+        }
+
         // translate isn't allowed when only one language on the site
         if ('translate' == $sType) {
             $aLangs = BxDolLanguages::getInstance()->getLanguages(false, true);
@@ -405,6 +409,7 @@ class BxDolWiki extends BxDolFactory implements iBxDolFactoryObject
                 'block_id' => $iBlockId,
                 'wiki_action_uri' => $this->getWikiUri(),
                 'action' => 'delete-version',
+                'txt_open_editor' => bx_js_string(_t('_sys_wiki_open_in_editor')),
             ));
         }
     }
@@ -635,6 +640,7 @@ class BxDolWiki extends BxDolFactory implements iBxDolFactoryObject
                 'block_id' => $iBlockId,
                 'wiki_action_uri' => $this->getWikiUri(),
                 'action' => $bTranslate ? 'translate' : 'edit',
+                'txt_open_editor' => bx_js_string(_t('_sys_wiki_open_in_editor')),
             ));
         } 
         else {
@@ -694,6 +700,36 @@ class BxDolWiki extends BxDolFactory implements iBxDolFactoryObject
         }
     }
 
+    public function actionConvertLinks ()
+    {
+        $s = bx_get('s');
+        if (!$s)
+            return ['s' => ''];
+
+        // convert links to be viewable in external editor
+        $s = preg_replace_callback('#\((([a-zA-Z0-9_]+)/([a-zA-Z0-9]+))\)#', function ($aMatches) {
+            $oStorage = BxDolStorage::getObjectInstance($aMatches[2]);
+            if ($oStorage) {
+                $sUrl = $oStorage->getFileUrlByRemoteId($aMatches[3]);
+                if ($sUrl)
+                    return '(' . $sUrl . ')';
+            }
+
+            return '(' . $aMatches[0] . ')';
+        }, $s);
+
+        // add references to existing pages, so short references will work in external editor
+        $s .= "\n<!-- " . _t("_sys_wiki_external_editor_references_comment") . " -->\n";
+
+        $this->_aPages = BxDolWikiQuery::getAllPages ();
+        if ($this->_aPages) {
+            foreach ($this->_aPages as $sUri => $r)
+                $s .= "[{$sUri}]: " . BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink($r['url']) . "\n";
+        }        
+
+        return ['s' => $s];
+    }
+
     protected function updateBlockIndexingData($iBlockId)
     {
         if (!($aLangs = $this->_oQuery->getBlockLangs ($iBlockId)))
@@ -800,6 +836,46 @@ class BxDolWiki extends BxDolFactory implements iBxDolFactoryObject
 
 class BxDolParsedown extends Parsedown
 {
+    protected $_aPages;
+
+    protected function textElements($text)
+    {
+        $res = parent::textElements($text);
+
+        // add all available pages as references
+        $this->_aPages = BxDolWikiQuery::getAllPages ();
+        if ($this->_aPages) {
+            foreach ($this->_aPages as $sUri => $r) {
+                $aData = array(
+                    // real link URL is set later when link is referenced
+                    'url' => 'bx-internal-page://' . $sUri, 
+                    'title' => !empty($r['title']) ? _t($r['title']) : null,
+                );
+                $this->DefinitionData['Reference'][$sUri] = $aData;
+            }
+        }
+
+        return $res;
+    }
+
+    protected function inlineLink($Excerpt)
+    {
+        $a = parent::inlineLink($Excerpt);
+
+        if (@isset($a['element']['attributes']['href']) && 0 === strncmp($a['element']['attributes']['href'], 'bx-internal-page://', 19)) {
+            $sUri = substr($a['element']['attributes']['href'], 19);
+            if (isset($this->_aPages[$sUri])) {
+                $sHref = BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink($this->_aPages[$sUri]['url']);
+                $a['element']['attributes']['href'] = $sHref;
+            }
+            else {
+                $a['element']['attributes']['href'] = $sUri;
+            }
+        }
+
+        return $a;
+    }
+
     protected function inlineImage($Excerpt)
     {
         $a = parent::inlineImage($Excerpt);

+ 6 - 0
inc/classes/BxDolWikiQuery.php

@@ -42,6 +42,12 @@ class BxDolWikiQuery extends BxDolDb
         return $aObject;
     }
 
+    static public function getAllPages ()
+    {
+        $sQuery = "SELECT `uri`, `title`, `url` FROM `sys_objects_page` WHERE `url` != '' ORDER BY `uri`";
+        return BxDolDb::getInstance()->getAllWithKey($sQuery, 'uri');
+    }
+
     /**
      * Get wiki block
      * @param $iBlockId block ID

+ 42 - 1
inc/js/classes/BxDolWiki.js

@@ -209,7 +209,7 @@ function bx_wiki_remove_img (sEditorId, sImgUrl, sImgName) {
         return;
 
     var sImg = "![IMGNAMEHERE](" + sImgUrl + ")";
-    sImg = sImg.replace(/[|\\{}()[\]^$+*?.]/mg, '\\$&').replace(/-/mg, '\\x2d'); // escape special chars
+    sImg = bx_regexp_escape(sImg);
     sImg = sImg.replace(/IMGNAMEHERE/, '(.*?)');
 
     var re = new RegExp(sImg, 'gm');
@@ -218,5 +218,46 @@ function bx_wiki_remove_img (sEditorId, sImgUrl, sImgName) {
     $(sEditorId).val(sVal);
 }
 
+function bx_wiki_open_editor(sSel, bBackground) {
+    const e = $(sSel).size() ? $(sSel)[0] : false;
+    if (!e)
+        return;
+
+    bx_wiki_open_editor_convert_links(e.value, function (s) {
+        // Open the iframe
+        const oStackedit = new Stackedit();
+        oStackedit.openFile({
+            content: {
+                text: s // and the Markdown content.
+            }
+        }, 'undefined' === typeof(bBackground) ? false : bBackground);
+
+        // Listen to StackEdit events and apply the changes to the textarea.
+        oStackedit.on('fileChange', (file) => {
+            e.value = bx_wiki_open_editor_convert_links_back(file.content.text);
+        });
+    });
+}
+
+function bx_wiki_open_editor_convert_links(s, onSuccess) {
+    var sActionUrl = sUrlRoot + 'r.php?_q=wiki-action/';
+    $.post(sActionUrl + 'convert-links', {s: s}, function (oData) {
+        if ('undefined' !== typeof(oData.s))
+            onSuccess(oData.s);
+    }, 'json');
+}
+
+function bx_wiki_open_editor_convert_links_back(s) {
+    
+    var re = new RegExp('\\\(' + bx_regexp_escape(sUrlRoot) + 's/([a-zA-Z0-9_]+)/([a-zA-Z0-9]+)[^\\\)]*\\\)', 'gm');
+    s = s.replace(re, "($1/$2)");
+
+    var sRefs = '<!-- ' + $('<textarea />').html(_t('_sys_wiki_external_editor_references_comment')).text() + ' -->';
+    var i = s.indexOf(sRefs);
+    if (-1 !== i)
+        s = s.substring(0, i);
+
+    return s;
+}
 
 /** @} */

+ 7 - 0
inc/js/functions.js

@@ -1295,4 +1295,11 @@ function bx_copy_to_clipboard(s, onSuccess, onFail)
     }
 }
 
+function bx_regexp_escape(s) 
+{
+    return s
+        .replace(/[|\\{}()[\]^$+*?.]/mg, '\\$&')
+        .replace(/-/mg, '\\x2d');
+}
+
 /** @} */

+ 2 - 0
modules/boonex/english/data/langs/system/en.xml

@@ -3538,6 +3538,8 @@ If it is not enabled then please consider implement this optimization, since it
     <string name="_sys_wiki_title_time"><![CDATA[{0} updated]]></string>
     <string name="_sys_wiki_orig"><![CDATA[Orig.]]></string>
     <string name="_sys_wiki_copy"><![CDATA[Copy to clipboard]]></string>
+    <string name="_sys_wiki_open_in_editor"><![CDATA[Open in editor]]></string>
+    <string name="_sys_wiki_external_editor_references_comment"><![CDATA[NOTE: don't modify this comment and lines below]]></string>
 
 	<string name="_adm_lmi_cpt_groups_roles"><![CDATA[Roles]]></string>
 	<string name="_adm_form_txt_groups_roles_add_popup"><![CDATA[Create role]]></string>

+ 2 - 0
modules/boonex/russian/data/langs/system/ru.xml

@@ -3503,6 +3503,8 @@
     <string name="_sys_wiki_title_time"><![CDATA[{0} обновлен]]></string>
     <string name="_sys_wiki_orig"><![CDATA[Ориг.]]></string>
     <string name="_sys_wiki_copy"><![CDATA[Копировать в буфер обмена]]></string>
+    <string name="_sys_wiki_open_in_editor"><![CDATA[Открыть в редакторе]]></string>
+    <string name="_sys_wiki_external_editor_references_comment"><![CDATA[ВНИМАНИЕ: не меняйте это сообщение и строки ниже]]></string>
 
 	<string name="_adm_lmi_cpt_groups_roles"><![CDATA[Роли]]></string>
 	<string name="_adm_form_txt_groups_roles_add_popup"><![CDATA[Создать роль]]></string>

+ 8 - 1
template/css/wiki.css

@@ -92,4 +92,11 @@
   display: inline-block;
   margin-right: 0.4rem;
 }
-
+.bx-wiki-open-editor {
+    position: absolute;
+    top: -1.5rem;
+    right: 0;
+}
+html .stackedit-container {
+    z-index:99999;
+}

+ 1 - 0
template/scripts/BxBaseServiceWiki.php

@@ -220,6 +220,7 @@ class BxBaseServiceWiki extends BxDol
         $o = BxDolTemplate::getInstance();
         $o->addCss('wiki.css');
         $o->addJs('BxDolWiki.js');
+        $o->addJsTranslation('_sys_wiki_external_editor_references_comment');
         if ($bAddPage)
             $o->addJs('studio/js/|forms.js');
         $this->_bJsCssAdded = true;

+ 2 - 0
template/wiki_form.html

@@ -24,5 +24,7 @@
             window.glBxDolWiki__block_id__.onChangeLangSelector(this);
             return false;
         });
+
+        $('#bx-wiki-form-__block_id__ textarea').parents('.bx-form-input-wrapper').append('<div class="bx-wiki-open-editor"><a href="javascript:void(0);" onclick="bx_wiki_open_editor(\'#bx-wiki-form-__block_id__ textarea\')">__txt_open_editor__</a></div>');
     });
 </script>