pdf-tei-editor / docs /code-assistant /coding-standards.md
cmboulanger's picture
disaster-recovery deploy of pdf-tei-editor
6a49f21 verified
|
Raw
History Blame Contribute Delete
5.33 kB

Coding Standards and Best Practices

🚨 CRITICAL: JSDoc Type Annotation Requirements

ALWAYS create comprehensive JSDoc headers for ALL functions and use specific types instead of generic "object".

When creating or modifying JavaScript functions, you MUST:

  1. Add JSDoc headers to ALL functions - No exceptions, even simple utility functions
  2. Use specific types instead of "object" - TypeScript can infer most types; leverage this
  3. Import types from relevant modules - Use @import statements for external types
  4. Add @param annotations with union types - E.g., @param {UserData|null} not @param {Object}
  5. Add @returns annotations with specific types - E.g., @returns {Promise<void>} not just @returns
  6. Type-cast variables when needed - Use /** @type {SpecificType|null} */ for variable declarations

Examples of CORRECT JSDoc annotations:

/**
 * @import { UserData } from './authentication.js'
 * @import { LookupItem } from '../modules/file-data-utils.js'
 */

/**
 * Checks if user has specific role
 * @param {UserData|null} user - User object or null
 * @param {string} role - Role name to check
 * @returns {boolean} True if user has role
 */
function userHasRole(user, role) {
  return user && user.roles && user.roles.includes(role)
}

/**
 * Gets file metadata by hash
 * @param {string} hash - File hash identifier
 * @returns {LookupItem|null} File data or null if not found
 */
function getFileData(hash) {
  /** @type {LookupItem|null} */
  const fileData = getFileDataByHash(hash)
  return fileData
}

AVOID these patterns:

  • @param {Object} - Too generic, use specific interface types
  • @param {object} - Same issue, specify the actual structure
  • Missing @returns on functions - Always specify return types
  • Untyped variables - Use @type comments for complex assignments

This ensures TypeScript error-free code and provides excellent IDE autocompletion support.

Python Development

  • Always prefer pathlib Path().as_posix() over manually concatenating path strings or os.path.join()
  • The backend auto-restarts when changes are detected - do not start, restart, or suggest restarting the server manually

Frontend Development

Shoelace Component Registration

When using new Shoelace components, ensure they are properly imported and exported in app/src/ui.js. Components not properly registered will have visibility: hidden due to the :not(:defined) CSS rule.

Example: if using sl-tree-item, import SlTreeItem from @shoelace-style/shoelace/dist/components/tree-item/tree-item.js and add it to the export list.

Shoelace Icon Resources

When using Shoelace icons programmatically (via icon attribute or StatusText widget) where the literal <sl-icon name="icon-name"></sl-icon> is not present in the codebase, add a comment with the HTML literal to ensure the build system includes the icon resource:

// <sl-icon name="icon-name"></sl-icon>

This is not needed when the icon tag already exists verbatim in templates or HTML.

Debug Logging

When adding temporary debug statements for interactive testing, use console.log("DEBUG ...") instead of logger.debug(). Always prefix the message with "DEBUG" to make them easily searchable and removable.

Example:

console.log("DEBUG Collection in options:", options.collection);

This allows easy filtering with browser dev tools and quick cleanup using search/replace.

UI Name Resolution System

The UI name resolution system allows lookup of DOM elements by a chain of nested "name" attributes. In runtime, it is updated by calling updateUi() from ui.js. Then, elements can be referred to by ui.<top-level-name>.<next-level-name>.... etc.

Each time a new element with a name is added to the DOM, updateUi() must be called again.

In code, this hierarchy must be manually added by JSDoc/TypeScript @typedef definitions to get autocompletion. TypeScript errors can indicate missing definitions - add them when needed.

JSDoc/TypeScript Best Practices

The application uses plain JavaScript to avoid transpilation. All type annotations are in JSDoc comments.

To avoid TypeScript errors, follow these best practices:

  • In catch blocks, use String(error) instead of error.message when the error message should be used in console messages, to avoid type checking overhead
  • Use specific types instead of generic object or Object
  • Always document return types, even for void functions
  • Import types from their source modules using @import

General Code Conventions

When making changes to files, first understand the file's code conventions. Mimic code style, use existing libraries and utilities, and follow existing patterns.

  • NEVER assume that a library is available, even if well known. Check package.json or neighboring files first
  • When creating a new component, look at existing components to understand framework choice, naming conventions, typing, and other conventions
  • When editing code, examine surrounding context (especially imports) to understand the code's choice of frameworks and libraries
  • Always follow security best practices. Never introduce code that exposes or logs secrets and keys. Never commit secrets or keys to the repository