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

fix(eslint): Fix linting javascript files, also lint typescript files #6725

Merged
merged 3 commits into from
Dec 2, 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
2 changes: 1 addition & 1 deletion .eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
module.exports = {
root: true,
extends: [
'@nextcloud/eslint-config/typescript',
'@nextcloud',
],
rules: {
'@typescript-eslint/no-unused-vars': ['off'],
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@
"build": "NODE_ENV=production NODE_OPTIONS='--max-old-space-size=4096' vite --mode production build",
"dev": "NODE_ENV=development NODE_OPTIONS='--max-old-space-size=4096' vite --mode development build",
"watch": "NODE_ENV=development NODE_OPTIONS='--max-old-space-size=8192' vite --mode development build --watch",
"lint": "tsc && eslint --ext .js,.vue src cypress",
"lint:fix": "tsc && eslint --ext .js,.vue src cypress --fix",
"lint": "tsc && eslint --ext .js,.ts,.vue src cypress",
"lint:fix": "tsc && eslint --ext .js,.ts,.vue src cypress --fix",
"stylelint": "stylelint src/**/*.vue src/**/*.scss src/**/*.css css/*.scss",
"stylelint:fix": "stylelint src/**/*.vue src/**/*.scss src/**/*.css css/*.scss --fix",
"test": "NODE_ENV=test vitest",
Expand Down
1 change: 1 addition & 0 deletions src/global.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ declare global {
// Nextcloud Globals
t: typeof import('@nextcloud/l10n').t
n: typeof import('@nextcloud/l10n').n
// eslint-disable-next-line @typescript-eslint/no-explicit-any
OCA: Record<string, any>
OCP: Nextcloud.v29.OCP
}
Expand Down
10 changes: 5 additions & 5 deletions src/markdownit/details.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ const SUMMARY_REGEX = /(?<=^<summary>).*(?=<\/summary>\s*$)/

/**
*
* @param state
* @param startLine
* @param endLine
* @param silent
* @param state - MarkdownIt state
* @param startLine - start line number
* @param endLine - end line number
* @param silent - validation mode
*/
function parseDetails(state: StateBlock, startLine: number, endLine: number, silent: boolean) {
// let autoClosedBlock = false
Expand Down Expand Up @@ -120,7 +120,7 @@ function parseDetails(state: StateBlock, startLine: number, endLine: number, sil
}

/**
* @param {object} md Markdown object
* @param {object} md - Markdown object
*/
export default function details(md: MarkdownIt) {
md.block.ruler.before('fence', 'details', parseDetails, {
Expand Down
246 changes: 152 additions & 94 deletions src/markdownit/taskLists.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,139 +21,197 @@ interface TaskListsOptions {

const checkboxRegex = /^ *\[([\sx])] /i

/**
*
* @param md -
* @param options - taskLists plugin options
*/
export default function taskLists(
md: MarkdownIt,
options: TaskListsOptions = { enabled: false, label: false, lineNumber: false }
md: MarkdownIt,
options: TaskListsOptions = { enabled: false, label: false, lineNumber: false },
): void {
md.core.ruler.after('inline', 'task-lists', (state) => processToken(state, options))
md.renderer.rules.taskListItemCheckbox = (tokens) => {
const token = tokens[0]
const checkedAttribute = token.attrGet('checked') ? 'checked="" ' : ''
const disabledAttribute = token.attrGet('disabled') ? 'disabled="" ' : ''
const line = token.attrGet('line')
const idAttribute = `id="${token.attrGet('id')}" `
const dataLineAttribute = line && options.lineNumber ? `data-line="${line}" ` : ''

return `<input class="task-list-item-checkbox" type="checkbox" ${checkedAttribute}${disabledAttribute}${dataLineAttribute}${idAttribute}/>`
}

md.renderer.rules.taskListItemLabel_close = () => {
return '</label>'
}

md.renderer.rules.taskListItemLabel_open = (tokens: Token[]) => {
const token = tokens[0]
const id = token.attrGet('id')
return `<label for="${id}">`
}
md.core.ruler.after('inline', 'task-lists', (state) => processToken(state, options))
md.renderer.rules.taskListItemCheckbox = (tokens) => {
const token = tokens[0]
const checkedAttribute = token.attrGet('checked') ? 'checked="" ' : ''
const disabledAttribute = token.attrGet('disabled') ? 'disabled="" ' : ''
const line = token.attrGet('line')
const idAttribute = `id="${token.attrGet('id')}" `
const dataLineAttribute = line && options.lineNumber ? `data-line="${line}" ` : ''

return `<input class="task-list-item-checkbox" type="checkbox" ${checkedAttribute}${disabledAttribute}${dataLineAttribute}${idAttribute}/>`
}

md.renderer.rules.taskListItemLabel_close = () => {
return '</label>'
}

md.renderer.rules.taskListItemLabel_open = (tokens: Token[]) => {
const token = tokens[0]
const id = token.attrGet('id')
return `<label for="${id}">`
}
}

/**
*
* @param state - markdownIt state
* @param options - taskLists plugin options
*/
function processToken(state: StateCore, options: TaskListsOptions): boolean {
const allTokens = state.tokens
for (let i = 2; i < allTokens.length; i++) {
if (!isTodoItem(allTokens, i)) {
continue
}

todoify(allTokens[i], options)
allTokens[i - 2].attrJoin('class', `task-list-item ${options.enabled ? ' enabled' : ''}`)

const parentToken = findParentToken(allTokens, i - 2)
if (parentToken) {
const classes = parentToken.attrGet('class') ?? ''
if (!classes.match(/(^| )contains-task-list/)) {
parentToken.attrJoin('class', 'contains-task-list')
}
}
}
return false
const allTokens = state.tokens
for (let i = 2; i < allTokens.length; i++) {
if (!isTodoItem(allTokens, i)) {
continue
}

todoify(allTokens[i], options)
allTokens[i - 2].attrJoin('class', `task-list-item ${options.enabled ? ' enabled' : ''}`)

const parentToken = findParentToken(allTokens, i - 2)
if (parentToken) {
const classes = parentToken.attrGet('class') ?? ''
if (!classes.match(/(^| )contains-task-list/)) {
parentToken.attrJoin('class', 'contains-task-list')
}
}
}
return false
}

/**
*
* @param tokens - MarkdownIt nodes/tokens
* @param index - index of the token to find
*/
function findParentToken(tokens: Token[], index: number): Token | undefined {
const targetLevel = tokens[index].level - 1
for (let currentTokenIndex = index - 1; currentTokenIndex >= 0; currentTokenIndex--) {
if (tokens[currentTokenIndex].level === targetLevel) {
return tokens[currentTokenIndex]
}
}
return undefined
const targetLevel = tokens[index].level - 1
for (let currentTokenIndex = index - 1; currentTokenIndex >= 0; currentTokenIndex--) {
if (tokens[currentTokenIndex].level === targetLevel) {
return tokens[currentTokenIndex]
}
}
return undefined
}

/**
*
* @param tokens - MarkdownIt nodes/tokens
* @param index - index of the token to check
*/
function isTodoItem(tokens: Token[], index: number): boolean {
return (
isInline(tokens[index]) &&
isParagraph(tokens[index - 1]) &&
isListItem(tokens[index - 2]) &&
startsWithTodoMarkdown(tokens[index])
)
return (
isInline(tokens[index])
&& isParagraph(tokens[index - 1])
&& isListItem(tokens[index - 2])
&& startsWithTodoMarkdown(tokens[index])
)
}

/**
*
* @param token - MarkdownIt node/token
* @param options - taskLists plugin options
*/
function todoify(token: Token, options: TaskListsOptions): void {
if (token.children == null) {
return
}
if (token.children == null) {
return
}

const id = generateIdForToken(token)
const id = generateIdForToken(token)

token.children.splice(0, 0, createCheckboxToken(token, options.enabled, id))
token.children[1].content = token.children[1].content.replace(checkboxRegex, '')
token.children.splice(0, 0, createCheckboxToken(token, options.enabled, id))
token.children[1].content = token.children[1].content.replace(checkboxRegex, '')

if (options.label) {
token.children.splice(1, 0, createLabelBeginToken(id))
token.children.push(createLabelEndToken())
}
if (options.label) {
token.children.splice(1, 0, createLabelBeginToken(id))
token.children.push(createLabelEndToken())
}
}

/**
*
* @param token - MarkdownIt node/token
*/
function generateIdForToken(token: Token): string {
if (token.map) {
return `task-item-${token.map[0]}`
} else {
return `task-item-${Math.ceil(Math.random() * (10000 * 1000) - 1000)}`
}
if (token.map) {
return `task-item-${token.map[0]}`
} else {
return `task-item-${Math.ceil(Math.random() * (10000 * 1000) - 1000)}`
}
}

/**
*
* @param token - MarkdownIt node/token
* @param enabled - whether input element is enabled or not
* @param id - ID of the taskLists item
*/
function createCheckboxToken(token: Token, enabled: boolean, id: string): Token {
const checkbox = new Token('taskListItemCheckbox', '', 0)
if (!enabled) {
checkbox.attrSet('disabled', 'true')
}
if (token.map) {
checkbox.attrSet('line', token.map[0].toString())
}

checkbox.attrSet('id', id)

const checkboxRegexResult = checkboxRegex.exec(token.content)
const isChecked = checkboxRegexResult?.[1].toLowerCase() === 'x'
if (isChecked) {
checkbox.attrSet('checked', 'true')
}

return checkbox
const checkbox = new Token('taskListItemCheckbox', '', 0)
if (!enabled) {
checkbox.attrSet('disabled', 'true')
}
if (token.map) {
checkbox.attrSet('line', token.map[0].toString())
}

checkbox.attrSet('id', id)

const checkboxRegexResult = checkboxRegex.exec(token.content)
const isChecked = checkboxRegexResult?.[1].toLowerCase() === 'x'
if (isChecked) {
checkbox.attrSet('checked', 'true')
}

return checkbox
}

/**
*
* @param id - ID of the taskLists item
*/
function createLabelBeginToken(id: string): Token {
const labelBeginToken = new Token('taskListItemLabel_open', '', 1)
labelBeginToken.attrSet('id', id)
return labelBeginToken
const labelBeginToken = new Token('taskListItemLabel_open', '', 1)
labelBeginToken.attrSet('id', id)
return labelBeginToken
}

/**
*
*/
function createLabelEndToken(): Token {
return new Token('taskListItemLabel_close', '', -1)
return new Token('taskListItemLabel_close', '', -1)
}

/**
*
* @param token - MarkdownIt node/token
*/
function isInline(token: Token): boolean {
return token.type === 'inline'
return token.type === 'inline'
}

/**
*
* @param token - MarkdownIt node/token
*/
function isParagraph(token: Token): boolean {
return token.type === 'paragraph_open'
return token.type === 'paragraph_open'
}

/**
*
* @param token - MarkdownIt node/token
*/
function isListItem(token: Token): boolean {
return token.type === 'list_item_open'
return token.type === 'list_item_open'
}

/**
*
* @param token - MarkdownIt node/token
*/
function startsWithTodoMarkdown(token: Token): boolean {
return checkboxRegex.test(token.content)
return checkboxRegex.test(token.content)
}
3 changes: 2 additions & 1 deletion src/services/Outbox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ type Sendable = {
}

export default class Outbox {

#awarenessUpdate = ''
#syncUpdate = ''
#syncQuery = ''
Expand All @@ -33,7 +34,7 @@ export default class Outbox {
}

getDataToSend(): Sendable {
return {
return {
steps: [this.#syncUpdate, this.#syncQuery].filter(s => s),
awareness: this.#awarenessUpdate,
}
Expand Down
2 changes: 1 addition & 1 deletion src/vue-shim.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

declare module "*.vue" {
declare module '*.vue' {
import Vue from 'vue'
export default Vue
}
2 changes: 1 addition & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"extends": "@vue/tsconfig",
"compilerOptions": {
"allowSyntheticDefaultImports": true,
"allowJs": true,
"allowJs": true,
"declaration": true,
"esModuleInterop": true,
"lib": ["DOM", "ESNext"],
Expand Down
Loading