Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added Biome linter and formatter with ci #1015

Merged
merged 1 commit into from
Aug 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,17 @@ jobs:

- name: Run spell check
run: cspell

quality:
name: Linting and formatting
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Setup Biome
uses: biomejs/setup-biome@v2

- name: Run Biome
run: biome ci .
41 changes: 41 additions & 0 deletions biome.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{
"$schema": "https://biomejs.dev/schemas/1.8.3/schema.json",
"organizeImports": {
"enabled": true
},
"linter": {
"enabled": true,
"rules": {
"recommended": false,
"complexity": {
"noStaticOnlyClass": "error",
"noUselessSwitchCase": "error",
"useFlatMap": "error"
},
"style": {
"noNegationElse": "off",
"useForOf": "error",
"useNodejsImportProtocol": "error",
"useNumberNamespace": "error"
},
"suspicious": {
"noDoubleEquals": "error",
"noThenProperty": "error",
"useIsArray": "error"
}
}
},
"files": {
"include": ["src/**/*", "utils/**/*.js", "www/**/*.js", "www/res/**/*.css"],
"ignore": [
"www/js/**/*.js",
"www/css/**/*.css",
"src/plugins/**/*",
"plugins/**/*",
"hooks/**/*",
"fastlane/**/*",
"res/**/*",
"platforms/**/*"
]
}
}
8 changes: 6 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@
"clean": "sh utils/scripts/clean.sh android android",
"plugin": "sh utils/scripts/plugin.sh",
"setup": "node ./utils/setup.js",
"spellcheck": "npx cspell"
"spellcheck": "npx cspell",
"lint": "biome lint --write",
"format": "biome format --write",
"check": "biome check --write"
},
"keywords": [
"ecosystem:cordova"
Expand Down Expand Up @@ -50,6 +53,7 @@
"@babel/preset-env": "^7.24.6",
"@babel/runtime": "^7.24.6",
"@babel/runtime-corejs3": "^7.24.6",
"@biomejs/biome": "1.8.3",
"@types/ace": "^0.0.52",
"@types/url-parse": "^1.4.11",
"autoprefixer": "^10.4.19",
Expand Down Expand Up @@ -102,4 +106,4 @@
"yargs": "^17.7.2"
},
"browserslist": "cover 100%,not android < 5"
}
}
21 changes: 21 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,27 @@ yarn setup
yarn build <platform (android)> <free|paid> <p|prod|d|dev>
```

## • Contributing

Acode Editor is an open-source project, and we welcome contributions from the community. To contribute, follow these steps:

1. Fork the repository.
2. Make your changes and commit them.
3. Push your changes to your fork.
4. Create a pull request and Wait for review.

Please ensure that your code is clean, well-formatted, and follows the project's coding standards. Acode uses [Biomejs](https://biomejs.dev/) for formatting and linting. You can use following commands to lints/format your code locally:
```shell
yarn lint # for linting
yarn format # for formatting
yarn spellcheck # for spellchecking
```
Also, ensure that your code is well-documented and includes comments where necessary.

> [!Note]
> You can use any package manager like npm or yarn or pnpm or bun.
> You can use your editor specific Biomejs plugin for auto-formatting and linting based on Acode's configs.

## • Developing a Plugin for Acode

For comprehensive documentation on creating plugins for Acode Editor, visit the [repository](https://github.com/deadlyjack/acode-plugin).
Expand Down
229 changes: 115 additions & 114 deletions src/ace/colorView.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
* @see https://github.com/easylogic/ace-colorpicker/blob/main/src/extension/ace/colorview.js
*/

import Color from 'utils/color';
import { HEX, HSL, HSLA, RGB, RGBA, isValidColor } from 'utils/color/regex';
import Color from "utils/color";
import { HEX, HSL, HSLA, RGB, RGBA, isValidColor } from "utils/color/regex";

const COLORPICKER_TOKEN_CLASS = '.ace_color';
const COLORPICKER_TOKEN_CLASS = ".ace_color";
const changedRules = [];

let editor = null;
Expand All @@ -17,139 +17,140 @@ let editor = null;
* @param {boolean} [force=false] Force update color view
*/
export default function initColorView(e, force = false) {
editor = e;
const { renderer } = editor;
editor = e;
const { renderer } = editor;

editor.on('changeMode', onChangeMode);
renderer.on('afterRender', afterRender);
editor.on("changeMode", onChangeMode);
renderer.on("afterRender", afterRender);

if (force) {
const { files } = editorManager;
if (force) {
const { files } = editorManager;

if (Array.isArray(files)) {
files.forEach(file => {
if (file.session) {
file.session._addedColorRule = false;
}
});
}
if (Array.isArray(files)) {
files.forEach((file) => {
if (file.session) {
file.session._addedColorRule = false;
}
});
}

onChangeMode();
}
onChangeMode();
}
}

export function deactivateColorView() {
const { renderer } = editor;
const { renderer } = editor;

changedRules.forEach((rule) => rule.shift());
changedRules.length = 0;
forceTokenizer();
changedRules.forEach((rule) => rule.shift());
changedRules.length = 0;
forceTokenizer();

editor.off('changeMode', onChangeMode);
renderer.off('afterRender', afterRender);
editor.off("changeMode", onChangeMode);
renderer.off("afterRender", afterRender);
}

/**
* Checks if the session supports color
* @param {AceAjax.IEditSession} session
* @returns
* @param {AceAjax.IEditSession} session
* @returns
*/
function sessionSupportsColor(session) {
const mode = session.getMode().$id.split('/').pop();
return /css|less|scss|sass|stylus|html|dart/.test(mode)
? mode
: false;
const mode = session.getMode().$id.split("/").pop();
return /css|less|scss|sass|stylus|html|dart/.test(mode) ? mode : false;
}

function onChangeMode() {
const session = editor.session;
let forceUpdate = false;

// if mode is not css, scss, sass, less, stylus, or html, return
const mode = sessionSupportsColor(session);
if (session._addedColorRule || !mode) {
return;
}

let rules = session.$mode.$highlightRules.getRules();

if (mode === 'css') {
rules = { 'ruleset': rules['ruleset'] };
} else if (mode === 'html') {
rules = { 'css-ruleset': rules['css-ruleset'] };
}

Object.keys(rules).forEach((key) => {
const rule = rules[key];
if (rule instanceof Array) {
const ruleExists = rule.some((r) => r.token === 'color');
if (ruleExists) return;
forceUpdate = true;
rule.unshift({
token: "color",
regex: `${HEX}|${RGB}|${RGBA}|${HSL}|${HSLA}`,
});
changedRules.push(rule);
return;
}
});

if (!forceUpdate) return;

forceTokenizer();
const session = editor.session;
let forceUpdate = false;

// if mode is not css, scss, sass, less, stylus, or html, return
const mode = sessionSupportsColor(session);
if (session._addedColorRule || !mode) {
return;
}

let rules = session.$mode.$highlightRules.getRules();

if (mode === "css") {
rules = { ruleset: rules["ruleset"] };
} else if (mode === "html") {
rules = { "css-ruleset": rules["css-ruleset"] };
}

Object.keys(rules).forEach((key) => {
const rule = rules[key];
if (Array.isArray(rule)) {
const ruleExists = rule.some((r) => r.token === "color");
if (ruleExists) return;
forceUpdate = true;
rule.unshift({
token: "color",
regex: `${HEX}|${RGB}|${RGBA}|${HSL}|${HSLA}`,
});
changedRules.push(rule);
return;
}
});

if (!forceUpdate) return;

forceTokenizer();
}

function afterRender() {
const { session, renderer } = editor;
const { content } = renderer;
let classes = COLORPICKER_TOKEN_CLASS;

// if session is css, scss, less, sass, stylus, or html (with css mode), continue

const mode = sessionSupportsColor(session);
if (!mode) {
return;
}

if (mode === 'scss') {
classes += ',.ace_function';
}

content.getAll(COLORPICKER_TOKEN_CLASS).forEach(( /**@type {HTMLElement} */ el, i, els) => {
let content = el.textContent;
const previousContent = els[i - 1]?.textContent;
const nextContent = els[i + 1]?.textContent;
const multiLinePrev = previousContent + content;
const multiLineNext = content + nextContent;

if (el.dataset.modified === 'true') return;
el.dataset.modified = 'true';

if (!isValidColor(content)) {
if (isValidColor(multiLinePrev)) {
content = multiLinePrev;
} else if (isValidColor(multiLineNext)) {
content = multiLineNext;
} else {
return;
}
}

try {
const fontColorString = Color(content).luminance > 0.5 ? "#000" : "#fff";
el.classList.add('ace_color');
el.style.cssText = `background-color: ${content}; color: ${fontColorString}; pointer-events: all;`;
} catch (error) {
console.log("Invalid color", content);
}
});
const { session, renderer } = editor;
const { content } = renderer;
let classes = COLORPICKER_TOKEN_CLASS;

// if session is css, scss, less, sass, stylus, or html (with css mode), continue

const mode = sessionSupportsColor(session);
if (!mode) {
return;
}

if (mode === "scss") {
classes += ",.ace_function";
}

content
.getAll(COLORPICKER_TOKEN_CLASS)
.forEach((/**@type {HTMLElement} */ el, i, els) => {
let content = el.textContent;
const previousContent = els[i - 1]?.textContent;
const nextContent = els[i + 1]?.textContent;
const multiLinePrev = previousContent + content;
const multiLineNext = content + nextContent;

if (el.dataset.modified === "true") return;
el.dataset.modified = "true";

if (!isValidColor(content)) {
if (isValidColor(multiLinePrev)) {
content = multiLinePrev;
} else if (isValidColor(multiLineNext)) {
content = multiLineNext;
} else {
return;
}
}

try {
const fontColorString =
Color(content).luminance > 0.5 ? "#000" : "#fff";
el.classList.add("ace_color");
el.style.cssText = `background-color: ${content}; color: ${fontColorString}; pointer-events: all;`;
} catch (error) {
console.log("Invalid color", content);
}
});
}

function forceTokenizer() {
const { session } = editor;
// force recreation of tokenizer
session.$mode.$tokenizer = null;
session.bgTokenizer.setTokenizer(session.$mode.getTokenizer());
// force re-highlight whole document
session.bgTokenizer.start(0);
const { session } = editor;
// force recreation of tokenizer
session.$mode.$tokenizer = null;
session.bgTokenizer.setTokenizer(session.$mode.getTokenizer());
// force re-highlight whole document
session.bgTokenizer.start(0);
}
Loading