3.7 KiB
date | title | slug | weight | toc | draft | menu | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
2021-10-13T16:00:00+02:00 | Guidelines for Frontend Development | guidelines-frontend | 20 | false | false |
|
Guidelines for Frontend Development
Table of Contents
{{< toc >}}
Background
Gitea uses Less CSS, Fomantic-UI (based on jQuery) and Vue2 for its frontend.
The HTML pages are rendered by Go HTML Template
General Guidelines
We recommend Google HTML/CSS Style Guide and Google JavaScript Style Guide
Gitea specific guidelines:
- Every feature (Fomantic-UI/jQuery module) should be put in separate files/directories.
- HTML ids and classes should use kebab-case.
- HTML ids and classes used in JavaScript should be unique for the whole project, and should contain 2-3 feature related keywords. We recommend to use the
js-
prefix for classes that are only used in JavaScript. - jQuery events across different features should use their own namespaces.
- CSS styling for classes provided by frameworks should not be overwritten. Always use new class-names to overwrite framework styles. We recommend to use the
us-
prefix for user defined styles. - The backend can pass complex data to the frontend by using
ctx.PageData["myModuleData"] = map[]{}
- Simple pages and SEO-related pages use Go HTML Template render to generate static Fomantic-UI HTML output. Complex pages can use Vue2 (or Vue3 in future).
async
Functions
Only mark a function as async
if and only if there are await
calls
or Promise
returns inside the function.
It's not recommended to use async
event listeners, which may lead to problems.
The reason is that the code after await is executed outside the event dispatch.
Reference: https://github.com/github/eslint-plugin-github/blob/main/docs/rules/async-preventdefault.md
If we want to call an async
function in a non-async context,
it's recommended to use const _promise = asyncFoo()
to tell readers
that this is done by purpose, we want to call the async function and ignore the Promise.
Some lint rules and IDEs also have warnings if the returned Promise is not handled.
DOM Event Listener
el.addEventListener('click', (e) => {
(async () => {
await asyncFoo(); // recommended
// then we shound't do e.preventDefault() after await, no effect
})();
const _promise = asyncFoo(); // recommended
e.preventDefault(); // correct
});
el.addEventListener('async', async (e) => { // not recommended but acceptable
e.preventDefault(); // acceptable
await asyncFoo(); // skip out event dispath
e.preventDefault(); // WRONG
});
jQuery Event Listener
$('#el').on('click', (e) => {
(async () => {
await asyncFoo(); // recommended
// then we shound't do e.preventDefault() after await, no effect
})();
const _promise = asyncFoo(); // recommended
e.preventDefault(); // correct
return false; // correct
});
$('#el').on('click', async (e) => { // not recommended but acceptable
e.preventDefault(); // acceptable
return false; // WRONG, jQuery expects the returned value is a boolean, not a Promise
await asyncFoo(); // skip out event dispath
return false; // WRONG
});
Vue2/Vue3 and JSX
Gitea is using Vue2 now, we plan to upgrade to Vue3. We decided not to introduce JSX to keep the HTML and the JavaScript code separated.