diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..bd6117b
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1 @@
+*.htm linguist-detectable=false
diff --git a/README.md b/README.md
index 137584c..42f93ef 100644
--- a/README.md
+++ b/README.md
@@ -4,6 +4,8 @@
![codeWe](https://github.com/allEyezOnCode/CodeWe/blob/master/imgs/ex.gif?raw=True "codeWe - exemple")
+---
+
## Installation
### Classic installation
@@ -19,7 +21,7 @@ The first step is to clone this repository.
Open a terminal and run:
```bash
-git clone https://github.com/allEyezOnCode/CodeWe.git
+git clone https://github.com/CodeWe-projet/CodeWe.git
```
Next step is to install depedencies
@@ -47,17 +49,54 @@ To run the server, run a shell in the `CodeWe/src` folder and run:
node ./src/server.js
```
-## Next features
-
-* Document with privileges (anon auth, and jwt usage)
-* New programming langages
-* More options
-* Server montioring with prometheus and grafana
+---
## Contribution
Feel free to contribute, open an issue, then fork the repo and submit a PR.
+
## Licence
-This project is under MIT licence. The full licence can be read [here](https://github.com/allEyezOnCode/CodeWe).
+This project is under MIT licence. The full licence can be read [here](https://github.com/CodeWe-projet/CodeWe/blob/master/LICENCE.md).
+
+---
+
+## Next features
+
+* Document with privileges (anon auth, and jwt usage)
+
+
+## Changelog
+
+### Version [2.1.0](https://github.com/CodeWe-projet/CodeWe/pull/40)
+#### Back-end
+* Preparing the back-end for authentication.
+* New prometheus gauges and counter.
+
+#### Front-end
+* Adding support of 20+ languages.
+* Allow sharing URL by QR Code.
+* Customize tabulation size.
+* Remove line and others major bugfixes.
+
+### Version [2.0.1](https://github.com/CodeWe-projet/CodeWe/pull/26)
+#### Back-end
+* Ability to redirect an http port to the main https port.
+* Update configuration.
+* Minor bug fixes.
+
+#### Front-end
+* Update legal content.
+* Major bug fixes.
+
+### Version [2.0.0](https://github.com/CodeWe-projet/CodeWe/tree/ad25d132ab92c0b9de227c9aedf04bda3f19681b)
+#### Back-end
+* Rewriting of the back end in nodejs.
+
+#### Front-end
+* Report issue button.
+* Minor bug fixes.
+
+### 1.0.0
+* Initialisation of project using python and Flask for backend.
diff --git a/src/config/langages.js b/src/config/langages.js
new file mode 100644
index 0000000..9fceba8
--- /dev/null
+++ b/src/config/langages.js
@@ -0,0 +1,25 @@
+module.exports = [
+ "python",
+ "c",
+ "c++",
+ "c#",
+ "javascript",
+ "java",
+ "haskell",
+ "smalltalk",
+ "coffescript",
+ "css",
+ "d",
+ "go",
+ "haskell",
+ "html",
+ "json",
+ "lua",
+ "php",
+ "r",
+ "ruby",
+ "scheme",
+ "shell",
+ "sql",
+ 'oz',
+];
diff --git a/src/db/MongoDB.js b/src/db/MongoDB.js
index 806f2ef..e679114 100644
--- a/src/db/MongoDB.js
+++ b/src/db/MongoDB.js
@@ -1,8 +1,10 @@
const { MongoClient, ObjectID } = require("mongodb");
var crypto = require('crypto');
const { nanoid } = require('nanoid');
+const languages = require('../config/langages');
const configs = require('../config/config');
const utils = require('../utils');
+const prom = require('../socket/prom')
const baseCode = [
{uuid: utils.uuid(Math.random().toString(), 10), content: 'def main(text: str) -> None:'},
@@ -12,7 +14,6 @@ const baseCode = [
{uuid: utils.uuid(Math.random().toString(), 10), content: ' main(\'Hello World !\')'}
];
-
class MongoDB {
constructor (url) {
this.client = new MongoClient(url, {
@@ -35,7 +36,7 @@ class MongoDB {
}
}
- async createDocument (language) {
+ async createDocument (documentLanguage) {
let doc = {
content: baseCode,
creationDate: Date.now(),
@@ -45,7 +46,7 @@ class MongoDB {
editors: [],
documentLink: '',
linkView: '',
- language: language,
+ language: documentLanguage,
tab: 4
};
try {
@@ -173,7 +174,7 @@ class MongoDB {
}
async changeLanguage(documentLink, newLanguage) {
- if (["python"].includes(newLanguage)) {
+ if (languages.includes(newLanguage)) {
return this.changeParam(documentLink, 'language', newLanguage);
}
}
@@ -216,6 +217,7 @@ class MongoDB {
case 'new-line':
results = await this.newLine(documentLink, data.previous, data.id, data.content);
if (!results) success = false;
+ prom.total_new_lines.inc();
break;
case 'delete-line':
results = await this.deleteLine(documentLink, data.id);
diff --git a/src/publics/css/base.less b/src/publics/css/base.less
index 098cce3..13f5bfa 100644
--- a/src/publics/css/base.less
+++ b/src/publics/css/base.less
@@ -2,7 +2,7 @@
| Generic |
\*******************/
-@background-color: #222;
+@background-color: #222222;
@color: #fff;
@font: sans-serif;
@absolute-color: #d5e6ed;
diff --git a/src/publics/css/editor.less b/src/publics/css/editor.less
index bcdfdf5..2d1bce5 100644
--- a/src/publics/css/editor.less
+++ b/src/publics/css/editor.less
@@ -1,3 +1,7 @@
+@background-color: #222222;
+@color: #fff;
+@header-height: 60px;
+
/******************\
| Header |
\******************/
@@ -57,3 +61,70 @@ section#editor{
background-color: red;
border-radius: 10px;
}
+
+/*******************\
+| Navigation Bar |
+\*******************/
+
+#customise{
+ position: fixed;
+ top: 1.1 * @header-height;
+ right: 0;
+ width: 20%;
+ height: 100%;
+ max-width: 300px;
+ min-width: 200px;
+ padding: 20px;
+ background-color: darken(@background-color, 2%);
+ border-left: 1px solid #111111;
+ z-index: 5;
+
+ ul{
+ list-style: none;
+
+ li{
+ padding-bottom: 20px;
+
+ h3{
+ padding: 5px 0;
+ color: darken(@color, 50%);
+ letter-spacing: 3px;
+ border-bottom: 1px solid lighten(@background-color, 10%);
+ display: inline;
+ }
+
+ > :not(h3){
+ padding: 7px;
+ margin-top: 20px;
+ border-radius: 10px;
+ }
+
+ select,
+ input{
+ color: @color;
+ background-color: lighten(@background-color, 5%);
+ border-color: @background-color;
+ width: 90%;
+ }
+
+ #qrcode{
+ background-color: white;
+ display: inline-block;
+
+ canvas{
+ width: 128px;
+ height: 128px;
+ margin: 10px;
+ background-color: white;
+ image-rendering: optimizeSpeed; /* */
+ image-rendering: -moz-crisp-edges; /* Firefox */
+ image-rendering: -o-crisp-edges; /* Opera */
+ image-rendering: -webkit-optimize-contrast; /* Chrome (and Safari) */
+ image-rendering: pixelated; /* Chrome as of 2019 */
+ image-rendering: optimize-contrast; /* CSS3 Proposed */
+ -ms-interpolation-mode: nearest-neighbor; /* IE8+ */
+ }
+ }
+ }
+ }
+}
diff --git a/src/publics/js/dev/component/custom.js b/src/publics/js/dev/component/custom.js
index cd2af38..15932fb 100644
--- a/src/publics/js/dev/component/custom.js
+++ b/src/publics/js/dev/component/custom.js
@@ -1,3 +1,62 @@
/**
- * Tab customization (allow convert current file)
+ * Tab customization
*/
+
+import {editor, socket} from "/js/dev/page/editor.js";
+import {patterns} from "/js/dev/page/editor/prism/patterns.js";
+import PrismCustom from "/js/dev/page/editor/prism/prismCustom.js";
+
+export default class Customize{
+ /** Init the customize object
+ * @param {Editable} editable
+ */
+ constructor(editable) {
+ this.editable = editable;
+
+ document.getElementById('option-language').addEventListener('change', e => {
+ language = e.target.value.toLowerCase();
+ this.editable.updateAllHighlighting();
+ socket.send('language', {language});
+ });
+
+ document.addEventListener('socket.receive.language', e => {
+ if(Object.keys(patterns).includes(e.detail.language.toLowerCase())){
+ language = e.detail.language.toLowerCase();
+ document.getElementById('option-language').value = language;
+ this.editable.updateAllHighlighting();
+ }
+ });
+
+ for(const lang of Object.keys(patterns)){
+ const option = document.createElement('option');
+ option.innerText = lang;
+ if(lang === language) option.selected = true;
+ document.getElementById('option-language').appendChild(option);
+ }
+
+ document.getElementById('option-space-size').addEventListener('change', e => {
+ editor.tab.setSize(e.target.value);
+
+ for(const child of this.editable.editable.children){
+ child.innerText = editor.tab.updateText(child.innerText);
+ new PrismCustom(child, language).apply();
+ }
+
+ socket.send('changeTabSize', {size: e.target.value});
+ });
+
+ document.getElementById('option-space-size').value = this.editable.tab.size;
+
+ document.addEventListener('socket.receive.changeTabSize', e => {
+ if(e.detail.size && Number.isInteger(parseInt(e.detail.size))){
+ editor.tab.setSize(e.detail.size);
+ document.getElementById('option-space-size').value = e.detail.size;
+
+ for(const child of this.editable.editable.children){
+ child.innerText = editor.tab.updateText(child.innerText);
+ new PrismCustom(child, language).apply();
+ }
+ }
+ });
+ }
+}
diff --git a/src/publics/js/dev/lib/qrcode.min.js b/src/publics/js/dev/lib/qrcode.min.js
new file mode 100644
index 0000000..1911078
--- /dev/null
+++ b/src/publics/js/dev/lib/qrcode.min.js
@@ -0,0 +1,11 @@
+/**
+ * @fileoverview
+ * - Using the 'QRCode for Javascript library'
+ * - Fixed dataset of 'QRCode for Javascript library' for support full-spec.
+ * - this library has no dependencies.
+ *
+ * @author davidshimjs
+ * @see http://www.d-project.com/
+ * @see http://jeromeetienne.github.com/jquery-qrcode/
+ */
+var QRCode;!function(){function a(a){this.mode=c.MODE_8BIT_BYTE,this.data=a,this.parsedData=[];for(var b=[],d=0,e=this.data.length;e>d;d++){var f=this.data.charCodeAt(d);f>65536?(b[0]=240|(1835008&f)>>>18,b[1]=128|(258048&f)>>>12,b[2]=128|(4032&f)>>>6,b[3]=128|63&f):f>2048?(b[0]=224|(61440&f)>>>12,b[1]=128|(4032&f)>>>6,b[2]=128|63&f):f>128?(b[0]=192|(1984&f)>>>6,b[1]=128|63&f):b[0]=f,this.parsedData=this.parsedData.concat(b)}this.parsedData.length!=this.data.length&&(this.parsedData.unshift(191),this.parsedData.unshift(187),this.parsedData.unshift(239))}function b(a,b){this.typeNumber=a,this.errorCorrectLevel=b,this.modules=null,this.moduleCount=0,this.dataCache=null,this.dataList=[]}function i(a,b){if(void 0==a.length)throw new Error(a.length+"/"+b);for(var c=0;c "+e+" Our Terms have been updated - Please review them
+
+
+ A downloadable PDF version can be found here.
+
+
+
+ '],h=0;d>h;h++){g.push("
"),c.innerHTML=g.join("");var j=c.childNodes[0],k=(b.width-j.offsetWidth)/2,l=(b.height-j.offsetHeight)/2;k>0&&l>0&&(j.style.margin=l+"px "+k+"px")},a.prototype.clear=function(){this._el.innerHTML=""},a}();QRCode=function(a,b){if(this._htOption={width:256,height:256,typeNumber:4,colorDark:"#000000",colorLight:"#ffffff",correctLevel:d.H},"string"==typeof b&&(b={text:b}),b)for(var c in b)this._htOption[c]=b[c];"string"==typeof a&&(a=document.getElementById(a)),this._android=n(),this._el=a,this._oQRCode=null,this._oDrawing=new q(this._el,this._htOption),this._htOption.text&&this.makeCode(this._htOption.text)},QRCode.prototype.makeCode=function(a){this._oQRCode=new b(r(a,this._htOption.correctLevel),this._htOption.correctLevel),this._oQRCode.addData(a),this._oQRCode.make(),this._el.title=a,this._oDrawing.draw(this._oQRCode),this.makeImage()},QRCode.prototype.makeImage=function(){"function"==typeof this._oDrawing.makeImage&&(!this._android||this._android>=3)&&this._oDrawing.makeImage()},QRCode.prototype.clear=function(){this._oDrawing.clear()},QRCode.CorrectLevel=d}();
diff --git a/src/publics/js/dev/page/editor.js b/src/publics/js/dev/page/editor.js
index 174bebd..9f71835 100644
--- a/src/publics/js/dev/page/editor.js
+++ b/src/publics/js/dev/page/editor.js
@@ -5,19 +5,28 @@
* @date Last modification on 16/11/2020
* @version 1.0.1
*/
+import Customize from "/js/dev/component/custom.js";
import Cursor from "/js/dev/page/editor/cursor.js";
import download from "/js/dev/page/editor/download.js";
import Editable from "/js/dev/page/editor/editable.js";
+import {patterns} from "/js/dev/page/editor/prism/patterns.js";
import PrismCustom from "/js/dev/page/editor/prism/prismCustom.js";
import EditorSocket from "/js/dev/page/editor/socket.js";
import _ from "/js/dev/utils/element.js";
+import qrCode from "/js/dev/utils/qrcode/qrcode-m-2.js";
export const socket = new EditorSocket(doc_id);
export const editor = new Editable(_.id('editor'));
export const cursor = new Cursor(_.id('editor'));
+download(_.id('download'), _.id('editor'));
+
+if(!Object.keys(patterns).includes(language)) language = 'generic';
+
for(const child of _.id('editor').children){
- new PrismCustom(child, 'python').ApplyWithCaret();
+ new PrismCustom(child, language).apply();
}
-download(_.id('download'), _.id('editor'));
+export const customize = new Customize(editor);
+
+qrCode('qrcode', document.documentURI.replace('/editor/', '/e/'));
diff --git a/src/publics/js/dev/page/editor/editable.js b/src/publics/js/dev/page/editor/editable.js
index 36778ea..81165ce 100644
--- a/src/publics/js/dev/page/editor/editable.js
+++ b/src/publics/js/dev/page/editor/editable.js
@@ -19,9 +19,9 @@ import Random from "/js/dev/utils/random.js";
import {insertInText} from "/js/dev/utils/string.js";
export default class Editable{
- constructor(element) {
+ constructor(element, tabSize=initial_size) {
this.editable = element;
- this.tab = new Tab(element, TabType.SPACES, 4);
+ this.tab = Number.isInteger(tabSize) ? new Tab(element, TabType.SPACES, tabSize) : 4;
this.linesManager = new LinesManager(element);
this.last_request = {};
@@ -79,7 +79,7 @@ export default class Editable{
}
break;
default:
- if(!e.ctrlKey && !e.altKey) PrismCustom.onCurrent('python').ApplyWithCaret();
+ if(!e.ctrlKey && !e.altKey && getNodeFromAttribute('uuid')) PrismCustom.onCurrent(language).ApplyWithCaret();
}
this.linesManager.change = true;
});
@@ -223,7 +223,7 @@ export default class Editable{
)
);
document.getSelection().collapseToEnd();
- PrismCustom.onCurrent('python').ApplyWithCaret();
+ PrismCustom.onCurrent(language).ApplyWithCaret();
}
/**
@@ -234,7 +234,7 @@ export default class Editable{
const currentElement = getNodeFromAttribute('uuid');
currentElement.innerHTML = insertInText(currentElement.innerText, lines[0], Caret.getBeginPosition(currentElement));
- PrismCustom.onCurrent('python').apply();
+ PrismCustom.onCurrent(language).apply();
let currentUuid = currentElement.getAttribute('uuid');
for(let i=1;i");for(var i=0;d>i;i++)g.push(' ")}g.push("');g.push("
', '
');
+ for(const br of previousSibling.getElementsByTagName('br')) br.remove();
+ if(previousSibling.firstChild.nodeName === 'BR'){
+ console.log(`"${previousSibling.innerText}"`);
+ Caret.setPosition(previousSibling.firstChild, 0);
+ }else Caret.setPosition(previousSibling, len);
line.remove();
- Caret.setPosition(previousSibling, len);
+ //new PrismCustom(previousSibling, language).ApplyWithCaret();
}
}
@@ -302,4 +307,16 @@ export default class Editable{
}
return requests;
}
+
+ /**
+ * Update all syntax highlighting
+ */
+ updateAllHighlighting(){
+ const current = getNodeFromAttribute('uuid')
+ for(const child of this.editable.children){
+ if(current === child) new PrismCustom(child, language).ApplyWithCaret();
+ else new PrismCustom(child, language).apply();
+
+ }
+ }
}
diff --git a/src/publics/js/dev/page/editor/linesManager.js b/src/publics/js/dev/page/editor/linesManager.js
index 62b7045..fd36446 100644
--- a/src/publics/js/dev/page/editor/linesManager.js
+++ b/src/publics/js/dev/page/editor/linesManager.js
@@ -67,7 +67,7 @@ export default class LinesManager{
let element = this.select(uuid);
if(element){
element.innerText = htmlEncode(content);
- new PrismCustom(element, 'python').apply();
+ new PrismCustom(element, language).apply();
}else{
Debug.warn(`Error when trying to update element with uuid '${uuid}': No div has this uuid.`)
}
diff --git a/src/publics/js/dev/page/editor/prism/patterns.js b/src/publics/js/dev/page/editor/prism/patterns.js
index 85018bc..6b60f3c 100644
--- a/src/publics/js/dev/page/editor/prism/patterns.js
+++ b/src/publics/js/dev/page/editor/prism/patterns.js
@@ -1,3 +1,7 @@
+// Those regex are based on https://github.com/ccampbell/rainbow/tree/master/src/language made by Craig Campbell
+// Big love to them <3
+// For oz it's base on vscode extension : https://github.com/mozart/vscode-oz/blob/master/syntaxes/oz.tmLanguage.json
+
export const patterns = {
generic: [
{
@@ -135,5 +139,1651 @@ export const patterns = {
name: 'comment.docstring',
pattern: /('{3}|"{3})[\s\S]*?\1/gm
}
- ]
-};
\ No newline at end of file
+ ],
+ javascript: [
+
+ /**
+ * matches $. or $(
+ */
+ {
+ name: 'selector',
+ pattern: /\$(?=\.|\()/g
+ },
+ {
+ name: 'support',
+ pattern: /\b(window|document)\b/g
+ },
+ {
+ name: 'keyword',
+ pattern: /\b(export|default|from)\b/g
+ },
+ {
+ name: 'function.call',
+ pattern: /\b(then)(?=\()/g
+ },
+ {
+ name: 'variable.language.this',
+ pattern: /\bthis\b/g
+ },
+ {
+ name: 'variable.language.super',
+ pattern: /super(?=\.|\()/g
+ },
+ {
+ name: 'storage.type',
+ pattern: /\b(const|let|var)(?=\s)/g
+ },
+ {
+ matches: {
+ 1: 'support.property'
+ },
+ pattern: /\.(length|node(Name|Value))\b/g
+ },
+ {
+ matches: {
+ 1: 'support.function'
+ },
+ pattern: /(setTimeout|setInterval)(?=\()/g
+ },
+ {
+ matches: {
+ 1: 'support.method'
+ },
+ pattern: /\.(getAttribute|replace|push|getElementById|getElementsByClassName|setTimeout|setInterval)(?=\()/g
+ },
+
+ /**
+ * matches any escaped characters inside of a js regex pattern
+ *
+ * @see https://github.com/ccampbell/rainbow/issues/22
+ *
+ * this was causing single line comments to fail so it now makes sure
+ * the opening / is not directly followed by a *
+ *
+ * The body of the regex to match a regex was borrowed from:
+ * http://stackoverflow.com/a/17843773/421333
+ */
+ {
+ name: 'string.regexp',
+ matches: {
+ 1: 'string.regexp.open',
+ 2: {
+ name: 'constant.regexp.escape',
+ pattern: /\\(.){1}/g
+ },
+ 3: 'string.regexp.close',
+ 4: 'string.regexp.modifier'
+ },
+ pattern: /(\/)((?![*+?])(?:[^\r\n\[/\\]|\\.|\[(?:[^\r\n\]\\]|\\.)*\])+)(\/)(?!\/)([igm]{0,3})/g
+ },
+
+ /**
+ * matches runtime function declarations
+ */
+ {
+ matches: {
+ 1: 'storage.type',
+ 3: 'entity.function'
+ },
+ pattern: /(var)?(\s|^)(\S+)(?=\s?=\s?function\()/g
+ },
+
+ /**
+ * matches constructor call
+ */
+ {
+ matches: {
+ 1: 'keyword',
+ 2: 'variable.type'
+ },
+ pattern: /(new)\s+(?!Promise)([^\(]*)(?=\()/g
+ },
+
+ /**
+ * matches any function call in the style functionName: function()
+ */
+ {
+ name: 'entity.function',
+ pattern: /(\w+)(?=:\s{0,}function)/g
+ },
+ {
+ name: 'constant.other',
+ pattern: /\*(?= as)/g
+ },
+ {
+ matches: {
+ 1: 'keyword',
+ 2: 'constant.other'
+ },
+ pattern: /(export)\s+(\*)/g
+ },
+ {
+ matches: {
+ 1: 'storage.type.accessor',
+ 2: 'entity.name.function'
+ },
+ pattern: /(get|set)\s+(\w+)(?=\()/g
+ },
+ {
+ matches: {
+ 2: 'entity.name.function'
+ },
+ pattern: /(^\s*)(\w+)(?=\([^\)]*?\)\s*\{)/gm
+ },
+ {
+ matches: {
+ 1: 'storage.type.class',
+ 2: 'entity.name.class',
+ 3: 'storage.modifier.extends',
+ 4: 'entity.other.inherited-class'
+ },
+ pattern: /(class)\s+(\w+)(?:\s+(extends)\s+(\w+))?(?=\s*\{)/g
+ },
+ {
+ name: 'storage.type.function.arrow',
+ pattern: /=>/g
+ },
+ {
+ name: 'support.class.promise',
+ pattern: /\bPromise(?=(\(|\.))/g
+ }
+ ],
+ java: [
+ {
+ name: "constant",
+ pattern: /\b(false|null|true|[A-Z_]+)\b/g
+ },
+ {
+ matches: {
+ 1: "keyword",
+ 2: "support.namespace"
+ },
+ pattern: /(import|package)\s(.+)/g
+ },
+ {
+ // see http://docs.oracle.com/javase/tutorial/java/nutsandbolts/_keywords.html
+ name: "keyword",
+ pattern: /\b(abstract|assert|boolean|break|byte|case|catch|char|class|const|continue|default|do|double|else|enum|extends|final|finally|float|for|goto|if|implements|import|instanceof|int|interface|long|native|new|package|private|protected|public|return|short|static|strictfp|super|switch|synchronized|this|throw|throws|transient|try|void|volatile|while)\b/g
+ },
+ {
+ name: "string",
+ pattern: /(".*?")/g
+ },
+ {
+ name: "char",
+ pattern: /(')(.|\\.|\\u[\dA-Fa-f]{4})\1/g
+ },
+ {
+ name: "integer",
+ pattern: /\b(0x[\da-f]+|\d+)L?\b/g
+ },
+ {
+ name: "comment",
+ pattern: /\/\*[\s\S]*?\*\/|(\/\/).*?$/gm
+ },
+ {
+ name: "support.annotation",
+ pattern: /@\w+/g
+ },
+ {
+ matches: {
+ 1: "entity.function"
+ },
+ pattern: /([^@\.\s]+)\(/g
+ },
+ {
+ name: "entity.class",
+ pattern: /\b([A-Z]\w*)\b/g
+ },
+ {
+ // see http://docs.oracle.com/javase/tutorial/java/nutsandbolts/operators.html
+ name: "operator",
+ pattern: /(\+{1,2}|-{1,2}|~|!|\*|\/|%|(?:<){1,2}|(?:>){1,3}|instanceof|(?:&){1,2}|\^|\|{1,2}|\?|:|(?:=|!|\+|-|\*|\/|%|\^|\||(?:<){1,2}|(?:>){1,3})?=)/g
+ }
+ ],
+ c: [
+ {
+ name: 'meta.preprocessor',
+ matches: {
+ 1: [
+ {
+ matches: {
+ 1: 'keyword.define',
+ 2: 'entity.name'
+ },
+ pattern: /(\w+)\s(\w+)\b/g
+ },
+ {
+ name: 'keyword.define',
+ pattern: /endif/g
+ },
+ {
+ name: 'constant.numeric',
+ pattern: /\d+/g
+ },
+ {
+ matches: {
+ 1: 'keyword.include',
+ 2: 'string'
+ },
+ pattern: /(include)\s(.*?)$/g
+ }
+ ]
+ },
+ pattern: /\#([\S\s]*?)$/gm
+ },
+ {
+ name: 'keyword',
+ pattern: /\b(do|goto|typedef)\b/g
+ },
+ {
+ name: 'entity.label',
+ pattern: /\w+:/g
+ },
+ {
+ matches: {
+ 1: 'storage.type',
+ 3: 'storage.type',
+ 4: 'entity.name.function'
+ },
+ pattern: /\b((un)?signed|const)? ?(void|char|short|int|long|float|double)\*? +((\w+)(?= ?\())?/g
+ },
+ {
+ matches: {
+ 2: 'entity.name.function'
+ },
+ pattern: /(\w|\*) +((\w+)(?= ?\())/g
+ },
+ {
+ name: 'storage.modifier',
+ pattern: /\b(static|extern|auto|register|volatile|inline)\b/g
+ },
+ {
+ name: 'support.type',
+ pattern: /\b(struct|union|enum)\b/g
+ }
+ ],
+ coffescript: [
+ {
+ name: 'comment.block',
+ pattern: /(\#{3})[\s\S]*\1/gm
+ },
+ {
+ name: 'string.block',
+ pattern: /('{3}|"{3})[\s\S]*\1/gm
+ },
+
+ /**
+ * multiline regex with comments
+ */
+ {
+ name: 'string.regex',
+ matches: {
+ 2: {
+ name: 'comment',
+ pattern: /\#(.*?)(?=\n)/g
+ }
+ },
+ pattern: /(\/{3})([\s\S]*)\1/gm
+ },
+ {
+ matches: {
+ 1: 'keyword'
+ },
+ pattern: /\b(in|when|is|isnt|of|not|unless|until|super)(?=\b)/gi
+ },
+ {
+ name: 'keyword.operator',
+ pattern: /\?/g
+ },
+ {
+ name: 'constant.language',
+ pattern: /\b(undefined|yes|on|no|off)\b/g
+ },
+ {
+ name: 'keyword.variable.coffee',
+ pattern: /@(\w+)/gi
+ },
+
+ /**
+ * reset global keywards from generic
+ */
+ {
+ name: 'reset',
+ pattern: /object|class|print/gi
+ },
+
+ /**
+ * named function
+ */
+ {
+ 'matches' : {
+ 1: 'entity.name.function',
+ 2: 'keyword.operator',
+ 3: {
+ name: 'function.argument.coffee',
+ pattern: /([\@\w]+)/g
+ },
+ 4: 'keyword.function'
+ },
+ pattern: /(\w+)\s{0,}(=|:)\s{0,}\((.*?)((-|=)>)/gi
+ },
+
+ /**
+ * anonymous function
+ */
+ {
+ matches: {
+ 1: {
+ name: 'function.argument.coffee',
+ pattern: /([\@\w]+)/g
+ },
+ 2: 'keyword.function'
+ },
+ pattern: /\s\((.*?)\)\s{0,}((-|=)>)/gi
+ },
+
+ /**
+ * direct function no arguments
+ */
+ {
+ 'matches' : {
+ 1: 'entity.name.function',
+ 2: 'keyword.operator',
+ 3: 'keyword.function'
+ },
+ pattern: /(\w+)\s{0,}(=|:)\s{0,}((-|=)>)/gi
+ },
+
+ /**
+ * class definitions
+ */
+ {
+ matches: {
+ 1: 'storage.class',
+ 2: 'entity.name.class',
+ 3: 'storage.modifier.extends',
+ 4: 'entity.other.inherited-class'
+ },
+ pattern: /\b(class)\s(\w+)(\sextends\s)?([\w\\]*)?\b/g
+ },
+
+ /**
+ * object instantiation
+ */
+ {
+ matches: {
+ 1: 'keyword.new',
+ 2: {
+ name: 'support.class',
+ pattern: /\w+/g
+ }
+ },
+ pattern: /\b(new)\s(.*?)(?=\s)/g
+ }
+ ],
+ 'c#': [
+ {
+ // @see http://msdn.microsoft.com/en-us/library/23954zh5.aspx
+ name: 'constant',
+ pattern: /\b(false|null|true)\b/g
+ },
+ {
+ // @see http://msdn.microsoft.com/en-us/library/x53a06bb%28v=vs.100%29.aspx
+ // Does not support putting an @ in front of a keyword which makes it not a keyword anymore.
+ name: 'keyword',
+ pattern: /\b(abstract|add|alias|ascending|as|async|await|base|bool|break|byte|case|catch|char|checked|class|const|continue|decimal|default|delegate|descending|double|do|dynamic|else|enum|event|explicit|extern|false|finally|fixed|float|foreach|for|from|get|global|goto|group|if|implicit|int|interface|internal|into|in|is|join|let|lock|long|namespace|new|object|operator|orderby|out|override|params|partial|private|protected|public|readonly|ref|remove|return|sbyte|sealed|select|set|short|sizeof|stackalloc|static|string|struct|switch|this|throw|try|typeof|uint|unchecked|ulong|unsafe|ushort|using|value|var|virtual|void|volatile|where|while|yield)\b/g
+ },
+ {
+ matches: {
+ 1: 'keyword',
+ 2: {
+ name: 'support.class',
+ pattern: /\w+/g
+ }
+ },
+ pattern: /(typeof)\s([^\$].*?)(\)|;)/g
+ },
+ {
+ matches: {
+ 1: 'keyword.namespace',
+ 2: {
+ name: 'support.namespace',
+ pattern: /\w+/g
+ }
+ },
+ pattern: /\b(namespace)\s(.*?);/g
+ },
+ {
+ matches: {
+ 1: 'storage.modifier',
+ 2: 'storage.class',
+ 3: 'entity.name.class',
+ 4: 'storage.modifier.extends',
+ 5: 'entity.other.inherited-class'
+ },
+ pattern: /\b(abstract|sealed)?\s?(class)\s(\w+)(\sextends\s)?([\w\\]*)?\s?\{?(\n|\})/g
+ },
+ {
+ name: 'keyword.static',
+ pattern: /\b(static)\b/g
+ },
+ {
+ matches: {
+ 1: 'keyword.new',
+ 2: {
+ name: 'support.class',
+ pattern: /\w+/g
+ }
+
+ },
+ pattern: /\b(new)\s([^\$].*?)(?=\)|\(|;|&)/g
+ },
+ {
+ name: 'string',
+ pattern: /(")(.*?)\1/g
+ },
+ {
+ name: 'integer',
+ pattern: /\b(0x[\da-f]+|\d+)\b/g
+ },
+ {
+ name: 'comment',
+ pattern: /\/\*[\s\S]*?\*\/|(\/\/)[\s\S]*?$/gm
+ },
+ {
+ name: 'operator',
+ // @see http://msdn.microsoft.com/en-us/library/6a71f45d%28v=vs.100%29.aspx
+ // ++ += + -- -= - <<= << <= => >>= >> >= != ! ~ ^ || && &= & ?? :: : *= * |= %= |= == =
+ pattern: /(\+\+|\+=|\+|--|-=|-|<<=|<<|<=|=>|>>=|>>|>=|!=|!|~|\^|\|\||&&|&=|&|\?\?|::|:|\*=|\*|\/=|%=|\|=|==|=)/g
+ },
+ {
+ // @see http://msdn.microsoft.com/en-us/library/ed8yd1ha%28v=vs.100%29.aspx
+ name: 'preprocessor',
+ pattern: /(\#if|\#else|\#elif|\#endif|\#define|\#undef|\#warning|\#error|\#line|\#region|\#endregion|\#pragma)[\s\S]*?$/gm
+ }
+ ],
+ css: [
+ {
+ name: 'comment',
+ pattern: /\/\*[\s\S]*?\*\//gm
+ },
+ {
+ name: 'constant.hex-color',
+ pattern: /#([a-f0-9]{3}|[a-f0-9]{6})(?=;|\s|,|\))/gi
+ },
+ {
+ matches: {
+ 1: 'constant.numeric',
+ 2: 'keyword.unit'
+ },
+ pattern: /(\d+)(px|em|cm|s|%)?/g
+ },
+ {
+ name: 'string',
+ pattern: /('|")(.*?)\1/g
+ },
+ {
+ name: 'support.css-property',
+ matches: {
+ 1: 'support.vendor-prefix'
+ },
+ pattern: /(-o-|-moz-|-webkit-|-ms-)?[\w-]+(?=\s?:)(?!.*\{)/g
+ },
+ {
+ matches: {
+ 1: [
+ {
+ name: 'entity.name.sass',
+ pattern: /&/g
+ },
+ {
+ name: 'direct-descendant',
+ pattern: />/g
+ },
+ {
+ name: 'entity.name.class',
+ pattern: /\.[\w\-_]+/g
+ },
+ {
+ name: 'entity.name.id',
+ pattern: /\#[\w\-_]+/g
+ },
+ {
+ name: 'entity.name.pseudo',
+ pattern: /:[\w\-_]+/g
+ },
+ {
+ name: 'entity.name.tag',
+ pattern: /\w+/g
+ }
+ ]
+ },
+ pattern: /([\w\ ,\n:\.\#\&\;\-_]+)(?=.*\{)/g
+ },
+ {
+ matches: {
+ 2: 'support.vendor-prefix',
+ 3: 'support.css-value'
+ },
+ pattern: /(:|,)\s*(-o-|-moz-|-webkit-|-ms-)?([a-zA-Z-]*)(?=\b)(?!.*\{)/g
+ }
+ ],
+ go: [
+ {
+ matches: {
+ 1: [
+ {
+ name: 'keyword.operator',
+ pattern: /\=|\+/g
+ }
+ ],
+ 2: {
+ name: 'string',
+ matches: {
+ name: 'constant.character.escape',
+ pattern: /\\(`|"){1}/g
+ }
+ }
+ },
+ pattern: /(\(|\s|\[|\=|:|\+|\{|,)((`|")([^\\\1]|\\.)*?(\3))/gm
+ },
+ {
+ name: 'comment',
+ pattern: /\/\*[\s\S]*?\*\/|(\/\/)(?!.*(`|").*?\1).*?$/gm
+ },
+ {
+ matches: {
+ 1: 'keyword'
+ },
+ pattern: /\b(d(efault|efer)|fallthrough|go(to)?|range|select)(?=\b)/gi
+ },
+ {
+ name: 'keyword',
+ pattern: /\bpackage(?=\s*\w)/gi
+ },
+ {
+ matches: {
+ 1: 'storage.type',
+ 2: 'entity.name.struct'
+ },
+ pattern: /\b(type)\s+(\w+)\b(?=\s+struct\b)/gi
+ },
+ {
+ matches: {
+ 1: 'storage.type',
+ 2: 'entity.name.type'
+ },
+ pattern: /\b(type)\s+(\w+)\b/gi
+ },
+ {
+ name: 'storage.type',
+ pattern: /\b(bool|byte|complex(64|128)|float(32|64)|func|interface|map|rune|string|struct|u?int(8|16|32|64)?|var)(?=\b)/g
+ },
+ {
+ name: 'keyword.operator.initialize',
+ pattern: /\:=/g
+ },
+ {
+ matches: {
+ 1: 'storage.function',
+ 2: 'entity.name.function'
+ },
+ pattern: /(func)\s+(?:\(.*?\))\s+(.*?)(?=\()/g
+ },
+ {
+ matches: {
+ 1: 'storage.function',
+ 2: 'entity.name.function'
+ },
+ pattern: /(func)\s+(.*?)(?=\()/g
+ }
+ ],
+ html : [
+ {
+ name: 'source.php.embedded',
+ matches: {
+ 1: 'variable.language.php-tag',
+ 2: {
+ language: 'php'
+ },
+ 3: 'variable.language.php-tag'
+ },
+ pattern: /(<\?php|<\?=?(?!xml))([\s\S]*?)(\?>)/gm
+ },
+ {
+ name: 'source.css.embedded',
+ matches: {
+ 1: {
+ matches: {
+ 1: 'support.tag.style',
+ 2: [
+ {
+ name: 'entity.tag.style',
+ pattern: /^style/g
+ },
+ {
+ name: 'string',
+ pattern: /('|")(.*?)(\1)/g
+ },
+ {
+ name: 'entity.tag.style.attribute',
+ pattern: /(\w+)/g
+ }
+ ],
+ 3: 'support.tag.style'
+ },
+ pattern: /(<\/?)(style.*?)(>)/g
+ },
+ 2: {
+ language: 'css'
+ },
+ 3: 'support.tag.style',
+ 4: 'entity.tag.style',
+ 5: 'support.tag.style'
+ },
+ pattern: /(<style.*?>)([\s\S]*?)(<\/)(style)(>)/gm
+ },
+ {
+ name: 'source.js.embedded',
+ matches: {
+ 1: {
+ matches: {
+ 1: 'support.tag.script',
+ 2: [
+ {
+ name: 'entity.tag.script',
+ pattern: /^script/g
+ },
+
+ {
+ name: 'string',
+ pattern: /('|")(.*?)(\1)/g
+ },
+ {
+ name: 'entity.tag.script.attribute',
+ pattern: /(\w+)/g
+ }
+ ],
+ 3: 'support.tag.script'
+ },
+ pattern: /(<\/?)(script.*?)(>)/g
+ },
+ 2: {
+ language: 'javascript'
+ },
+ 3: 'support.tag.script',
+ 4: 'entity.tag.script',
+ 5: 'support.tag.script'
+ },
+ pattern: /(<script(?! src).*?>)([\s\S]*?)(<\/)(script)(>)/gm
+ },
+ {
+ name: 'comment.html',
+ pattern: /<\!--[\S\s]*?-->/g
+ },
+ {
+ matches: {
+ 1: 'support.tag.open',
+ 2: 'support.tag.close'
+ },
+ pattern: /(<)|(\/?\??>)/g
+ },
+ {
+ name: 'support.tag',
+ matches: {
+ 1: 'support.tag',
+ 2: 'support.tag.special',
+ 3: 'support.tag-name'
+ },
+ pattern: /(<\??)(\/|\!?)(\w+)/g
+ },
+ {
+ matches: {
+ 1: 'support.attribute'
+ },
+ pattern: /([a-z-]+)(?=\=)/gi
+ },
+ {
+ matches: {
+ 1: 'support.operator',
+ 2: 'string.quote',
+ 3: 'string.value',
+ 4: 'string.quote'
+ },
+ pattern: /(=)('|")(.*?)(\2)/g
+ },
+ {
+ matches: {
+ 1: 'support.operator',
+ 2: 'support.value'
+ },
+ pattern: /(=)([a-zA-Z\-0-9]*)\b/g
+ },
+ {
+ matches: {
+ 1: 'support.attribute'
+ },
+ pattern: /\s([\w-]+)(?=\s|>)(?![\s\S]*<)/g
+ }
+ ],
+ json : [
+ {
+ matches: {
+ 0: {
+ name: 'string',
+ matches: {
+ name: 'constant.character.escape',
+ pattern: /\\('|"){1}/g
+ }
+ }
+ },
+ pattern: /(\"|\')(\\?.)*?\1/g
+ },
+ {
+ name: 'constant.numeric',
+ pattern: /\b(-?(0x)?\d*\.?[\da-f]+|NaN|-?Infinity)\b/gi
+ },
+ {
+ name: 'constant.language',
+ pattern: /\b(true|false|null)\b/g
+ }
+ ],
+ lua: [
+ {
+ matches: {
+ 1: {
+ name: 'keyword.operator',
+ pattern: /\=/g
+ },
+ 2: {
+ name: 'string',
+ matches: {
+ name: 'constant.character.escape',
+ pattern: /\\('|"){1}/g
+ }
+ }
+ },
+ pattern: /(\(|\s|\[|\=)(('|")([^\\\1]|\\.)*?(\3))/gm
+ },
+ {
+ name: 'comment',
+ pattern: /\-{2}\[{2}\-{2}[\s\S]*?\-{2}\]{2}\-{2}|(\-{2})[\s\S]*?$/gm
+ },
+ {
+ name: 'constant.numeric',
+ pattern: /\b(\d+(\.\d+)?(e(\+|\-)?\d+)?(f|d)?|0x[\da-f]+)\b/gi
+ },
+ {
+ matches: {
+ 1: 'keyword'
+ },
+ pattern: /\b((a|e)nd|in|repeat|break|local|return|do|for|then|else(if)?|function|not|if|or|until|while)(?=\b)/gi
+ },
+ {
+ name: 'constant.language',
+ pattern: /true|false|nil/g
+ },
+ {
+ name: 'keyword.operator',
+ pattern: /\+|\!|\-|&(gt|lt|amp);|\||\*|\=|#|\.{2}/g
+ },
+ {
+ matches: {
+ 1: 'storage.function',
+ 2: 'entity.name.function'
+ },
+ pattern: /(function)\s+(\w+[\:|\.]?\w+?)(?=\()/g
+ },
+ {
+ matches: {
+ 1: 'support.function'
+ },
+ pattern: /\b(print|require|module|\w+\.\w+)(?=\()/g
+ }
+ ],
+ php: [
+ {
+ name: 'support',
+ pattern: /\becho\b/ig
+ },
+ {
+ matches: {
+ 1: 'variable.dollar-sign',
+ 2: 'variable'
+ },
+ pattern: /(\$)(\w+)\b/g
+ },
+ {
+ name: 'constant.language',
+ pattern: /true|false|null/ig
+ },
+ {
+ name: 'constant',
+ pattern: /\b[A-Z0-9_]{2,}\b/g
+ },
+ {
+ name: 'keyword.dot',
+ pattern: /\./g
+ },
+ {
+ name: 'keyword',
+ pattern: /\b(die|end(for(each)?|switch|if)|case|require(_once)?|include(_once)?)(?=\b)/ig
+ },
+ {
+ matches: {
+ 1: 'keyword',
+ 2: {
+ name: 'support.class',
+ pattern: /\w+/g
+ }
+ },
+ pattern: /(instanceof)\s([^\$].*?)(\)|;)/ig
+ },
+
+ /**
+ * these are the top 50 most used PHP functions
+ * found from running a script and checking the frequency of each function
+ * over a bunch of popular PHP frameworks then combining the results
+ */
+ {
+ matches: {
+ 1: 'support.function'
+ },
+ pattern: /\b(array(_key_exists|_merge|_keys|_shift)?|isset|count|empty|unset|printf|is_(array|string|numeric|object)|sprintf|each|date|time|substr|pos|str(len|pos|tolower|_replace|totime)?|ord|trim|in_array|implode|end|preg_match|explode|fmod|define|link|list|get_class|serialize|file|sort|mail|dir|idate|log|intval|header|chr|function_exists|dirname|preg_replace|file_exists)(?=\()/ig
+ },
+ {
+ name: 'variable.language.php-tag',
+ pattern: /(<\?(php)?|\?>)/ig
+ },
+ {
+ matches: {
+ 1: 'keyword.namespace',
+ 2: {
+ name: 'support.namespace',
+ pattern: /\w+/g
+ }
+ },
+ pattern: /\b(namespace|use)\s(.*?);/ig
+ },
+ {
+ matches: {
+ 1: 'storage.modifier',
+ 2: 'storage.class',
+ 3: 'entity.name.class',
+ 4: 'storage.modifier.extends',
+ 5: 'entity.other.inherited-class',
+ 6: 'storage.modifier.extends',
+ 7: 'entity.other.inherited-class'
+ },
+ pattern: /\b(abstract|final)?\s?(class|interface|trait)\s(\w+)(\sextends\s)?([\w\\]*)?(\simplements\s)?([\w\\]*)?\s?\{?(\n|\})/ig
+ },
+ {
+ name: 'keyword.static',
+ pattern: /self::|static::/ig
+ },
+ {
+ matches: {
+ 1: 'storage.function',
+ 2: 'entity.name.function.magic'
+ },
+ pattern: /(function)\s(__.*?)(?=\()/ig
+ },
+ {
+ matches: {
+ 1: 'storage.function',
+ 2: 'entity.name.function'
+ },
+ pattern: /(function)\s(.*?)(?=\()/ig
+ },
+ {
+ matches: {
+ 1: 'keyword.new',
+ 2: {
+ name: 'support.class',
+ pattern: /\w+/g
+ }
+ },
+ pattern: /\b(new)\s([^\$][a-z0-9_\\]*?)(?=\)|\(|;)/ig
+ },
+ {
+ matches: {
+ 1: {
+ name: 'support.class',
+ pattern: /\w+/g
+ },
+ 2: 'keyword.static'
+ },
+ pattern: /([\w\\]*?)(::)(?=\b|\$)/g
+ },
+ {
+ matches: {
+ 2: {
+ name: 'support.class',
+ pattern: /\w+/g
+ }
+ },
+ pattern: /(\(|,\s?)([\w\\]*?)(?=\s\$)/g
+ }
+ ],
+ ruby: [
+ /**
+ * __END__ DATA
+ */
+ {
+ matches: {
+ 1: 'variable.language',
+ 2: {
+ language: null
+ }
+ },
+ //find __END__ and consume remaining text
+ pattern: /^(__END__)\n((?:.*\n)*)/gm
+ },
+ /**
+ * Strings
+ * 1. No support for multi-line strings
+ */
+ {
+ name: 'string',
+ matches: {
+ 1: 'string.open',
+ 2: [{
+ name: 'string.interpolation',
+ matches: {
+ 1: 'string.open',
+ 2: {
+ language: 'ruby'
+ },
+ 3: 'string.close'
+ },
+ pattern: /(\#\{)(.*?)(\})/g
+ }],
+ 3: 'string.close'
+ },
+ pattern: /("|`)(.*?[^\\\1])?(\1)/g
+ },
+ {
+ name: 'string',
+ pattern: /('|"|`)([^\\\1\n]|\\.)*?\1/g
+ },
+ {
+ name: 'string',
+ pattern: /%[qQ](?=(\(|\[|\{|<|.)(.*?)(?:'|\)|\]|\}|>|\1))(?:\(\2\)|\[\2\]|\{\2\}|\<\2>|\1\2\1)/g
+ },
+ /**
+ * Heredocs
+ * Heredocs of the form `<<'HTML' ... HTML` are unsupported.
+ */
+ {
+ matches: {
+ 1: 'string',
+ 2: 'string',
+ 3: 'string'
+ },
+ pattern: /(<<)(\w+).*?$([\s\S]*?^\2)/gm
+ },
+ {
+ matches: {
+ 1: 'string',
+ 2: 'string',
+ 3: 'string'
+ },
+ pattern: /(<<\-)(\w+).*?$([\s\S]*?\2)/gm
+ },
+ /**
+ * Regular expressions
+ * Escaped delimiter (`/\//`) is unsupported.
+ */
+ {
+ name: 'string.regexp',
+ matches: {
+ 1: 'string.regexp',
+ 2: {
+ name: 'string.regexp',
+ pattern: /\\(.){1}/g
+ },
+ 3: 'string.regexp',
+ 4: 'string.regexp'
+ },
+ pattern: /(\/)(.*?)(\/)([a-z]*)/g
+ },
+ {
+ name: 'string.regexp',
+ matches: {
+ 1: 'string.regexp',
+ 2: {
+ name: 'string.regexp',
+ pattern: /\\(.){1}/g
+ },
+ 3: 'string.regexp',
+ 4: 'string.regexp'
+ },
+ pattern: /%r(?=(\(|\[|\{|<|.)(.*?)('|\)|\]|\}|>|\1))(?:\(\2\)|\[\2\]|\{\2\}|\<\2>|\1\2\1)([a-z]*)/g
+ },
+ /**
+ * Comments
+ */
+ {
+ name: 'comment',
+ pattern: /#.*$/gm
+ },
+ {
+ name: 'comment',
+ pattern: /^\=begin[\s\S]*?\=end$/gm
+ },
+ /**
+ * Symbols
+ */
+ {
+ matches: {
+ 1: 'constant'
+ },
+ pattern: /(\w+:)[^:]/g
+ },
+ {
+ matches: {
+ 1: 'constant.symbol'
+ },
+ pattern: /[^:](:(?:\w+|(?=['"](.*?)['"])(?:"\2"|'\2')))/g
+ },
+ {
+ name: 'constant.numeric',
+ pattern: /\b(0x[\da-f]+|[\d_]+)\b/g
+ },
+ {
+ name: 'support.class',
+ pattern: /\b[A-Z]\w*(?=((\.|::)[A-Za-z]|\[))/g
+ },
+ {
+ name: 'constant',
+ pattern: /\b[A-Z]\w*\b/g
+ },
+ /**
+ * Keywords, variables, constants, and operators
+ * In Ruby some keywords are valid method names, e.g., MyClass#yield
+ * Don't mark those instances as "keywords"
+ */
+ {
+ matches: {
+ 1: 'storage.class',
+ 2: 'entity.name.class',
+ 3: 'entity.other.inherited-class'
+ },
+ pattern: /\s*(class)\s+((?:(?:::)?[A-Z]\w*)+)(?:\s+<\s+((?:(?:::)?[A-Z]\w*)+))?/g
+ },
+ {
+ matches: {
+ 1: 'storage.module',
+ 2: 'entity.name.class'
+ },
+ pattern: /\s*(module)\s+((?:(?:::)?[A-Z]\w*)+)/g
+ },
+ {
+ name: 'variable.global',
+ pattern: /\$([a-zA-Z_]\w*)\b/g
+ },
+ {
+ name: 'variable.class',
+ pattern: /@@([a-zA-Z_]\w*)\b/g
+ },
+ {
+ name: 'variable.instance',
+ pattern: /@([a-zA-Z_]\w*)\b/g
+ },
+ {
+ matches: {
+ 1: 'keyword.control'
+ },
+ pattern: /[^\.]\b(BEGIN|begin|case|class|do|else|elsif|END|end|ensure|for|if|in|module|rescue|then|unless|until|when|while)\b(?![?!])/g
+ },
+ {
+ matches: {
+ 1: 'keyword.control.pseudo-method'
+ },
+ pattern: /[^\.]\b(alias|alias_method|break|next|redo|retry|return|super|undef|yield)\b(?![?!])|\bdefined\?|\bblock_given\?/g
+ },
+ {
+ matches: {
+ 1: 'constant.language'
+ },
+ pattern: /\b(nil|true|false)\b(?![?!])/g
+ },
+ {
+ matches: {
+ 1: 'variable.language'
+ },
+ pattern: /\b(__(FILE|LINE)__|self)\b(?![?!])/g
+ },
+ {
+ matches: {
+ 1: 'keyword.special-method'
+ },
+ pattern: /\b(require|gem|initialize|new|loop|include|extend|raise|attr_reader|attr_writer|attr_accessor|attr|catch|throw|private|module_function|public|protected)\b(?![?!])/g
+ },
+ {
+ name: 'keyword.operator',
+ pattern: /\s\?\s|=|<<|<<=|%=|&=|\*=|\*\*=|\+=|\-=|\^=|\|{1,2}=|<<|<=>|<(?!<|=)|>(?!<|=|>)|<=|>=|===|==|=~|!=|!~|%|&|\*\*|\*|\+|\-|\/|\||~|>>/g
+ },
+ {
+ matches: {
+ 1: 'keyword.operator.logical'
+ },
+ pattern: /[^\.]\b(and|not|or)\b/g
+ },
+
+ /**
+ * Functions
+ * 1. No support for marking function parameters
+ */
+ {
+ matches: {
+ 1: 'storage.function',
+ 2: 'entity.name.function'
+ },
+ pattern: /(def)\s(.*?)(?=(\s|\())/g
+ }
+ ],
+ sql: [
+ {
+ matches: {
+ 2: {
+ name: 'string',
+ matches: {
+ name: 'constant.character.escape',
+ pattern: /\\('|"|`){1}/g
+ }
+ }
+ },
+ pattern: /(\(|\s|\[|\=|:|\+|\.|\{|,)(('|"|`)([^\\\1]|\\.)*?(\3))/gm
+ },
+ {
+ name: 'comment',
+ pattern: /--.*$|\/\*[\s\S]*?\*\/|(\/\/)[\s\S]*?$/gm
+ },
+ {
+ name: 'constant.numeric',
+ pattern: /\b(\d+(\.\d+)?(e(\+|\-)?\d+)?(f|d)?|0x[\da-f]+)\b/gi
+ },
+ {
+ name: 'function.call',
+ pattern: /(\w+?)(?=\()/g
+ },
+ {
+ name: 'keyword',
+ pattern: /\b(ABSOLUTE|ACTION|ADA|ADD|ALL|ALLOCATE|ALTER|AND|ANY|ARE|AS|ASC|ASSERTION|AT|AUTHORIZATION|AVG|BEGIN|BETWEEN|BIT|BIT_LENGTH|BOTH|BY|CASCADE|CASCADED|CASE|CAST|CATALOG|CHAR|CHARACTER|CHARACTER_LENGTH|CHAR_LENGTH|CHECK|CLOSE|COALESCE|COLLATE|COLLATION|COLUMN|COMMIT|CONNECT|CONNECTION|CONSTRAINT|CONSTRAINTS|CONTINUE|CONVERT|CORRESPONDING|COUNT|CREATE|CROSS|CURRENT|CURRENT_DATE|CURRENT_TIME|CURRENT_TIMESTAMP|CURRENT_USER|CURSOR|DATE|DAY|DEALLOCATE|DEC|DECIMAL|DECLARE|DEFAULT|DEFERRABLE|DEFERRED|DELETE|DESC|DESCRIBE|DESCRIPTOR|DIAGNOSTICS|DISCONNECT|DISTINCT|DOMAIN|DOUBLE|DROP|ELSE|END|END-EXEC|ESCAPE|EXCEPT|EXCEPTION|EXEC|EXECUTE|EXISTS|EXTERNAL|EXTRACT|FALSE|FETCH|FIRST|FLOAT|FOR|FOREIGN|FORTRAN|FOUND|FROM|FULL|GET|GLOBAL|GO|GOTO|GRANT|GROUP|HAVING|HOUR|IDENTITY|IMMEDIATE|IN|INCLUDE|INDEX|INDICATOR|INITIALLY|INNER|INPUT|INSENSITIVE|INSERT|INT|INTEGER|INTERSECT|INTERVAL|INTO|IS|ISOLATION|JOIN|KEY|LANGUAGE|LAST|LEADING|LEFT|LEVEL|LIKE|LIMIT|LOCAL|LOWER|MATCH|MAX|MIN|MINUTE|MODULE|MONTH|NAMES|NATIONAL|NATURAL|NCHAR|NEXT|NO|NONE|NOT|NULL|NULLIF|NUMERIC|OCTET_LENGTH|OF|ON|ONLY|OPEN|OPTION|OR|ORDER|OUTER|OUTPUT|OVERLAPS|PAD|PARTIAL|PASCAL|POSITION|PRECISION|PREPARE|PRESERVE|PRIMARY|PRIOR|PRIVILEGES|PROCEDURE|PUBLIC|READ|REAL|REFERENCES|RELATIVE|RESTRICT|REVOKE|RIGHT|ROLLBACK|ROWS|SCHEMA|SCROLL|SECOND|SECTION|SELECT|SESSION|SESSION_USER|SET|SIZE|SMALLINT|SOME|SPACE|SQL|SQLCA|SQLCODE|SQLERROR|SQLSTATE|SQLWARNING|SUBSTRING|SUM|SYSTEM_USER|TABLE|TEMPORARY|THEN|TIME|TIMESTAMP|TIMEZONE_HOUR|TIMEZONE_MINUTE|TO|TRAILING|TRANSACTION|TRANSLATE|TRANSLATION|TRIM|TRUE|UNION|UNIQUE|UNKNOWN|UPDATE|UPPER|USAGE|USER|USING|VALUE|VALUES|VARCHAR|VARYING|VIEW|WHEN|WHENEVER|WHERE|WITH|WORK|WRITE|YEAR|ZONE|USE)(?=\b)/gi
+ },
+ {
+ name: 'keyword.operator',
+ pattern: /\+|\!|\-|&(gt|lt|amp);|\||\*|=/g
+ }
+ ],
+ scheme: [
+ {
+ /* making peace with HTML */
+ name: 'plain',
+ pattern: />|</g
+ },
+ {
+ name: 'comment',
+ pattern: /;.*$/gm
+ },
+ {
+ name: 'constant.language',
+ pattern: /#t|#f|'\(\)/g
+ },
+ {
+ name: 'constant.symbol',
+ pattern: /'[^()\s#]+/g
+ },
+ {
+ name: 'constant.number',
+ pattern: /\b\d+(?:\.\d*)?\b/g
+ },
+ {
+ name: 'string',
+ pattern: /".+?"/g
+ },
+ {
+ matches: {
+ 1: 'storage.function',
+ 2: 'variable'
+ },
+ pattern: /\(\s*(define)\s+\(?(\S+)/g
+ },
+ {
+ matches: {
+ 1: 'keyword'
+ },
+ pattern: /\(\s*(begin|define\-syntax|if|lambda|quasiquote|quote|set!|syntax\-rules|and|and\-let\*|case|cond|delay|do|else|or|let|let\*|let\-syntax|letrec|letrec\-syntax)(?=[\]()\s#])/g
+ },
+ {
+ matches: {
+ 1: 'entity.function'
+ },
+ pattern: /\(\s*(eqv\?|eq\?|equal\?|number\?|complex\?|real\?|rational\?|integer\?|exact\?|inexact\?|=|<|>|<=|>=|zero\?|positive\?|negative\?|odd\?|even\?|max|min|\+|\-|\*|\/|abs|quotient|remainder|modulo|gcd|lcm|numerator|denominator|floor|ceiling|truncate|round|rationalize|exp|log|sin|cos|tan|asin|acos|atan|sqrt|expt|make\-rectangular|make\-polar|real\-part|imag\-part|magnitude|angle|exact\->inexact|inexact\->exact|number\->string|string\->number|not|boolean\?|pair\?|cons|car|cdr|set\-car!|set\-cdr!|caar|cadr|cdar|cddr|caaar|caadr|cadar|caddr|cdaar|cdadr|cddar|cdddr|caaaar|caaadr|caadar|caaddr|cadaar|cadadr|caddar|cadddr|cdaaar|cdaadr|cdadar|cdaddr|cddaar|cddadr|cdddar|cddddr|null\?|list\?|list|length|append|reverse|list\-tail|list\-ref|memq|memv|member|assq|assv|assoc|symbol\?|symbol\->string|string\->symbol|char\?|char=\?|char<\?|char>\?|char<=\?|char>=\?|char\-ci=\?|char\-ci<\?|char\-ci>\?|char\-ci<=\?|char\-ci>=\?|char\-alphabetic\?|char\-numeric\?|char\-whitespace\?|char\-upper\-case\?|char\-lower\-case\?|char\->integer|integer\->char|char\-upcase|char\-downcase|string\?|make\-string|string|string\-length|string\-ref|string\-set!|string=\?|string\-ci=\?|string<\?|string>\?|string<=\?|string>=\?|string\-ci<\?|string\-ci>\?|string\-ci<=\?|string\-ci>=\?|substring|string\-append|string\->list|list\->string|string\-copy|string\-fill!|vector\?|make\-vector|vector|vector\-length|vector\-ref|vector\-set!|vector\->list|list\->vector|vector\-fill!|procedure\?|apply|map|for\-each|force|call\-with\-current\-continuation|call\/cc|values|call\-with\-values|dynamic\-wind|eval|scheme\-report\-environment|null\-environment|interaction\-environment|call\-with\-input\-file|call\-with\-output\-file|input\-port\?|output\-port\?|current\-input\-port|current\-output\-port|with\-input\-from\-file|with\-output\-to\-file|open\-input\-file|open\-output\-file|close\-input\-port|close\-output\-port|read|read\-char|peek\-char|eof\-object\?|char\-ready\?|write|display|newline|write\-char|load|transcript\-on|transcript\-off)(?=[\]()\s#])/g
+ }
+ ],
+ r: [
+ /**
+ * Note that a valid variable name is of the form:
+ * [.a-zA-Z][0-9a-zA-Z._]*
+ */
+ {
+ matches: {
+ 1: {
+ name: 'keyword.operator',
+ pattern: /\=|<\-|<-/g
+ },
+ 2: {
+ name: 'string',
+ matches: {
+ name: 'constant.character.escape',
+ pattern: /\\('|"){1}/g
+ }
+ }
+ },
+ pattern: /(\(|\s|\[|\=|:)(('|")([^\\\1]|\\.)*?(\3))/gm
+ },
+
+ /**
+ * Most of these are known via the Language Reference.
+ * The built-in constant symbols are known via ?Constants.
+ */
+ {
+ matches: {
+ 1: 'constant.language'
+ },
+ pattern: /\b(NULL|NA|TRUE|FALSE|T|F|NaN|Inf|NA_integer_|NA_real_|NA_complex_|NA_character_)\b/g
+ },
+ {
+ matches: {
+ 1: 'constant.symbol'
+ },
+ pattern: /[^0-9a-zA-Z\._](LETTERS|letters|month\.(abb|name)|pi)/g
+ },
+
+ /**
+ * @todo: The list subsetting operator isn't quite working properly.
+ * It includes the previous variable when it should only match [[
+ */
+ {
+ name: 'keyword.operator',
+ pattern: /<-|<-|-|==|<=|<=|>>|>=|<|>|&&|&&|&|&|!=|\|\|?|\*|\+|\^|\/|%%|%\/%|\=|%in%|%\*%|%o%|%x%|\$|:|~|\[{1,2}|\]{1,2}/g
+ },
+ {
+ matches: {
+ 1: 'storage',
+ 3: 'entity.function'
+ },
+ pattern: /(\s|^)(.*)(?=\s?=\s?function\s\()/g
+ },
+ {
+ matches: {
+ 1: 'storage.function'
+ },
+ pattern: /[^a-zA-Z0-9._](function)(?=\s*\()/g
+ },
+ {
+ matches: {
+ 1: 'namespace',
+ 2: 'keyword.operator',
+ 3: 'function.call'
+ },
+ pattern: /([a-zA-Z][a-zA-Z0-9._]+)([:]{2,3})([.a-zA-Z][a-zA-Z0-9._]*(?=\s*\())\b/g
+ },
+
+ /*
+ * Note that we would perhaps match more builtin functions and
+ * variables, but there are so many that most are ommitted for now.
+ * See ?builtins for more info.
+ *
+ * @todo: Fix the case where we have a function like tmp.logical().
+ * This should just be a function call, at the moment it's
+ * only partly a function all.
+ */
+ {
+ name: 'support.function',
+ pattern: /(^|[^0-9a-zA-Z\._])(array|character|complex|data\.frame|double|integer|list|logical|matrix|numeric|vector)(?=\s*\()/g
+ }
+ ],
+ haskell: [
+ ///- Comments
+ {
+ name: 'comment',
+ pattern: /\{\-\-[\s\S(\w+)]+[\-\-][\}$]/gm
+ // /\{\-{2}[\s\S(.*)]+[\-\-][\}$]/gm [multiple lines]
+ },
+ {
+ name: 'comment',
+ pattern: /\-\-(.*)/g
+ // /\-\-\s(.+)$/gm [single]
+ },
+ ///- End Comments
+
+ ///- Namespace (module)
+ {
+ matches: {
+ 1: 'keyword',
+ 2: 'support.namespace'
+ },
+ pattern: /\b(module)\s(\w+)\s[\(]?(\w+)?[\)?]\swhere/g
+ },
+ ///- End Namespace (module)
+
+ ///- Keywords and Operators
+ {
+ name: 'keyword.operator',
+ pattern: /\+|\!|\-|&(gt|lt|amp);|\/\=|\||\@|\:|\.|\+{2}|\:|\*|\=|#|\.{2}|(\\)[a-zA-Z_]/g
+ },
+ {
+ name: 'keyword',
+ pattern: /\b(case|class|foreign|hiding|qualified|data|family|default|deriving|do|else|if|import|in|infix|infixl|infixr|instance|let|in|otherwise|module|newtype|of|then|type|where)\b/g
+ },
+ {
+ name: 'keyword',
+ pattern: /[\`][a-zA-Z_']*?[\`]/g
+ },
+ ///- End Keywords and Operators
+
+
+ ///- Infix|Infixr|Infixl
+ {
+ matches: {
+ 1: 'keyword',
+ 2: 'keyword.operator'
+ },
+ pattern: /\b(infix|infixr|infixl)+\s\d+\s(\w+)*/g
+ },
+ ///- End Infix|Infixr|Infixl
+
+ {
+ name: 'entity.class',
+ pattern: /\b([A-Z][A-Za-z0-9_']*)/g
+ },
+
+ // From c.js
+ {
+ name: 'meta.preprocessor',
+ matches: {
+ 1: [
+ {
+ matches: {
+ 1: 'keyword.define',
+ 2: 'entity.name'
+ },
+ pattern: /(\w+)\s(\w+)\b/g
+ },
+ {
+ name: 'keyword.define',
+ pattern: /endif/g
+ },
+ {
+ name: 'constant.numeric',
+ pattern: /\d+/g
+ },
+ {
+ matches: {
+ 1: 'keyword.include',
+ 2: 'string'
+ },
+ pattern: /(include)\s(.*?)$/g
+ }
+ ]
+ },
+ pattern: /^\#([\S\s]*?)$/gm
+ }
+ ],
+ d: [
+ {
+ name: 'constant',
+ pattern: /\b(false|null|true)\b/gm
+ },
+ {
+ // http://dlang.org/lex.html
+ name: 'keyword',
+ pattern: /\b(abstract|alias|align|asm|assert|auto|body|bool|break|byte|case|cast|catch|cdouble|cent|cfloat|char|class|const|continue|creal|dchar|debug|default|delegate|delete|deprecated|do|double|else|enum|export|extern|final|finally|float|for|foreach|foreach_reverse|function|goto|idouble|if|ifloat|immutable|import|in|inout|int|interface|invariant|ireal|is|lazy|long|macro|mixin|module|new|nothrow|null|out|override|package|pragma|private|protected|public|pure|real|ref|return|scope|shared|short|size_t|static|string|struct|super|switch|synchronized|template|this|throw|try|typedef|typeid|typeof|ubyte|ucent|uint|ulong|union|unittest|ushort|version|void|volatile|wchar|while|with|__FILE__|__LINE__|__gshared|__traits|__vector|__parameters)\b/gm
+ },
+ {
+ matches: {
+ 1: 'keyword',
+ 2: {
+ name: 'support.class',
+ pattern: /\w+/gm
+ }
+ },
+ pattern: /(typeof)\s([^\$].*?)(\)|;)/gm
+ },
+ {
+ matches: {
+ 1: 'keyword.namespace',
+ 2: {
+ name: 'support.namespace',
+ pattern: /\w+/gm
+ }
+ },
+ pattern: /\b(namespace)\s(.*?);/gm
+ },
+ {
+ matches: {
+ 1: 'storage.modifier',
+ 2: 'storage.class',
+ 3: 'entity.name.class',
+ 4: 'storage.modifier.extends',
+ 5: 'entity.other.inherited-class'
+ },
+ pattern: /\b(abstract|sealed)?\s?(class)\s(\w+)(\sextends\s)?([\w\\]*)?\s?\{?(\n|\})/gm
+ },
+ {
+ name: 'keyword.static',
+ pattern: /\b(static)\b/gm
+ },
+ {
+ matches: {
+ 1: 'keyword.new',
+ 2: {
+ name: 'support.class',
+ pattern: /\w+/gm
+ }
+
+ },
+ pattern: /\b(new)\s([^\$].*?)(?=\)|\(|;|&)/gm
+ },
+ {
+ name: 'string',
+ pattern: /("|')(.*?)\1/gm
+ },
+ {
+ name: 'integer',
+ pattern: /\b(0x[\da-f]+|\d+)\b/gm
+ },
+ {
+ name: 'comment',
+ pattern: /\/\*[\s\S]*?\*\/|\/\+[\s\S]*?\+\/|(\/\/)[\s\S]*?$/gm
+ },
+ {
+ // http://dlang.org/operatoroverloading.html
+ name: 'operator',
+ // / /= &= && & |= || | -= -- - += ++ + <= << < <<= <>= <> > >>>= >>= >= >> >>> != !<>= !<> !<= !< !>= !> ! [ ] $ == = *= * %= % ^^= ^= ^^ ^ ~= ~ @ => :
+ pattern: /(\/|\/=|&=|&&|&|\|=|\|\|\||\-=|\-\-|\-|\+=|\+\+|\+|<=|<<|<|<<=|<>=|<>|>|>>>=|>>=|>=|>>|>>>|!=|!<>=|!<>|!<=|!<|!>=|!>|!|[|]|\$|==|=|\*=|\*|%=|%|\^\^=|\^=|\^\^|\^|~=|~|@|=>|\:)/gm
+ }
+ ],
+ smalltalk: [
+ {
+ name: 'keyword.pseudovariable',
+ pattern: /self|thisContext/g
+ },
+ {
+ name: 'keyword.constant',
+ pattern: /false|nil|true/g
+ },
+ {
+ name: 'string',
+ pattern: /'([^']|'')*'/g
+ },
+ {
+ name: 'string.symbol',
+ pattern: /#\w+|#'([^']|'')*'/g
+ },
+ {
+ name: 'string.character',
+ pattern: /\$\w+/g
+ },
+ {
+ name: 'comment',
+ pattern: /"([^"]|"")*"/g
+ },
+ {
+ name: 'constant.numeric',
+ pattern: /-?\d+(\.\d+)?((r-?|s)[A-Za-z0-9]+|e-?[0-9]+)?/g
+ },
+ {
+ name: 'entity.name.class',
+ pattern: /\b[A-Z]\w*/g
+ },
+ {
+ name: 'entity.name.function',
+ pattern: /\b[a-z]\w*:?/g
+ },
+ {
+ name: 'entity.name.binary',
+ pattern: /(<|>|&|[=~\|\\\/!@*\-_+])+/g
+ },
+ {
+ name: 'operator.delimiter',
+ pattern: /;[\(\)\[\]\{\}]|#\[|#\(^\./g
+ }
+ ],
+ oz : [
+ // https://github.com/mozart/vscode-oz/blob/master/syntaxes/oz.tmLanguage.json
+ // TODO add missing css
+ {
+ name: "operator",
+ pattern: /(<:|:>|::|&|@|#|_|\[\]|\.\.\.)/g
+ },
+ {
+ name: "operator.assignment",
+ pattern: /(\=|\:=)/g
+ },
+ {
+ name: "operator.comparison",
+ pattern: /<|=<|==|\=|>=|>/g
+ },
+ {
+ name: "operator.list",
+ pattern: /\b\|\b/g
+ },
+ {
+ name: "constant.numeric",
+ pattern: /(\d+\.\d+|\d+)/g
+ },
+ {
+ name: "constant.language",
+ pattern: /\b(false|true|nil)\b/g
+ },
+ {
+ name: "variable",
+ pattern: /[A-Z][0-9A-z]*/g
+ },
+ {
+ name: "keyword.control",
+ pattern: /(? b - a);
}
-/**
- * Encodes < and > as html entities
- *
- * @param {string} code
- * @return {string}
- */
-function htmlEntities(code) {
- return code.replace(//g, '>').replace(/&(?![\w\#]+;)/g, '&');
-}
-
/**
* Determines if two different matches have complete overlap with each other
*
@@ -250,6 +240,7 @@ export class Prism {
regex = _cloneRegex(regex);
const match = regex.exec(code);
+
if (!match) {
return false;
}
@@ -439,4 +430,4 @@ export class Prism {
this.refract = _processCodeWithPatterns;
}
-}
\ No newline at end of file
+}
diff --git a/src/publics/js/dev/page/editor/tab.js b/src/publics/js/dev/page/editor/tab.js
index 47719a4..249a1c0 100644
--- a/src/publics/js/dev/page/editor/tab.js
+++ b/src/publics/js/dev/page/editor/tab.js
@@ -2,8 +2,8 @@
* This module deals with tabs.
* @author Brieuc Dubois
* @date Created on 15/11/2020
- * @date Last modification on 15/11/2020
- * @version 1.0.0
+ * @date Last modification on 27/11/2020
+ * @version 1.1.0
*/
@@ -26,6 +26,7 @@ export default class Tab{
*/
constructor(element, type=TabType.SPACES, size=null) {
this.element = element;
+ this.oldSize = size || 4;
this.set(type, size);
console.log(this);
}
@@ -38,7 +39,6 @@ export default class Tab{
set(type, size=null){
this.type = type;
this.setSize(size);
- console.log(this);
}
/**
@@ -46,6 +46,7 @@ export default class Tab{
* @param {number} size
*/
setSize(size){
+ this.oldSize = this.size;
if(this.type === TabType.TAB){
this.size = size;
if(!this.size) this.size = 8;
@@ -53,7 +54,6 @@ export default class Tab{
}else if(this.type === TabType.SPACES){
this.size = size;
if(!this.size) this.size = 4;
- console.log(this.size, size);
this.element.style.tabSize = this.size*2 + 'px';
}else{
this.size = size;
@@ -73,6 +73,7 @@ export default class Tab{
/**
* Return spaces based on position
* @param {number} position
+ * @return {string}
*/
getCompletion(position){
if(this.type === TabType.SPACES) return ' '.repeat(this.size-position%this.size);
@@ -82,9 +83,21 @@ export default class Tab{
/**
* Return spaces based on position
* @param {number} position
+ * @return {number}
*/
getCompletionSize(position){
if(this.type === TabType.SPACES) return this.size-position%this.size;
return 1;
}
+
+ /**
+ * Update text based on oldSize
+ * @param {string} text
+ * @return {string}
+ */
+ updateText(text){
+ const current = Math.max(text.search(/\S/), 0);
+ const amount = ~~(current/this.oldSize) * this.size + current%this.oldSize;
+ return ' '.repeat(amount) + text.slice(current)
+ }
}
diff --git a/src/publics/js/dev/utils/qrcode/qrcode-complet.js b/src/publics/js/dev/utils/qrcode/qrcode-complet.js
new file mode 100644
index 0000000..b8e1053
--- /dev/null
+++ b/src/publics/js/dev/utils/qrcode/qrcode-complet.js
@@ -0,0 +1,315 @@
+const version = 2; // 1 or 2
+const size = ((version-1)*4)+21;
+const text = 'https://codewe.org/abcde';
+const mode = 2; // 0 = Numeric, 1 = Alphanumeric, 2 = Binary
+const correction_level = '00'; // https://www.thonky.com/qr-code-tutorial/format-version-information
+const mask_pattern = int2bin(1, 3); // https://www.thonky.com/qr-code-tutorial/mask-patterns
+const ie = '101000100100101'.split('').map(parseInt); // https://www.thonky.com/qr-code-tutorial/format-version-tables
+
+function int2bin(int, size=0){
+ const str_bin = parseInt(int).toString(2);
+ return '0'.repeat(Math.max(0, size-str_bin.length)) + str_bin;
+}
+
+/**
+ * Convert String to binary string with given size
+ * @param {string} str
+ * @return {string}
+ */
+function str2bin(str){
+ return str.split('').map(char => {
+ const tb = char.charCodeAt(0).toString(2);
+ return '0'.repeat(Math.max(0, 8-tb.length)) + tb;
+ }).join('');
+}
+
+const ALPHA_TABLE = {'0': 0,'1': 1,'2': 2,'3': 3,'4': 4,'5': 5,'6': 6,'7': 7,'8': 8,'9': 9,'A': 10,'B': 11,'C': 12,'D': 13,'E': 14,'F': 15,'G': 16,'H': 17,'I': 18,'J': 19,'K': 20,'L': 21,'M': 22,'N': 23,'O': 24,'P': 25,'Q': 26,'R': 27,'S': 28,'T': 29,'U': 30,'V': 31,'W': 32,'X': 33,'Y': 34,'Z': 35,' ': 36,'$': 37,'%': 38,'*': 39,'+': 40,'-': 41,'.': 42,'/': 43,':': 44};
+function alpha(char){
+ return ALPHA_TABLE[char];
+}
+
+// Mode
+let codewords = '';
+switch (mode){
+ case 0:
+ codewords += '0001';
+ break;
+ case 1:
+ codewords += '0010';
+ break;
+ case 2:
+ codewords += '0100';
+ break
+ default:
+ console.error(`Unknown mode ${mode}`);
+}
+
+// length
+const len = text.length;
+switch (mode){
+ case 0:
+ codewords += int2bin(len, 10);
+ break;
+ case 1:
+ codewords += int2bin(len, 9);
+ break;
+ case 2:
+ codewords += int2bin(len, 8);
+ break;
+}
+
+// Content
+switch (mode){
+ case 0:
+ codewords += text.match(/.{3}/g).map(x => int2bin(x, 10)).join('');
+ if(text.length%3 === 1) codewords += int2bin(parseInt(text.slice(-1)), 4);
+ if(text.length%3 === 2) codewords += int2bin(parseInt(text.slice(-2)), 7);
+ break;
+ case 1:
+ codewords += text.match(/.{2}/g).map(function (x){
+ if(x.length === 1) x = '0' + x;
+ return int2bin(alpha(x[0])*45 + alpha(x[1]), 11);
+ }).join('');
+ if(text.length%2 === 1) codewords += int2bin(alpha(text.slice(-1)), 6);
+ break;
+ case 2:
+ codewords += str2bin(text);
+ break
+ default:
+ console.error(`Unknown mode ${mode}`);
+}
+
+// Terminator
+codewords += '0000';
+
+// Bit padding
+codewords += '0'.repeat((8-(codewords.length % 8))%8);
+
+// Byte padding
+//TODO Calculate length programmatically
+// M-1: 128
+// M-2: 224
+const padding_len = 224 - codewords.length;
+codewords += '1110110000010001'.repeat(18).slice(0, padding_len);
+
+/**************************************\
+| CALCULATE LOG AND ANTI-LOG TABLE |
+\**************************************/
+// Based on https://www.thonky.com/qr-code-tutorial/log-antilog-table
+// Log[x] = 2*Log[x-1] if result < 256 else result XOR 285
+// Antilog is the reversed table of log. Example: Log[2] = 4, so Antilog[4] = 2
+
+const log = [1];
+const antilog = [NaN];
+
+let last = 1;
+for(let i=1;i<256;i++){
+ last = 2 * last;
+ if(last >= 256) last ^= 285;
+ log[i] = last;
+ antilog[last] = i;
+}
+
+/*************************************\
+| NUMERATORS AND DENOMINATORS |
+\*************************************/
+
+// codewords are split into 8-bits blocks and convert in numbers
+const split = codewords.match(/.{8}/g);
+const numbers = split.map(x => parseInt(x,2));
+
+// Based on https://www.thonky.com/qr-code-tutorial/error-correction-table
+// Data get from calculator https://www.thonky.com/qr-code-tutorial/generator-polynomial-tool?degree=16
+const BASE_GENERATOR = //[[0, 10], [251,9], [67,8], [46,7], [61,6], [118,5], [70,4], [64,3], [94,2], [32,1], [45, 0]];
+
+// 2-M
+[
+ [0,16], [120, 15], [104,14], [107,13], [109,12], [102,11], [161,10], [76,9],
+ [3,8], [91,7],[191,6], [147,5],[169,4], [182,3], [194,2], [225,1], [120, 0]
+];
+// 2-M : 16
+// 1-M : 10
+const CORRECTOR_COUNT = BASE_GENERATOR.length-1;
+
+// Numerator is calculated according to codewords and CORRECTION_COUNT
+let numerator = [];
+for(let i=0;i
")}ApplyWithCaret(){const t=c.getBeginPosition(this.element);this.apply(),c.setPosition(this.element,t)}static onCurrent(t){return new A(w("uuid"),t)}}class T{static trigger(t,e){document.dispatchEvent(new CustomEvent(t,e))}static triggerCustom(t,e){document.dispatchEvent(new CustomEvent(t,{detail:e}))}}class S{static string(t,e="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"){let n="";for(let a=0;a
",{uuid:t}),a.nextSibling)}}remove(t){let e=this.select(t);e?e.remove():f.warn(`The element with uuid '${t}' can't be removed: it doesn't exist.`)}decompose(t){let e=[],n={};for(const a of t)e.push(a.uuid),n[a.uuid]=a.content;return[e,n]}getDiff(t){const[e,n]=this.decompose(this.history.get(-2)),[a,r]=this.decompose(this.history.get(-1));let s=[];for(const[a,r]of this.history.get(-1).entries())e.includes(r.uuid)?n[r.uuid]===r.content||r.uuid in t&&t[r.uuid]===r.content||s.push(["set",[r.uuid,r.content]]):r.uuid in t?r.content!==t[r.uuid]&&s.push(["set",[r.uuid,r.content]]):s.push(["new",[r.uuid,this.history.get(-1)[a-1].uuid,r.content]]);for(const t of this.history.get(-2))a.includes(t.uuid)||s.push(["delete",[t.uuid]]);return s}}class R{static setLine(t,e){return{type:"set-line",data:{id:t,content:e}}}static newLine(t,e,n){return{type:"new-line",data:{id:t,previous:e,content:n}}}static deleteLine(t){return{type:"delete-line",data:{id:t}}}static save(t){return{type:"save",data:t}}}class L{constructor(t,e=1,n=null){this.element=t,this.oldSize=n||4,this.set(e,n),console.log(this)}set(t,e=null){this.type=t,this.setSize(e)}setSize(t){this.oldSize=this.size,0===this.type?(this.size=t,this.size||(this.size=8),this.element.style.tabSize=this.size+"px"):1===this.type?(this.size=t,this.size||(this.size=4),this.element.style.tabSize=2*this.size+"px"):(this.size=t,this.element.style.tabSize="inherit")}get(){return 1===this.type?" ".repeat(this.size):0===this.type?"\t":void 0}getCompletion(t){return 1===this.type?" ".repeat(this.size-t%this.size):0===this.type?"\t":void 0}getCompletionSize(t){return 1===this.type?this.size-t%this.size:1}updateText(t){const e=Math.max(t.search(/\S/),0),n=~~(e/this.oldSize)*this.size+e%this.oldSize;return" ".repeat(n)+t.slice(e)}}class x{constructor(t){window.WebSocket?(this.options=t||{},f.debug("Websocket connection to",this.uri()),this.ws=new WebSocket(this.uri().href),this.ws.onmessage=this.onMessage,this.waitingStack=new g(120),document.addEventListener("socket.confirm",(t=>{this.confirm(t.detail)})),setInterval((()=>{const t=this.waitingStack.getSize();t>20?N("Connexion","It seems than you are disconnected",2e3,"#ff501e"):t>5&&N("Connexion","It seems than you are disconnected",2e3,"#ff9000")}),1e3),document.addEventListener("socket.receive.ping",(t=>{this.send(JSON.stringify({event:"pong",time:Date.now()}))}))):f.critical("Browser doesn\t support websockets")}uri(){const t=new URL("ws://localhost");if(t.protocol=this.options.secure?"wss":"ws",t.port=this.port(t.protocol.endsWith(":")?t.protocol.slice(0,-1):t.protocol),t.hostname=this.options.hostname||window.location.origin,t.pathname=void 0!==this.options.pathname?"/"+this.options.pathname||0:"",this.options.params)for(const[e,n]of Object.entries(this.options.params))t.searchParams.set(e,n);return t}port(t){return this.options.port&&("wss"===t&&443!==Number(this.options.port)||"ws"===t&&80!==Number(this.options.port))?this.options.port:""}send(t){if("join"!==t.event){const e=S.string(9);this.waitingStack.add(e,t),f.debug(`SEND ${e} to '${t.event}': `,t),t.uuid=e}this.ws.send(JSON.stringify(t))}onMessage(t){try{const e=JSON.parse(t.data);f.debug("RECEIVE PACKET",e),e.event&&e.data?T.triggerCustom(`socket.receive.${e.event}`,e.data):e.code&&e.uuid&&e.time?T.triggerCustom("socket.confirm",e):f.error("This packet hasn't valid event and data.",e)}catch(e){f.debug(e),f.error("This packet can't be parsed as JSON.",t)}}confirm(t){const e=t.code,n=t.uuid,a=t.time;"OK"!==e&&f.warn(`${n} come back with a non OK code.`);const r=this.waitingStack.archive(n,a);f.debug(`up: ${r.server-r.send}ms, down: ${r.received-r.server}ms`)}}const O=new class{constructor(t,e=1e3){this.doc_id=t,this.ws=new x({secure:"https:"===document.location.protocol,port:window.location.port,hostname:window.location.host.includes(":")?window.location.host.split(":")[0]:window.location.host}),this.stack={UPDATE_EVENT:[]},this.preprocess=[],this.ws.ws.onopen=()=>{this.join(),setInterval((()=>{for(const t of this.preprocess)t[0](...t[1]);this.stack.UPDATE_EVENT.length&&this.send("update",this.stack.UPDATE_EVENT.splice(0,this.stack.UPDATE_EVENT.length))}),e)},document.addEventListener("socket.send",(t=>{t.detail.hasOwnProperty("request")&&this.stack.UPDATE_EVENT.push(t.detail.request),t.detail.hasOwnProperty("requests")&&this.stack.UPDATE_EVENT.push(...t.detail.requests)})),document.addEventListener("socket.send_now",(t=>{this.send(t.detail.name,t.detail.requests)})),document.addEventListener("socket.preprocess",(t=>{const e=t.detail[0];let n=t.detail[1];if(void 0===e)return;void 0===n&&(n=[]);const a=[e,n];this.preprocess.includes(a)||(this.preprocess.push(a),f.debug("New socket.preprocess",a))}))}send(t,e={}){this.ws.send({event:t,room:this.doc_id,data:e})}join(){this.send("join")}}(doc_id),_=new class{constructor(t,e=initial_size){this.editable=t,this.tab=Number.isInteger(e)?new L(t,1,e):4,this.linesManager=new C(t),this.last_request={},this.keepSpace=!1,document.addEventListener("socket.receive.update",(t=>{if(t&&t.detail&&t.detail&&"function"==typeof t.detail[Symbol.iterator])for(const e of t.detail)e.type?T.triggerCustom("editor."+e.type,e.data):f.warn("Trying to trigger a null received event.");else f.warn("Trying to iterate on non-iterable data.")})),T.triggerCustom("socket.preprocess",[this.coroutine,[this]]),this.editable.addEventListener("keyup",(t=>{if(!I.isExtra(t.keyCode)){switch(t.keyCode){case 13:try{this.keepSpace=!1;let t=w("uuid"),e=t.previousElementSibling,n=S.string(10);t.setAttribute("uuid",n);let a=e.innerText.search(/\S/);a<0&&(a=0),e.innerText.trimEnd().endsWith(":")&&(a+=this.tab.getCompletionSize(a)),t.innerHTML=" ".repeat(a)+t.innerHTML,c.setPosition(t,a),0===t.innerText.length&&(t.innerHTML="
")}catch(t){f.error("Error when trying to customize the new line")}break;default:t.ctrlKey||t.altKey||A.onCurrent(language).ApplyWithCaret()}this.linesManager.change=!0}})),this.editable.addEventListener("paste",(t=>{const e=document.getSelection();let n=(t.clipboardData||window.clipboardData).getData("text");if(n){const a=n.split("\n");!function(t){return!!E(["div","section"]).hasAttribute("uuid")&&E(["div","section"],e.anchorNode)===E(["div","section"],e.focusNode)&&(1===t.length||e.anchorNode===e.focusNode&&e.anchorOffset===e.focusOffset)}(a)?(t.preventDefault(),f.debug("Prevent action when trying to paste on multiple line."),N("Paste Event","Sorry, you can't past over a multiline selection",5e3)):a.length>1&&(t.preventDefault(),this.multilinesInsert(a))}else t.preventDefault(),f.warn("Error when trying to get the content of your clipboard."),N("Paste Event","Error with content of your clipboard",5e3)})),this.editable.addEventListener("keydown",(t=>{if(I.ctrl(t)&&83===t.keyCode)return t.preventDefault(),void N("Save","Your document is still saved automatically",5e3,"#228b22");if(I.isExtra(t.keyCode))return;const e=document.getSelection(),n=E(["div","section"],e.anchorNode),a=E(["div","section"],e.focusNode),r=w("uuid");if(!r)return t.preventDefault(),void N("Editor","Sorry, your action has been canceled because you are not on any line.",5e3);switch(n.hasAttribute("uuid")&&a.hasAttribute("uuid")&&(0!==c.getBeginPosition(r)&&0!==c.getEndPosition(r)||n===a)||c.setRangeStart(r,1),t.keyCode){case 9:t.preventDefault(),this.insertTab();break;case 13:if(t.shiftKey)return N("Shift+Enter","Please just use Enter to avoid any bugs.",5e3),void t.preventDefault();this.keepSpace?(f.debug("Prevent action when trying to add new line (key is probably maintain)."),t.preventDefault()):this.keepSpace=!0;break;case 8:0===c.getBeginPosition(r)&&(t.preventDefault(),this.removeLine(r))}})),document.addEventListener("editor.set-line",(t=>{const e=t.detail.id,n=t.detail.content;this.last_request[e]=n,this.linesManager.update(e,n)})),document.addEventListener("editor.new-line",(t=>{const e=t.detail.id,n=t.detail.previous,a=t.detail.content;this.last_request[e]=a,this.linesManager.new(e,n,a)})),document.addEventListener("editor.delete-line",(t=>{const e=t.detail.id;e in this.last_request&&delete this.last_request[e],this.linesManager.remove(e)}))}insertTab(){document.getSelection().collapseToStart(),document.getSelection().getRangeAt(0).insertNode(document.createTextNode(this.tab.getCompletion(c.getBeginPosition(w("uuid"))))),document.getSelection().collapseToEnd(),A.onCurrent(language).ApplyWithCaret()}multilinesInsert(t){const e=w("uuid");var n,a,r;e.innerHTML=(n=e.innerText,a=t[0],r=c.getBeginPosition(e),n.slice(0,r)+a+n.slice(r)),A.onCurrent(language).apply();let s=e.getAttribute("uuid");for(let e=1;e
","
"),t.remove(),c.setPosition(e,n)}}coroutine(t){if(t.linesManager.hasChange()){t.linesManager.getAll();const e=t.makeRequestsForDiff();T.triggerCustom("socket.send",{requests:e}),t.linesManager.change=!1}}makeRequestsForDiff(t=this.linesManager.getDiff(this.last_request)){let e=[];for(const n of t)switch(n[0]){case"set":e.push(R.setLine(...n[1]));break;case"new":e.push(R.newLine(...n[1]));break;case"delete":e.push(R.deleteLine(...n[1]))}return e}updateAllHighlighting(){const t=w("uuid");for(const e of this.editable.children)t===e?new A(e,language).ApplyWithCaret():new A(e,language).apply()}}(b.id("editor"));var D,z;new class{constructor(t){this.editor=t,this.current=new Map,this.color=S.randInt(0,255,3),this.uuid=S.string(10),this.request={},document.addEventListener("editor.cursor-moves",(t=>{this.update(t)})),document.dispatchEvent(new CustomEvent("socket.preprocess",{detail:[this.sendCursorPosition,[this]]})),this.editor.addEventListener("focus",(()=>{y()!==this.editor&&(this.request=this.cursorRequest())})),this.editor.addEventListener("click",(()=>{y()!==this.editor&&(this.request=this.cursorRequest())})),this.editor.addEventListener("keypress",(()=>{y()!==this.editor&&(this.request=this.cursorRequest())}))}cursorRequest(){let t=w("uuid");for(const e of this.current.entries())if(e[0]!==this.uuid&&e[1][1]===t)return{};return t.hasAttribute("uuid")?{type:"cursor-moves",data:{uuid:t.getAttribute("uuid"),userId:this.uuid,color:this.color}}:{}}sendCursorPosition(t){const e=t.request;t&&Object.keys(e).length>0&&(T.triggerCustom("socket.send",{request:e}),t.request={})}update(t){const e=t.detail;this.current.has(e.userId)&&(this.current.get(e.userId)[0].remove(),this.current.get(e.userId)[1].removeAttribute("contenteditable"),this.current.get(e.userId)[1].classList.remove("noteditable"),this.current.delete(e.userId));const n=document.querySelector('div[uuid="'+e.uuid+'"]');if(null===n)return void(l.isDebug()&&console.log("Cursor position doesn't exist"));const a=document.createElement("div");a.classList.add("pointer"),a.style.top=n.offsetTop+"px",a.style.backgroundColor="rgb("+e.color[0]+", "+e.color[1]+", "+e.color[2]+")",l.isDebug()&&(a.id=S.string(20)),b.id("body").appendChild(a),n.setAttribute("contenteditable","false"),n.classList.add("noteditable"),setTimeout((()=>{this.current.has(e.userId)&&Date.now()-this.current.get(e.userId)[2]>9e3&&(this.current.get(e.userId)[0].remove(),this.current.get(e.userId)[1].removeAttribute("contenteditable"),this.current.get(e.userId)[1].classList.remove("noteditable"),this.current.delete(e.userId))}),1e4),this.current.set(e.userId,[a,n,Date.now()])}}(b.id("editor")),D=b.id("download"),z=b.id("editor"),D.addEventListener("click",(()=>{const t=z.innerText.replaceAll("\n\n","\n");D.setAttribute("href","data:Content-type, "+escape(t))})),Object.keys(a).includes(language)||(language="generic");for(const t of b.id("editor").children)new A(t,language).apply();new class{constructor(t){this.editable=t,document.getElementById("option-language").addEventListener("change",(t=>{language=t.target.value.toLowerCase(),this.editable.updateAllHighlighting(),O.send("language",{language})})),document.addEventListener("socket.receive.language",(t=>{Object.keys(a).includes(t.detail.language.toLowerCase())&&(language=t.detail.language.toLowerCase(),document.getElementById("option-language").value=language,this.editable.updateAllHighlighting())}));for(const t of Object.keys(a)){const e=document.createElement("option");e.innerText=t,t===language&&(e.selected=!0),document.getElementById("option-language").appendChild(e)}document.getElementById("option-space-size").addEventListener("change",(t=>{_.tab.setSize(t.target.value);for(const t of this.editable.editable.children)t.innerText=_.tab.updateText(t.innerText),new A(t,language).apply();O.send("changeTabSize",{size:t.target.value})})),document.getElementById("option-space-size").value=this.editable.tab.size,document.addEventListener("socket.receive.changeTabSize",(t=>{if(t.detail.size&&Number.isInteger(parseInt(t.detail.size))){_.tab.setSize(t.detail.size),document.getElementById("option-space-size").value=t.detail.size;for(const t of this.editable.editable.children)t.innerText=_.tab.updateText(t.innerText),new A(t,language).apply()}}))}}(_),function(t,e){const n=25,a="101000100100101".split("").map(Number.parseInt);function r(t,e=0){const n=Number.parseInt(t).toString(2);return"0".repeat(Math.max(0,e-n.length))+n}let s="0100"+r(e.length,8)+e.split("").map((t=>{const e=t.charCodeAt(0).toString(2);return"0".repeat(Math.max(0,8-e.length))+e})).join("")+"0000";s+="0".repeat((8-s.length%8)%8),s+="1110110000010001".repeat(18).slice(0,224-s.length);const i=[1],o=[NaN];let c=1;for(let t=1;t<256;t++)c*=2,c>=256&&(c^=285),i[t]=c,o[c]=t;const l=s.match(/.{8}/g).map((t=>Number.parseInt(t,2))),p=[[0,16],[120,15],[104,14],[107,13],[109,12],[102,11],[161,10],[76,9],[3,8],[91,7],[191,6],[147,5],[169,4],[182,3],[194,2],[225,1],[120,0]],g=p.length-1;let u=[];for(let t=0;tCODEWE
\ No newline at end of file
+CODEWE
+CODEWE - {{ document['document_id'] }}
+ CODEWE - {{ document['document_id'] }}
@@ -20,11 +20,31 @@ CODE{{ line['content'] }}
{% endfor %}
+
{% endblock %}
{% block scripts %}
{% if production %}
diff --git a/src/views/legal/Privacy Policy - CodeWe.docx b/src/views/legal/Privacy Policy - CodeWe.docx
index d3060a3..a117ffb 100644
Binary files a/src/views/legal/Privacy Policy - CodeWe.docx and b/src/views/legal/Privacy Policy - CodeWe.docx differ
diff --git a/src/views/legal/Terms and Conditions - CodeWe.docx b/src/views/legal/Terms and Conditions - CodeWe.docx
index 31cd07e..fa50af8 100644
Binary files a/src/views/legal/Terms and Conditions - CodeWe.docx and b/src/views/legal/Terms and Conditions - CodeWe.docx differ
diff --git a/src/views/legal/archive/privacy-20201117.html b/src/views/legal/archive/privacy-20201117.htm
similarity index 100%
rename from src/views/legal/archive/privacy-20201117.html
rename to src/views/legal/archive/privacy-20201117.htm
diff --git a/src/views/legal/archive/privacy-20201120.html b/src/views/legal/archive/privacy-20201120.htm
similarity index 100%
rename from src/views/legal/archive/privacy-20201120.html
rename to src/views/legal/archive/privacy-20201120.htm
diff --git a/src/views/legal/archive/privacy-20201122.html b/src/views/legal/archive/privacy-20201122.htm
similarity index 100%
rename from src/views/legal/archive/privacy-20201122.html
rename to src/views/legal/archive/privacy-20201122.htm
diff --git a/src/views/legal/archive/privacy-20201122.pdf b/src/views/legal/archive/privacy-20201122.pdf
deleted file mode 100644
index 5cce4aa..0000000
Binary files a/src/views/legal/archive/privacy-20201122.pdf and /dev/null differ
diff --git a/src/views/legal/archive/privacy-20201203.htm b/src/views/legal/archive/privacy-20201203.htm
new file mode 100644
index 0000000..3a81d0f
--- /dev/null
+++ b/src/views/legal/archive/privacy-20201203.htm
@@ -0,0 +1,200 @@
+{% extends 'component/base.html' %}
+
+{% block title %}CodeWe{% endblock %}
+
+{% block head %}
+
+{% endblock %}
+
+{% block corps %}
+Privacy Policy
+
+
+
+
+
+
+
+
+ Last Revision: November 22th, 2020
+
+
+ Valid Starting: November 30th, 2020.
+
+
+ This Policy describes the information We process to support CodeWe.
+
+ These Policies is an entire part of the Terms, thus:
+
+
+
+ This summary section is a “tl;dr” (too long; didn’t read) of these Policies. They represent a summary of what We think is important. This section SHALL NOT be representative or valid in any dispute.
+
+ We don’t collect any directly personal information. Ever. We never ask You to give Us Your name or (email) address.
+
+ We do however collect and save the content You create and share on CodeWe. This content is usually deleted within 3 days.
+
+ We use a standard method of logging actions and connection saved in files called Logs. These Logs MAY include the IP address Your Internet Service Provider assigned to You. These Logs are usually kept for a period of 90 days or so.
+
+ To be able to provide You with CodeWe, We have to process information about You. +
++ Information and content You provide. We collect the content and other information You provide when using CodeWe, including when You create or share content. This can include information in or about the content You provide. Our systems + automatically process the content and communications You and others provide to analyse the context and what’s in them for the purposes described below. +
++ We MAY receive information about what internet browser/internet explorer You use as well as it’s version. We do not, however, use, process or store this information in normal situations. +
++ If You decide to report an error that occurred on CodeWe (thank You already!) We receive and store the message You wrote and some anonymous browser-related data, like which browser You used, it’s version and extension used. We also receive the + last communications between Your Device and CodeWe as well as timings. +
++ We only use necessary cookies to minimize the welcome notification. Having accepted these Terms and Policies once, You SHALL accept them until termination. +
+ ++ We use the information We have as described here below and to provide and support CodeWe. +
+ We use the information We have to combat harmful conduct, detect and prevent spam and other bad experiences, maintain the integrity of CodeWe, and promote safety and security.
+
+ Example: We use the information We have to investigate suspicious activity or violations of Our Terms or Policies.
+
+ Your information is shared with others in the following ways:
+
+ Sharing on CodeWe.
+
+ We collect, use and share the data We have in the ways described above: +
+ Under the General Data Protection Regulation, You have the right to access, rectify, port and erase Your data. You also have the right to object to and restrict certain processing of Your data. To exercise any of these rights, feel free to + contact Us. +
+ +
+ We store data until it is no longer necessary to provide CodeWe. Content You provide is generally deleted after 48 hours but can be extended to 7 days.
+
+ We use a standard method of logging actions and connection saved in files called Logs. These Logs MAY include the IP address Your Internet Service Provider assigned to You. These Logs are usually kept for a period of 90 days or so.
+
+ We access, preserve or share Your information with regulators, law enforcement or others. +
+ To the best of Our abilities, We will attempt to notify You changes a reasonable time before the changes take effect to allow You to review the changes unless changes are required by an external force. +
+ +
+ If You have questions about this Policy, You can contact Us as described below.
+
+ Email: privacy@codewe.bhasher.com
+
+ Last Revision: November 22th, 2020 + | ++ Valid Starting: November 30th, 2020. + | +
+
+
+ A downloadable PDF version can be found here.
+
+
+
+
+ Hello! We are happy to see You here at CodeWe!
+
+ Read these Terms and Conditions and Privacy Policy carefully before accessing the Service.
+
+ CodeWe is a Service that allows You to share and collaborate on programs and scripts. These are the Terms and Conditions that regulate and govern Your use of Our Service. They also inform You about the sharing Service. When You access our Website
+ or Service, You fully agree to these terms.
+
+ We don’t charge You to use CodeWe. Because We don’t like advertisements so We don’t advertise (besides, You are probably using an adblocker anyway 😉). We, therefore, have no reason to collect personal data and even less to sell or share any data
+ or information that MAY directly identify You (these are things like Your name, (email) address and other).
+
+ Your access to and use of the Service is conditioned by the acceptance of these Terms. These Terms and Conditions apply to all and any visitor, user and others who access or use the Service.
+
+ Our Privacy Policy explains how We (don’t) collect and use Your personal information to provide Our Service. These Privacy Policies should be read alongside these Terms.
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only
+ when, they appear in all capitals, as shown here.
+
+ Words of which the first letter is capitalized, such as “Terms”, have meanings that are defined in the section here-under. The definitions apply whatever derivative form they take.
+
+ For the purpose and in context of these Terms and Conditions,
+
+ The Owners of this Project or Service are the people regularly updating, maintaining and supervising the evolution of the Project, in other words: +
We would like to thank every person having contributed to this Project.
+ +We provide and make available to You to the best of Our abilities a Service that allows You to share, distribute and collaborate on programs, scripts and more.
+ ++ We try to make this Service as broadly available to any and everyone who wishes to use it, but We don’t allow You to use Our Service SHOULD: +
+ We wish that people can use CodeWe to share and collaborate on algorithms and code freely but under no circumstance at the expense of the safety of You and others. You, therefore, agree not to engage in the behaviour or conduct described below + (or to facilitate or support others in doing so): +
+ To correctly and efficiently provide You with Our Service, We need permission Your permission to store or save content You create and share
+
+ The content You create and share is saved temporarily in our database. Some content that You create and make available to others MAY be protected by intellectual property rights.
+
+ You (or the owner) own(s) the intellectual property rights (e.g.: copyright or trademarks) in any such content that You create or share on CodeWe. Nothing in these Terms takes away these rights You have to Your content. You are free to share or
+ not Your content with anyone else, whenever You want.
+
+ However, to be able to provide Our Service, You MUST give Us legal permissions (“license”) to store or save this content. This is solely for the purpose to provide Our Service (as described above).
+
+ Specifically, when You create, share or make available content that is covered by intellectual property rights, on CodeWe, You grant Us a non-exclusive, transferable, sub-licensable, royalty-free, and worldwide licence or authorisation to host,
+ save, store, distribute, modify, run, copy, duplicate, publicly display and create derivative works of Your content.
+
+
+ Example: You share a script on CodeWe. You give Us permission to store, save, copy and share it with others. This is the intent after all, isn’t it?
+
+
+ Content stored for longer than 48 hours after last activity or view will automatically be removed. You can download the content You created or shared anytime by using the “Download” button.
+
+ When content is deleted, it’s no longer accessible to other users, however, it MAY continue to exist elsewhere on CodeWe where:
+
+ This project is licensed under the MIT License available here. You are free to obtain a copy of this project. If You obtain a copy of this Project, these Terms and + Condition, as well as the Privacy Policy, no longer apply and We cannot be held responsible for any actions when using this copy. +
+ +
+ We constantly work on improving CodeWe and develop new features to make Our Service better for You and others. We thus MAY need to update and maintain these Terms now and then to accurately reflect Our services and practices. We will only make
+ any changes if We feel the Terms are no longer appropriate or incomplete.
+
+ We will attempt to notify You of such changes a reasonable time before the changes take effect to allow You to review the changes to these Terms unless changes are required by an external force. Once the Terms have been updated, You will be bound
+ by them if You continue using CodeWe. You MUST, however, periodically check these Terms by Yourself.
+
+ We still hope that You will continue using CodeWe, but should You no longer agree to these Terms, You MUST terminate Your connection to Us as described in the Termination section here below.
+
+ We want CodeWe to be a place to safely share and collaborate.
+
+ If We determine that You clearly, seriously or repeatedly breached Our Terms and Privacy Policy, We MAY suspend or permanently disable Your access to CodeWe without prior notice. We MAY also suspend or disable Your access to CodeWe if You
+ repeatedly infringe or disregard other people’s intellectual rights or where We are REQUIRED by legal reasons, here too, without prior notice.
+
+ Once You have been subject to suspension or termination, You MUST delete any and all data linking or connecting You to Us in any way. You MUST comply with Our decision and MUST NOT attempt to circumvent or find another way to use CodeWe.
+
+ If You think We have terminated Your access wrongfully, contact Us using the information in the Contact section.
+
+ If You wish to terminate this agreement, You MUST immediately stop using CodeWe and delete any and all data linking or connecting You to Us in any way. Once this agreement terminated, You will have to consent again before using CodeWe.
+
+ Please note that the following sections will prevail and continue to be valid after termination:
+
+ We MUST NOT be held liable for any special, incidental, indirect, or consequential damages whatsoever. This includes, but is not limited to, damages for loss of profits, loss of data or other information, for business interruption, for personal
+ injury, loss of privacy arising out of or in any way related to the use of or inability to use the Service, Third-Party software and/or Third-Party hardware used with CodeWe, or otherwise in connection with any provision of these Terms. This,
+ even if We have been advised of the possibility that such damages MAY occur and even if the remedy fails of its essential purpose.
+
+ Knowing that some states do not allow the exclusion of implied warranties or limitation of liability for incidental or consequential damages, some of the above limitations MAY not apply. In these states, each party's liability will be limited to
+ the greatest extent permitted by law.
+
+ CodeWe, not only being in active development but also in estimated alpha (not ready for public release) stage and generally, is provided to You “AS IS” and “AS AVAILABLE”, with all its faults, defects and bugs, without warranty of any kind. To
+ the maximum extent permitted under applicable law, We expressly disclaim all warranties, whether express, implied, statutory or otherwise. Respecting the Service, this includes all implied warranties of merchantability, fitness for a particular
+ purpose, title and non-infringement. Warranties that MAY arise out of course of dealing, performance usage or trade practice are also included.
+
+ Without limiting the foregoing, We provide no warranty or undertaking and make no representation of any kind that CodeWe will meet Your requirements, achieve any intended or implied results, be compatible or work with any other software,
+ application, system or service. We do not warrant that CodeWe will be running without any interruptions meet any performance or reliability standard or be error-free. We also give no warranty that any errors or defects will be corrected.
+
+ Without limiting the foregoing, We don’t make any representation or warranty of any kind, be it express or implied:
+
+ In an attempt to limit or avoid disputes between You and Us, We try to provide clear regulations and guidelines. However, if a dispute does arise, You agree to first and foremost attempt to resolve it with Us without involving the public before
+ resolving it in any legal court. You also agree that the laws of Belgium govern these Terms and Privacy Policies including any conflicts of law provisions.
+
+ There MAY exist translations of these Terms. In case of any dispute, You agree that the English version will be valid and considered.
+
+ These Terms make up the entire agreement between You and Us, Owners of this Project.
+
+ If any part of these Terms is found to be unenforceable, the remaining portion MUST be considered having full force or effect. If We fail to enforce any of these Terms, it MUST NOT be considered a waiver. Any amendment to or waiver of these Terms
+ MUST be made in writing and signed by Us.
+
+ You MUST NOT transfer or delegate any of Your rights or obligations under these Terms to anyone else without Our explicit consent.
+
+ We always appreciate Your feedback, suggestions about and issue findings on CodeWe. You agree that We MAY use them without any restriction or obligation to compensate You and We are under no obligation to keep them confidential.
+
+ These Terms only cover the Project instance hosted, managed, created, developed and maintained by Us. If You fork, copy, modify or alter a separate version of this Project, these Terms MUST NOT apply to You.
+
+ In this document, the key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" are to be interpreted as described in RFC 2119. An arranged copy can be found in the Annex section. +
++ The Policy Privacy describes how We collect and use Your personal information to provide CodeWe. They are a fully integrated part of these Terms. +
++ The Service is hosted and made available through a virtual private server hosted by Groupe PulseHerge. By using Our Service, You also accept their terms and condition available at https://www.pulseheberg.com/legal. +
+
+ Our Service MAY contain hyperlinks, links or references to Third Party websites that are not owned or controlled by Us.
+
+ We have no control over and assume no responsibility for, the content, privacy policies or practices of any Third-Party web site or service. You further acknowledge and agree that We shall not be held responsible or liable, it being directly or
+ indirectly, for any damage, loss or modification alleged to be caused by, in or during a connection with the use of or reliance on any such content, goods or services available on or through any such web site, web page or service.
+
+ We strongly advise You to carefully read the terms of service and privacy policies of any Third-Party web site, web page or services that You visit.
+
If You have any request or require additional clarification, do not hesitate to contact Us!
+
+ Email: terms@codewe.bhasher.com
+
+ The original was found at https://tools.ietf.org/html/rfc2119 on November 9th, 2020 +
+
+ Updated by: 8174 + + Network Working Group + Request for Comments: 2119 + BCP: 14 + Category: Best Current Practice + |
+
+ BEST CURRENT PRACTICE + Errata Exist + S. Bradner + Harvard University + March 1997 + |
+
+ This document specifies an Internet Best Current Practices for the Internet Community, and requests discussion and suggestions for improvements. Distribution of this memo is unlimited. +
+
+ In many standards track documents several words are used to signify the requirements in the specification. These words are often capitalized. This document defines these words as they should be interpreted in IETF documents. Authors who follow
+ these guidelines should incorporate this phrase near the beginning of their document:
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119.
+
+ Note that the force of these words is modified by the requirement level of the document in which they are used.
+
+ This word, or the terms "REQUIRED" or "SHALL", mean that the definition is an absolute requirement of the specification. +
++ This phrase, or the phrase "SHALL NOT", mean that the definition is an absolute prohibition of the specification. +
++ This word, or the adjective "RECOMMENDED", mean that there may exist valid reasons in particular circumstances to ignore a particular item, but the full implications must be understood and carefully weighed before choosing a different course. +
++ This phrase, or the phrase "NOT RECOMMENDED" mean that there may exist valid reasons in particular circumstances when the particular behavior is acceptable or even useful, but the full implications should be understood and the case carefully + weighed before implementing any behavior described with this label. +
++ This word, or the adjective "OPTIONAL", mean that an item is truly optional. One vendor may choose to include the item because a particular marketplace requires it or because the vendor feels that it enhances the product while another vendor may + omit the same item. An implementation which does not include a particular option MUST be prepared to interoperate with another implementation which does include the option, though perhaps with reduced functionality. In the same vein an + implementation which does include a particular option MUST be prepared to interoperate with another implementation which does not include the option (except, of course, for the feature the option provides.) +
++ Imperatives of the type defined in this memo must be used with care and sparingly. In particular, they MUST only be used where it is actually required for interoperation or to limit behavior which has potential for causing harm (e.g., limiting + retransmisssions). For example, they must not be used to try to impose a particular method on implementors where the method is not required for interoperability. +
++ These terms are frequently used to specify behavior with security implications. The effects on security of not implementing a MUST or SHOULD, or doing something the specification says MUST NOT or SHOULD NOT be done may be very subtle. Document + authors should take the time to elaborate the security implications of not following recommendations or requirements as most implementors will not have had the benefit of the experience and discussion that produced the specification. +
++ The definitions of these terms are an amalgam of definitions taken from a number of RFCs. In addition, suggestions have been incorporated from a number of people including Robert Ullmann, Thomas Narten, Neal McBurnett, and Robert Elz. +
+
+ Scott Bradner
+ Harvard University
+ 1350 Mass. Ave.
+ Cambridge, MA 02138
+ Phone - +1 617 495 3864
+ Email - sob@harvard.edu
+
+ + Internet Engineering Task Force (IETF) + Request for Comments: 8174 + BCP: 14 + Updates: 2119 + Category: Best Current Practice + ISSN: 2070-1721 + |
+
+ BEST CURRENT PRACTICE + Errata Exist + B. Leiba + Huawei Technologies + May 2017 + |
+
+ RFC 2119 specifies common key words that may be used in protocol specifications. This document aims to reduce the ambiguity by clarifying that only UPPERCASE usage of the keywords have the defined special meanings. +
+
+ This memo documents an Internet Best Current Practice.
+
+ This document is a product of the Internet Engineering Task Force (IETF). It represents the consensus of the IETF community. It has received public review and has been approved for publication by the Internet Engineering Steering Group (IESG).
+ Further information on BCPs is available in Section 2 of RFC 7841.
+
+ Information about the current status of this document, any errata, and how to provide feedback on it may be obtained at http://www.rfc-editor.org/info/rfc8174.
+
+ Copyright (c) 2017 IETF Trust and the persons identified as the document authors. All rights reserved.
+
+ This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (http://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they
+ describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Simplified BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty
+ as described in the Simplified BSD License.
+
+ RFC 2119 specifies common key words, such as "MUST", "SHOULD", and "MAY", that may be used in protocol specifications. It says that the key words "are often capitalized," which has caused confusion about how to interpret non-capitalized words
+ such as "must" and "should".
+
+ This document updates RFC 2119 by clarifying that only UPPERCASE usage of the key words have the defined special meanings. This document is part of BCP 14.
+
+ The following change is made to [RFC2119]:
+
+ === OLD ===
+
+ In many standards track documents several words are used to signify the requirements in the specification. These words are often capitalized. This document defines these words as they should be interpreted in IETF documents. Authors who follow
+ these guidelines should incorporate this phrase near the beginning of their document:
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119.
+
+ === NEW ===
+
+ In many IETF documents, several words, when they are in all capitals as shown below, are used to signify the requirements in the specification. These capitalized words can bring significant clarity and consistency to documents because their
+ meanings are well defined. This document defines how those words are interpreted in IETF documents when the words are in all capitals.
+
+ This document does not require any IANA actions. +
++ This document is purely procedural; there are no related security considerations. +
++ [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997, http://www.rfc-editor.org/info/rfc2119. +
+
+ Barry Leiba
+ Huawei Technologies
+ Phone: +1 646 827 0648
+ Email: barryleiba@computer.org
+ URI: http://internetmessagingtechnology.org/
+
+ Copyright (c) < year>, < copyright holder>
+
+ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
If You have questions about this Policy, You can contact Us as described below.
- Email: privacy@codewe.bhasher.com
+ Email: privacy-codewe@bhasher.com
- This project is licensed under the MIT License available here. You are free to obtain a copy of this project. If You obtain a copy of this Project, these Terms and
+ This project is licensed under the MIT License available here. You are free to obtain a copy of this project. If You obtain a copy of this Project, these Terms and
Condition, as well as the Privacy Policy, no longer apply and We cannot be held responsible for any actions when using this copy.
+
+ Copying the project SHALL NOT grant You any copyrights over it.
If You have any request or require additional clarification, do not hesitate to contact Us!
- Email: terms@codewe.bhasher.com
+ Email: terms-codewe@bhasher.com