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
- 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)
138 lines
5.2 KiB
Markdown
138 lines
5.2 KiB
Markdown
# 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
|
|
|
|
```json
|
|
{
|
|
"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](#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](#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 |
|
|
|
|
```js
|
|
// 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:
|
|
|
|
```json
|
|
{
|
|
"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:
|
|
|
|
```js
|
|
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/`](https://github.com/shiaho777/web-to-app/tree/main/modules) for complete working examples.
|