ep_markdown 11.0.19 → 12.0.1

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
@@ -53,10 +52,21 @@ jobs:
53
52
  fetch-depth: 0
54
53
  -
55
54
  name: Bump version (patch)
55
+ id: bump
56
56
  run: |
57
57
  LATEST_TAG=$(git describe --tags --abbrev=0) || exit 1
58
58
  NEW_COMMITS=$(git rev-list --count "${LATEST_TAG}"..) || exit 1
59
- [ "${NEW_COMMITS}" -gt 0 ] || exit 0
59
+ # No new commits since the last tag → nothing to publish.
60
+ # Setting `bumped=false` lets the publish step below skip
61
+ # itself instead of trying to republish the existing version
62
+ # (which fails with "cannot publish over previously published
63
+ # versions"). Only manual `gh workflow run` invocations on a
64
+ # tag-current branch hit this path; on:push always sees ≥1
65
+ # new commit because the push event is what triggered us.
66
+ if [ "${NEW_COMMITS}" -le 0 ]; then
67
+ echo "bumped=false" >> "${GITHUB_OUTPUT}"
68
+ exit 0
69
+ fi
60
70
  git config user.name 'github-actions[bot]'
61
71
  git config user.email '41898282+github-actions[bot]@users.noreply.github.com'
62
72
  pnpm i --frozen-lockfile
@@ -84,9 +94,11 @@ jobs:
84
94
  # rejects the tag push too, and the next workflow tick can retry
85
95
  # cleanly against the up-to-date refs.
86
96
  git push --atomic origin "${GITHUB_REF_NAME}" "${NEW_TAG}"
97
+ echo "bumped=true" >> "${GITHUB_OUTPUT}"
87
98
  # This is required if the package has a prepare script that uses something
88
99
  # in dependencies or devDependencies.
89
100
  -
101
+ if: steps.bump.outputs.bumped == 'true'
90
102
  run: pnpm i
91
103
  # `npm publish` must come after `git push` otherwise there is a race
92
104
  # condition: If two PRs are merged back-to-back then master/main will be
@@ -104,4 +116,5 @@ jobs:
104
116
  # whichever `npm` is on PATH; calling `npm` directly avoids any shim
105
117
  # ambiguity.
106
118
  - name: Publish to npm via OIDC
119
+ if: steps.bump.outputs.bumped == 'true'
107
120
  run: npm publish --provenance --access public
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.19",
4
+ "version": "12.0.1",
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>