diff --git a/404.html b/404.html index 1b60085..78225b7 100644 --- a/404.html +++ b/404.html @@ -17,8 +17,14 @@

Page not found

-

There is nothing at this address. Markdown Wizard is a single page, so the editor is the only place to go.

+

There is nothing at this address. The editor is at the top of the site, and everything else is linked below.

Open the editor

+
diff --git a/css/app.css b/css/app.css index 744f6f8..1439741 100644 --- a/css/app.css +++ b/css/app.css @@ -452,3 +452,72 @@ body.dropping .editor-pane { outline: 2px dashed var(--accent); outline-offset: .notfound h1 { margin: 0 0 .5rem; font-size: 1.6rem; } .notfound p { margin: 0 0 1.25rem; color: var(--muted); line-height: 1.6; } .notfound a.btn { display: inline-block; text-decoration: none; padding: 8px 16px; } + +/* ------------------------------------------------- static content pages + privacy / terms / docs / support (DS §9). + + `body` above is a fixed-height flex column with `overflow: hidden`, because + the editor is an app shell whose two panes scroll independently and the + window itself must never scroll. A legal page is the opposite shape — one + long document — so it gets its own scroll container rather than the rule + being relaxed on body, which would let the editor scroll away from under + the toolbar. + + These pages reuse `.sheet.md-body`, the same document styling the preview + pane renders into. That is deliberate: the legal copy then looks like a + document produced by this editor, and there is one prose stylesheet to keep + correct instead of two. `.sheet` fills the preview pane via min-height, so + that has to be released here or a short page stretches to the viewport. */ +.page { + flex: 1 1 auto; + overflow-y: auto; + padding: 28px 20px 56px; +} +.page .sheet { min-height: 0; } +.page .md-body > h1 { margin-top: 0; } + +/* `.btn` is styled for
+
diff --git a/privacy.html b/privacy.html new file mode 100644 index 0000000..0bad0a9 --- /dev/null +++ b/privacy.html @@ -0,0 +1,101 @@ + + + + + + Privacy Policy — Markdown Wizard + + + + + + + + + +
+
Markdown Wizard
+
Open the editor
+
+ +
+
+

Privacy Policy

+

Last updated: September 3, 2026

+ +

The short version

+

Markdown Wizard runs entirely in your browser. The text you type, paste, or open is + never sent to a server — there is no backend to send it to. It is rendered, + converted, and exported on your own device, and it is saved only in your browser's local + storage so your work survives a reload. There are no accounts, no logins, and no record + anywhere of what you wrote.

+ +

Your document

+ + +

Images you reference

+

This is the one case where using the editor can cause a request to leave your device, so it + is stated plainly rather than buried. If your Markdown references a remote image — + ![](https://example.com/photo.png) — the preview loads that image, which tells + the server hosting it your IP address and browser user-agent, exactly as it would on any web + page. That request goes to whatever host you referenced; it never passes through us, + and the text of your document is not part of it. Referencing no remote images means no such + request happens.

+ +

This website

+

markdownwizard.app is served by Cloudflare Pages, which receives standard web request + metadata (IP address, user agent, requested URL, timestamp) in order to deliver the page and + protect against abuse.

+

For analytics we use self-hosted, cookieless + Plausible, running on our + own server rather than a third-party service. It records that a page was visited — never what + you typed. There are no cookies, no cross-site tracking, no personal identifiers, and nothing + is shared with ad networks. It does not load at all when the app is opened offline from + file://.

+ +

What we never collect

+ + +

Data sharing

+

We do not sell, rent, or share your personal information. The only third parties involved + are Cloudflare, which serves this site, and our own self-hosted Plausible instance.

+ +

Children's privacy

+

Markdown Wizard does not knowingly collect any personal information from children under 13 + years of age.

+ +

Changes to this policy

+

We may update this policy from time to time; material changes are reflected in the + "Last updated" date above.

+ +

Contact

+

Questions about this policy? See the support page for how to reach + us.

+
+ + +
+ + + diff --git a/sitemap-0.xml b/sitemap-0.xml index 86b0874..b6b99ad 100644 --- a/sitemap-0.xml +++ b/sitemap-0.xml @@ -3,4 +3,16 @@ https://markdownwizard.app/ + + https://markdownwizard.app/docs + + + https://markdownwizard.app/privacy + + + https://markdownwizard.app/support + + + https://markdownwizard.app/terms + diff --git a/support.html b/support.html new file mode 100644 index 0000000..3e7a64f --- /dev/null +++ b/support.html @@ -0,0 +1,68 @@ + + + + + + Support — Markdown Wizard + + + + + + + + + +
+
Markdown Wizard
+
Open the editor
+
+ +
+
+

Support

+ +

Need help? Here is how to get it.

+ +

Before you write

+

Most questions are answered in the documentation — how the editor works, + every download format, the keyboard shortcuts, and what to do when an export does not look + the way you expected.

+

Three of the most common ones, answered here:

+ + +

Report a bug or ask for a feature

+

Markdown Wizard is developed in the open. The fastest way to reach us is to + open + an issue on GitHub — bug reports, format problems, and feature requests all belong there, + and you can see what has already been reported.

+

A good bug report says which browser and operating system you are on, which download format + misbehaved, and what you expected instead. If a specific document triggers it, a small + example that reproduces the problem is worth more than anything else you can send.

+ +

Security

+

If you have found a security issue, please report it privately through + GitHub's + private vulnerability reporting rather than opening a public issue.

+
+ + +
+ + + diff --git a/terms.html b/terms.html new file mode 100644 index 0000000..80d3c7f --- /dev/null +++ b/terms.html @@ -0,0 +1,112 @@ + + + + + + Terms of Use — Markdown Wizard + + + + + + + + + +
+
Markdown Wizard
+
Open the editor
+
+ +
+
+

Terms of Use

+

Last updated: September 3, 2026

+ +

These Terms govern your use of Markdown Wizard (the "Service"). By using the Service, you + agree to them. This summary is provided for convenience and is not legal advice.

+ +

The product

+

Markdown Wizard is a Markdown editor and document converter that runs entirely in your + browser. There is no account, no upload, and no backend — your text is processed on your own + device, as described in the Privacy Policy. The Service is currently + free to use; there is no paid tier, no checkout, and no payment information is ever + collected.

+ +

Your content and your responsibility

+

The documents you write, open, and export belong to you and stay on your device — they are + never in our possession. You are responsible for how you use the Service and its output, and + for complying with the laws that apply to you.

+ +

Acceptable use

+

You agree not to use the Service to violate the law or the rights of others, and not to + attempt to disrupt, or gain unauthorized access to, the Service or its users.

+ +

Disclaimer of warranties

+

The Service is provided "as is" and "as available," without warranties of any kind, express + or implied. We do not guarantee uninterrupted or error-free operation. Document conversion in + particular is best-effort: exported files are generated by third-party libraries in your + browser, and fidelity varies by format and by the application you open them in. Keep your own + copy of anything important.

+ +

Limitation of liability

+

To the maximum extent permitted by law, Markdown Wizard and its developer are not liable for + indirect, incidental, or consequential damages, or for any loss of data or documents, or for + amounts exceeding the fees you paid in the 12 months before the claim (which, while the + Service is free, is $0).

+ +

Termination

+

You may stop using the Service at any time — closing the site abandons any locally stored + data, and clearing your browser data removes it. We may suspend or terminate access to + protect the Service and its users.

+ +

Changes

+

We may update these Terms; material changes are reflected in the "Last updated" date above. + Continued use after changes constitutes acceptance.

+ +

Governing law

+

These Terms are governed by and construed in accordance with the laws of the jurisdiction in + which the developer resides, without regard to conflict-of-law provisions.

+ +

Severability

+

If any provision of these Terms is found unenforceable or invalid, it shall be limited or + eliminated to the minimum extent necessary so that the remaining Terms stay in full force and + effect.

+ +

Third-party notices

+

Markdown Wizard is built with open-source components, each used under its own license. Full + license texts for the bundled libraries ship with the app under + js/vendor/licenses/.

+ + +

Contact

+

Questions about these Terms? See the support page for how to reach + us.

+
+ + +
+ + + diff --git a/tests/e2e.mjs b/tests/e2e.mjs index df74cdb..dd2cfd0 100644 --- a/tests/e2e.mjs +++ b/tests/e2e.mjs @@ -243,6 +243,57 @@ await page.click('#btnTheme'); await page.screenshot({ path: path.join(dlDir, 'screenshot-http.png') }); +console.log('\n== required pages (DS \u00a79) =='); + +// These four pages all returned 404 on the live site until 2026-09-03. A +// missing required page is invisible from the editor -- nothing links to it +// from the app shell by default and nothing else in this suite loads it -- so +// it is checked here rather than trusted. The canonical assertion is the half +// that catches a copy-paste: four pages built from one template will happily +// ship four identical canonical URLs, which is worse than none. +const REQUIRED = [ + { path: 'docs.html', route: '/docs', h1: 'Documentation' }, + { path: 'privacy.html', route: '/privacy', h1: 'Privacy Policy' }, + { path: 'support.html', route: '/support', h1: 'Support' }, + { path: 'terms.html', route: '/terms', h1: 'Terms of Use' }, +]; + +for (const pg of REQUIRED) { + await page.goto(`http://127.0.0.1:${port}/${pg.path}`); + const h1 = (await page.textContent('h1').catch(() => '')) || ''; + check(`${pg.route} renders its heading`, h1.trim() === pg.h1, h1.trim()); + + const canonical = await page.getAttribute('link[rel=canonical]', 'href').catch(() => null); + check(`${pg.route} declares its own canonical`, + canonical === `https://markdownwizard.app${pg.route}`, String(canonical)); + + // The app shell is a fixed-height flex column with overflow:hidden, so a long + // document only scrolls if .page supplies its own scroll container. Without it + // the page renders and silently truncates -- it looks fine in a screenshot. + const scrollable = await page.evaluate(() => { + const el = document.querySelector('.page'); + return !!el && getComputedStyle(el).overflowY === 'auto'; + }); + check(`${pg.route} content can scroll`, scrollable); + + const linked = await page.evaluate(() => + [...document.querySelectorAll('.pagefoot a')].map((a) => a.getAttribute('href'))); + check(`${pg.route} carries the site nav`, REQUIRED.every((r) => linked.includes(r.route)), + linked.join(' ')); +} + +// Reachability: a required page nothing links to is a page nobody finds. The +// editor has no site footer, so these live on the toolbar's trailing edge. +await page.goto(`http://127.0.0.1:${port}/`); +const editorLinks = await page.evaluate(() => + [...document.querySelectorAll('.tlinks a')].map((a) => a.getAttribute('href'))); +check('editor links every required page', + REQUIRED.every((r) => editorLinks.includes(r.route)), editorLinks.join(' ')); + +const sitemap = fs.readFileSync(path.join(appDir, 'sitemap-0.xml'), 'utf8'); +check('sitemap lists every required page', + REQUIRED.every((r) => sitemap.includes(`https://markdownwizard.app${r.route}<`))); + console.log('\n== file:// operation (offline / double-click use) =='); const page2 = await browser.newPage({ viewport: { width: 1440, height: 900 } }); const errors2 = [];