ep_markdown 11.0.20 → 12.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -33,7 +33,7 @@ jobs:
33
33
  - uses: pnpm/action-setup@v6
34
34
  name: Install pnpm
35
35
  with:
36
- version: 10
36
+ package_json_file: ./etherpad-lite/package.json
37
37
  run_install: false
38
38
  - name: Get pnpm store directory
39
39
  shell: bash
@@ -23,7 +23,7 @@ jobs:
23
23
  - uses: pnpm/action-setup@v6
24
24
  name: Install pnpm
25
25
  with:
26
- version: 10
26
+ package_json_file: ./etherpad-lite/package.json
27
27
  run_install: false
28
28
  - name: Get pnpm store directory
29
29
  shell: bash
@@ -34,7 +34,6 @@ jobs:
34
34
  - uses: pnpm/action-setup@v6
35
35
  name: Install pnpm
36
36
  with:
37
- version: 10
38
37
  run_install: false
39
38
  - name: Get pnpm store directory
40
39
  shell: bash
package/AGENTS.md ADDED
@@ -0,0 +1,75 @@
1
+ # Agent Guide — ep_markdown
2
+
3
+ Edit and Export as Markdown in Etherpad.
4
+
5
+ ## Tech stack
6
+
7
+ * Etherpad plugin framework (hooks declared in `ep.json`)
8
+ * EJS templates rendered server-side via `eejsBlock_*` hooks
9
+ * html10n for i18n (`locales/<lang>.json`, `data-l10n-id` in templates)
10
+ * `ep_plugin_helpers` for shared boilerplate
11
+
12
+ ## Project structure
13
+
14
+ ```
15
+ ep_markdown/
16
+ ├── AGENTS.md
17
+ ├── CONTRIBUTING.md
18
+ ├── ep.json
19
+ ├── exportMarkdown.ts
20
+ ├── express.ts
21
+ ├── index.ts
22
+ ├── locales/
23
+ │ ├── ar.json
24
+ │ ├── bn.json
25
+ │ ├── ca.json
26
+ │ ├── cs.json
27
+ │ ├── de.json
28
+ │ ├── diq.json
29
+ │ └── ...
30
+ ├── package.json
31
+ ├── static/
32
+ │ ├── css/
33
+ │ ├── js/
34
+ │ ├── tests/
35
+ ├── templates/
36
+ │ ├── exportcolumn.html
37
+ ```
38
+
39
+ ## Helpers used
40
+
41
+ * `pad-toggle` from `ep_plugin_helpers`
42
+
43
+
44
+ ## Helpers NOT used
45
+
46
+ _To be audited in the helpers-adoption sweep (Phase 4)._
47
+
48
+
49
+ ## Running tests locally
50
+
51
+ `ep_markdown` runs inside Etherpad's test harness. From an etherpad checkout that has installed this plugin via `pnpm run plugins i --path ../ep_markdown`:
52
+
53
+ ```bash
54
+ # Backend (Mocha) — harness boots its own server
55
+ pnpm --filter ep_etherpad-lite run test
56
+
57
+ # Playwright — needs `pnpm run dev` in a second terminal
58
+ pnpm --filter ep_etherpad-lite run test-ui
59
+ ```
60
+
61
+ ## Standing rules for agent edits
62
+
63
+ * PRs target `main`. Linear commits, no merge commits.
64
+ * Every bug fix includes a regression test in the same commit.
65
+ * All user-facing strings in `locales/`. No hardcoded English in templates.
66
+ * No hardcoded `aria-label` on icon-only controls — etherpad's html10n auto-populates `aria-label` from the localized string when (a) the element has a `data-l10n-id` and (b) no author-supplied `aria-label` is present. Adding a hardcoded English `aria-label` blocks that and leaves it untranslated. (See `etherpad-lite/src/static/js/vendors/html10n.ts:665-678`.)
67
+ * No nested interactive elements (no `<button>` inside `<a>`).
68
+ * LLM/Agent contributions are explicitly welcomed by maintainers.
69
+
70
+ ## Quick reference: hooks declared in `ep.json`
71
+
72
+ * Server: `expressCreateServer`, `loadSettings`, `clientVars`, `eejsBlock_exportColumn`, `eejsBlock_mySettings`, `eejsBlock_padSettings`, `import`
73
+ * Client: `aceEditorCSS`, `postAceInit`, `handleClientMessage_CLIENT_MESSAGE`
74
+
75
+ When adding a hook, register it in both `ep.json` *and* the matching `exports.<hook> = ...` in the JS file.
package/CONTRIBUTING.md CHANGED
@@ -1,2 +1,74 @@
1
- # Auto publishing
2
- To publish a new version of this plugin to NPM just bump the version number in package.json and travis will auto publish for you.
1
+ # Contributing to ep_markdown
2
+
3
+ Thanks for helping improve `ep_markdown` — a plugin for [Etherpad](https://etherpad.org/). LLM/Agent contributions are explicitly welcome, provided they follow the rules below.
4
+
5
+ For shared rules that apply to all Etherpad code (linear commits, deprecation policy, feature flags, stability guarantees), please read [ether/etherpad's CONTRIBUTING.md](https://github.com/ether/etherpad/blob/develop/CONTRIBUTING.md). This document only covers what's specific to plugin work.
6
+
7
+ ## Plugin-specific rules
8
+
9
+ * **Target branch:** PRs go to `main` on this repo. Plugin repos do not use git-flow's `develop` branch.
10
+ * **Linear commits, no merge commits.** Rebase if needed.
11
+ * **Every bug fix must include a regression test in the same commit.**
12
+ * **Internationalization (i18n):** every user-facing string lives in `locales/<lang>.json` and is referenced via `data-l10n-id` in templates or `html10n.get(key)` in code. No hardcoded English in markup.
13
+ * **Accessibility (a11y):** no nested interactive elements (no `<button>` inside `<a>`); every interactive control has an accessible name; keyboard focus order matches visual order. Note that on icon-only controls you should rely on Etherpad's html10n to populate `aria-label` from the `data-l10n-id` translation — adding a hardcoded English `aria-label` blocks that and leaves the control untranslated.
14
+
15
+ ## Local development
16
+
17
+ `ep_markdown` is a plugin, so you develop it inside a checkout of [ether/etherpad](https://github.com/ether/etherpad).
18
+
19
+ ```bash
20
+ # Once: clone etherpad alongside this repo
21
+ git clone https://github.com/ether/etherpad.git
22
+ cd etherpad
23
+ pnpm install
24
+
25
+ # Install ep_markdown from your local clone
26
+ pnpm run plugins i --path ../ep_markdown
27
+
28
+ # Start the dev server (port 9001)
29
+ pnpm --filter ep_etherpad-lite run dev
30
+ ```
31
+
32
+ Edits in `../ep_markdown/` are picked up after a server restart.
33
+
34
+ ## Tests
35
+
36
+ Tests live inside this repo and are executed by Etherpad's test harness:
37
+
38
+ * Backend (Mocha): `static/tests/backend/specs/`
39
+ * Playwright (frontend E2E): `static/tests/frontend-new/specs/`
40
+
41
+ Run them from the etherpad checkout:
42
+
43
+ ```bash
44
+ # Backend (no separate server needed, harness boots one)
45
+ pnpm --filter ep_etherpad-lite run test
46
+
47
+ # Playwright (requires `pnpm run dev` in another terminal)
48
+ pnpm --filter ep_etherpad-lite run test-ui
49
+ ```
50
+
51
+ Lint locally before pushing:
52
+
53
+ ```bash
54
+ pnpm run lint
55
+ ```
56
+
57
+ ## Coding style
58
+
59
+ * JS/CSS/HTML: 2 spaces, no tabs.
60
+ * `pnpm run lint` must pass (configured via `eslint-config-etherpad`).
61
+ * Avoid breaking changes to public hooks, the line-attribute storage shape, or HTML export output. The backend export spec enforces a stable shape.
62
+
63
+ ## Bug reports
64
+
65
+ Please include:
66
+
67
+ * Etherpad version, ep_markdown version, browser + OS
68
+ * Steps to reproduce
69
+ * What you expected, what actually happened
70
+ * Server log excerpt (set `"loglevel": "DEBUG"` in `settings.json` for verbose output)
71
+
72
+ ## AI agents
73
+
74
+ If you are an LLM/agent contributor, also read [`AGENTS.md`](AGENTS.md) — it documents the file layout, helper usage, and standing rules for autonomous edits.
package/ep.json CHANGED
@@ -4,13 +4,17 @@
4
4
  "name": "markdown",
5
5
  "hooks":{
6
6
  "expressCreateServer": "ep_markdown/express",
7
+ "loadSettings": "ep_markdown/index",
8
+ "clientVars": "ep_markdown/index",
7
9
  "eejsBlock_exportColumn": "ep_markdown/index",
8
10
  "eejsBlock_mySettings": "ep_markdown/index",
11
+ "eejsBlock_padSettings": "ep_markdown/index",
9
12
  "import": "ep_markdown/index"
10
13
  },
11
14
  "client_hooks": {
12
15
  "aceEditorCSS": "ep_markdown/static/js/markdown",
13
- "postAceInit": "ep_markdown/static/js/markdown"
16
+ "postAceInit": "ep_markdown/static/js/markdown",
17
+ "handleClientMessage_CLIENT_MESSAGE": "ep_markdown/static/js/markdown:handleClientMessage_CLIENT_MESSAGE"
14
18
  }
15
19
  }
16
20
  ]
package/index.ts CHANGED
@@ -1,10 +1,25 @@
1
1
  'use strict';
2
2
 
3
3
  const eejs = require('ep_etherpad-lite/node/eejs');
4
- import settings from 'ep_etherpad-lite/node/utils/Settings';
4
+ const {padToggle} = require('ep_plugin_helpers/pad-toggle-server');
5
5
  import {promises} from 'fs';
6
6
  const fsp = promises
7
7
 
8
+ // Parallel User Settings + Pad Wide Settings checkboxes for "Show Markdown".
9
+ // Helper owns storage, broadcast, enforce, and i18n wiring.
10
+ const markdownToggle = padToggle({
11
+ pluginName: 'ep_markdown',
12
+ settingId: 'markdown',
13
+ l10nId: 'ep_markdown.showMarkdown',
14
+ defaultLabel: 'Show Markdown',
15
+ defaultEnabled: false,
16
+ });
17
+
18
+ exports.loadSettings = markdownToggle.loadSettings;
19
+ exports.clientVars = markdownToggle.clientVars;
20
+ exports.eejsBlock_mySettings = markdownToggle.eejsBlock_mySettings;
21
+ exports.eejsBlock_padSettings = markdownToggle.eejsBlock_padSettings;
22
+
8
23
  exports.eejsBlock_exportColumn = (hookName, context) => {
9
24
  context.content += eejs.require('./templates/exportcolumn.html', {}, module);
10
25
  };
@@ -13,17 +28,6 @@ exports.eejsBlock_styles = (hookName, context) => {
13
28
  context.content += eejs.require('./templates/styles.html', {}, module);
14
29
  };
15
30
 
16
- exports.eejsBlock_mySettings = (hookName, context) => {
17
- let checkedState = 'unchecked';
18
- if (!settings.ep_markdown_default) {
19
- checkedState = 'unchecked';
20
- } else if (settings.ep_markdown_default === true) {
21
- checkedState = 'checked';
22
- }
23
- context.content +=
24
- eejs.require('./templates/markdown_entry.ejs', {checked: checkedState}, module);
25
- };
26
-
27
31
  exports.import = async (hookName, {destFile, fileEnding, srcFile}) => {
28
32
  if (fileEnding !== '.md') return;
29
33
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "ep_markdown",
3
3
  "description": "Edit and Export as Markdown in Etherpad",
4
- "version": "11.0.20",
4
+ "version": "12.0.2",
5
5
  "author": {
6
6
  "name": "John McLear",
7
7
  "email": "john@mclear.co.uk",
@@ -12,6 +12,7 @@
12
12
  "url": "https://github.com/ether/ep_markdown.git"
13
13
  },
14
14
  "dependencies": {
15
+ "ep_plugin_helpers": "^0.3.2",
15
16
  "showdown": "^2.1.0"
16
17
  },
17
18
  "contributors": [],
@@ -22,7 +23,7 @@
22
23
  },
23
24
  "devDependencies": {
24
25
  "@types/mocha": "^10.0.10",
25
- "@types/node": "^25.6.0",
26
+ "@types/node": "^25.6.2",
26
27
  "eslint": "^8.57.1",
27
28
  "eslint-config-etherpad": "^4.0.5",
28
29
  "typescript": "^6.0.3"
@@ -1,5 +1,26 @@
1
1
  'use strict';
2
2
 
3
+ // Sub-path import keeps the client bundle clean. Importing the top-level
4
+ // `ep_plugin_helpers` index pulls in every helper's getters; `settings` and
5
+ // `toggle` reach server-only modules (eejs, Settings) which esbuild can't
6
+ // resolve for the browser.
7
+ const {padToggle} = require('ep_plugin_helpers/pad-toggle');
8
+
9
+ // Same config as the server-side instance — must agree on pluginName,
10
+ // settingId, l10nId, and defaultLabel for the checkbox ids and clientVars
11
+ // lookup to line up.
12
+ const markdownToggle = padToggle({
13
+ pluginName: 'ep_markdown',
14
+ settingId: 'markdown',
15
+ l10nId: 'ep_markdown.showMarkdown',
16
+ defaultLabel: 'Show Markdown',
17
+ defaultEnabled: false,
18
+ });
19
+
20
+ // Re-export so the helper sees pad-wide broadcasts and refreshes our state
21
+ // when another user toggles the pad-wide checkbox.
22
+ exports.handleClientMessage_CLIENT_MESSAGE = markdownToggle.handleClientMessage_CLIENT_MESSAGE;
23
+
3
24
  exports.postAceInit = (hookName, context) => {
4
25
  const padRootPath = new RegExp(/.*\/p\/[^/]+/)
5
26
  .exec(document.location.pathname) || clientVars.padId;
@@ -20,19 +41,8 @@ exports.postAceInit = (hookName, context) => {
20
41
  $('#strikethrough').removeAttr('style');
21
42
  };
22
43
 
23
- /* init */
24
- if ($('#options-markdown').is(':checked')) {
25
- enable();
26
- } else {
27
- disable();
28
- }
29
- /* on click */
30
- $('#options-markdown').on('click', () => {
31
- if ($('#options-markdown').is(':checked')) {
32
- enable();
33
- } else {
34
- disable();
35
- }
44
+ markdownToggle.init({
45
+ onChange: (enabled) => { enabled ? enable() : disable(); },
36
46
  });
37
47
  };
38
48
 
@@ -1,4 +0,0 @@
1
- <p>
2
- <input type="checkbox" id="options-markdown" <%= checked %>></input>
3
- <label for="options-markdown" data-l10n-id="ep_markdown.showMarkdown">Show markdown</label>
4
- </p>