OpenCode AI e9899d2e6d
Some checks failed
Android CI Build / check (push) Has been cancelled
Android CI Build / package-apks (push) Has been cancelled
Docs Deploy / build (push) Has been cancelled
Module Market Check / Validate modules/ (push) Has been cancelled
Module Market Publish / Generate submissions.json (push) Has been cancelled
Docs Deploy / deploy (push) Has been cancelled
Initial DruksCode V2: fresh fork of web-to-app (f3b488e) with DruksCode identity
- Package rename com.webtoapp -> br.com.drukstech.codeapp
- Product rename WebToApp/web-to-app -> DruksCode/drukscode
- Design system Wta* -> Dkc*
- applicationId br.com.drukstech.codeapp (.play for gplay flavor)
- rootProject.name DruksCode
- Fresh git history (upstream kept as remote for sync)
2026-09-12 02:42:02 +02:00

5.2 KiB

JS Modules

A JS module is the most capable native extension format: a manifest, a script, optional CSS, a config UI, and an optional floating panel — all packaged together.

File layout

my-module/
├── module.json    # required — the manifest
├── main.js        # required — runs in the WebView
├── style.css      # optional — auto-injected when hasCss / cssCode present
└── icon.png       # optional — ≤256KB; png/svg/webp/jpg/jpeg

module.json schema

{
  "id": "my-module",
  "name": "My Module",
  "description": "What it does",
  "icon": "star",
  "category": "CONTENT_ENHANCE",
  "tags": ["demo"],
  "version": { "code": 1, "name": "1.0.0", "changelog": "Initial release" },
  "author": { "name": "You", "url": "https://example.com" },
  "runAt": "DOCUMENT_END",
  "urlMatches": [
    { "pattern": "*://example.com/*", "isRegex": false, "exclude": false }
  ],
  "permissions": ["DOM_ACCESS", "STORAGE"],
  "configItems": [
    {
      "key": "greeting",
      "name": "Greeting text",
      "type": "TEXT",
      "defaultValue": "Hello",
      "required": true
    }
  ]
}

::: warning version is an object version has code (int), name (semver string), and changelog. Don't make it a plain string in module.json. :::

Field reference

Field Notes
id Globally unique.
icon A Material Icons name (e.g. star, package).
category One of: CONTENT_FILTER, CONTENT_ENHANCE, STYLE_MODIFIER, THEME, FUNCTION_ENHANCE, AUTOMATION, NAVIGATION, DATA_EXTRACT, DATA_SAVE, INTERACTION, ACCESSIBILITY, MEDIA, VIDEO, IMAGE, AUDIO, SECURITY, ANTI_TRACKING, SOCIAL, SHOPPING, READING, TRANSLATE, DEVELOPER, OTHER.
runAt DOCUMENT_START, DOCUMENT_END (default), DOCUMENT_IDLE, CONTEXT_MENU, BEFORE_UNLOAD.
urlMatches[] {pattern, isRegex=false, exclude=false}. See URL matching.
permissions[] Display-only; the runtime does not sandbox based on these. Dangerous ones (e.g. CAMERA, LOCATION, EVAL, FILE_ACCESS) get extra review.
configItems[] User-configurable fields; see Config items.

URL matching

  • isRegex: false (default) — Chrome-style glob. * matches anything; *:// expands to (https?|ftp|file)://; * or <all_urls> matches everything. Falls back to substring contains if the glob fails to match.
  • isRegex: true — Java regex with a 200ms timeout; a timeout counts as no match.
  • exclude: true — removes matching URLs from the result set.

The main.js contract

Your code is wrapped in an IIFE with a try/catch (errors go to console.error and never break the page). These globals are available:

Global Value
__MODULE_INFO__ {id, name, icon, version, uiConfig, runMode}
__MODULE_CONFIG__ The resolved config object
__MODULE_UI_CONFIG__ UI config
__MODULE_RUN_MODE__ 'INTERACTIVE' or 'AUTO'
__MODULE_PANEL_HTML__ Your panelHtml, if any
getConfig(key, defaultValue) Convenience accessor for config values
// main.js
const greeting = getConfig('greeting', 'Hello')
const banner = document.createElement('div')
banner.textContent = greeting
banner.style.cssText = 'position:fixed;top:0;left:0;z-index:99999;padding:8px;background:#2563eb;color:#fff'
document.body.appendChild(banner)

::: warning No top-level return Because your code is wrapped in an IIFE, a top-level return statement is invalid and is rejected by the market validator. :::

Config items

configItems[] build a settings UI for the user. Each item:

{
  "key": "speedLevel",
  "name": "Speed",
  "description": "Scroll speed multiplier",
  "type": "NUMBER",
  "defaultValue": "3",
  "options": [],
  "required": false,
  "placeholder": "",
  "validation": ""
}

Supported type values: TEXT, TEXTAREA, NUMBER, BOOLEAN, SELECT, MULTI_SELECT, RADIO, CHECKBOX, COLOR, URL, EMAIL, PASSWORD, REGEX, CSS_SELECTOR, JAVASCRIPT, JSON, RANGE, DATE, TIME, DATETIME, FILE, IMAGE.

Read values with getConfig(key, defaultValue).

Interactive panel

For a floating UI, provide panelHtml and register a panel button:

window.__DKC_MODULE_UI__.register({
  id: __MODULE_INFO__.id,
  name: __MODULE_INFO__.name,
  icon: __MODULE_INFO__.icon
})

Inside panelHtml, use data-dkc-action attributes wired to window.__dkc_module_action_<name> handlers, and style with the var(--dkc-*) theme variables so your panel matches the app theme.

Multi-file modules

codeFiles is a Map<filename, source>. The entry point is auto-detected from main.js, index.js, app.js, script.js, or content.js.

Packaging & sharing

  • Module export extension: .dkcmod; a bundle of modules: .dkcpkg.
  • Share code prefix: DKC1: (full gzip + Base64) or DKC2: (defaults-diff + max compression, emitted when V1 overflows one QR code), shareable via QR. Decoders accept V2, V1, and legacy bare Base64.

See the built-in hello-world and auto-scroll modules under modules/ for complete working examples.