<commit_before>"use strict";

/**
 * hvScriptSet
 * Version: 1.0.9
 * Author: Человек-Шаман
 * license: MIT
 *
 * Что нового:
 * 1. Исправлен баг многострочной маски
 * 2. Поправлена работа маски со скриптом рамки
 * 3. Стили маски изменены на уникальные
 * 4. Исправлены баги работы скрипта в теге code
 */

let hvScriptSet = {

    addMask: function (opt) {
        let changeList = {
            'author': {
                title: 'Ник',
                description: 'Только текст',
                tag: 'nick,nic',
                class: 'pa-author',
                type: 'link'
            },
            'title': {
                title: 'Статус',
                description: 'Только текст',
                tag: 'status,sta',
                class: 'pa-title',
                type: 'text'
            },
            'avatar': {
                title: 'Аватар',
                description: 'Прямая ссылка на картинку формата jpg, gif или png',
                tag: 'icon,ava',
                class: 'pa-avatar',
                type: 'avatar'
            },
            'signature': {
                title: 'Подпись',
                description: 'Принимает bb-коды, кроме таблицы',
                tag: 'sign,sgn',
                class: 'post-sig',
                type: 'signature'
            }
        };
        if (opt.changeList) {
            for (let key in opt.changeList) {
                if (opt.changeList.hasOwnProperty(key)) {
                    if (changeList[key]) {
                        for (let i in changeList[key]) {
                            if (opt.changeList[key][i]) {
                                changeList[key][i] = opt.changeList[key][i];
                            }
                        }
                    } else {
                        changeList[key] = opt.changeList[key];
                        if (!opt.changeList[key].type) {
                            changeList[key].type = 'html';
                        }
                    }
                }
            }
        }

        let tmpMask = {};
        let previewForm = {};
        let errorList = {};

        let userFields = opt.userFields ? opt.userFields : ['pa-author', 'pa-title', 'pa-avatar', 'pa-fld1', 'pa-reg',
            'pa-posts', 'pa-respect', 'pa-positive', 'pa-awards', 'pa-gifts'];
        let allTagsList = getTagList();

        let defaultAvatar = opt.defaultAvatar || 'http://i.imgur.com/bQuC3S1.png';

        let prevMasks = getStorageMask() !== '' ? getStorageMask().split('|splitKey|') : [];

        let posts = [];

        function getPosts() {
            posts = document.querySelectorAll('.post');
            let changedPosts = {};
            let changedUsersId = [];
            for (let i = 0; i < posts.length; i++) {
                let postEl = posts[i].querySelector('.post-content');
                let postId = posts[i].getAttribute('id');
                let postProfile = posts[i].querySelector('.post-author ul');
                let postText = postEl.innerHTML;
                let postSignature = posts[i].querySelector('.post-sig dd');
                let postChangeList = getTags(postText);

                let userId = '1';
                let postUserNameLink = postProfile.querySelector('.pa-author a');

                if (postUserNameLink) {
                    if (postUserNameLink.href.indexOf('/profile.php') + 1) {
                        userId = postUserNameLink.href.split('=')[1];
                    } else {
                        let postProfileLinks = posts[i].querySelector('.post-links');
                        let postProfileUserLink = postProfileLinks.querySelector('a[href*="/profile.php"]');
                        userId = postProfileUserLink.href.split('=')[1];
                    }
                }

                if (Object.keys(postChangeList).length !== 0) {
                    changedPosts[i] = {
                        postId: postId,
                        userId: userId,
                        text: postEl,
                        clearedText: getClearedPost(postEl, postChangeList),
                        profile: postProfile,
                        changeList: postChangeList,
                        signature: postSignature
                    };
                    if (!(changedUsersId.indexOf(userId) + 1)) {
                        changedUsersId.push(userId);
                    }
                }
            }
            let checkAccess = changedUsersId.length > 0 ? getAccess(changedUsersId) : {};
            for (let _i in changedPosts) {
                if (changedPosts.hasOwnProperty(_i)) {
                    changedPosts[_i].username = checkAccess[changedPosts[_i].userId].username;
                    changedPosts[_i].groupId = checkAccess[changedPosts[_i].userId].groupId;
                    changedPosts[_i].groupTitle = checkAccess[changedPosts[_i].userId].groupTitle;
                    changedPosts[_i].access = checkAccess[changedPosts[_i].userId].access;

                    if (changedPosts[_i].changeList.avatar && changedPosts[_i].access.common) {
                        if (!changedPosts[_i].profile.querySelector('.pa-avatar img')) {
                            let fieldIndex = userFields.indexOf('pa-avatar');
                            let block = document.createElement('li');
                            block.className = 'pa-avatar';
                            block.innerHTML = `<img src="" title="${changedPosts[_i].username}">`;
                            for (let index = ++fieldIndex; index <= userFields.length; index++) {
                                let nextSibling = changedPosts[_i].profile.querySelector('.' + userFields[index]);
                                if (nextSibling) {
                                    let parent = nextSibling.parentNode;
                                    parent.insertBefore(block, nextSibling);
                                    break;
                                }
                                if (index === userFields.length) {
                                    changedPosts[_i].profile.appendChild(block);
                                }
                            }
                        }
                        let avatar = changedPosts[_i].profile.querySelector(`.pa-avatar img[title='${changedPosts[_i].username}']`);
                        avatar.src = changedPosts[_i].changeList.avatar.content;
                        avatar.removeAttribute('width');
                        avatar.removeAttribute('height');
                    }
                }
                if (changedPosts.hasOwnProperty(_i) && changedPosts[_i].access.extended) {
                    let thisChanges = changedPosts[_i].changeList;
                    for (let change in thisChanges) {
                        if (thisChanges.hasOwnProperty(change)) {
                            if (thisChanges[change].field === 'pa-author' && changedPosts[_i].userId === '1') {
                                changedPosts[_i].changeList[change].type = 'text';
                            }
                            if (!changedPosts[_i].profile.getElementsByClassName(changedPosts[_i]
                                    .changeList[change].field)[0]) {
                                let _fieldIndex = userFields.indexOf(changedPosts[_i].changeList[change].field);
                                let _block = document.createElement('li');
                                _block.className = thisChanges[change].field;
                                for (let _index = ++_fieldIndex; _index <= userFields.length; _index++) {
                                    let _nextSibling = changedPosts[_i].profile.querySelector('.' + userFields[_index]);
                                    if (_nextSibling) {
                                        let parent = _nextSibling.parentNode;
                                        parent.insertBefore(_block, _nextSibling);
                                        break;
                                    }
                                    if (_index === userFields.length) {
                                        changedPosts[_i].profile.appendChild(_block);
                                    }
                                }
                            }
                            let fieldEl = changedPosts[_i].profile.getElementsByClassName(changedPosts[_i]
                                .changeList[change].field)[0];
                            switch (changedPosts[_i].changeList[change].type) {
                                case 'html':
                                    let content = strToHtml(changedPosts[_i].changeList[change].content);
                                    if (content === '') {
                                        console.error(`Что-то не так с маской в посте #${changedPosts[_i].postId}`);
                                        if (GroupID === 1 || GroupID === 2) {
                                            let errorMess = document.getElementById('admin_msg1');
                                            errorMess.innerHTML = `Что-то не так с маской в посте #${changedPosts[_i].postId}. Он подсвечен красным.<br><i>Сообщение показано только администрации.</i>`;
                                            errorMess.style.display = 'block';
                                            errorMess.style.zIndex = 10000;
                                            document.getElementById(changedPosts[_i].postId)
                                                .style.border = 'solid 1px #f00';
                                        }
                                    }
                                    fieldEl.innerHTML = content.length > 999 ? content.slice(0, 999) : content;
                                    break;
                                case 'bbcode':
                                    let __content = changedPosts[_i].changeList[change].content;
                                    fieldEl.innerHTML = __content.length > 999 ? __content.slice(0, 999) : __content;
                                    break;
                                case 'text':
                                    let _content = changedPosts[_i].changeList[change].content
                                        .replace(/</i, '&lt').replace(/>/i, '&rt');
                                    switch (change) {
                                        case 'author':
                                            fieldEl.innerHTML = _content.length > 25 ? _content.slice(0, 25) : _content;
                                            break;
                                        case 'title':
                                            fieldEl.innerHTML = _content.length > 50 ? _content.slice(0, 50) : _content;
                                            break;
                                        default:
                                            fieldEl.innerHTML = _content.length > 999 ? _content.slice(0, 999) : _content;
                                    }
                                    break;
                                case 'link':
                                    fieldEl.querySelector('a').innerText =
                                        changedPosts[_i].changeList[change].content.length > 25 ?
                                            changedPosts[_i].changeList[change].content.slice(0, 25) :
                                            changedPosts[_i].changeList[change].content;
                                    break;
                                case 'signature':
                                    if (GroupID !== '3') {
                                        if (!changedPosts[_i].signature) {
                                            let signEl = document.createElement('dl');
                                            signEl.className = 'post-sig';
                                            signEl.innerHTML = `
                        <dl class="post-sig">
                          <dt>
                            <span>Подпись автора</span>
                          </dt>
                          <dd></dd>
                        </dl>`;
                                            changedPosts[_i].text.appendChild(signEl);
                                            changedPosts[_i].signature = signEl.querySelector('.post-sig dd');
                                        }
                                        changedPosts[_i].signature.innerHTML = changedPosts[_i].changeList[change].content;
                                    }
                                    break;
                            }
                        }
                    }
                }
                let sign = changedPosts[_i].text.innerHTML.match(/<dl class="post-sig">([\s\S]*?)?<\/dl>/);
                changedPosts[_i].profile.classList.add('hv-mask');
                changedPosts[_i].text.innerHTML = changedPosts[_i].clearedText + (sign ? sign[0] : '');
            }
        }

        function hideTags() {
            posts = document.querySelectorAll('.post');
            for (let i in posts) {
                if (posts.hasOwnProperty(i)) {
                    let text = posts[i].querySelector('.post-content');
                    for (let tag in allTagsList) {
                        if (allTagsList.hasOwnProperty(tag)) {
                            let pattern =
                                new RegExp('\\[' + allTagsList[tag] + '\\](.*?)\\[\/' + allTagsList[tag] + '\\]', 'gi');
                            text.innerHTML = text.innerHTML.replace(pattern, '');
                        }
                    }
                }
            }
        }

        function hidePreviewTags() {
            let text = document.querySelector('.post-content');
            if (!text) return;
            for (let tag in allTagsList) {
                if (allTagsList.hasOwnProperty(tag)) {
                    let pattern =
                        new RegExp('\\[' + allTagsList[tag] + '\\](.*?)\\[\/' + allTagsList[tag] + '\\]', 'gi');
                    text.innerHTML = text.innerHTML.replace(pattern, '');
                }
            }
        }

        function getTags(text) {
            let postChangeList = {};
            let clearedText = text.replace(/<div class="code-box"><strong class="legend">Код:<\/strong><div class="blockcode"><div class="scrollbox" style="(?:.*?)"><pre>([\s\S]*?)?<\/pre><\/div><\/div><\/div>/gi, '');
            for (let field in changeList) {
                if (changeList.hasOwnProperty(field)) {
                    let tags = changeList[field].tag.split(',');
                    for (let i = tags.length; i >= 0; i--) {
                        if (tags.hasOwnProperty(i)) {
                            let pattern = new RegExp('\\[' + tags[i] + '\\]([\\s\\S]*?)\\[\\/' + tags[i] + '\\]', 'gmi');
                            let clearPattern = new RegExp('\\[(\\/?)' + tags[i] + '\\]', 'gmi');
                            if (clearedText.match(pattern)) {
                                postChangeList[field] = {
                                    'tag': tags[i],
                                    'field': changeList[field].class,
                                    'content': text.match(pattern)[0].replace(clearPattern, ''),
                                    'type': changeList[field].type
                                };
                            }
                        }
                    }
                }
            }
            return postChangeList;
        }

        function getTagList() {
            let tagList = [];
            for (let field in changeList) {
                if (changeList.hasOwnProperty(field)) {
                    let tags = changeList[field].tag.split(',');
                    for (let i in tags) {
                        if (tags.hasOwnProperty(i) && !tagList.indexOf(tags[i]) + 1) {
                            tagList.push(tags[i]);
                        }
                    }
                }
            }
            return tagList;
        }

        function getAccess(usersId) {
            let userInfo = getUsersInfo(usersId);
            for (let id in userInfo) {
                if (userInfo.hasOwnProperty(id)) {
                    switch (userInfo[id].groupId) {
                        case '1':
                        case '2':
                            userInfo[id].access = {
                                'common': true,
                                'extended': true
                            };
                            break;
                        case '3':
                            userInfo[id].access = {
                                'common': opt.guestAccess ?
                                    Boolean(opt.guestAccess.indexOf(FORUM.topic.forum_name) + 1) : false,
                                'extended': opt.guestAccess ?
                                    Boolean(opt.guestAccess.indexOf(FORUM.topic.forum_name) + 1) : false
                            };
                            break;
                        default:
                            userInfo[id].access = {
                                'common': opt.forumAccess && opt.forumAccess[FORUM.topic.forum_name] ?
                                    Boolean(opt.forumAccess[FORUM.topic.forum_name].indexOf(userInfo[id].groupTitle) + 1) :
                                    true,
                                'extended': opt.forumAccessExtended && opt.forumAccessExtended[FORUM.topic.forum_name] ?
                                    Boolean(opt.forumAccessExtended[FORUM.topic.forum_name]
                                            .indexOf(userInfo[id].groupTitle) + 1) : false
                            };
                    }
                }
            }
            return userInfo;
        }

        function getUsersInfo(usersId) {
            let usersIdStr = usersId.join(',');
            let usersInfo = {};
            if (usersId.indexOf('1') + 1) {
                usersInfo['1'] = {
                    'userId': '1',
                    'username': 'Guest',
                    'groupId': '3',
                    'groupTitle': 'Гость'
                };
            }
            $.ajax({
                async: false,
                url: '/api.php',
                data: {
                    method: 'users.get',
                    user_id: usersIdStr
                },
                success: function success(json) {
                    for (let i in json.response.users) {
                        if (json.response.users.hasOwnProperty(i)) {
                            usersInfo[json.response.users[i].user_id] = {
                                'userId': i,
                                'username': json.response.users[i].username,
                                'groupId': json.response.users[i].group_id,
                                'groupTitle': json.response.users[i].group_title
                            };
                        }
                    }
                }
            });

            return usersInfo;
        }

        function getDialog() {
            let maskButton = addButton();
            if (maskButton) {
                if (checkAccessExtended() || getAccessByForumName() === 'extended') {
                    maskButton.addEventListener('click', (event) => {
                        if (event.ctrlKey || event.metaKey) {
                            insertAvatarTags();
                        } else {
                            callMaskDialog();
                        }
                    });
                } else {
                    maskButton.addEventListener('click', insertAvatarTags);
                }
            }
            let maskDialog = buildMaskDialog();
            let main = document.querySelector('#pun-main');
            main.appendChild(maskDialog);

            getStyle();
        }

        function getStyle() {
            let style = document.createElement('style');
            style.innerHTML = `#mask_dialog .hv-bg {
                position: fixed;
                display: flex;
                align-content: center;
                justify-content: center;
                align-items: center;
                z-index: 10;
                width: 100%;
                height: 100%;
                left: 0;
                top: 0;
                background: rgba(0, 0, 0, .4);
                cursor: pointer;
            }
            
            #mask_dialog .inner {
                cursor: default;
                margin: 0;
                width: 760px;
                max-width: 99%;
                max-height: 90%;
                overflow-x: auto;
                z-index: 100;
                box-shadow: 0 0 40px #222;
                background: #F4F5F6 url("http://i.imgur.com/akmlat3.png");
                padding: 8px;
            }
            
            #mask_dialog .inner * {
                box-sizing: border-box;
            }
            
            #mask_dialog .inner .hv-mask-dialog-title {
                text-align: center;
                font-weight: 700;
                font-size: 18px;
                line-height: 34px;
                position: relative;
            }
            
            #mask_dialog .inner .hv-error-list {
                padding: 8px;
                margin: 8px;
                background: #DAA396;
                color: #BD0909;
                border: solid 1px;
            }
            
            #mask_dialog .inner .hv-mask-block {
                display: flex;
                justify-content: space-between;
                align-items: stretch;
            }
            
            #mask_dialog .inner .hv-mask-block .hv-preview-block {
                flex: 0 0 120px;
                text-align: center;
                max-width: 120px;
                overflow: hidden;
                word-break: break-word;
            }
            
            #mask_dialog .inner .hv-mask-block .hv-preview-block > div {
                padding: 3px 0;
            }
            
            #mask_dialog .inner .hv-mask-block .hv-form-block {
                flex: 1 1 auto;
            }
            
            #mask_dialog .inner .hv-mask-block .hv-preview-block .hv-preview-avatar img {
                max-width: 100px;
            }
            
            #mask_dialog .inner .hv-mask-block .hv-form-block {
                flex: 1 1 auto;
            }
            
            #mask_dialog .inner .hv-mask-block .hv-form-block label {
                display: block;
                margin-bottom: px;
            }
            
            #mask_dialog .inner .hv-mask-block .hv-form-block label:after {
                content: "";
                display: table;
                clear: both;
                margin-bottom: 2px;
            }
            
            #mask_dialog .inner .hv-mask-block .hv-form-block .hv-description {
                font-size: .9em;
                color: #999;
                font-style: italic;
            }
            
            #mask_dialog .inner .hv-mask-block .hv-form-block .hv-add-template {
                cursor: pointer;
                float: right;
                padding: 2px 4px;
                border: solid 1px #ccc;
            }
            
            #mask_dialog .inner .hv-mask-block .hv-form-block input,
            #mask_dialog .inner .hv-mask-block .hv-form-block textarea {
                width: 100%;
            }
            
            #mask_dialog .inner .hv-mask-block .hv-form-block .hv-mask-field {
                position: relative;
            }
            
            #mask_dialog .inner .hv-mask-block .hv-form-block .hv-mask-field + .hv-mask-field {
                margin-top: 10px;
            }
            
            #mask_dialog .inner .hv-masks-storage {
                flex: 0 1 140px;
                display: flex;
                align-items: flex-start;
                align-content: flex-start;
                justify-content: flex-start;
                padding: 8px;
                flex-wrap: wrap;
                list-style: none;
            }
            
            #mask_dialog .inner .hv-masks-storage.hidden {
                display: none;
            }
            
            #mask_dialog .inner .hv-masks-storage .hv-mask-element {
                width: 60px;
                padding: 4px;
                position: relative;
            }
            
            #mask_dialog .inner .hv-masks-storage .hv-mask-element img {
                max-width: 100%;
                cursor: pointer;
            }
            
            #mask_dialog .inner .hv-masks-storage .hv-mask-element .hv-mask-tooltip {
                position: absolute;
                top: 4px;
                min-width: 160px;
                right: 60px;
                padding: 4px;
                z-index: 5;
                overflow-y: auto;
                background: rgba(255, 255, 255, .6);
                border: solid 1px #ccc;
                display: none;
            }
            
            #mask_dialog .inner .hv-masks-storage .hv-mask-element > img:hover + .hv-mask-tooltip {
                display: block;
            }
            
            #mask_dialog .inner .hv-masks-storage .hv-mask-element .hv-mask-tooltip > * {
                zoom: .7
            }
            
            #mask_dialog .inner .hv-masks-storage .hv-mask-element .hv-delete-mask {
                display: block;
                font-size: 10px;
                text-align: center;
                cursor: pointer;
            }
            
            #mask_dialog .inner .hv-control {
                padding: 8px;
                text-align: center;
                position: relative;
            }
            
            #mask_dialog .inner .hv-control input + input {
                margin-left: 10px;
            }
            
            #mask_dialog .inner .hv-control .hv-clear-storage {
                position: absolute;
                right: 0;
                bottom: 0;
                color: #666;
                cursor: pointer;
            }`;

            let docstyle = document.head.querySelector('link[href*="style"]');
            document.head.insertBefore(style, docstyle);
        }

        function insertAvatarTags() {
            bbcode('[icon]', '[/icon]');
        }
<commit_msg>1.0.9 fix<commit_after>"use strict";

/**
 * hvScriptSet
 * Version: 1.0.9
 * Author: Человек-Шаман
 * license: MIT
 *
 * Что нового:
 * 1. Исправлен баг многострочной маски
 * 2. Поправлена работа маски со скриптом рамки
 * 3. Стили маски изменены на уникальные
 * 4. Исправлены баги работы скрипта в теге code
 * 5. Исправлен баг в темах с удалённым создателем
 */

let hvScriptSet = {

    addMask: function (opt) {
        let changeList = {
            'author': {
                title: 'Ник',
                description: 'Только текст',
                tag: 'nick,nic',
                class: 'pa-author',
                type: 'link'
            },
            'title': {
                title: 'Статус',
                description: 'Только текст',
                tag: 'status,sta',
                class: 'pa-title',
                type: 'text'
            },
            'avatar': {
                title: 'Аватар',
                description: 'Прямая ссылка на картинку формата jpg, gif или png',
                tag: 'icon,ava',
                class: 'pa-avatar',
                type: 'avatar'
            },
            'signature': {
                title: 'Подпись',
                description: 'Принимает bb-коды, кроме таблицы',
                tag: 'sign,sgn',
                class: 'post-sig',
                type: 'signature'
            }
        };
        if (opt.changeList) {
            for (let key in opt.changeList) {
                if (opt.changeList.hasOwnProperty(key)) {
                    if (changeList[key]) {
                        for (let i in changeList[key]) {
                            if (opt.changeList[key][i]) {
                                changeList[key][i] = opt.changeList[key][i];
                            }
                        }
                    } else {
                        changeList[key] = opt.changeList[key];
                        if (!opt.changeList[key].type) {
                            changeList[key].type = 'html';
                        }
                    }
                }
            }
        }

        let tmpMask = {};
        let previewForm = {};
        let errorList = {};

        let userFields = opt.userFields ? opt.userFields : ['pa-author', 'pa-title', 'pa-avatar', 'pa-fld1', 'pa-reg',
            'pa-posts', 'pa-respect', 'pa-positive', 'pa-awards', 'pa-gifts'];
        let allTagsList = getTagList();

        let defaultAvatar = opt.defaultAvatar || 'http://i.imgur.com/bQuC3S1.png';

        let prevMasks = getStorageMask() !== '' ? getStorageMask().split('|splitKey|') : [];

        let posts = [];

        function getPosts() {
            posts = document.querySelectorAll('.post');
            let changedPosts = {};
            let changedUsersId = [];
            for (let i = 0; i < posts.length; i++) {
                let postEl = posts[i].querySelector('.post-content');
                let postId = posts[i].getAttribute('id');
                let postProfile = posts[i].querySelector('.post-author ul');
                let postText = postEl.innerHTML;
                let postSignature = posts[i].querySelector('.post-sig dd');
                let postChangeList = getTags(postText);

                let userId = '1';
                let postUserNameLink = postProfile.querySelector('.pa-author a');

                if (postUserNameLink) {
                    if (postUserNameLink.href.indexOf('/profile.php') + 1) {
                        userId = postUserNameLink.href.split('=')[1];
                    } else {
                        let postProfileLinks = posts[i].querySelector('.post-links');
                        let postProfileUserLink = postProfileLinks.querySelector('a[href*="/profile.php"]');
                        userId = postProfileUserLink.href.split('=')[1];
                    }
                }

                if (Object.keys(postChangeList).length !== 0) {
                    changedPosts[i] = {
                        postId: postId,
                        userId: userId,
                        text: postEl,
                        clearedText: getClearedPost(postEl, postChangeList),
                        profile: postProfile,
                        changeList: postChangeList,
                        signature: postSignature
                    };
                    if (!(changedUsersId.indexOf(userId) + 1)) {
                        changedUsersId.push(userId);
                    }
                }
            }
            let checkAccess = changedUsersId.length > 0 ? getAccess(changedUsersId) : {};
            for (let _i in changedPosts) {
                if (changedPosts.hasOwnProperty(_i)) {
                    changedPosts[_i].username = checkAccess[changedPosts[_i].userId].username;
                    changedPosts[_i].groupId = checkAccess[changedPosts[_i].userId].groupId;
                    changedPosts[_i].groupTitle = checkAccess[changedPosts[_i].userId].groupTitle;
                    changedPosts[_i].access = checkAccess[changedPosts[_i].userId].access;

                    if (changedPosts[_i].changeList.avatar && changedPosts[_i].access.common) {
                        if (!changedPosts[_i].profile.querySelector('.pa-avatar img')) {
                            let fieldIndex = userFields.indexOf('pa-avatar');
                            let block = document.createElement('li');
                            block.className = 'pa-avatar';
                            block.innerHTML = `<img src="" title="${changedPosts[_i].username}">`;
                            for (let index = ++fieldIndex; index <= userFields.length; index++) {
                                let nextSibling = changedPosts[_i].profile.querySelector('.' + userFields[index]);
                                if (nextSibling) {
                                    let parent = nextSibling.parentNode;
                                    parent.insertBefore(block, nextSibling);
                                    break;
                                }
                                if (index === userFields.length) {
                                    changedPosts[_i].profile.appendChild(block);
                                }
                            }
                        }
                        let avatar = changedPosts[_i].profile.querySelector(`.pa-avatar img[title='${changedPosts[_i].username}']`);
                        avatar.src = changedPosts[_i].changeList.avatar.content;
                        avatar.removeAttribute('width');
                        avatar.removeAttribute('height');
                    }
                }
                if (changedPosts.hasOwnProperty(_i) && changedPosts[_i].access.extended) {
                    let thisChanges = changedPosts[_i].changeList;
                    for (let change in thisChanges) {
                        if (thisChanges.hasOwnProperty(change)) {
                            if (thisChanges[change].field === 'pa-author' && changedPosts[_i].userId === '1') {
                                changedPosts[_i].changeList[change].type = 'text';
                            }
                            if (!changedPosts[_i].profile.getElementsByClassName(changedPosts[_i]
                                    .changeList[change].field)[0]) {
                                let _fieldIndex = userFields.indexOf(changedPosts[_i].changeList[change].field);
                                let _block = document.createElement('li');
                                _block.className = thisChanges[change].field;
                                for (let _index = ++_fieldIndex; _index <= userFields.length; _index++) {
                                    let _nextSibling = changedPosts[_i].profile.querySelector('.' + userFields[_index]);
                                    if (_nextSibling) {
                                        let parent = _nextSibling.parentNode;
                                        parent.insertBefore(_block, _nextSibling);
                                        break;
                                    }
                                    if (_index === userFields.length) {
                                        changedPosts[_i].profile.appendChild(_block);
                                    }
                                }
                            }
                            let fieldEl = changedPosts[_i].profile.getElementsByClassName(changedPosts[_i]
                                .changeList[change].field)[0];
                            switch (changedPosts[_i].changeList[change].type) {
                                case 'html':
                                    let content = strToHtml(changedPosts[_i].changeList[change].content);
                                    if (content === '') {
                                        console.error(`Что-то не так с маской в посте #${changedPosts[_i].postId}`);
                                        if (GroupID === 1 || GroupID === 2) {
                                            let errorMess = document.getElementById('admin_msg1');
                                            errorMess.innerHTML = `Что-то не так с маской в посте #${changedPosts[_i].postId}. Он подсвечен красным.<br><i>Сообщение показано только администрации.</i>`;
                                            errorMess.style.display = 'block';
                                            errorMess.style.zIndex = 10000;
                                            document.getElementById(changedPosts[_i].postId)
                                                .style.border = 'solid 1px #f00';
                                        }
                                    }
                                    fieldEl.innerHTML = content.length > 999 ? content.slice(0, 999) : content;
                                    break;
                                case 'bbcode':
                                    let __content = changedPosts[_i].changeList[change].content;
                                    fieldEl.innerHTML = __content.length > 999 ? __content.slice(0, 999) : __content;
                                    break;
                                case 'text':
                                    let _content = changedPosts[_i].changeList[change].content
                                        .replace(/</i, '&lt').replace(/>/i, '&rt');
                                    switch (change) {
                                        case 'author':
                                            fieldEl.innerHTML = _content.length > 25 ? _content.slice(0, 25) : _content;
                                            break;
                                        case 'title':
                                            fieldEl.innerHTML = _content.length > 50 ? _content.slice(0, 50) : _content;
                                            break;
                                        default:
                                            fieldEl.innerHTML = _content.length > 999 ? _content.slice(0, 999) : _content;
                                    }
                                    break;
                                case 'link':
                                    fieldEl.querySelector('a').innerText =
                                        changedPosts[_i].changeList[change].content.length > 25 ?
                                            changedPosts[_i].changeList[change].content.slice(0, 25) :
                                            changedPosts[_i].changeList[change].content;
                                    break;
                                case 'signature':
                                    if (GroupID !== '3') {
                                        if (!changedPosts[_i].signature) {
                                            let signEl = document.createElement('dl');
                                            signEl.className = 'post-sig';
                                            signEl.innerHTML = `
                                                <dl class="post-sig">
                                                  <dt>
                                                    <span>Подпись автора</span>
                                                  </dt>
                                                  <dd></dd>
                                                </dl>`;
                                            changedPosts[_i].text.appendChild(signEl);
                                            changedPosts[_i].signature = signEl.querySelector('.post-sig dd');
                                        }
                                        changedPosts[_i].signature.innerHTML = changedPosts[_i].changeList[change].content;
                                    }
                                    break;
                            }
                        }
                    }
                }
                let sign = changedPosts[_i].text.innerHTML.match(/<dl class="post-sig">([\s\S]*?)?<\/dl>/);
                changedPosts[_i].profile.classList.add('hv-mask');
                changedPosts[_i].text.innerHTML = changedPosts[_i].clearedText + (sign ? sign[0] : '');
            }
        }

        function hideTags() {
            posts = document.querySelectorAll('.post');
            for (let i in posts) {
                if (posts.hasOwnProperty(i)) {
                    let text = posts[i].querySelector('.post-content');
                    for (let tag in allTagsList) {
                        if (allTagsList.hasOwnProperty(tag)) {
                            let pattern =
                                new RegExp('\\[' + allTagsList[tag] + '\\](.*?)\\[\/' + allTagsList[tag] + '\\]', 'gi');
                            text.innerHTML = text.innerHTML.replace(pattern, '');
                        }
                    }
                }
            }
        }

        function hidePreviewTags() {
            let text = document.querySelector('.post-content');
            if (!text) return;
            for (let tag in allTagsList) {
                if (allTagsList.hasOwnProperty(tag)) {
                    let pattern =
                        new RegExp('\\[' + allTagsList[tag] + '\\](.*?)\\[\/' + allTagsList[tag] + '\\]', 'gi');
                    text.innerHTML = text.innerHTML.replace(pattern, '');
                }
            }
        }

        function getTags(text) {
            let postChangeList = {};
            let clearedText = text.replace(/<div class="code-box"><strong class="legend">Код:<\/strong><div class="blockcode"><div class="scrollbox" style="(?:.*?)"><pre>([\s\S]*?)?<\/pre><\/div><\/div><\/div>/gi, '');
            for (let field in changeList) {
                if (changeList.hasOwnProperty(field)) {
                    let tags = changeList[field].tag.split(',');
                    for (let i = tags.length; i >= 0; i--) {
                        if (tags.hasOwnProperty(i)) {
                            let pattern = new RegExp('\\[' + tags[i] + '\\]([\\s\\S]*?)\\[\\/' + tags[i] + '\\]', 'gmi');
                            let clearPattern = new RegExp('\\[(\\/?)' + tags[i] + '\\]', 'gmi');
                            if (clearedText.match(pattern)) {
                                postChangeList[field] = {
                                    'tag': tags[i],
                                    'field': changeList[field].class,
                                    'content': text.match(pattern)[0].replace(clearPattern, ''),
                                    'type': changeList[field].type
                                };
                            }
                        }
                    }
                }
            }
            return postChangeList;
        }

        function getTagList() {
            let tagList = [];
            for (let field in changeList) {
                if (changeList.hasOwnProperty(field)) {
                    let tags = changeList[field].tag.split(',');
                    for (let i in tags) {
                        if (tags.hasOwnProperty(i) && !tagList.indexOf(tags[i]) + 1) {
                            tagList.push(tags[i]);
                        }
                    }
                }
            }
            return tagList;
        }

        function getAccess(usersId) {
            let userInfo = getUsersInfo(usersId);
            for (let id in userInfo) {
                if (userInfo.hasOwnProperty(id)) {
                    switch (userInfo[id].groupId) {
                        case '1':
                        case '2':
                            userInfo[id].access = {
                                'common': true,
                                'extended': true
                            };
                            break;
                        case '3':
                            userInfo[id].access = {
                                'common': opt.guestAccess ?
                                    Boolean(opt.guestAccess.indexOf(FORUM.topic.forum_name) + 1) : false,
                                'extended': opt.guestAccess ?
                                    Boolean(opt.guestAccess.indexOf(FORUM.topic.forum_name) + 1) : false
                            };
                            break;
                        default:
                            userInfo[id].access = {
                                'common': opt.forumAccess && opt.forumAccess[FORUM.topic.forum_name] ?
                                    Boolean(opt.forumAccess[FORUM.topic.forum_name].indexOf(userInfo[id].groupTitle) + 1) :
                                    true,
                                'extended': opt.forumAccessExtended && opt.forumAccessExtended[FORUM.topic.forum_name] ?
                                    Boolean(opt.forumAccessExtended[FORUM.topic.forum_name]
                                            .indexOf(userInfo[id].groupTitle) + 1) : false
                            };
                    }
                }
            }
            return userInfo;
        }

        function getUsersInfo(usersId) {
            let usersIdStr = usersId.filter(item => +item > 1).join(',');
            let usersInfo = {};
            if (usersId.indexOf('1') + 1) {
                usersInfo['1'] = {
                    'userId': '1',
                    'username': 'Guest',
                    'groupId': '3',
                    'groupTitle': 'Гость'
                };
            }
            $.ajax({
                async: false,
                url: '/api.php',
                data: {
                    method: 'users.get',
                    user_id: usersIdStr
                },
                success: function success(json) {
                    for (let i in json.response.users) {
                        if (json.response.users.hasOwnProperty(i)) {
                            usersInfo[json.response.users[i].user_id] = {
                                'userId': i,
                                'username': json.response.users[i].username,
                                'groupId': json.response.users[i].group_id,
                                'groupTitle': json.response.users[i].group_title
                            };
                        }
                    }
                }
            });

            return usersInfo;
        }

        function getDialog() {
            let maskButton = addButton();
            if (maskButton) {
                if (checkAccessExtended() || getAccessByForumName() === 'extended') {
                    maskButton.addEventListener('click', (event) => {
                        if (event.ctrlKey || event.metaKey) {
                            insertAvatarTags();
                        } else {
                            callMaskDialog();
                        }
                    });
                } else {
                    maskButton.addEventListener('click', insertAvatarTags);
                }
            }
            let maskDialog = buildMaskDialog();
            let main = document.querySelector('#pun-main');
            main.appendChild(maskDialog);

            getStyle();
        }

        function getStyle() {
            let style = document.createElement('style');
            style.innerHTML = `#mask_dialog .hv-bg {
                position: fixed;
                display: flex;
                align-content: center;
                justify-content: center;
                align-items: center;
                z-index: 10;
                width: 100%;
                height: 100%;
                left: 0;
                top: 0;
                background: rgba(0, 0, 0, .4);
                cursor: pointer;
            }
            
            #mask_dialog .inner {
                cursor: default;
                margin: 0;
                width: 760px;
                max-width: 99%;
                max-height: 90%;
                overflow-x: auto;
                z-index: 100;
                box-shadow: 0 0 40px #222;
                background: #F4F5F6 url("http://i.imgur.com/akmlat3.png");
                padding: 8px;
            }
            
            #mask_dialog .inner * {
                box-sizing: border-box;
            }
            
            #mask_dialog .inner .hv-mask-dialog-title {
                text-align: center;
                font-weight: 700;
                font-size: 18px;
                line-height: 34px;
                position: relative;
            }
            
            #mask_dialog .inner .hv-error-list {
                padding: 8px;
                margin: 8px;
                background: #DAA396;
                color: #BD0909;
                border: solid 1px;
            }
            
            #mask_dialog .inner .hv-mask-block {
                display: flex;
                justify-content: space-between;
                align-items: stretch;
            }
            
            #mask_dialog .inner .hv-mask-block .hv-preview-block {
                flex: 0 0 120px;
                text-align: center;
                max-width: 120px;
                overflow: hidden;
                word-break: break-word;
            }
            
            #mask_dialog .inner .hv-mask-block .hv-preview-block > div {
                padding: 3px 0;
            }
            
            #mask_dialog .inner .hv-mask-block .hv-form-block {
                flex: 1 1 auto;
            }
            
            #mask_dialog .inner .hv-mask-block .hv-preview-block .hv-preview-avatar img {
                max-width: 100px;
            }
            
            #mask_dialog .inner .hv-mask-block .hv-form-block {
                flex: 1 1 auto;
            }
            
            #mask_dialog .inner .hv-mask-block .hv-form-block label {
                display: block;
                margin-bottom: px;
            }
            
            #mask_dialog .inner .hv-mask-block .hv-form-block label:after {
                content: "";
                display: table;
                clear: both;
                margin-bottom: 2px;
            }
            
            #mask_dialog .inner .hv-mask-block .hv-form-block .hv-description {
                font-size: .9em;
                color: #999;
                font-style: italic;
            }
            
            #mask_dialog .inner .hv-mask-block .hv-form-block .hv-add-template {
                cursor: pointer;
                float: right;
                padding: 2px 4px;
                border: solid 1px #ccc;
            }
            
            #mask_dialog .inner .hv-mask-block .hv-form-block input,
            #mask_dialog .inner .hv-mask-block .hv-form-block textarea {
                width: 100%;
            }
            
            #mask_dialog .inner .hv-mask-block .hv-form-block .hv-mask-field {
                position: relative;
            }
            
            #mask_dialog .inner .hv-mask-block .hv-form-block .hv-mask-field + .hv-mask-field {
                margin-top: 10px;
            }
            
            #mask_dialog .inner .hv-masks-storage {
                flex: 0 1 140px;
                display: flex;
                align-items: flex-start;
                align-content: flex-start;
                justify-content: flex-start;
                padding: 8px;
                flex-wrap: wrap;
                list-style: none;
            }
            
            #mask_dialog .inner .hv-masks-storage.hidden {
                display: none;
            }
            
            #mask_dialog .inner .hv-masks-storage .hv-mask-element {
                width: 60px;
                padding: 4px;
                position: relative;
            }
            
            #mask_dialog .inner .hv-masks-storage .hv-mask-element img {
                max-width: 100%;
                cursor: pointer;
            }
            
            #mask_dialog .inner .hv-masks-storage .hv-mask-element .hv-mask-tooltip {
                position: absolute;
                top: 4px;
                min-width: 160px;
                right: 60px;
                padding: 4px;
                z-index: 5;
                overflow-y: auto;
                background: rgba(255, 255, 255, .6);
                border: solid 1px #ccc;
                display: none;
            }
            
            #mask_dialog .inner .hv-masks-storage .hv-mask-element > img:hover + .hv-mask-tooltip {
                display: block;
            }
            
            #mask_dialog .inner .hv-masks-storage .hv-mask-element .hv-mask-tooltip > * {
                zoom: .7
            }
            
            #mask_dialog .inner .hv-masks-storage .hv-mask-element .hv-delete-mask {
                display: block;
                font-size: 10px;
                text-align: center;
                cursor: pointer;
            }
            
            #mask_dialog .inner .hv-control {
                padding: 8px;
                text-align: center;
                position: relative;
            }
            
            #mask_dialog .inner .hv-control input + input {
                margin-left: 10px;
            }
            
            #mask_dialog .inner .hv-control .hv-clear-storage {
                position: absolute;
                right: 0;
                bottom: 0;
                color: #666;
                cursor: pointer;
            }`;

            let docstyle = document.head.querySelector('link[href*="style"]');
            document.head.insertBefore(style, docstyle);
        }

        function insertAvatarTags() {
            bbcode('[icon]','[/icon]');
        }

{'fraction_non_alphanumeric': 0.10704926624737945, 'fraction_numerical': 0.00799266247379455, 'mean_word_length': 0.9449197276930358, 'pattern_counts': {'":': 0, '<': 59, '<?xml version=': 0, '>': 79, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 216, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3235809', 'n_tokens_mistral': 13450, 'n_tokens_neox': 12465, 'n_words': 2326}