Update eslintrc, fix up codeblocks plugin, shift codeblock CSS towards BEM style, start adding codeblock theme styles

pull/2/head
BakedPVP 4 years ago
parent e0c6d0bb38
commit 920b9a6860

@ -242,12 +242,9 @@
"jsdoc/newline-after-description": [ "warn", "never" ],
"jsdoc/no-undefined-types": [ "warn" ],
"jsdoc/require-hyphen-before-param-description": [ "warn", "never" ],
"jsdoc/require-jsdoc": [ "warn" ],
"jsdoc/require-param": [ "warn" ],
"jsdoc/require-param-description": [ "warn" ],
"jsdoc/require-param-name": [ "warn" ],
"jsdoc/require-param-type": [ "warn" ],
"jsdoc/require-returns": [ "warn" ],
"jsdoc/require-returns-check": [ "warn" ],
"jsdoc/require-returns-type": [ "warn" ],
"jsdoc/valid-types": [ "warn" ]
@ -286,6 +283,7 @@
"Voice": "Voice"
},
"tagNamePreference": {
"component": "component",
"augments": "extends",
"warn": "warn",
"bug": "bug",

@ -1,12 +1,13 @@
const { clipboard } = require('electron');
const { react: { findInReactTree } } = require('@util');
const { joinClassNames, react: { findInReactTree, getReactInstance } } = require('@util');
const { getModule, hljs } = require('@webpack');
const { patch, unpatch } = require('@patcher');
const { Plugin } = require('@entities');
const { Messages } = require('@i18n');
const { React } = require('@react');
module.exports = class Codeblocks extends Plugin {
module.exports = class CodeBlocks extends Plugin {
onStart () {
this.injectStyles('styles/main.scss');
this.patchCodeblocks();
@ -15,15 +16,13 @@ module.exports = class Codeblocks extends Plugin {
onStop () {
unpatch('vz-codeblocks-inline');
unpatch('vz-codeblocks-embed');
document.querySelectorAll('.hljs [class^=vizality]').forEach(e => e.style.display = 'none');
this._forceUpdate();
}
async patchCodeblocks () {
const parser = getModule('parse', 'parseTopic');
patch('vz-codeblocks-inline', parser.defaultRules.codeBlock, 'react', (args, res) => {
this.injectCodeblock(args, res);
return res;
});
@ -34,9 +33,9 @@ module.exports = class Codeblocks extends Plugin {
this.injectCodeblock(null, codeblock);
}
}
return res;
});
this._forceUpdate();
}
injectCodeblock (args, codeblock) {
@ -44,37 +43,53 @@ module.exports = class Codeblocks extends Plugin {
codeblock.props.render = (codeblock) => {
const res = render(codeblock);
const { children } = res.props;
const isDangerouslySetInnerHTML = children.props.dangerouslySetInnerHTML;
const lang = args ? args[0].lang : children.props.className.split(' ').find(className => !className.includes('-') && className !== 'hljs');
// @todo Don't forget to make these into settings and add `theme`.
children.props.className = joinClassNames(
children.props.className,
'vz-code-block',
'vz-has-line-numbers',
'vz-has-copy-button',
{
'vz-has-header': isDangerouslySetInnerHTML
}
);
if (children.props.dangerouslySetInnerHTML) {
res.props.className = joinClassNames(res.props.className, 'vz-code-block__pre');
children.props.children = this.renderCodeblock(lang, children.props.dangerouslySetInnerHTML);
delete children.props.dangerouslySetInnerHTML;
} else if (typeof children.props.children === 'string') {
children.props.children = this.renderCodeblock(lang, children.props.children);
}
return res;
};
}
_forceUpdate () {
document.querySelectorAll(`[id^='chat-messages-']`).forEach(e => getReactInstance(e).memoizedProps.onMouseMove());
}
renderCodeblock (lang, content) {
const children = [];
const isDangerouslySetInnerHTML = typeof content === 'object';
const isValidLanguage = typeof hljs.getLanguage(lang) !== 'undefined';
const language = hljs.getLanguage(lang) ? hljs.getLanguage(lang).name : undefined;
const isValidLanguage = typeof language !== 'undefined';
children.push(React.createElement('div', {
className: 'vz-code-block__inner',
dangerouslySetInnerHTML: isDangerouslySetInnerHTML ? content : null
}, isDangerouslySetInnerHTML ? null : content), isValidLanguage && React.createElement('div', {
className: 'vizality-codeblock-lang'
}, lang), React.createElement('div', {
className: 'vizality-lines'
className: 'vz-code-block__header'
}, language), React.createElement('div', {
className: 'vz-code-block__line-numbers'
}), React.createElement('button', {
className: 'vizality-codeblock-copy-btn',
className: 'vz-code-block__copy-button',
onClick: this._onClickHandler
}, 'copy'));
}, Messages.COPY));
return children;
}
@ -82,23 +97,17 @@ module.exports = class Codeblocks extends Plugin {
_onClickHandler (e) {
const { target } = e;
if (target.classList.contains('copied')) {
return;
}
if (target.classList.contains('vz-is-copied')) return;
target.innerText = 'copied!';
target.classList.add('copied');
target.innerText = Messages.COPIED;
target.classList.add('vz-is-copied');
setTimeout(() => {
target.innerText = 'copy';
target.classList.remove('copied');
target.innerText = Messages.COPY;
target.classList.remove('vz-is-copied');
}, 1000);
const codeContent = target.parentElement.children[0];
const vzCopy = codeContent.querySelector('[data-vizality-codeblock-copy]');
if (vzCopy) {
return clipboard.writeText(vzCopy.textContent);
}
const range = document.createRange();
range.selectNode(codeContent);
@ -107,7 +116,7 @@ module.exports = class Codeblocks extends Plugin {
selection.removeAllRanges();
selection.addRange(range);
clipboard.writeText(selection.toString());
clipboard.writeText(selection.toString().trim());
selection.removeAllRanges();
}

@ -1,77 +1,39 @@
.vizality-codeblock-copy-btn {
color: var(--header-secondary);
border-radius: 4px;
box-shadow: var(--elevation-medium);
@use 'themes';
line-height: 1.5;
padding: 8px 12px;
font-family: 'Raleway', sans-serif;
font-size: 0.8em;
text-transform: uppercase;
font-weight: 700;
margin: 10px;
background: var(--background-tertiary);
position: absolute;
right: 0 !important;
bottom: 0 !important;
opacity: 0;
transition: .2s;
&.copied {
background-color: #00c853;
color: #fff;
opacity: 1;
.vz-code-block {
$block: &;
&__pre {
max-width: 100% !important;
}
}
.vizality-codeblock-lang {
color: var(--text-normal);
background: rgb(0 0 0 / .1);
border-bottom: 1px solid var(--background-tertiary);
line-height: 20px;
padding: 0 10px;
font-family: 'Raleway', sans-serif;
font-size: 0.8em;
text-transform: uppercase;
font-weight: bold;
font-style: initial;
position: absolute;
top: 0 !important;
left: 0 !important;
right: 0 !important;
bottom: initial !important;
}
/* Attribution: ThuverX#9814 */
$numbers: '';
@for $i from 1 through 999 {
$numbers: $numbers + $i + '\A '
}
.hljs {
overflow: hidden;
position: relative;
padding-left: calc(35px + .5em) !important;
&:not([class$='hljs']) {
padding-top: calc(20px + .5em) !important;
.vizality-lines:after {
top: calc(20px + .5em);
}
&__header {
color: var(--text-normal);
background: rgb(0 0 0 / .1);
border-bottom: 1px solid var(--background-tertiary);
line-height: 20px;
padding: 0 10px;
font-family: 'Raleway', sans-serif;
font-size: 0.8em;
text-transform: uppercase;
font-weight: bold;
font-style: initial;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: initial;
}
.vizality-lines {
&__line-numbers {
text-align: right;
height: 100%;
width: 30px;
line-height: 1.125rem;
font-weight: initial;
font-style: initial;
&:after {
&::after {
$numbers: '';
@for $i from 1 through 999 {
$numbers: $numbers + $i + '\A '
}
overflow: hidden;
content: $numbers;
position: absolute;
@ -82,8 +44,54 @@ $numbers: '';
border-right: 1px solid rgba(0, 0, 0, .2);
}
}
&:hover .vizality-codeblock-copy-btn {
opacity: 1;
/*
* 75% height and small bottom and right distances is to take into account
* single line generic codeblocks that have no header.
*/
&__copy-button {
color: var(--header-secondary);
border-radius: 4px;
box-shadow: var(--elevation-medium);
line-height: 1.5;
padding: 0 12px;
font-family: "Raleway", sans-serif;
font-size: 0.8em;
text-transform: uppercase;
font-weight: 700;
background: var(--background-tertiary);
position: absolute;
right: 5px;
bottom: 5px;
opacity: 0;
transition: 0.2s;
height: 75%;
max-height: 32px;
&.vz-is-copied {
background-color: #00c853;
color: #fff;
opacity: 1;
}
}
&.vz-has-line-numbers,
&.vz-has-header,
&.vz-has-copy-button {
overflow: hidden;
position: relative;
}
&.vz-has-line-numbers {
padding-left: calc(35px + .5em);
}
&.vz-has-header {
padding-top: calc(20px + .5em);
#{$block}__line-numbers {
&::after {
top: calc(20px + .5em);
}
}
}
&:hover {
#{$block}__copy-button {
opacity: 1;
}
}
}

@ -0,0 +1,73 @@
.vz-code-block {
&#{&}--theme-dracula {
.hljs {
&,
&-subst {
color: #f8f8f2;
}
&-built_in,
&-selector-id,
&-attribute,
&-link,
&-meta-string,
&-doctag {
color: #8be9fd;
}
&-keyword,
&-selector-tag,
&-subst,
&-meta {
color: #ff79c6;
}
&-title,
&-selector-pseudo,
&-selector-class {
color: #50fa7b;
}
&-params,
&-strong {
font-style: italic;
color: #ffb86c;
}
&-string,
&-name,
&-type,
&-attr,
&-emphasis,
&-symbol,
&-regexp,
&-bullet,
&-addition,
&-variable,
&-selector-attr,
&-template-tag,
&-template-variable {
color: #f1fa8c;
}
&-comment,
&-quote,
&-deletion {
color: #6272a4;
}
&-keyword,
&-selector-tag,
&-literal,
&-title,
&-section,
&-doctag,
&-type,
&-name,
&-strong {
font-weight: 700;
}
&-literal,
&-number,
&-section {
color: #bd93f9;
}
&-emphasis {
font-style: italic;
}
}
}
}

@ -0,0 +1,2 @@
@use 'dracula';
@use 'monokai-sublime';

@ -0,0 +1,66 @@
.vz-code-block {
&#{&}--theme-monokai-sublime {
.hljs {
&,
&-subst,
&-tag {
color: #f8f8f2;
}
&-emphasis,
&-strong {
color: #a8a8a2;
}
&-bullet,
&-link,
&-literal,
&-number,
&-quote,
&-regexp {
color: #ae81ff;
}
&-code,
&-section,
&-selector-class,
&-title {
color: #a6e22e;
}
&-strong {
font-weight: 700;
}
&-emphasis {
font-style: italic;
}
&-attr,
&-keyword,
&-name,
&-selector-tag {
color: #f92672;
}
&-attribute,
&-symbol {
color: #66d9ef;
}
&-class &-title,
&-params {
color: #f8f8f2;
}
&-addition,
&-built_in,
&-builtin-name,
&-selector-attr,
&-selector-id,
&-selector-pseudo,
&-string,
&-template-variable,
&-type,
&-variable {
color: #e6db74;
}
&-comment,
&-deletion,
&-meta {
color: #75715e;
}
}
}
}
Loading…
Cancel
Save