diff --git a/.github/workflows/help.preview.yml b/.github/workflows/help.preview.yml new file mode 100644 index 000000000..f21643e5f --- /dev/null +++ b/.github/workflows/help.preview.yml @@ -0,0 +1,81 @@ +name: Notesnook Help PR Preview + +on: + pull_request: + types: [opened, reopened, synchronize] + branches: [master, beta] + paths: + - "docs/help/**" + # re-run workflow if workflow file changes + - ".github/workflows/help.preview.yml" + +jobs: + build-and-deploy: + if: ${{ github.event.pull_request.head.repo.full_name == github.repository }} + runs-on: ubuntu-latest + env: + CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} + CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} + steps: + - name: Checkout + uses: actions/checkout@v5 + with: + fetch-depth: 0 + + - name: Setup Node + uses: ./.github/actions/setup-node-with-cache + + - name: Install dependencies + run: | + npm ci --ignore-scripts --prefer-offline --no-audit + npm run bootstrap -- --scope=help + + - name: Build help + run: npm run build:help + + - name: Deploy to Cloudflare Pages + id: deploy + working-directory: ./docs/help + run: | + set -euo pipefail + BRANCH=pr-${{ github.event.number }}-$(echo "${{ github.sha }}" | cut -c1-7) + echo "Deploying branch: $BRANCH" + DEPLOY_OUT=$(npx --yes wrangler pages deploy --project-name=notesnook-help --branch="$BRANCH" ./.vitepress/dist 2>&1) || { echo "$DEPLOY_OUT"; exit 1; } + echo "$DEPLOY_OUT" + PREVIEW_URL=$(printf "%s" "$DEPLOY_OUT" | grep -Eo 'https?://[^ ]+' | head -1 || true) + if [ -z "$PREVIEW_URL" ]; then + echo "WARNING: could not parse preview URL from wrangler output" + fi + echo "preview_url=$PREVIEW_URL" >> $GITHUB_ENV + + - name: Post or update PR comment + uses: actions/github-script@v6 + env: + preview_url: ${{ env.preview_url }} + with: + script: | + const marker = ''; + const prNumber = context.issue.number; + const previewUrl = process.env.preview_url || ''; + const body = `${marker}\n**Cloudflare Pages Docs Preview**\n\n${previewUrl || 'Preview URL unavailable — check workflow logs.'}\n\nCommit: ${process.env.GITHUB_SHA}\n`; + const { data: comments } = await github.rest.issues.listComments({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: prNumber, + }); + const existing = comments.find(c => c.body && c.body.includes(marker)); + if (existing) { + await github.rest.issues.updateComment({ + owner: context.repo.owner, + repo: context.repo.repo, + comment_id: existing.id, + body, + }); + } else { + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: prNumber, + body, + }); + } diff --git a/.github/workflows/help.publish.yml b/.github/workflows/help.publish.yml index 9520cbe67..19198be2e 100644 --- a/.github/workflows/help.publish.yml +++ b/.github/workflows/help.publish.yml @@ -2,11 +2,6 @@ name: Publish Notesnook Help on: workflow_dispatch: - push: - branches: - - "master" - paths: - - "docs/help/**" jobs: build: @@ -14,17 +9,21 @@ jobs: runs-on: ubuntu-22.04 steps: - name: Checkout - uses: actions/checkout@v5 - - uses: actions-rs/toolchain@v1 + uses: actions/checkout@v4 with: - toolchain: stable + # VitePress reads git history to show the last updated date per page. + fetch-depth: 0 - - name: Install docgen - run: cargo install --git https://github.com/thecodrr/docgen + - name: Setup Node + uses: ./.github/actions/setup-node-with-cache - - name: Build site - run: docgen build --release - working-directory: docs/help + - name: Install dependencies + run: | + npm ci --ignore-scripts --prefer-offline --no-audit + npm run bootstrap -- --scope=help + + - name: Build help + run: npm run build:help - name: Setup environment run: | @@ -32,4 +31,4 @@ jobs: echo "CLOUDFLARE_API_TOKEN=${{ secrets.CLOUDFLARE_API_TOKEN }}" >> $GITHUB_ENV - name: Publish on Cloudflare Pages - run: npx --yes wrangler pages deploy --project-name notesnook-help ./docs/help/site/ --branch main + run: npx --yes wrangler pages deploy --project-name notesnook-help ./docs/help/.vitepress/dist/ --branch main diff --git a/.github/workflows/web.preview.yml b/.github/workflows/web.preview.yml index fed377a79..bc8c2a470 100644 --- a/.github/workflows/web.preview.yml +++ b/.github/workflows/web.preview.yml @@ -27,7 +27,9 @@ jobs: uses: ./.github/actions/setup-node-with-cache - name: Install dependencies - run: npm ci + run: | + npm ci --ignore-scripts --prefer-offline --no-audit + npm run bootstrap -- --scope=web - name: Build web run: npm run build:web diff --git a/docs/help/.gitignore b/docs/help/.gitignore new file mode 100644 index 000000000..ce596990c --- /dev/null +++ b/docs/help/.gitignore @@ -0,0 +1,4 @@ +.vitepress/dist +.vitepress/cache +contents/v*/ +.vitepress/sidebars/generated.mjs diff --git a/docs/help/.vitepress/config.mts b/docs/help/.vitepress/config.mts new file mode 100644 index 000000000..c00ff338c --- /dev/null +++ b/docs/help/.vitepress/config.mts @@ -0,0 +1,219 @@ +import { defineConfig } from "vitepress"; +import { tabsMarkdownPlugin } from "vitepress-plugin-tabs"; +import taskLists from "markdown-it-task-lists"; +import { sidebar } from "./sidebar.mjs"; +import { + LATEST, + isArchivedPath, + versionOfPath, + versionsNavItem +} from "./versions.mjs"; +// Latest docs live at the root; the /v/ trees and their sidebars are +// composed from contents/_versions/ by scripts/build-versions.mjs, which runs +// before dev and build. +import { archivedSidebars } from "./sidebars/generated.mjs"; +import { seoHead, seoTitle } from "./seo.mjs"; +import { stringsMarkdownPlugin } from "./strings.mjs"; + +export default defineConfig({ + title: "Notesnook Help", + description: + "Your complete and free resource to using Notesnook as a daily note taking app to organize your work and life while safeguarding your privacy.", + lang: "en-US", + srcDir: "./contents", + // Version overrides are source material for build-versions.mjs, not pages. + // The Standard Notes importer is unpublished for now — the page is kept in + // the repo but is not built, linked or listed in the sitemap. Delete the + // second entry (and restore the sidebar link) to publish it again. + srcExclude: [ + "_versions/**", + "importing-notes/import-notes-from-standardnotes.md" + ], + cleanUrls: true, + lastUpdated: true, + metaChunk: true, + sitemap: { + hostname: "https://help.notesnook.com", + // Only the latest docs belong in the sitemap. + transformItems: (items) => + items.filter( + (i) => !isArchivedPath(`/${i.url}`) && !i.url.startsWith("404") + ) + }, + + transformPageData(pageData, ctx) { + const path = `/${pageData.relativePath}`; + pageData.frontmatter.head ??= []; + + // Archived pages are kept out of search engines so they don't compete with + // the latest docs, and are tagged so the layout can show a version banner. + if (isArchivedPath(path)) { + pageData.frontmatter.archivedVersion = versionOfPath(path); + pageData.frontmatter.latestVersion = LATEST; + pageData.frontmatter.head.push([ + "meta", + { name: "robots", content: "noindex,follow" } + ]); + return; + } + + // Canonical, Open Graph, Twitter cards and JSON-LD for the live docs. + seoTitle(pageData); + pageData.frontmatter.head.push(...seoHead(pageData, ctx)); + }, + + head: [ + ["link", { rel: "icon", href: "/favicon.ico" }], + // The two weights that render above the fold on every page. + [ + "link", + { + rel: "preload", + href: "/fonts/Inter-Regular.woff2", + as: "font", + type: "font/woff2", + crossorigin: "" + } + ], + [ + "link", + { + rel: "preload", + href: "/fonts/Inter-SemiBold.woff2", + as: "font", + type: "font/woff2", + crossorigin: "" + } + ], + ["meta", { name: "theme-color", content: "#008837" }], + ["meta", { property: "og:type", content: "website" }], + ["meta", { property: "og:site_name", content: "Notesnook Help" }], + ["meta", { property: "og:image", content: "/logo.png" }], + [ + "script", + { + async: "", + defer: "", + "data-website-id": "ad34576b-2721-436c-b36a-47a614009d2b", + src: "https://aas.streetwriters.co/script.js", + "data-domains": "help.notesnook.com" + } + ] + ], + + markdown: { + config(md) { + md.use(tabsMarkdownPlugin); + // `- [x] item` renders as a real checkbox instead of literal "[x]". + md.use(taskLists, { label: true, labelAfter: true }); + + // `{{archive}}` becomes the live label from packages/intl. + md.use(stringsMarkdownPlugin); + + // An image that shares a line with text is a UI glyph ("press the ⋯ + // button"), not a figure. Tag those so CSS can keep them in the line — + // :only-child can't be used for this because it ignores text nodes. + md.core.ruler.push("nn_inline_glyphs", (state) => { + for (const token of state.tokens) { + if (token.type !== "inline" || !token.children) continue; + // Line breaks split the inline token into segments. A screenshot on + // its own line inside a numbered step lives in the same inline token + // as the step's text, so "does this token contain text?" would wrongly + // shrink it — the question is whether text sits on *its* line. + let segment: typeof token.children = []; + const segments = [segment]; + for (const child of token.children) { + if (child.type === "softbreak" || child.type === "hardbreak") { + segment = []; + segments.push(segment); + } else segment.push(child); + } + for (const line of segments) { + const sharesLineWithText = line.some( + (child) => + (child.type === "text" && child.content.trim()) || + child.type === "code_inline" + ); + if (!sharesLineWithText) continue; + for (const child of line) { + if (child.type === "image") + child.attrJoin("class", "inline-glyph"); + } + } + } + return true; + }); + }, + image: { lazyLoading: true } + }, + + themeConfig: { + logo: "/logo.png", + siteTitle: "Help", + + nav: [ + versionsNavItem, + { text: "Downloads", link: "https://notesnook.com/downloads" }, + { text: "Pricing", link: "https://notesnook.com/pricing" }, + { + text: "More", + items: [ + { text: "Notesnook", link: "https://notesnook.com" }, + { text: "Blog", link: "https://blog.notesnook.com" }, + { text: "Roadmap", link: "https://notesnook.com/roadmap" }, + { text: "Contact us", link: "https://notesnook.com/contact-us" }, + { + text: "Report an issue", + link: "https://github.com/streetwriters/notesnook/issues/new/choose" + } + ] + } + ], + + sidebar: { ...archivedSidebars, "/": sidebar }, + + search: { + provider: "local", + options: { + detailedView: true, + // Archived versions are excluded so a search for "archive a note" does + // not return the same article once per version. + _render(src, env, md) { + if (isArchivedPath(`/${env.relativePath}`)) return ""; + return md.render(src, env); + } + } + }, + + outline: { level: [2, 3], label: "On this page" }, + + editLink: { + pattern: + "https://github.com/streetwriters/notesnook/edit/master/docs/help/contents/:path", + text: "Suggest an edit to this page" + }, + + lastUpdated: { + text: "Last updated", + formatOptions: { dateStyle: "medium", forceLocale: false } + }, + + socialLinks: [ + { icon: "github", link: "https://github.com/streetwriters/notesnook" }, + { icon: "mastodon", link: "https://mastodon.social/@notesnook" }, + { icon: "discord", link: "https://discord.com/invite/zQBK97EE22" }, + { icon: "x", link: "https://x.com/notesnook" } + ], + + footer: { + message: + 'Made with care by Streetwriters. Notesnook is open source.', + copyright: "Copyright © 2026 Streetwriters (Private) Limited" + }, + + docFooter: { prev: "Previous", next: "Next" }, + externalLinkIcon: true, + returnToTopLabel: "Back to top", + darkModeSwitchLabel: "Appearance" + } +}); diff --git a/docs/help/.vitepress/seo.mts b/docs/help/.vitepress/seo.mts new file mode 100644 index 000000000..c67d53d34 --- /dev/null +++ b/docs/help/.vitepress/seo.mts @@ -0,0 +1,207 @@ +/** + * Per-page SEO: canonical URL, Open Graph, Twitter cards and JSON-LD. + * + * The help site ranks #1 for high-intent queries like "import enex", so every + * page needs to be individually addressable, individually described, and + * eligible for rich results. Driven from each page's frontmatter: + * + * --- + * title: Import from Evernote # sidebar label + * description: One sentence… # meta description + search snippet + * pageTitle: How to import Evernote… # optional: overrides the only + * keywords: [import enex, evernote…] # optional + * schema: howto | faq | article # optional, default article + * faqs: # required when schema: faq + * - q: … + * a: … + * --- + */ +import { readFileSync } from "node:fs"; +import { join } from "node:path"; +import type { HeadConfig, TransformPageContext, PageData } from "vitepress"; +import { resolveString } from "./strings.mjs"; + +const SITE = "https://help.notesnook.com"; +const OG_IMAGE = `${SITE}/logo.png`; + +const url = (relativePath: string) => + `${SITE}/${relativePath.replace(/(index)?\.md$/, "").replace(/\/$/, "")}`.replace( + /\/$/, + "" + ) || SITE; + +/** "organizing-notes/archive-notes.md" -> ["Organizing notes", "Archive notes"] */ +function breadcrumbs(relativePath: string, title: string) { + const parts = relativePath.split("/").slice(0, -1); + const crumbs = [{ name: "Notesnook Help", item: SITE }]; + let path = ""; + for (const part of parts) { + path += `/${part}`; + crumbs.push({ + name: part.replace(/-/g, " ").replace(/^./, (c) => c.toUpperCase()), + item: `${SITE}${path}` + }); + } + crumbs.push({ name: title, item: url(relativePath) }); + return crumbs; +} + +/** + * The page's markdown. `transformPageData`'s context does not carry the source, + * so it is read back off disk. + */ +function pageSource(relativePath: string) { + try { + return readFileSync(join(process.cwd(), "contents", relativePath), "utf8"); + } catch { + return ""; + } +} + +/** Numbered list items in the first tab of a page become HowTo steps. */ +const STRING_TOKEN = /\{\{\s*([A-Za-z][A-Za-z0-9_]*)(?::(\d+))?\s*\}\}/g; + +function howToSteps(src: string) { + const steps: { name: string; text: string }[] = []; + for (const line of src.split("\n")) { + const m = line.match(/^\s*\d+\.\s+(.*\S)\s*$/); + if (!m) continue; + const text = m[1] + .replace(/!\[[^\]]*\]\([^)]*\)/g, "") + .replace(/\[([^\]]+)\]\([^)]*\)/g, "$1") + // These steps come from the raw markdown, before the markdown-it plugin + // has swapped `{{key}}` for the app's label — resolve them here too, or + // the structured data Google reads ships the raw tokens. + .replace(STRING_TOKEN, (_m, key: string, count?: string) => + resolveString(key, count ? Number(count) : undefined) + ) + .replace(/[`*_]/g, "") + .trim(); + if (text.length > 3) steps.push({ name: text.slice(0, 110), text }); + if (steps.length >= 12) break; + } + return steps; +} + +function jsonLd(pageData: PageData, ctx: TransformPageContext) { + const fm = pageData.frontmatter; + const title = (fm.pageTitle || fm.title || pageData.title) as string; + const description = (fm.description || "") as string; + const pageUrl = url(pageData.relativePath); + const graph: Record<string, unknown>[] = []; + + graph.push({ + "@type": "BreadcrumbList", + itemListElement: breadcrumbs(pageData.relativePath, title).map((c, i) => ({ + "@type": "ListItem", + position: i + 1, + name: c.name, + item: c.item + })) + }); + + const publisher = { + "@type": "Organization", + name: "Notesnook", + url: "https://notesnook.com", + logo: OG_IMAGE + }; + + if (fm.schema === "faq" && Array.isArray(fm.faqs) && fm.faqs.length) { + graph.push({ + "@type": "FAQPage", + mainEntity: fm.faqs.map((f: { q: string; a: string }) => ({ + "@type": "Question", + name: f.q, + acceptedAnswer: { "@type": "Answer", text: f.a } + })) + }); + } else if (fm.schema === "howto") { + const steps = howToSteps(pageSource(pageData.relativePath)); + if (steps.length) + graph.push({ + "@type": "HowTo", + name: title, + description, + url: pageUrl, + step: steps.map((s, i) => ({ + "@type": "HowToStep", + position: i + 1, + name: s.name, + text: s.text, + url: `${pageUrl}#${i + 1}` + })), + tool: [{ "@type": "HowToTool", name: "Notesnook" }], + totalTime: fm.totalTime || undefined + }); + } + + graph.push({ + "@type": "TechArticle", + headline: title, + description, + url: pageUrl, + inLanguage: "en", + isPartOf: { + "@type": "WebSite", + name: "Notesnook Help", + url: SITE + }, + about: { + "@type": "SoftwareApplication", + name: "Notesnook", + applicationCategory: "ProductivityApplication", + operatingSystem: "Windows, macOS, Linux, Android, iOS, Web" + }, + author: publisher, + publisher, + dateModified: pageData.lastUpdated + ? new Date(pageData.lastUpdated).toISOString() + : undefined + }); + + return JSON.stringify({ "@context": "https://schema.org", "@graph": graph }); +} + +/** + * Head tags for one page. Returned as frontmatter `head` entries so VitePress + * merges them into the rendered <head>. + */ +export function seoHead( + pageData: PageData, + ctx: TransformPageContext +): HeadConfig[] { + const fm = pageData.frontmatter; + if (fm.layout === "home" && !fm.description) return []; + + const title = (fm.pageTitle || fm.title || pageData.title) as string; + const description = (fm.description || "") as string; + const pageUrl = url(pageData.relativePath); + const fullTitle = fm.pageTitle + ? `${fm.pageTitle} | Notesnook Help` + : `${title} | Notesnook Help`; + + const head: HeadConfig[] = [ + ["link", { rel: "canonical", href: pageUrl }], + ["meta", { property: "og:title", content: fullTitle }], + ["meta", { property: "og:description", content: description }], + ["meta", { property: "og:url", content: pageUrl }], + ["meta", { property: "og:image", content: OG_IMAGE }], + ["meta", { name: "twitter:card", content: "summary" }], + ["meta", { name: "twitter:title", content: fullTitle }], + ["meta", { name: "twitter:description", content: description }] + ]; + + if (Array.isArray(fm.keywords) && fm.keywords.length) + head.push(["meta", { name: "keywords", content: fm.keywords.join(", ") }]); + + head.push(["script", { type: "application/ld+json" }, jsonLd(pageData, ctx)]); + + return head; +} + +/** The <title> tag: prefer an SEO-shaped `pageTitle` when the page defines one. */ +export function seoTitle(pageData: PageData) { + if (pageData.frontmatter.pageTitle) + pageData.title = pageData.frontmatter.pageTitle as string; +} diff --git a/docs/help/.vitepress/sidebar.mjs b/docs/help/.vitepress/sidebar.mjs new file mode 100644 index 000000000..bc5449d4a --- /dev/null +++ b/docs/help/.vitepress/sidebar.mjs @@ -0,0 +1,320 @@ +/** + * Help site navigation. + * + * A page that is not listed here is unreachable from the sidebar, so every new + * article needs an entry. `link` values are extensionless and root-absolute — + * they mirror the file path under `contents/`, which is also the public URL. + */ +export const sidebar = [ + { + text: "Getting started", + collapsed: false, + items: [ + { text: "All help topics", link: "/docs" }, + { text: "Create your first note", link: "/create-a-note-in-notesnook" }, + { text: "Search & navigation", link: "/search-and-navigation" }, + { text: "Keyboard shortcuts", link: "/keyboard-shortcuts" }, + { text: "Plans & limits", link: "/plans-and-limits" } + ] + }, + { + text: "Organizing notes", + collapsed: false, + items: [ + { + text: "Notebooks", + link: "/organizing-notes/organize-notes-using-notebooks" + }, + { text: "Tags", link: "/organizing-notes/organize-notes-using-tags" }, + { text: "Colors", link: "/organizing-notes/organize-notes-using-colors" }, + { + text: "Favorites", + link: "/organizing-notes/organize-notes-using-favorites" + }, + { text: "Pins", link: "/organizing-notes/pin-notes" }, + { text: "Archive", link: "/organizing-notes/archive-notes" }, + { + text: "Side menu shortcuts", + link: "/organizing-notes/side-menu-shortcuts" + }, + { text: "Reminders", link: "/reminders" } + ] + }, + { + text: "Working with notes", + collapsed: false, + items: [ + { text: "Note actions", link: "/notes/note-actions" }, + { text: "Note links", link: "/note-links-and-backlinks" }, + { text: "Expiring notes", link: "/notes/note-expiry" }, + { text: "Version history", link: "/note-version-history" }, + { text: "Trash", link: "/trash" } + ] + }, + { + text: "Editor", + collapsed: false, + items: [ + { + text: "Editor toolbar", + link: "/rich-text-editor/rich-text-editor-toolbar" + }, + { text: "Tabs & panes", link: "/rich-text-editor/editor-tabs-and-panes" }, + { + text: "Personalizing the editor", + link: "/rich-text-editor/personalizing-rich-text-editor" + }, + { + text: "Markdown shortcuts", + link: "/rich-text-editor/markdown-notes-editing" + }, + { + text: "Headings", + link: "/rich-text-editor/headings-and-collapsible-sections" + }, + { text: "Tables", link: "/rich-text-editor/tables" }, + { text: "Task lists", link: "/rich-text-editor/task-and-todo-lists" }, + { text: "Outline lists", link: "/rich-text-editor/outline-lists" }, + { text: "Callouts", link: "/rich-text-editor/callouts" }, + { text: "Code blocks", link: "/rich-text-editor/code-blocks" }, + { text: "Math & formulas", link: "/rich-text-editor/math-and-formulas" }, + { + text: "Images & embeds", + link: "/rich-text-editor/images-attachments-and-embeds" + }, + { text: "Find & replace", link: "/rich-text-editor/search-and-replace" } + ] + }, + { + text: "Importing notes", + collapsed: false, + items: [ + { text: "Overview", link: "/importing-notes/" }, + { text: "Evernote", link: "/importing-notes/import-notes-from-evernote" }, + { + text: "Google Keep", + link: "/importing-notes/import-notes-from-googlekeep" + }, + { text: "Joplin", link: "/importing-notes/import-notes-from-joplin" }, + { text: "Obsidian", link: "/importing-notes/import-notes-from-obsidian" }, + { + text: "Simplenote", + link: "/importing-notes/import-notes-from-simplenote" + }, + // Standard Notes is unpublished for now; the page is excluded from the + // build in config.mts. Restore this entry when it goes live again. + // { + // text: "Standard Notes", + // link: "/importing-notes/import-notes-from-standardnotes" + // }, + { + text: "ColorNote", + link: "/importing-notes/import-notes-from-colornote" + }, + { text: "UpNote", link: "/importing-notes/import-notes-from-upnote" }, + { + text: "Skiff Pages", + link: "/importing-notes/import-notes-from-skiff-pages" + }, + { + text: "Zoho Notebook", + link: "/importing-notes/import-notes-from-zoho-notebook" + }, + { + text: "Fusebase (Nimbus Note)", + link: "/importing-notes/import-notes-from-fusebase" + }, + { + text: "Markdown files", + link: "/importing-notes/import-notes-from-markdown-files" + }, + { + text: "HTML files", + link: "/importing-notes/import-notes-from-html-files" + }, + { + text: "Plaintext files", + link: "/importing-notes/import-notes-from-plaintext-files" + }, + { + text: "TextBundle files", + link: "/importing-notes/import-notes-from-textbundle-files" + } + ] + }, + { + text: "Backup & export", + collapsed: false, + items: [ + { + text: "Backup and restore", + link: "/backup-and-restore-notes-in-notesnook" + }, + { text: "Exporting notes", link: "/export-notes-from-notesnook" }, + { text: "Attachments & files", link: "/attachments-and-files" } + ] + }, + { + text: "Sync", + collapsed: false, + items: [ + { text: "How sync works", link: "/sync/how-sync-works" }, + { text: "Sync settings", link: "/sync/sync-settings" }, + { text: "Troubleshooting sync", link: "/sync/troubleshooting-sync" } + ] + }, + { + text: "Privacy & security", + collapsed: false, + items: [ + { text: "How is my data encrypted?", link: "/how-is-my-data-encrypted" }, + { text: "Private vault", link: "/lock-notes-with-private-vault" }, + { text: "App lock", link: "/app-lock" }, + { text: "Two-factor authentication", link: "/two-factor-authentication" }, + { text: "Privacy mode", link: "/privacy-mode" } + ] + }, + { + text: "Publishing", + collapsed: false, + items: [{ text: "Monographs", link: "/publish-notes-with-monographs" }] + }, + { + text: "Web clipper", + collapsed: false, + items: [ + { text: "Installation", link: "/web-clipper/installation" }, + { + text: "Clipping your first page", + link: "/web-clipper/clipping-your-first-web-page-with-web-clipper" + }, + { text: "Troubleshooting", link: "/web-clipper/troubleshooting" } + ] + }, + { + text: "Mobile", + collapsed: false, + items: [ + { + text: "Home screen widgets", + link: "/mobile-integration/home-screen-widgets" + }, + { + text: "Android quick actions", + link: "/mobile-integration/android-quick-actions" + }, + { + text: "Pin to notifications", + link: "/mobile-integration/pin-notes-to-notifications" + }, + { + text: "Quick notes", + link: "/mobile-integration/quick-note-from-notification" + }, + { + text: "Share from other apps", + link: "/mobile-integration/share-things-from-other-apps" + } + ] + }, + { + text: "Desktop", + collapsed: false, + items: [ + { + text: "Auto start", + link: "/desktop-integration/auto-start-on-system-startup" + }, + { + text: "System tray menu", + link: "/desktop-integration/system-tray-menu" + }, + { + text: "Jumplist & dock menu", + link: "/desktop-integration/jumplist-and-dock-menu" + }, + { text: "Spell checker", link: "/desktop-integration/spell-checker" }, + { + text: "Updates & advanced", + link: "/desktop-integration/updates-and-advanced-settings" + } + ] + }, + { + text: "Appearance & themes", + collapsed: false, + items: [ + { text: "Customizing the app", link: "/customizing-notesnook" }, + { + text: "Using themes", + link: "/custom-themes/using-themes", + items: [ + { text: "How themes work", link: "/custom-themes/introduction" }, + { + text: "Theme Builder", + link: "/custom-themes/create-a-theme-with-theme-builder" + }, + { + text: "Install from file", + link: "/custom-themes/install-a-theme-from-file" + }, + { + text: "Publish a new theme", + link: "/custom-themes/publish-a-theme" + } + ] + } + ] + }, + { + text: "Your account", + collapsed: false, + items: [ + { text: "Account settings", link: "/account-settings" }, + { text: "Notesnook Circle", link: "/notesnook-circle" }, + { text: "Recovering your account", link: "/recovering-your-account" }, + { text: "Deleting your account", link: "/deleting-your-account" }, + { text: "Gift cards", link: "/gift-cards" }, + { text: "Notesnook Wrapped", link: "/notesnook-wrapped" } + ] + }, + { + text: "Advanced", + collapsed: false, + items: [ + { + text: "Inbox API", + items: [ + { + text: "Getting started", + link: "/inbox-api/getting-started" + }, + { + text: "Self-hosting the Inbox API", + link: "/inbox-api/self-hosting-inbox-api" + } + ] + } + // { text: "Self-hosting Notesnook", link: "/self-hosting" } + ] + }, + { + text: "FAQs", + collapsed: false, + items: [ + { + text: "What are merge conflicts?", + link: "/faqs/what-are-merge-conflicts" + }, + { text: "Is there an ETA for X feature?", link: "/faqs/is-there-an-eta" }, + { + text: "Why login is needed to upload attachments", + link: "/faqs/login-to-upload-attachments" + }, + { + text: "Why login is needed to restore attachments", + link: "/faqs/login-to-restore-attachments-in-backup" + } + ] + } +]; diff --git a/docs/help/.vitepress/strings.mts b/docs/help/.vitepress/strings.mts new file mode 100644 index 000000000..ec05cdbce --- /dev/null +++ b/docs/help/.vitepress/strings.mts @@ -0,0 +1,131 @@ +/** + * Live UI strings, straight from the app. + * + * The docs quote hundreds of button and menu labels. Typing them by hand means + * they rot the moment someone renames a string, so pages write a key instead: + * + * Click on `{{archive}}` -> Click on `Archive` + * + * The key is resolved at build time from `@notesnook/intl` — the same catalogue + * the apps render from — so renaming a string in the app updates every page that + * quotes it on the next build. An unknown key fails the build rather than + * shipping a placeholder. + * + * This only *reads* the catalogue. Never add strings to `packages/intl` for the + * docs' sake: if a label has no string, write it as plain text and say why. + */ +import { readFileSync } from "node:fs"; +import { createRequire } from "node:module"; +import { i18n } from "@lingui/core"; +import { strings, setI18nGlobal } from "@notesnook/intl"; + +const require = createRequire(import.meta.url); + +// The compiled English catalogue lives beside the package's dist output. +const localePath = require.resolve("@notesnook/intl/locales/$en.json"); +const locale = JSON.parse(readFileSync(localePath, "utf8")); +i18n.load({ en: locale.messages }); +i18n.activate("en"); +setI18nGlobal(i18n); + +export type StringKey = keyof typeof strings; + +const cache = new Map<string, string>(); + +/** + * Resolve one key to the English text the app shows. + * + * A few catalogue entries are plural forms that take a count — quote those as + * `{{notebooks:2}}` and the number is passed through. + */ +export function resolveString(key: string, count?: number): string { + const cacheKey = count === undefined ? key : `${key}:${count}`; + const cached = cache.get(cacheKey); + if (cached !== undefined) return cached; + + const entry = (strings as Record<string, unknown>)[key]; + if (typeof entry !== "function") + throw new Error( + `Unknown UI string "${key}". It must be an existing key in packages/intl ` + + `(see strings.ts). Do not invent one — write the label as plain text instead.` + ); + + let value: unknown; + try { + value = + count === undefined + ? (entry as () => unknown)() + : (entry as (n: number) => unknown)(count); + } catch { + throw new Error( + `UI string "${key}" needs arguments. If it is a plural, quote it as ` + + `{{${key}:2}}; otherwise write the label as plain text.` + ); + } + + if (typeof value !== "string" || !value.trim()) + throw new Error(`UI string "${key}" did not resolve to text.`); + + cache.set(cacheKey, value); + return value; +} + +/** + * Reverse index: rendered text -> the key(s) that produce it. Used by + * `scripts/check-strings.mjs` to find hardcoded labels that could be keys. + */ +export function buildReverseIndex(): Map<string, string[]> { + const index = new Map<string, string[]>(); + for (const key of Object.keys(strings)) { + let value: unknown; + try { + value = (strings as Record<string, () => unknown>)[key](); + } catch { + continue; // needs arguments + } + if (typeof value !== "string" || !value.trim()) continue; + const existing = index.get(value); + if (existing) existing.push(key); + else index.set(value, [key]); + } + return index; +} + +/** Every key used across the docs this build, for reporting. */ +export const usedKeys = new Set<string>(); + +const TOKEN = /\{\{\s*([A-Za-z][A-Za-z0-9_]*)(?::(\d+))?\s*\}\}/g; + +/** + * markdown-it rule: swap `{{key}}` for the live string while parsing, so the + * rendered HTML contains real text and Vue never sees a moustache. + */ +export function stringsMarkdownPlugin(md: any) { + md.core.ruler.push("nn_ui_strings", (state: any) => { + const where = state.env?.relativePath ? ` in ${state.env.relativePath}` : ""; + const swap = (text: string) => + text.replace(TOKEN, (_match: string, key: string, count?: string) => { + try { + const value = resolveString(key, count ? Number(count) : undefined); + usedKeys.add(key); + return value; + } catch (error) { + throw new Error((error as Error).message + where); + } + }); + + for (const token of state.tokens) { + if (token.type === "inline" && token.children) { + for (const child of token.children) { + if (child.type === "text" || child.type === "code_inline") + child.content = swap(child.content); + } + } else if (token.type === "fence" || token.type === "html_block") { + // Leave code fences alone; a doc may legitimately show `{{ }}` syntax. + continue; + } + if (token.type === "inline") token.content = swap(token.content); + } + return true; + }); +} diff --git a/docs/help/.vitepress/theme/components/DocsIndex.vue b/docs/help/.vitepress/theme/components/DocsIndex.vue new file mode 100644 index 000000000..6f4932979 --- /dev/null +++ b/docs/help/.vitepress/theme/components/DocsIndex.vue @@ -0,0 +1,89 @@ +<script setup lang="ts"> +/** + * Every page on the site, grouped exactly as the sidebar groups them. + * + * The home page has no sidebar, so without this there is no way to see what the + * documentation actually covers. Reads the same sidebar module the site is + * built from, so it can never drift from the navigation. + */ +import { sidebar } from "../../sidebar.mjs"; + +type Item = { text: string; link?: string; items?: Item[] }; + +// Drop this page's own entry — listing the index inside the index is noise. +const groups = (sidebar as Item[]).map((group) => ({ + ...group, + items: group.items?.filter((item) => item.link !== "/docs") +})); + +const pageCount = groups.reduce( + (total, group) => total + (group.items?.filter((i) => i.link).length ?? 0), + 0 +); +</script> + +<template> + <div class="nn-index"> + <p class="nn-index__count">{{ pageCount }} pages, grouped by what you're trying to do.</p> + <div class="nn-index__grid"> + <section v-for="group in groups" :key="group.text" class="nn-index__group"> + <h2 class="nn-index__heading">{{ group.text }}</h2> + <ul class="nn-index__list"> + <li v-for="item in group.items" :key="item.link || item.text"> + <a v-if="item.link" :href="item.link">{{ item.text }}</a> + <span v-else>{{ item.text }}</span> + </li> + </ul> + </section> + </div> + </div> +</template> + +<style scoped> +.nn-index__count { + margin: 0 0 28px; + color: var(--vp-c-text-2); +} + +.nn-index__grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); + gap: 28px 32px; +} + +.nn-index__group { + break-inside: avoid; +} + +.nn-index__heading { + margin: 0 0 10px; + padding: 0 0 8px; + border: none; + border-bottom: 1px solid var(--vp-c-divider); + font-size: 12px; + font-weight: 600; + letter-spacing: 0.04em; + text-transform: uppercase; + color: var(--vp-c-text-3); +} + +.nn-index__list { + margin: 0; + padding: 0; + list-style: none; +} + +.nn-index__list li { + margin: 0 0 6px; + line-height: 1.5; +} + +.nn-index__list a { + font-weight: 400; + text-decoration: none; +} + +.nn-index__list a:hover { + text-decoration: underline; +} +</style> diff --git a/docs/help/.vitepress/theme/components/GetNotesnook.vue b/docs/help/.vitepress/theme/components/GetNotesnook.vue new file mode 100644 index 000000000..8982a43fd --- /dev/null +++ b/docs/help/.vitepress/theme/components/GetNotesnook.vue @@ -0,0 +1,95 @@ +<script setup lang="ts"> +/** + * Conversion block for high-intent pages (importers, comparisons, "how do I…" + * pages that people land on from search). Renders real anchors so crawlers and + * no-JS clients follow them. + */ +withDefaults( + defineProps<{ + title?: string; + text?: string; + /** Primary link target: "download" | "pricing" */ + action?: string; + }>(), + { + title: "Ready to move your notes?", + text: "Notesnook is free to use, end-to-end encrypted by default, and open source. Install it on every device you own and your notes stay in sync — readable only by you.", + action: "download" + } +); +</script> + +<template> + <aside class="nn-cta"> + <p class="nn-cta__title">{{ title }}</p> + <p class="nn-cta__text">{{ text }}</p> + <p class="nn-cta__actions"> + <a + v-if="action === 'download'" + class="nn-cta__button" + href="https://notesnook.com/downloads" + >Download Notesnook</a + > + <a + v-else + class="nn-cta__button" + href="https://notesnook.com/pricing" + >See plans and pricing</a + > + <a class="nn-cta__link" href="/plans-and-limits">What's included in each plan</a> + </p> + </aside> +</template> + +<style scoped> +.nn-cta { + margin: 32px 0; + padding: 20px 24px; + border: 1px solid var(--vp-c-divider); + border-left: 3px solid var(--nn-accent); + border-radius: var(--nn-radius-large); + background-color: var(--vp-c-bg-alt); +} + +.nn-cta__title { + margin: 0 0 6px; + font-weight: 600; + color: var(--vp-c-text-1); +} + +.nn-cta__text { + margin: 0 0 14px; + font-size: 15px; + line-height: 1.6; + color: var(--vp-c-text-2); +} + +.nn-cta__actions { + display: flex; + align-items: center; + flex-wrap: wrap; + gap: 16px; + margin: 0; +} + +.nn-cta__button { + display: inline-block; + padding: 8px 16px; + border-radius: var(--nn-radius-button); + background-color: var(--nn-accent); + color: var(--nn-accent-foreground) !important; + font-size: 14px; + font-weight: 600; + text-decoration: none !important; + transition: background-color 100ms ease-out; +} + +.nn-cta__button:hover { + background-color: #008837e6; +} + +.nn-cta__link { + font-size: 14px; + font-weight: 500; +} +</style> diff --git a/docs/help/.vitepress/theme/components/HomeSearch.vue b/docs/help/.vitepress/theme/components/HomeSearch.vue new file mode 100644 index 000000000..e30982f0f --- /dev/null +++ b/docs/help/.vitepress/theme/components/HomeSearch.vue @@ -0,0 +1,118 @@ +<script setup lang="ts"> +import { onMounted, ref } from "vue"; + +const isMac = ref(false); +onMounted(() => { + isMac.value = /mac/i.test(navigator.platform || navigator.userAgent); +}); + +/** + * Open the site's own search modal. VitePress listens for a Cmd/Ctrl+K keydown + * on `window` and its nav button triggers search by dispatching exactly this + * synthetic event, so we reuse that path rather than reimplementing search. + */ +function openSearch() { + const event = new Event("keydown") as Event & { key: string; metaKey: boolean }; + event.key = "k"; + event.metaKey = true; + window.dispatchEvent(event); +} +</script> + +<template> + <div class="nn-home-search"> + <button + type="button" + class="nn-home-search__button" + aria-label="Search the documentation" + @click="openSearch" + > + <span class="nn-home-search__icon" aria-hidden="true"> + <svg viewBox="0 0 24 24" width="18" height="18" fill="currentColor"> + <path + d="M9.5,3A6.5,6.5 0 0,1 16,9.5C16,11.11 15.41,12.59 14.44,13.73L14.71,14H15.5L20.5,19L19,20.5L14,15.5V14.71L13.73,14.44C12.59,15.41 11.11,16 9.5,16A6.5,6.5 0 0,1 3,9.5A6.5,6.5 0 0,1 9.5,3M9.5,5C7,5 5,7 5,9.5C5,12 7,14 9.5,14C12,14 14,12 14,9.5C14,7 12,5 9.5,5Z" + /> + </svg> + </span> + <span class="nn-home-search__placeholder">Search the docs…</span> + <kbd class="nn-home-search__key">{{ isMac ? "⌘" : "Ctrl" }} K</kbd> + </button> + <p class="nn-home-search__hint"> + Try “import from Evernote”, “app lock”, or “why is my note not syncing”. + </p> + </div> +</template> + +<style scoped> +.nn-home-search { + max-width: 640px; + /* The hero's own bottom padding stops here, so the space below the search box + has to come from this margin — without it the features grid rides up over + the hint text. */ + margin: 16px auto 56px; + padding: 0 24px; +} + +@media (max-width: 640px) { + .nn-home-search { + margin: 8px auto 40px; + } +} + +.nn-home-search__button { + display: flex; + align-items: center; + gap: 10px; + width: 100%; + padding: 14px 16px; + border: 1.5px solid var(--vp-c-divider); + border-radius: var(--nn-radius-button, 10px); + background-color: var(--vp-c-bg); + color: var(--vp-c-text-3); + font-size: 16px; + text-align: left; + cursor: text; + transition: border-color 120ms ease-out, box-shadow 120ms ease-out; +} + +.nn-home-search__button:hover, +.nn-home-search__button:focus-visible { + border-color: var(--nn-accent); + box-shadow: 0 0 0 3px var(--vp-c-brand-soft); + outline: none; +} + +.nn-home-search__icon { + display: flex; + color: var(--vp-c-text-3); +} + +.nn-home-search__placeholder { + flex: 1; +} + +.nn-home-search__key { + flex-shrink: 0; + padding: 2px 6px; + border: 1px solid var(--vp-c-divider); + border-bottom-width: 2px; + border-radius: var(--nn-radius-default, 5px); + background-color: var(--vp-c-bg-alt); + font-family: var(--vp-font-family-mono); + font-size: 11px; + line-height: 1.6; + color: var(--vp-c-text-3); +} + +.nn-home-search__hint { + margin: 10px 2px 0; + font-size: 13px; + color: var(--vp-c-text-3); +} + +@media (max-width: 640px) { + .nn-home-search__key { + display: none; + } +} +</style> diff --git a/docs/help/.vitepress/theme/components/PlanTag.vue b/docs/help/.vitepress/theme/components/PlanTag.vue new file mode 100644 index 000000000..24c29b38f --- /dev/null +++ b/docs/help/.vitepress/theme/components/PlanTag.vue @@ -0,0 +1,89 @@ +<script setup lang="ts"> +import { computed } from "vue"; + +const props = defineProps<{ + /** essential | pro | believer | free — the LOWEST plan that unlocks the feature. */ + plan: string; + /** Set when the feature is limited to one platform, e.g. "Android only". */ + note?: string; +}>(); + +const PLANS: Record<string, { label: string; title: string }> = { + free: { + label: "Free", + title: "Available on every plan, including Free" + }, + essential: { + label: "Essential", + title: "Requires the Essential plan or higher (Essential, Pro, Believer)" + }, + pro: { + label: "Pro", + title: "Requires the Pro plan or higher (Pro, Believer)" + }, + believer: { + label: "Believer", + title: "Requires the Believer plan" + } +}; + +const tier = computed(() => PLANS[props.plan.toLowerCase()] ?? PLANS.pro); +</script> + +<template> + <span class="nn-plan-tag ignore-header" :class="`nn-plan-tag--${plan.toLowerCase()}`" :title="tier.title"> + {{ tier.label }} + <span v-if="note" class="nn-plan-tag__note">· {{ note }}</span> + </span> +</template> + +<style scoped> +.nn-plan-tag { + display: inline-block; + vertical-align: middle; + margin-left: 6px; + padding: 1px 8px; + border-radius: 100px; + border: 1px solid transparent; + font-size: 11px; + font-weight: 600; + letter-spacing: 0.03em; + line-height: 1.7; + white-space: nowrap; + text-transform: uppercase; + cursor: help; +} + +.nn-plan-tag__note { + font-weight: 500; + text-transform: none; + opacity: 0.85; +} + +.nn-plan-tag--free { + background-color: var(--vp-c-bg-alt); + border-color: var(--vp-c-divider); + color: var(--vp-c-text-2); +} + +.nn-plan-tag--essential, +.nn-plan-tag--pro, +.nn-plan-tag--believer { + background-color: var(--vp-c-brand-soft); + border-color: var(--vp-c-brand-soft); + color: var(--vp-c-brand-1); +} + +.nn-plan-tag--believer { + background-color: transparent; + border-color: var(--nn-accent); +} + +h1 .nn-plan-tag, +h2 .nn-plan-tag, +h3 .nn-plan-tag { + position: relative; + top: -2px; + font-size: 12px; +} +</style> diff --git a/docs/help/.vitepress/theme/components/VersionBanner.vue b/docs/help/.vitepress/theme/components/VersionBanner.vue new file mode 100644 index 000000000..3966ec000 --- /dev/null +++ b/docs/help/.vitepress/theme/components/VersionBanner.vue @@ -0,0 +1,57 @@ +<script setup lang="ts"> +import { computed } from "vue"; +import { useData } from "vitepress"; + +const { frontmatter, page } = useData(); + +const archived = computed(() => frontmatter.value.archivedVersion as string | undefined); +const latest = computed(() => frontmatter.value.latestVersion as string | undefined); + +// The same article in the latest docs, if it still exists there. +const latestLink = computed(() => { + const path = page.value.relativePath + .replace(/^v[\d.]+\//, "/") + .replace(/(index)?\.md$/, ""); + return path.startsWith("/") ? path : `/${path}`; +}); +</script> + +<template> + <div v-if="archived" class="nn-version-banner"> + <p> + You are reading the documentation for <strong>Notesnook v{{ archived }}</strong>. + The current version is v{{ latest }}. + </p> + <a :href="latestLink">Read the latest version of this page →</a> + </div> +</template> + +<style scoped> +.nn-version-banner { + margin-bottom: 24px; + padding: 15px 20px; + border: 1px solid var(--vp-c-warning-soft); + border-left: 3px solid var(--vp-c-warning-1); + border-radius: var(--nn-radius-large); + background-color: var(--vp-custom-block-warning-bg); + font-size: 14px; + line-height: 1.6; +} + +.nn-version-banner p { + margin: 0; + color: var(--vp-c-text-1); +} + +.nn-version-banner a { + display: inline-block; + margin-top: 6px; + color: var(--vp-c-brand-1); + font-weight: 500; + text-decoration: none; +} + +.nn-version-banner a:hover { + text-decoration: underline; +} +</style> diff --git a/docs/help/.vitepress/theme/fonts.css b/docs/help/.vitepress/theme/fonts.css new file mode 100644 index 000000000..9dd7e2b23 --- /dev/null +++ b/docs/help/.vitepress/theme/fonts.css @@ -0,0 +1,77 @@ +/** + * Self-hosted webfonts, matching the Notesnook app. + * Inter is the app's UI font (apps/web/src/app.css), Fira Code its code font. + */ + +@font-face { + font-family: "Inter"; + font-style: normal; + font-weight: 400; + font-display: swap; + src: local(""), url("/fonts/Inter-Regular.woff2") format("woff2"); +} + +@font-face { + font-family: "Inter"; + font-style: normal; + font-weight: 500; + font-display: swap; + src: local(""), url("/fonts/Inter-Medium.woff2") format("woff2"); +} + +@font-face { + font-family: "Inter"; + font-style: normal; + font-weight: 600; + font-display: swap; + src: local(""), url("/fonts/Inter-SemiBold.woff2") format("woff2"); +} + +@font-face { + font-family: "Inter"; + font-style: normal; + font-weight: 700; + font-display: swap; + src: local(""), url("/fonts/Inter-Bold.woff2") format("woff2"); +} + +@font-face { + font-family: "Inter"; + font-style: italic; + font-weight: 400; + font-display: swap; + src: local(""), url("/fonts/Inter-Italic.woff2") format("woff2"); +} + +@font-face { + font-family: "Inter"; + font-style: italic; + font-weight: 500; + font-display: swap; + src: local(""), url("/fonts/Inter-MediumItalic.woff2") format("woff2"); +} + +@font-face { + font-family: "Inter"; + font-style: italic; + font-weight: 600; + font-display: swap; + src: local(""), url("/fonts/Inter-SemiBoldItalic.woff2") format("woff2"); +} + +@font-face { + font-family: "Inter"; + font-style: italic; + font-weight: 700; + font-display: swap; + src: local(""), url("/fonts/Inter-BoldItalic.woff2") format("woff2"); +} + +@font-face { + font-family: "Fira Code"; + font-style: normal; + font-weight: 400; + font-display: swap; + src: local(""), url("/fonts/fira-code-v21-latin-regular.woff2") + format("woff2"); +} diff --git a/docs/help/.vitepress/theme/index.ts b/docs/help/.vitepress/theme/index.ts new file mode 100644 index 000000000..930d303c1 --- /dev/null +++ b/docs/help/.vitepress/theme/index.ts @@ -0,0 +1,31 @@ +import type { Theme } from "vitepress"; +// theme-without-fonts skips the default theme's own bundled Inter — we ship the +// exact Inter files the Notesnook app uses instead (see fonts.css). +import DefaultTheme from "vitepress/theme-without-fonts"; +import { enhanceAppWithTabs } from "vitepress-plugin-tabs/client"; +import { h } from "vue"; +import VersionBanner from "./components/VersionBanner.vue"; +import PlanTag from "./components/PlanTag.vue"; +import GetNotesnook from "./components/GetNotesnook.vue"; +import HomeSearch from "./components/HomeSearch.vue"; +import DocsIndex from "./components/DocsIndex.vue"; +import "./fonts.css"; +import "./notesnook.css"; + +export default { + extends: DefaultTheme, + Layout: () => + h(DefaultTheme.Layout, null, { + // Renders only on pages under an archived /v<version>/ tree. + "doc-before": () => h(VersionBanner), + // The home page has no sidebar, so search is the primary way in. + "home-hero-after": () => h(HomeSearch) + }), + enhanceApp({ app }) { + enhanceAppWithTabs(app); + // Usable directly in markdown, no per-page import. + app.component("PlanTag", PlanTag); + app.component("GetNotesnook", GetNotesnook); + app.component("DocsIndex", DocsIndex); + } +} satisfies Theme; diff --git a/docs/help/.vitepress/theme/notesnook.css b/docs/help/.vitepress/theme/notesnook.css new file mode 100644 index 000000000..b77a62051 --- /dev/null +++ b/docs/help/.vitepress/theme/notesnook.css @@ -0,0 +1,628 @@ +/** + * Notesnook design tokens applied to VitePress. + * + * Values come from @notesnook/theme (default-light / default-dark v2.1) and + * apps/web: + * accent #008837 packages/theme default themes + * radii 2.5 / 5 / 7 / 10 packages/theme/src/theme/index.ts + * space scale 6 / 10 / 15 / 20 packages/theme/src/theme/index.ts + * shadows menu / dialog packages/theme/src/theme/index.ts + * fonts Inter, Fira Code apps/web/src/app.css + * + * Notesnook's UI is flat: 5px radii, hairline borders, hover fills instead of + * cards, and a single accent used sparingly. This file keeps VitePress in that + * register rather than layering a second design language on top of it. + */ + +/* ========================================================================== */ +/* Tokens */ +/* ========================================================================== */ + +:root { + /* Notesnook primitives */ + --nn-accent: #008837; + --nn-accent-foreground: #ffffff; + --nn-shade: #0088371a; /* alpha(accent, .1) */ + + --nn-radius-small: 2.5px; + --nn-radius-default: 5px; + --nn-radius-large: 7px; + --nn-radius-dialog: 10px; + --nn-radius-button: 10px; + + --nn-space-1: 6px; + --nn-space-2: 10px; + --nn-space-3: 15px; + --nn-space-4: 20px; + --nn-space-5: 25px; + + --nn-static-orange: #ff9800; + + /* Typography */ + --vp-font-family-base: "Inter", "Noto Sans", Frutiger, Calibri, Myriad, Arial, + Ubuntu, Helvetica, -apple-system, BlinkMacSystemFont, sans-serif; + --vp-font-family-mono: "Fira Code", "Fira Mono", Hack, Menlo, Consolas, + "Liberation Mono", "Courier New", monospace; + + /* Layout — a help site reads better slightly narrower than VitePress' default */ + --vp-layout-max-width: 1440px; + --vp-sidebar-width: 288px; + --vp-nav-height: 60px; +} + +/* ------------------------------- light ---------------------------------- */ +:root { + --vp-c-brand-1: #008837; + --vp-c-brand-2: #008837e6; /* app button hover — alpha(accent, .9) */ + --vp-c-brand-3: #008837cc; /* app button active — alpha(accent, .8) */ + --vp-c-brand-soft: var(--nn-shade); + + --vp-c-bg: #ffffff; + --vp-c-bg-alt: #f7f7f7; + --vp-c-bg-soft: #f7f7f7; + --vp-c-bg-elv: #ffffff; + + --vp-c-divider: #e8e8e8; + --vp-c-border: #e8e8e8; + --vp-c-gutter: #e8e8e8; + + --vp-c-text-1: #202020; /* heading */ + --vp-c-text-2: #505050; /* paragraph */ + --vp-c-text-3: #777777; /* paragraph-secondary */ + + --nn-hover: #eeeeee; + --nn-selected-bg: #eeeeee; + --nn-selected-fg: #212121; + --nn-code-bg: #f7f7f7; + --nn-shadow-menu: 0px 0px 10px 0px #00000022; + --nn-shadow-dialog: 0px 0px 25px 5px #0000004e; + + --vp-c-tip-1: #4f8a10; + --vp-c-tip-soft: #4f8a101a; + --vp-c-danger-1: #f54b42; + --vp-c-danger-soft: #f54b421a; + --vp-c-warning-1: #b26a00; /* darkened static orange for AA on white */ + --vp-c-warning-soft: #ff98001f; +} + +/* -------------------------------- dark ---------------------------------- */ +.dark { + /* #008837 is only 3.06:1 on the app's #181818, so text-bearing brand steps + are lightened for readability. Solid accent fills stay exactly #008837. */ + --vp-c-brand-1: #00b34a; + --vp-c-brand-2: #00c853; + --vp-c-brand-3: #008837; + --vp-c-brand-soft: #00883733; + + --vp-c-bg: #181818; + --vp-c-bg-alt: #202020; + --vp-c-bg-soft: #202020; + --vp-c-bg-elv: #202020; + + --vp-c-divider: #383838; + --vp-c-border: #2b2b2b; + --vp-c-gutter: #2b2b2b; + + --vp-c-text-1: #e3e3e3; + --vp-c-text-2: #d3d3d3; + --vp-c-text-3: #818589; + + --nn-hover: #2b2b2b; + --nn-selected-bg: #494949; + --nn-selected-fg: #fbfbfb; + --nn-code-bg: #202020; + --nn-shadow-menu: 0px 0px 10px 0px #00000078; + --nn-shadow-dialog: 0px 0px 25px 5px #000000aa; + + --vp-c-tip-1: #7bb32e; + --vp-c-tip-soft: #4f8a1033; + --vp-c-danger-1: #f76b64; + --vp-c-danger-soft: #f54b4226; + --vp-c-warning-1: #ffa726; + --vp-c-warning-soft: #ff980026; +} + +/* --------------------------- derived bindings ---------------------------- */ +:root, +.dark { + --vp-button-brand-bg: var(--nn-accent); + --vp-button-brand-text: var(--nn-accent-foreground); + --vp-button-brand-border: transparent; + --vp-button-brand-hover-bg: #008837e6; + --vp-button-brand-hover-text: var(--nn-accent-foreground); + --vp-button-brand-hover-border: transparent; + --vp-button-brand-active-bg: #008837cc; + --vp-button-brand-active-text: var(--nn-accent-foreground); + + --vp-code-bg: var(--nn-code-bg); + --vp-code-block-bg: var(--nn-code-bg); + --vp-code-copy-code-bg: var(--nn-code-bg); + --vp-code-copy-code-hover-bg: var(--nn-hover); + + --vp-shadow-1: var(--nn-shadow-menu); + --vp-shadow-2: var(--nn-shadow-menu); + --vp-shadow-3: var(--nn-shadow-menu); + --vp-shadow-4: var(--nn-shadow-dialog); + --vp-shadow-5: var(--nn-shadow-dialog); + + --vp-custom-block-tip-bg: var(--vp-c-tip-soft); + --vp-custom-block-warning-bg: var(--vp-c-warning-soft); + --vp-custom-block-danger-bg: var(--vp-c-danger-soft); + --vp-custom-block-info-bg: var(--vp-c-bg-alt); + --vp-custom-block-details-bg: var(--vp-c-bg-alt); +} + +/* ========================================================================== */ +/* Base */ +/* ========================================================================== */ + +html { + scroll-behavior: smooth; +} + +::selection { + background-color: #00883766; + color: var(--nn-selected-fg); +} + +.vp-doc h1, +.vp-doc h2, +.vp-doc h3, +.vp-doc h4 { + letter-spacing: -0.015em; + font-weight: 600; +} + +.vp-doc h1 { + font-size: 32px; + line-height: 1.25; + margin-bottom: var(--nn-space-3); +} + +/* The app never underlines its own separators heavily — keep section rules + hairline and give sections room to breathe. */ +.vp-doc h2 { + margin-top: 44px; + padding-top: var(--nn-space-4); + border-top: 1px solid var(--vp-c-divider); + font-size: 22px; + letter-spacing: -0.01em; +} + +.vp-doc h3 { + margin-top: 28px; + font-size: 17px; +} + +.vp-doc p, +.vp-doc li { + line-height: 1.7; +} + +.vp-doc a { + font-weight: 500; + text-decoration: none; + text-underline-offset: 3px; +} + +.vp-doc a:hover { + text-decoration: underline; +} + +/* ========================================================================== */ +/* Navigation & sidebar — modelled on the app's navigation menu */ +/* ========================================================================== */ + +.VPNav { + backdrop-filter: saturate(160%) blur(12px); +} + +.VPNavBar:not(.home.top) { + background-color: color-mix(in srgb, var(--vp-c-bg) 88%, transparent); +} + +.VPSidebar { + background-color: var(--vp-c-bg-alt) !important; + padding-top: var(--nn-space-3); +} + +.VPSidebarItem.level-0 > .item > .text { + font-size: 12px; + font-weight: 600; + letter-spacing: 0.04em; + text-transform: uppercase; + color: var(--vp-c-text-3); +} + +/* Flat rows with a hover fill — same treatment as list items in the app. */ +.VPSidebarItem.is-link > .item .link, +.VPSidebarItem .item > .link { + border-radius: var(--nn-radius-default); +} + +/* The hover fill bleeds left of the label so item text keeps the same left edge + as the group headers and the nav logo (32px), instead of sitting 10px in. */ +.VPSidebarItem.level-1 .item, +.VPSidebarItem.level-2 .item, +.VPSidebarItem.level-3 .item { + border-radius: var(--nn-radius-default); + margin-left: calc(var(--nn-space-2) * -1); + padding-left: var(--nn-space-2); + padding-right: var(--nn-space-1); + transition: background-color 100ms ease-out; +} + +.VPSidebarItem.level-1:not(.is-active) .item:hover, +.VPSidebarItem.level-2:not(.is-active) .item:hover, +.VPSidebarItem.level-3:not(.is-active) .item:hover { + background-color: var(--nn-hover); +} + +.VPSidebarItem.is-active > .item { + background-color: var(--nn-selected-bg); +} + +.VPSidebarItem.is-active > .item > .indicator { + background-color: var(--nn-accent); +} + +.VPSidebarItem.is-active > .item .link .text { + color: var(--nn-selected-fg); + font-weight: 600; +} + +.VPSidebarItem .text { + font-size: 14px; +} + +/* ========================================================================== */ +/* Buttons */ +/* ========================================================================== */ + +/* One radius for every button on the site. `!important` is needed because the + default theme's own button rules carry a scoped [data-v-*] attribute, which + outranks a plain class selector. */ +.VPButton, +.VPButton.small, +.VPButton.medium, +.VPButton.big, +.VPNavBarSearchButton, +.DocSearch-Button, +.VPNavBarHamburger, +.VPLocalNav button, +.VPBackToTop, +.VPSidebarItem .caret, +.VPLocalSearchBox button, +.VPDocFooter button, +[class*="language-"] > button.copy, +[class*="language-"] > span.lang + button, +.vp-doc button { + border-radius: var(--nn-radius-button) !important; +} + +/* ========================================================================== */ +/* Home page */ +/* ========================================================================== */ + +.VPHero .image-bg { + display: none; +} + +/* The default theme nudges the hero image up and left by 32px to optically + centre it against the blurred `image-bg` circle behind it. We hide that + circle, so the nudge has nothing left to compensate for — it just lifts the + logo above the middle of the text column, leaving it centred on the heading + and tagline with the action buttons hanging below. Dropping the transform + centres it against the whole column: heading, tagline and actions. */ +@media (min-width: 960px) { + .VPHero .image-container { + transform: none; + } +} + +.VPHero .image-container img { + max-width: 208px; + max-height: 208px; + border-radius: 44px; + box-shadow: var(--nn-shadow-dialog); +} + +.VPHome .VPFeature { + border-radius: var(--nn-radius-large); + border-color: var(--vp-c-divider); + transition: border-color 120ms ease-out, background-color 120ms ease-out; +} + +.VPHome .VPFeature:hover { + border-color: var(--nn-accent); + background-color: var(--vp-c-bg-alt); +} + +/* ========================================================================== */ +/* Custom blocks */ +/* ========================================================================== */ + +.vp-doc .custom-block { + border-radius: var(--nn-radius-large); + border: 1px solid var(--vp-c-divider); + border-left-width: 3px; + padding: var(--nn-space-3) var(--nn-space-4); + font-size: 15px; +} + +.vp-doc .custom-block .custom-block-title { + font-weight: 600; + letter-spacing: -0.01em; +} + +.vp-doc .custom-block p { + line-height: 1.65; +} + +.vp-doc .custom-block.info { + border-color: var(--vp-c-divider); + border-left-color: var(--vp-c-text-3); +} + +.vp-doc .custom-block.tip { + border-color: var(--vp-c-tip-soft); + border-left-color: var(--vp-c-tip-1); +} + +.vp-doc .custom-block.warning { + border-color: var(--vp-c-warning-soft); + border-left-color: var(--vp-c-warning-1); +} + +.vp-doc .custom-block.danger { + border-color: var(--vp-c-danger-soft); + border-left-color: var(--vp-c-danger-1); +} + +.vp-doc .custom-block.details { + border-left-color: var(--vp-c-text-3); +} + +.vp-doc .custom-block img { + margin-top: var(--nn-space-2); +} + +/* ========================================================================== */ +/* Platform tabs (vitepress-plugin-tabs) */ +/* ========================================================================== */ + +.vp-doc .plugin-tabs { + border-radius: var(--nn-radius-large); + border: 1px solid var(--vp-c-divider); + background-color: transparent; + box-shadow: none; + overflow: hidden; +} + +.vp-doc .plugin-tabs--tab-list { + background-color: var(--vp-c-bg-alt); + border-bottom: 1px solid var(--vp-c-divider); + padding: var(--nn-space-1) var(--nn-space-1) 0; +} + +.vp-doc .plugin-tabs--tab { + font-size: 13px; + font-weight: 500; + color: var(--vp-c-text-2); + padding: var(--nn-space-1) var(--nn-space-2); + border-radius: var(--nn-radius-default) var(--nn-radius-default) 0 0; + transition: color 100ms ease-out, background-color 100ms ease-out; +} + +.vp-doc .plugin-tabs--tab:hover { + background-color: var(--nn-hover); + color: var(--vp-c-text-1); +} + +.vp-doc .plugin-tabs--tab[aria-selected="true"] { + color: var(--vp-c-brand-1); + font-weight: 600; + background-color: var(--vp-c-bg); +} + +.vp-doc .plugin-tabs--tab::after { + background-color: transparent; + height: 2px; +} + +.vp-doc .plugin-tabs--tab[aria-selected="true"]::after { + background-color: var(--nn-accent); +} + +.vp-doc .plugin-tabs--content { + padding: var(--nn-space-4); +} + +.vp-doc .plugin-tabs--content > :first-child { + margin-top: 0; +} + +.vp-doc .plugin-tabs--content > :last-child { + margin-bottom: 0; +} + +/* Nested tabs inside a custom block should not double up on chrome. */ +.vp-doc .custom-block .plugin-tabs { + background-color: var(--vp-c-bg); +} + +/* ========================================================================== */ +/* Media, code, tables */ +/* ========================================================================== */ + +.vp-doc img { + border-radius: var(--nn-radius-large); + border: 1px solid var(--vp-c-divider); + max-width: 100%; +} + +/* The CSS reset makes every image `display: block`, which breaks the line when a + UI glyph is referenced mid-sentence ("press the ⋯ button"). An image sharing + its *line* with text is treated as a glyph — inline, sized to the text, + unframed. An image on its own line stays a block, even when it sits inside a + numbered step whose text is on the line above. */ +.vp-doc img.inline-glyph { + display: inline-block; + vertical-align: text-bottom; + max-height: 1.5em; + width: auto; + margin: 0 2px; + border: none; + border-radius: var(--nn-radius-small); +} + +/* ---------------------------- task lists -------------------------------- */ + +.vp-doc .contains-task-list { + padding-left: 0; + list-style: none; +} + +.vp-doc .task-list-item { + display: flex; + align-items: flex-start; + gap: 8px; +} + +.vp-doc .task-list-item-checkbox { + appearance: none; + flex-shrink: 0; + width: 16px; + height: 16px; + margin: 6px 0 0; + border: 1.5px solid var(--vp-c-divider); + border-radius: var(--nn-radius-small); + background-color: var(--vp-c-bg); +} + +.vp-doc .task-list-item-checkbox:checked { + border-color: var(--nn-accent); + background-color: var(--nn-accent); + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='3.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'/%3E%3C/svg%3E"); + background-size: 12px; + background-position: center; + background-repeat: no-repeat; +} + +.vp-doc .task-list-item label { + cursor: default; +} + +.vp-doc img[src$=".svg"] { + border: none; +} + +.vp-doc [class*="language-"] { + border-radius: var(--nn-radius-large); + border: 1px solid var(--vp-c-divider); +} + +.vp-doc code { + font-size: 0.875em; + border-radius: var(--nn-radius-small); + padding: 3px 5px; +} + +.vp-doc :not(pre) > code { + color: var(--vp-c-text-1); + background-color: var(--vp-c-bg-alt); + border: 1px solid var(--vp-c-divider); +} + +.vp-doc kbd { + display: inline-block; + padding: 2px 6px; + border-radius: var(--nn-radius-default); + border: 1px solid var(--vp-c-divider); + border-bottom-width: 2px; + background-color: var(--vp-c-bg-alt); + font-family: var(--vp-font-family-mono); + font-size: 12px; + line-height: 1.6; +} + +.vp-doc table { + display: table; + width: 100%; + border-radius: var(--nn-radius-large); + overflow: hidden; + border: 1px solid var(--vp-c-divider); + border-collapse: separate; + border-spacing: 0; +} + +.vp-doc th, +.vp-doc td { + border: none; + border-bottom: 1px solid var(--vp-c-divider); +} + +.vp-doc tr:last-child td { + border-bottom: none; +} + +.vp-doc tr:nth-child(2n) { + background-color: transparent; +} + +.vp-doc tr:hover td { + background-color: var(--nn-hover); +} + +.vp-doc th { + background-color: var(--vp-c-bg-alt); + font-weight: 600; + font-size: 13px; + letter-spacing: 0.01em; +} + +/* ========================================================================== */ +/* Search, footer nav */ +/* ========================================================================== */ + +.VPLocalSearchBox .search-bar { + border-radius: var(--nn-radius-default); + border: 1.5px solid var(--vp-c-divider); +} + +.VPLocalSearchBox .search-bar:focus-within { + border-color: var(--nn-accent); + border-width: 2px; +} + +.VPLocalSearchBox .result { + border-radius: var(--nn-radius-default); +} + +.pager-link { + border-radius: var(--nn-radius-large); + border-color: var(--vp-c-divider); + transition: background-color 100ms ease-out, border-color 100ms ease-out; +} + +.pager-link:hover { + background-color: var(--vp-c-bg-alt); + border-color: var(--nn-accent); +} + +.VPDocFooter .edit-link-button { + font-weight: 500; +} + +@media (max-width: 640px) { + .vp-doc h1 { + font-size: 27px; + } + .vp-doc h2 { + font-size: 20px; + } + .vp-doc .plugin-tabs--content, + .vp-doc .custom-block { + padding: var(--nn-space-3); + } +} diff --git a/docs/help/.vitepress/versions.mjs b/docs/help/.vitepress/versions.mjs new file mode 100644 index 000000000..ce29df17e --- /dev/null +++ b/docs/help/.vitepress/versions.mjs @@ -0,0 +1,36 @@ +/** + * Documentation versions. + * + * The **latest** version is served from the site root (`/create-a-note`, + * `/organizing-notes/...`) so canonical URLs never move. Older versions are + * served from `/v<version>/`. + * + * Older versions are stored as *differences*, not copies. `contents/_versions/` + * holds only the pages whose content actually differs from the current docs; + * every other page is shared, and the full `/v<version>/` tree is composed at + * build time by `scripts/build-versions.mjs`. + * + * Cutting a new version: npm run version -- 3.5 + * Changing a page afterwards: npm run fork -- 3.4 <page> (before editing) + */ + +/** The version the docs at the site root describe. */ +export const LATEST = "3.4"; + +/** Older versions, newest first. */ +export const ARCHIVED = []; + +export const isArchivedPath = (path) => + ARCHIVED.some((v) => path.startsWith(`/v${v}/`)); + +export const versionOfPath = (path) => + ARCHIVED.find((v) => path.startsWith(`/v${v}/`)) ?? LATEST; + +/** The version picker shown in the nav bar. */ +export const versionsNavItem = { + text: `v${LATEST}`, + items: [ + { text: `v${LATEST} (latest)`, link: "/" }, + ...ARCHIVED.map((v) => ({ text: `v${v}`, link: `/v${v}/` })) + ] +}; diff --git a/docs/help/README.md b/docs/help/README.md new file mode 100644 index 000000000..fda8bb74a --- /dev/null +++ b/docs/help/README.md @@ -0,0 +1,85 @@ +# Notesnook Help + +The source of [help.notesnook.com](https://help.notesnook.com), built with [VitePress](https://vitepress.dev). + +```bash +npm install +npm run dev # http://localhost:5173 +npm run build # production build; fails on dead internal links +npm run preview # serve the built site +``` + +## Where things are + +| | | +| ------------------------ | --------------------------------------------------- | +| `contents/` | the articles — a file's path here is its public URL | +| `contents/public/` | images and fonts, served from `/` | +| `.vitepress/config.mts` | site config, nav, head | +| `.vitepress/sidebar.mjs` | the sidebar — **add every new article here** | +| `.vitepress/theme/` | Notesnook design tokens and self-hosted fonts | + +## UI labels come from the app + +Button and menu labels are written as string keys and resolved at build time from `@notesnook/intl`: + +```md +Click on `{{archive}}` to archive the note. +``` + +Rename that string in the app and this page updates on the next build. An unknown key fails the build. Run `npm run strings` to see which hardcoded labels could become keys (`-- --fix` rewrites them). Don't add strings to `packages/intl` for the docs — if there's no key, write plain text. + +## Writing an article + +1. Create `contents/<section>/<slug>.md` with `title` (short, used in the sidebar) and `description` (one sentence, used as the search snippet) frontmatter. +2. Add it to the right group in `.vitepress/sidebar.mjs`. +3. Run `npm run build` before opening a PR. + +Steps that differ per platform go in tabs, which stay in sync across the whole site via `key:platform`: + +```md +:::tabs key:platform +== Desktop/Web + +1. Right click on a note to open the `Note properties` menu. + +== Mobile + +1. Press the three dot button on a note. + +::: +``` + +Callouts use VitePress containers — `::: info`, `::: tip`, `::: warning`, `::: danger`, `::: details`. + +Renaming or moving a file changes a live URL that the apps and support replies link to. Don't, unless a 301 goes into `contents/public/_redirects` with it. Some pages are linked from inside the app via `packages/intl/src/strings.ts`, and the importer package links to the `importing-notes/*` slugs — grep both before touching a slug. + +## Versioning + +The docs are versioned by Notesnook version. The **latest** version lives at the site root, so canonical URLs never move; older versions are served from `/v<version>/` and reachable from the version picker in the nav bar. + +Older versions are stored as **differences, not copies**. A page is shared by every version until it actually changes; only then does the old text get its own file. `.vitepress/versions.mjs` holds `LATEST` and the list of older versions. + +**When Notesnook ships a new version:** + +```bash +npm run version -- <next-version> +``` + +Nothing is copied — the outgoing version becomes an older version whose pages are all still shared with the root. + +**When you change a page in a way that doesn't apply to the old version**, preserve the old text first, then edit the root copy as usual: + +```bash +npm run fork -- <old-version> organizing-notes/archive-notes +``` + +That writes `contents/_versions/<old-version>/organizing-notes/archive-notes.md` — the only file that version needs. For a page that didn't exist in an older version, add its path to `contents/_versions/<version>/_excluded.txt` instead. + +`npm run versions` (run automatically before dev and build) composes the full `/v<version>/` trees from the shared pages plus those overrides. The composed trees live in `contents/v<version>/` and are gitignored — never edit them. + +Archived pages carry a banner linking to the current version of the same page, are excluded from search and the sitemap, and are `noindex` so they don't compete with the latest docs. Images are shared across versions. + +## Deployment + +`.github/workflows/help.publish.yml` builds and deploys `.vitepress/dist/` to Cloudflare Pages on every push to `master` that touches `docs/help/**`. diff --git a/docs/help/STYLE.md b/docs/help/STYLE.md new file mode 100644 index 000000000..f5b12cb6d --- /dev/null +++ b/docs/help/STYLE.md @@ -0,0 +1,138 @@ +# Help docs — writing conventions + +Every page on help.notesnook.com follows these. They cover accuracy, plan tags, SEO and linking. + +## 1. Accuracy is non-negotiable + +Never describe UI from memory. Every menu label, settings path, limit, default and plan gate must be traced to source in this monorepo before it is written: + +- user-facing strings — `packages/intl/src/strings.ts` +- web/desktop UI — `apps/web/src/`, `apps/desktop/src/` +- mobile UI — `apps/mobile/app/` +- limits and plan gates — `packages/common/src/utils/is-feature-available.ts` +- behaviour, sync, encryption, retention — `packages/core/src/` + +### Quote labels by key, not by hand + +Don't type a label and hope it stays true. Write the **string key** and the build resolves it from the app's own catalogue: + +```md +Click on `{{archive}}` renders: Click on `Archive` +Open `{{privacyAndSecurity}}` renders: Open `Privacy & security` +``` + +Keys come from `packages/intl/src/strings.ts` — the same catalogue the apps render from — so when someone renames a string in the app, every page quoting it updates on the next build. An unknown key **fails the build**; it never ships as a placeholder. + +- Plural entries take a count: `{{notebooks:2}}`. +- `npm run strings` lists labels that could be keys but aren't; `-- --fix` rewrites the unambiguous ones. +- **Never add a string to `packages/intl` for the docs' sake.** If a label has no key — third-party UI, native OS text, a screen that isn't localized — write it as plain text. + +If web and mobile differ, both go in the platform tabs. If you cannot verify something, leave it out and flag it — never guess. + +## 2. Frontmatter + +```yaml +--- +title: Archive # short sidebar label, 2–3 words +pageTitle: How to archive notes… # optional: SEO <title>, ~60 chars +description: One sentence… # required, <160 chars, becomes the search snippet +keywords: # optional, real search phrases + - archive notes notesnook +schema: howto # optional: howto | faq | article (default article) +faqs: # required when schema: faq + - q: … + a: … +--- +``` + +`schema: howto` turns the page's numbered steps into HowTo structured data automatically. `schema: faq` emits FAQPage structured data from the `faqs` list — the same Q&As must also appear in the page body. + +## 3. Plan tags + +Any feature that needs a paid plan is tagged inline, on the heading that introduces it: + +```md +## Set a note to expire <PlanTag plan="pro" /> +``` + +`plan` is the **lowest** plan that unlocks it: `essential`, `pro` or `believer`. Plans are cumulative — a `pro` tag means Pro and Believer. For platform-limited features add a note: + +```md +## Pin a note to your notifications <PlanTag plan="pro" note="Android only" /> +``` + +Verify the tier in `is-feature-available.ts` before tagging. Also state the consequence in prose where it matters ("free plans keep 100 versions per note"), and link to [Plans & limits](/plans-and-limits). + +## 4. Article shape + +```md +# Full human title + +One or two sentences: what this is and why someone would want it. + +## Task in imperative form + +:::tabs key:platform +== Desktop/Web + +1. … + +== Mobile + +1. … + +::: +``` + +- One `# H1`, first line of the body. +- `##` per task, phrased as an action: "Archive a note", not "Archiving". +- Numbered steps, one action each, ideally ≤ 6. +- Close with the confirmation state — what the user should now see. +- `key:platform` is mandatory on platform tabs so the choice syncs sitewide. Labels: `Desktop/Web`, `Desktop`, `Web`, `Mobile`, `Android`, `iOS`, `Windows`, `macOS`, `Linux`. +- If a feature is missing on a platform, say so in that tab rather than omitting it. + +## 5. Callouts + +`::: info` context · `::: tip` shortcut · `::: warning` data loss or something irreversible · `::: danger` unrecoverable · `::: details` folded tangent. + +Anything touching the vault, encryption, recovery or deletion must state plainly that **Notesnook cannot recover data or passwords for you**. + +## 6. SEO + +The help site already ranks #1 for high-intent queries like `import enex`, so each page is a landing page: + +- **Write the H1 as the question a person types.** "How do I import notes from Evernote?" beats "Evernote importing". +- **Use real phrasings in `##` headings** — "Can I use it offline?", "Why is my note not syncing?" — they win featured snippets. +- **Answer in the first 40 words** after the H1. That paragraph is what Google quotes. +- **Never leave alt text empty.** Describe what the reader should look for: `![The Archive item in the note context menu](/img.png)`. +- **Every page ends with a `## Related pages` list** of 3–6 links with descriptive anchors (the home page, `/docs` and `/404` are exempt — they are already link lists) — "[backing up your notes](/backup-and-restore-notes-in-notesnook)", never "click here". This is what builds the internal link graph. +- **Link the first mention** of any concept that has its own page, in body text, with the concept as the anchor. +- **Add `<GetNotesnook />`** to pages people arrive at from search with buying intent — importers, comparisons, "how do I move from X" — placed after the instructions, never before them. +- Prefer one page that fully answers a question over three thin pages. + +## 7. Internal linking clusters + +Pages are grouped into clusters, each with a hub that links to every member and members that link back to the hub and sideways to siblings: + +| Cluster | Hub | +| ------------------ | ------------------------------------------------------------- | +| Importing | [Importing notes](/importing-notes/) | +| Editor | [Editor toolbar](/rich-text-editor/rich-text-editor-toolbar) | +| Organization | [Notebooks](/organizing-notes/organize-notes-using-notebooks) | +| Privacy & security | [How is my data encrypted?](/how-is-my-data-encrypted) | +| Sync | [How sync works](/sync/how-sync-works) | +| Plans | [Plans & limits](/plans-and-limits) | + +Any page that mentions a paid feature links to the plans hub. Any page that mentions encryption links to the encryption hub. + +## 8. Things that are not allowed + +- Undocumented guesses about UI, limits or plan gates. +- Version numbers in body copy ("as of v3.2"). +- "Simply", "just", "easily", "seamlessly", "powerful". +- Telling the reader to contact support before the documented steps. +- Image paths that don't exist — leave `<!-- TODO: screenshot — … -->` instead. +- Renaming or moving an existing page (its URL is live and linked from the apps). Some pages are linked from inside the app itself via `packages/intl/src/strings.ts` — grep it before touching a slug. +- More than one `# H1` on a page, and `##`/`###` headings inside a `:::tabs` block. Headings in tabs are emitted once per tab, so they show up twice in the page outline with duplicate anchors. +- Unquoted frontmatter values containing `: ` — the YAML parser fails the build. Quote them. +- Alt text that describes nothing: `drawing`, a filename, or an unfilled template. Inline UI glyphs ("press the ⋯ button") are the one case where a short label is correct. diff --git a/docs/help/contents/404.md b/docs/help/contents/404.md index 6ea93094c..7068d6f9f 100644 --- a/docs/help/contents/404.md +++ b/docs/help/contents/404.md @@ -1,5 +1,6 @@ --- title: Oops! +description: The page you're looking for could not be found. Here are some helpful links to get you back on track. --- # Oops! @@ -8,6 +9,8 @@ Unfortunately, we cannot find what you are looking for. Here are some other pages you might be interested in: -1. [Installing Notesnook](organizing-notes/organize-notes-using-notebooks) -2. [Creating your first note](create-a-note-in-notesnook) -3. [How is my data encrypted?](how-is-my-data-encrypted) +1. [Creating your first note](/create-a-note-in-notesnook) +2. [Organizing notes with notebooks](/organizing-notes/organize-notes-using-notebooks) +3. [How is my data encrypted?](/how-is-my-data-encrypted) + +Still stuck? [Contact us](https://notesnook.com/contact-us). diff --git a/docs/help/contents/README.md b/docs/help/contents/README.md deleted file mode 100644 index 0de26a35c..000000000 --- a/docs/help/contents/README.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -title: Notesnook Help -description: Your complete and free resource to using Notesnook as a daily note taking app to organize your work and life while safeguarding your privacy. ---- - -# Welcome to Notesnook Help - -Notesnook is a free and open source note taking app focused on user privacy & ease of use. To ensure zero knowledge principles, Notesnook encrypts everything on your device using `XChaCha20-Poly1305` & `Argon2`. - -Notesnook is our **proof** that privacy does _not_ (always) have to come at the cost of convenience. Our goal is to provide users peace of mind & 100% confidence that their notes are safe and secure. The decision to go fully open source is one of the most crucial steps towards that. - -And with that convenience in mind, we believe that it is equally important to put together a simple & useful help website about everything Notesnook. Our help is a complete walkthrough of the Notesnook app and it's features. - -Before we get started, let's [download & install Notesnook](https://notesnook.com/downloads) on all your devices. - -Once that's done, let's learn how to [create your first note](/create-a-note-in-notesnook) in Notesnook. diff --git a/docs/help/contents/_include/_head.html b/docs/help/contents/_include/_head.html deleted file mode 100644 index 11393b557..000000000 --- a/docs/help/contents/_include/_head.html +++ /dev/null @@ -1,8 +0,0 @@ -<link rel="stylesheet" type="text/css" href="/custom.css" /> -<script - async - defer - data-website-id="ad34576b-2721-436c-b36a-47a614009d2b" - src="https://aas.streetwriters.co/script.js" - data-domains="help.notesnook.com" -></script> diff --git a/docs/help/contents/_include/custom.css b/docs/help/contents/_include/custom.css deleted file mode 100644 index ef5c70ed9..000000000 --- a/docs/help/contents/_include/custom.css +++ /dev/null @@ -1,194 +0,0 @@ -/* open-sans-regular - vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic */ -@font-face { - font-family: "Open Sans"; - font-style: normal; - font-display: swap; - font-weight: 400; - src: local(""), - url("/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-regular.woff2") - format("woff2"), - /* Super Modern Browsers */ - url("/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-regular.woff") - format("woff"), - /* Modern Browsers */ - url("/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-regular.ttf") - format("truetype"); -} -/* open-sans-600 - vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic */ -@font-face { - font-family: "Open Sans"; - font-style: normal; - font-weight: 600; - font-display: swap; - src: local(""), - url("/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-600.woff2") - format("woff2"), - /* Super Modern Browsers */ - url("/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-600.woff") - format("woff"), - /* Modern Browsers */ - url("/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-600.ttf") - format("truetype"); -} -/* open-sans-700 - vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic */ -@font-face { - font-family: "Open Sans"; - font-style: normal; - font-weight: 700; - font-display: swap; - src: local(""), - url("/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-700.woff2") - format("woff2"), - /* Super Modern Browsers */ - url("/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-700.woff") - format("woff"), - /* Modern Browsers */ - url("/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-700.ttf") - format("truetype"); -} -/* open-sans-italic - vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic */ -@font-face { - font-family: "Open Sans"; - font-style: italic; - font-weight: 400; - font-display: swap; - src: local(""), - url("/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-italic.woff2") - format("woff2"), - /* Super Modern Browsers */ - url("/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-italic.woff") - format("woff"), - /* Modern Browsers */ - url("/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-italic.ttf") - format("truetype"); -} -/* open-sans-600italic - vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic */ -@font-face { - font-family: "Open Sans"; - font-style: italic; - font-weight: 600; - font-display: swap; - src: local(""), - url("/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-600italic.woff2") - format("woff2"), - /* Super Modern Browsers */ - url("/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-600italic.woff") - format("woff"), - /* Modern Browsers */ - url("/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-600italic.ttf") - format("truetype"); -} -/* open-sans-700italic - vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic */ -@font-face { - font-family: "Open Sans"; - font-style: italic; - font-weight: 700; - font-display: swap; - src: local(""), - url("/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-700italic.woff2") - format("woff2"), - /* Super Modern Browsers */ - url("/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-700italic.woff") - format("woff"), - /* Modern Browsers */ - url("/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-700italic.ttf") - format("truetype"); -} - -/* fira-code-regular - latin */ -@font-face { - font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ - font-family: "Fira Code"; - font-style: normal; - font-weight: 400; - src: url("/fonts/fira-code-v21-latin-regular.woff2") format("woff2"), - /* Super Modern Browsers */ url("/fonts/fira-code-v21-latin-regular.woff") - format("woff"), - /* Modern Browsers */ url("/fonts/fira-code-v21-latin-regular.ttf") - format("truetype"); /* Safari, Android, iOS */ -} - -html.light { - --font-family: "Open Sans", sans-serif; - --monospace-font-family: "Fira Code", monospace; - --primary: #008837; - --primary-fg: #fff; - --header-fg: #008837; - --link: #008837; - --heading: #000; - --page-bg: #ffffff; - --document-bg: #f7f7f7; - --selection-bg: #00883766; - --selection-fg: #fff; - --border: #e8e8e8; - --input-border: #e8e8e8; - - --hover-bg: #e8e8e8; - --info-dim: #00883720; - - --fg: #403f53; - --fg-dim: #403f53cc; - --fg-dimmer: #403f53bb; - --code-bg: #e8e8e8; -} - -html.dark { - --font-family: "Open Sans", sans-serif; - --monospace-font-family: "Fira Code", monospace; - --primary: #008837; - --primary-fg: #fff; - --header-fg: #008837; - --link: #008837; - --page-bg: #0d0d0d; - --document-bg: #151515; - --border: #383838; - - --info-dim: #00883720; - - --button-bg: #3b3b3b; - --hover-bg: #202020; - --button-fg: #fff; - - --input-bg: #2b2b2b; - --input-placeholder: #ababab; - - --code-bg: #202020; - --selection-bg: #00883766; - --selection-fg: #fff; - --border-dim: #383838; - --input-border: #383838; - --input-bg: #151515; -} -nav li { - line-height: 24px; -} - -li.nested { - min-height: 38px !important; -} - -nav li li:not(li.nested):hover { - background-color: var(--hover-bg); -} - -pre { - border: 1px solid var(--border); -} - -.project-title a { - color: var(--fg); - font-weight: 600; -} - -.project-subtitle { - color: var(--fg); - font-weight: 600; -} - -.docgen-content { - box-shadow: none; -} - -nav details[open] { - max-height: max-content; -} diff --git a/docs/help/contents/_include/fonts/fira-code-v21-latin-regular.ttf b/docs/help/contents/_include/fonts/fira-code-v21-latin-regular.ttf deleted file mode 100644 index 9eabb703b..000000000 Binary files a/docs/help/contents/_include/fonts/fira-code-v21-latin-regular.ttf and /dev/null differ diff --git a/docs/help/contents/_include/fonts/fira-code-v21-latin-regular.woff b/docs/help/contents/_include/fonts/fira-code-v21-latin-regular.woff deleted file mode 100644 index cfbc99a95..000000000 Binary files a/docs/help/contents/_include/fonts/fira-code-v21-latin-regular.woff and /dev/null differ diff --git a/docs/help/contents/_include/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-600.ttf b/docs/help/contents/_include/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-600.ttf deleted file mode 100644 index 0f921544b..000000000 Binary files a/docs/help/contents/_include/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-600.ttf and /dev/null differ diff --git a/docs/help/contents/_include/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-600.woff b/docs/help/contents/_include/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-600.woff deleted file mode 100644 index 32c56a307..000000000 Binary files a/docs/help/contents/_include/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-600.woff and /dev/null differ diff --git a/docs/help/contents/_include/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-600.woff2 b/docs/help/contents/_include/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-600.woff2 deleted file mode 100644 index 26599958d..000000000 Binary files a/docs/help/contents/_include/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-600.woff2 and /dev/null differ diff --git a/docs/help/contents/_include/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-600italic.ttf b/docs/help/contents/_include/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-600italic.ttf deleted file mode 100644 index 797f40f30..000000000 Binary files a/docs/help/contents/_include/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-600italic.ttf and /dev/null differ diff --git a/docs/help/contents/_include/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-600italic.woff b/docs/help/contents/_include/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-600italic.woff deleted file mode 100644 index 8612cca5c..000000000 Binary files a/docs/help/contents/_include/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-600italic.woff and /dev/null differ diff --git a/docs/help/contents/_include/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-600italic.woff2 b/docs/help/contents/_include/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-600italic.woff2 deleted file mode 100644 index 932bb4d0e..000000000 Binary files a/docs/help/contents/_include/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-600italic.woff2 and /dev/null differ diff --git a/docs/help/contents/_include/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-700.ttf b/docs/help/contents/_include/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-700.ttf deleted file mode 100644 index e183c89bd..000000000 Binary files a/docs/help/contents/_include/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-700.ttf and /dev/null differ diff --git a/docs/help/contents/_include/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-700.woff b/docs/help/contents/_include/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-700.woff deleted file mode 100644 index fd9eb374f..000000000 Binary files a/docs/help/contents/_include/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-700.woff and /dev/null differ diff --git a/docs/help/contents/_include/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-700.woff2 b/docs/help/contents/_include/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-700.woff2 deleted file mode 100644 index e44d73d1f..000000000 Binary files a/docs/help/contents/_include/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-700.woff2 and /dev/null differ diff --git a/docs/help/contents/_include/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-700italic.ttf b/docs/help/contents/_include/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-700italic.ttf deleted file mode 100644 index 408f07d21..000000000 Binary files a/docs/help/contents/_include/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-700italic.ttf and /dev/null differ diff --git a/docs/help/contents/_include/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-700italic.woff b/docs/help/contents/_include/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-700italic.woff deleted file mode 100644 index e9cf9d654..000000000 Binary files a/docs/help/contents/_include/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-700italic.woff and /dev/null differ diff --git a/docs/help/contents/_include/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-700italic.woff2 b/docs/help/contents/_include/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-700italic.woff2 deleted file mode 100644 index fd04386e1..000000000 Binary files a/docs/help/contents/_include/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-700italic.woff2 and /dev/null differ diff --git a/docs/help/contents/_include/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-italic.ttf b/docs/help/contents/_include/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-italic.ttf deleted file mode 100644 index c761fc6d0..000000000 Binary files a/docs/help/contents/_include/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-italic.ttf and /dev/null differ diff --git a/docs/help/contents/_include/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-italic.woff b/docs/help/contents/_include/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-italic.woff deleted file mode 100644 index 7b91f730c..000000000 Binary files a/docs/help/contents/_include/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-italic.woff and /dev/null differ diff --git a/docs/help/contents/_include/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-italic.woff2 b/docs/help/contents/_include/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-italic.woff2 deleted file mode 100644 index f559fd43e..000000000 Binary files a/docs/help/contents/_include/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-italic.woff2 and /dev/null differ diff --git a/docs/help/contents/_include/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-regular.ttf b/docs/help/contents/_include/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-regular.ttf deleted file mode 100644 index cafe79820..000000000 Binary files a/docs/help/contents/_include/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-regular.ttf and /dev/null differ diff --git a/docs/help/contents/_include/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-regular.woff b/docs/help/contents/_include/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-regular.woff deleted file mode 100644 index 9bc5d1eed..000000000 Binary files a/docs/help/contents/_include/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-regular.woff and /dev/null differ diff --git a/docs/help/contents/_include/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-regular.woff2 b/docs/help/contents/_include/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-regular.woff2 deleted file mode 100644 index 2aa7f3338..000000000 Binary files a/docs/help/contents/_include/fonts/open-sans-v34-vietnamese_latin-ext_latin_hebrew_greek-ext_greek_cyrillic-ext_cyrillic-regular.woff2 and /dev/null differ diff --git a/docs/help/contents/_include/robots.txt b/docs/help/contents/_include/robots.txt deleted file mode 100644 index 7f4904e35..000000000 --- a/docs/help/contents/_include/robots.txt +++ /dev/null @@ -1,3 +0,0 @@ -# https://www.robotstxt.org/robotstxt.html -User-agent: * -Allow: / \ No newline at end of file diff --git a/docs/help/contents/account-settings.md b/docs/help/contents/account-settings.md new file mode 100644 index 000000000..5cc936d46 --- /dev/null +++ b/docs/help/contents/account-settings.md @@ -0,0 +1,166 @@ +--- +title: Your account +pageTitle: Manage your Notesnook account — email, password, profile +description: Change your Notesnook email or password, set a profile name and picture, save your recovery key, and log out of your devices. +keywords: + - change notesnook email + - change notesnook password + - notesnook recovery key + - notesnook log out all devices +schema: howto +--- + +# How do I manage my Notesnook account? + +Everything about your account — email, password, profile name and picture, recovery key and sessions — lives in one place: `{{settings}}` → `{{profile}}` and `{{settings}}` → `{{authentication}}` on desktop and web, or `{{settings}}` → `{{account}}` → `{{manageAccount}}` on mobile. + +## Change your email address + +Changing your email is a two-step flow: you confirm your password, then enter a 6-digit code sent to the **new** address. + +:::tabs key:platform +== Desktop/Web + +1. Go to `{{settings}}` → `{{profile}}`. +2. Press `{{changeEmail}}`. +3. Fill in `{{newEmail}}` and `{{accountPassword}}`, then press `{{next}}`. +4. Enter the `{{sixDigitCode}}` sent to your new address and press `{{next}}`. + +`Resend code in …` on the code field is disabled for 60 seconds after each send. + +== Mobile + +1. Go to `{{settings}}` → `{{account}}` → `{{manageAccount}}`. +2. Tap `{{changeEmail}}`. +3. Fill in the new email and your account password, then tap `{{verify}}`. +4. Enter the 6-digit code sent to your new address and tap `{{changeEmail}}`. + +::: + +::: warning You will be logged out from all your devices +The dialog says so explicitly. Your subscription and every other setting stay as they are — only the address changes. + +::: + +## Change your password + +:::tabs key:platform +== Desktop/Web + +1. Go to `{{settings}}` → `{{authentication}}`. +2. Press `{{changePassword}}`. +3. Enter `Current password` and `{{newPassword}}`. + +A backup is taken automatically before the change goes through. When it finishes you see `{{passwordChangedSuccessfully}}` and the `{{saveRecoveryKey}}` dialog opens — save the new key. + +== Mobile + +1. Go to `{{settings}}` → `{{account}}` → `{{manageAccount}}` → `{{changePassword}}`. +2. Enter `Current password` and `{{newPassword}}`. +3. Tap `{{changePasswordConfirm}}`. + +The screen warns that changing your password logs you out from all your devices, that you should not close the app while it runs, and that you must save the new account recovery key afterwards. A backup runs automatically first. + +::: + +### Are my notes re-encrypted when I change my password? + +**No, and that is why it is fast.** Your notes are encrypted with data keys, and those keys are what your password protects. When you change your password, Notesnook derives a new master key from the new password and re-wraps the existing keys — your attachments key, monograph passwords key, inbox keys and data encryption keys — with it. The notes themselves are never re-encrypted, so the time it takes does not grow with the size of your notes. + +::: danger Your password is the only way in +Notesnook never sees your password and cannot reset it for you. If you forget it, your [account recovery key](/recovering-your-account) is the only way back to your data. Your email must be confirmed before you can change your password. + +::: + +## Set a profile name and picture + +Your full name and profile picture are stored **end-to-end encrypted and are only visible to you** — they are personalization, not a public profile. + +:::tabs key:platform +== Desktop/Web + +1. Go to `{{settings}}` → `{{profile}}`. +2. Click the pencil next to `{{yourFullName}}` to open `{{editFullName}}`, type a name and confirm. You get a `{{fullNameUpdated}}` toast. +3. Hover the avatar and click `{{edit}}` to open `{{editProfilePicture}}`. + +== Mobile + +1. Go to `{{settings}}` → `{{account}}` → `{{manageAccount}}`. +2. `{{removeFullName}}` and `{{removeProfilePicture}}` appear here once you have set them, each asking for confirmation before clearing the value. + +::: + +## Save your account recovery key + +The recovery key is what gets you back into your data if you forget your password. Save it before you need it. + +:::tabs key:platform +== Desktop/Web + +1. Go to `{{settings}}` → `{{profile}}`. +2. Press `{{save}}` next to `{{saveDataRecoveryKey}}` and confirm the `{{verifyItsYou}}` prompt. +3. In the `{{saveRecoveryKey}}` dialog use `{{saveQRCode}}` or `Download`. +4. Press `{{keyBackedUp}}` to close the dialog. + +== Mobile + +1. Go to `{{settings}}` → `{{account}}` → `{{manageAccount}}`. +2. Tap `{{saveDataRecoveryKey}}` and confirm your identity. +3. Save the key from the dialog that opens. + +::: + +The same dialog opens automatically right after you change your password, because the key changes with it. + +## Log out from all other devices + +:::tabs key:platform +== Desktop/Web + +1. Go to `{{settings}}` → `{{profile}}`. +2. Under `{{sessions}}`, press `{{logoutAllOtherDevices}}` and confirm. + +You get a `{{loggedOutAllOtherDevices}}` toast. The device you are using stays signed in. + +== Mobile + +This is not available in the mobile app — use the desktop or web app to force a logout on your other devices. + +::: + +::: info There is no list of active sessions +Notesnook does not show a per-device session list. `{{logoutAllOtherDevices}}` clears every session except the one you are on; changing your email or password logs out every device including this one. + +::: + +## Log out of this device + +:::tabs key:platform +== Desktop/Web + +1. Go to `{{settings}}` → `{{profile}}`. +2. Under `{{sessions}}`, press `{{logout}}`. +3. Leave `{{backupDataBeforeLogout}}` ticked — it is on by default — and confirm. + +== Mobile + +1. Go to `{{settings}}` → `{{account}}` → `{{manageAccount}}` → `{{logout}}`. +2. Leave `{{backupDataBeforeLogout}}` ticked — it is on by default — and confirm. + +::: + +If you have unsynced changes, the confirmation adds a warning about them before you continue. If the pre-logout backup fails, Notesnook asks whether you want to log out anyway — answering no cancels the logout so you can fix the problem first. + +::: warning Logging out clears local data +Logging out resets the local database on that device. Anything that has not synced is gone, which is exactly what the backup checkbox is there to prevent. See [backup and restore](/backup-and-restore-notes-in-notesnook). + +::: + +## Related pages + +- [Recovering your account](/recovering-your-account) — using your recovery key after a forgotten password +- [Two-factor authentication](/two-factor-authentication) — adding a second step to every login +- [Backup and restore](/backup-and-restore-notes-in-notesnook) — keeping your own copy before you log out +- [Plans & limits](/plans-and-limits) — managing your subscription and billing +- [Deleting your account](/deleting-your-account) — removing your account and data for good +- [How is my data encrypted?](/how-is-my-data-encrypted) — what your password actually protects diff --git a/docs/help/contents/app-lock.md b/docs/help/contents/app-lock.md index c51005ad9..a47781080 100644 --- a/docs/help/contents/app-lock.md +++ b/docs/help/contents/app-lock.md @@ -1,51 +1,103 @@ -# App lock +--- +title: App lock +pageTitle: Lock the Notesnook app with a PIN, password or biometrics +description: Turn on app lock in Notesnook to require a PIN, password, biometrics or a security key before your notes open, even when your device is already unlocked. +keywords: + - lock notes app + - password protect notes app + - fingerprint lock notes +--- -You can use app lock to restrict access to your app even when your system is unlocked. +# App lock <PlanTag plan="pro" /> -## [Desktop](#/tab/desktop) +You can use app lock to restrict access to your app even when your system is unlocked. It works on desktop, web and mobile, and it is separate from the [private vault](/lock-notes-with-private-vault) — app lock covers the whole app, the vault covers individual notes. -### Turn on App Lock +App lock is part of the [Pro plan and above](/plans-and-limits). If a paid plan expires, app lock is switched off automatically, so set up your device's own lock screen if you rely on it. -1. Go to Settings and Click on App lock. Then turn on the App lock switch. You will be prompted to enter your App Lock Password. When it is successful App Lock will be turned on. +## Ways to unlock -<img src="/desktop-enable-app-lock.png" alt="drawing" height="500"/> +| Method | Where | +| --------------------------------- | ----------------------- | +| PIN or password | Desktop, web and mobile | +| Biometrics (fingerprint, Face ID) | Mobile | +| Security key | Desktop and web | -### Setting App Lock Time Out +## Turn on app lock -2. You can set the time out for your App Lock from one minute to an hour or you can turn it off by setting it to **Never**. +:::tabs key:platform +== Desktop/Web -<img src="/desktop-lock-app-after.png" alt="drawing" height="500"/> +1. Go to `{{settings}}` → `{{appLock}}`. +2. Turn on `{{enableAppLock}}`. +3. Enter a password or PIN when prompted, and confirm it. -### Change Password +![The App lock section of Notesnook desktop settings, with the Enable app lock switch turned on](/desktop-enable-app-lock.png) -3. You can also change the pin or password or you can set a security key if you want a more secure app. +== Mobile -<img src="/desktop-password-key.png" alt="drawing" height="500"/> +1. Go to `{{settings}}` → `{{appLock}}`. -## [Mobile/IOS](#/tab/mobile) + ![The App lock entry in the Notesnook mobile settings list](/app-lock-setting.png) -### Turn on App Lock +2. Turn on `{{enableAppLock}}` and enter a PIN, or authenticate with your fingerprint or face. -1. Go to Settings and Tap on App lock. + ![The App lock switch turned on in Notesnook mobile settings](/app-lock-setting-on-off.png) - <img src="/app-lock-setting.png" alt="drawing" height="500"/> +::: -2. Then turn on the App lock switch. You will be prompted to enter a pin or fingerprint. When it is successful App Lock will be turned on. +Notesnook now asks for your credential every time it starts, and after the timeout you set below. - <img src="/app-lock-setting-on-off.png" alt="drawing" height="500"/> +## Set how long before it locks -### Setting App Lock Time Out +`Lock app after` decides how long the app can sit idle before it locks itself again. `{{never}}` means Notesnook only asks when it starts. -3. You can set the time out for your App Lock +:::tabs key:platform +== Desktop/Web - <img src="/app-lock-setting-time-out.png" alt="drawing" height="500"/> +1. Go to `{{settings}}` → `{{appLock}}`. +2. Set `Lock app after` to `{{immediately}}`, `1`, `5`, `10`, `15`, `30` or `45` minutes, `1 hour`, or `{{never}}`. -### Set a pin +![The Lock app after dropdown in Notesnook desktop settings, showing the available timeout intervals](/desktop-lock-app-after.png) -4. You can set a pin instead of a fingerprint if you are more comfortable with it (or if your mobile is not fingerprint friendly). +== Mobile - <img src="/setup-app-lock-pin.png" alt="drawing" height="500"/> +1. Go to `{{settings}}` → `{{appLock}}`. +2. Set `{{appLockTimeout}}` to `{{never}}`, `{{immediately}}`, `1`, `5`, `15` or `30` minutes. -5. You can also change or remove the pin. + ![The App lock timeout options in Notesnook mobile settings](/app-lock-setting-time-out.png) - <img src="/change-remove-app-lock-pin.png" alt="drawing" height="500"/> +::: + +## Change or remove your PIN, password or security key + +:::tabs key:platform +== Desktop/Web + +Under `{{credientials}}` on the same screen: + +- `{{passwordPin}}` — press `{{change}}` to set a new one, or `{{disable}}` to remove it. +- `{{securityKey}}` — press `{{register}}` to add a hardware security key, or `{{unregister}}` to remove it. + +![The Credentials section of Notesnook desktop app lock settings, with the password and security key options](/desktop-password-key.png) + +== Mobile + +- `{{setupAppLockPin}}` or `{{setupAppLockPassword}}` add a credential; once one exists the entries read `{{changeAppLockPin}}` and `{{changeAppLockPassword}}`. +- `{{removeAppLockPin}}` and `{{removeAppLockPassword}}` take one away. App lock is switched off entirely if you remove the last remaining method. + + ![Setting an app lock PIN in Notesnook on mobile](/setup-app-lock-pin.png) + + ![Changing or removing the app lock PIN in Notesnook settings on mobile](/change-remove-app-lock-pin.png) + +::: + +## Lock the app right now + +Rather than waiting for the timeout, you can lock immediately. On desktop and web, click the lock icon in the status bar at the bottom of the window. + +## Related pages + +- [Private vault](/lock-notes-with-private-vault) — encrypt individual notes behind a separate password +- [Privacy mode](/privacy-mode) — stop screenshots and hide the app from the task switcher +- [How is my data encrypted?](/how-is-my-data-encrypted) — what protects your notes on the server +- [Plans & limits](/plans-and-limits) — what the Pro plan unlocks diff --git a/docs/help/contents/attachments-and-files.md b/docs/help/contents/attachments-and-files.md new file mode 100644 index 000000000..04532c2a9 --- /dev/null +++ b/docs/help/contents/attachments-and-files.md @@ -0,0 +1,205 @@ +--- +title: Attachments & files +pageTitle: How do I attach files and images to a note in Notesnook? +description: Attach images and files to your notes, read PDFs without downloading them, see the per-plan size and storage limits, and manage every attachment. +keywords: + - notesnook attach file to note + - notesnook attachment size limit + - notesnook attachment manager + - notesnook orphaned attachments + - notesnook pdf preview +schema: howto +--- + +# How do I attach files and images to a note in Notesnook? + +Open the insert menu in the editor and pick `{{image}}` or `{{attachment}}`. The file is encrypted on your device before it is uploaded, so nobody — including us — can read it. Attaching files requires a Notesnook account, and how large a file can be depends on your plan. + +::: info You need an account to attach files +Trying to insert an attachment while logged out shows `{{notLoggedIn}}` with the message `Login to upload attachments.` Attachments are stored on Notesnook's servers in encrypted form, which is why an account is required. See [why login is needed to upload attachments](/faqs/login-to-upload-attachments). + +::: + +## Attach a file or an image + +:::tabs key:platform +== Desktop/Web + +1. Put the cursor where the file should go. +2. Open the insert menu (the `+` button on the toolbar). +3. Choose `{{attachment}}` for any file, or `{{image}}` → `{{uploadFromDisk}}` for a picture. +4. Pick one or more files. + +Shortcuts: `Ctrl/Cmd + Shift + A` for an attachment, `Ctrl/Cmd + Shift + I` for an image. You can also drag files straight into the editor. + +== Mobile + +1. Put the cursor where the file should go. +2. Open the insert menu (the `+` button on the toolbar). +3. Choose `{{attachment}}` for any file, or `{{image}}` for a picture. +4. Under `{{image}}` you also get `{{takePhotoUsingCamera}}`, which is mobile only. + +::: + +Notesnook hashes each file first, so attaching the same file twice reuses the copy that is already uploaded instead of consuming your storage again. + +## File size and storage limits + +| | Free | Essential | Pro | Believer | +| ----------------- | ----- | --------- | ----- | -------- | +| Maximum file size | 10 MB | 100 MB | 1 GB | 5 GB | +| Storage per month | 50 MB | 1 GB | 10 GB | 25 GB | + +Storage counts **attachments only** — images, files, audio and web clips. Your notes never count against it. If a file is over your plan's limit, the upload is refused with a message telling you the size you are allowed. Full details are on [Plans & limits](/plans-and-limits). + +### Upload images at full quality <PlanTag plan="pro" /> + +By default Notesnook compresses images before uploading. The `{{imageCompression}}` setting offers `{{askEveryTime}}`, `{{enableRecommended}}` and `{{disable}}` — and `{{disable}}`, which uploads at full quality, needs **Pro** or **Believer**. + +:::tabs key:platform +== Desktop/Web +Go to `{{settings}}` → `{{behaviour}}` → `{{imageCompression}}`. + +== Mobile + +Go to `{{settings}}` → `{{customization}}` → `{{behavior}}` → `{{imageCompression}}`. + +::: + +## Manage your attachments + +The attachment manager lists every file in your account with its name, upload status, size and upload date. + +:::tabs key:platform +== Desktop/Web +Go to `{{settings}}` → `{{profile}}` → `{{attachments}}` and press `{{open}}`. + +== Mobile + +Go to `{{settings}}` → `{{account}}` → `{{manageAccount}}` → `{{manageAttachments}}`. + +::: + +### Filter and search + +Both apps group attachments by type. On desktop and web the sidebar has `All files`, `Images`, `Documents`, `Videos`, `Audios`, `{{uploads}}` and `{{orphaned}}`, each with a count. Mobile shows `All files`, `Images`, `Audios`, `Videos`, `Documents`, `{{orphaned}}` and `Errors`. + +- **`{{uploads}}`** — files that are still waiting to be uploaded. +- **`{{orphaned}}`** — files that are no longer referenced by any note, usually left behind by a note you deleted. These are safe to delete once you are sure you don't want the file itself. + +The search box at the top filters the list by filename. On desktop and web you can also sort by clicking the `{{name}}`, `{{size}}` or `{{dateUploaded}}` column headers. + +### Act on an attachment + +Open an attachment's menu — right click desktop and web, tap the item on mobile — for: + +| Action | What it does | +| ------------------------------------------------ | ----------------------------------------------------------------------------- | +| `{{previewAttachment}}` | Opens images and PDFs without downloading them (desktop and web) | +| `{{linkedNotes}}` | Lists the notes that use this file; picking one opens it | +| `{{fileCheck}}` | Verifies the uploaded file is intact and decryptable | +| `{{rename}}` | Changes the filename | +| `Download` | Saves the file to your device | +| `Reupload` | Replaces a broken upload — you must pick the same file, the hash has to match | +| `{{deletePermanently}}` (`{{delete}}` on mobile) | Removes the file from your account and from the notes that use it | + +`Download`, `{{fileCheck}}` and `{{delete}}` also work on a multi-selection from the toolbar at the top of the desktop and web list. + +::: tip Fix a failed attachment +A file that shows an error usually needs `{{fileCheck}}` first. If the check reports a problem, `Reupload` with the original file repairs it. + +::: + +<!-- TODO: screenshot — the attachment manager with the type sidebar and the toolbar actions --> + +### Download every attachment + +The download button at the bottom of the desktop and web sidebar is `{{downloadAllAttachments}}`; on mobile it is the download icon in the header. A progress ring appears while it runs, and pressing the button again cancels it. This is the quickest way to get a local copy of everything you have uploaded. + +### Clear the cache + +`{{clearCache}}` removes the local copies of files without touching what is on the server. The confirmation spells out what happens: downloaded images and files are **cleared**, pending uploads are **cleared**, and uploaded images and files are **unaffected**. + +:::tabs key:platform +== Desktop/Web +Use the `{{clearCache}}` button at the bottom of the attachment manager's sidebar. + +== Mobile + +Go to `{{settings}}` → `{{account}}` → `{{manageAccount}}` → `{{clearCache}}`. The setting shows the current cache size. + +::: + +::: warning Pending uploads are cleared too +Anything that has not finished uploading is lost when you clear the cache. Let uploads finish first. + +::: + +## Read a PDF without downloading it + +PDFs open in a viewer inside Notesnook, so you can read one without saving it to your device first. The file is downloaded to the local cache, decrypted in memory and shown — it is never handed to another app unless you ask for that. + +To open one, click or tap the PDF attachment where it sits in the note. On desktop and web there is a second route: open the file's menu in the [attachment manager](#manage-your-attachments) and choose `{{previewAttachment}}`. That entry appears only on images and PDFs, and the attachment manager on mobile has no preview action — go through the note instead. + +:::tabs key:platform +== Desktop/Web + +The PDF opens in a **side pane to the right of the editor**, so you can read it and write at the same time. Drag the divider between the two to resize them. + +The pane's toolbar has: + +| Control | What it does | +| ---------------------- | --------------------------------------------------------------- | +| `{{search}}` | Searches the text of the PDF and highlights the matches | +| `{{goToPreviousPage}}` | Back one page | +| Page number | Shows the current page and the total; type a number to jump | +| `{{goToNextPage}}` | Forward one page | +| `{{zoomOut}}` / `{{zoomIn}}` | Steps the zoom down or up; the current percentage sits between them | +| `Download` | Saves the PDF to your device | +| `{{enterFullScreen}}` | Hands the whole screen to the PDF | +| `{{close}}` | Closes the pane and returns the space to the editor | + +The table of contents and the note properties share this space, so opening the PDF preview closes whichever of those was open. + +== Mobile + +The PDF opens **full screen** over the app. In its header you get: + +- a back arrow to close the viewer and return to the note; +- the current page number with the page total beside it — tap the number, type a page and confirm to jump straight to it; +- a download button to save the file to your device; +- an open-in-new button that hands the PDF to another app on your phone, so you can read it in your usual PDF reader or share it onward. + +Scroll and pinch to zoom as you would in any other viewer. + +::: + +::: info Password-protected PDFs +A PDF with a password on it opens on a `{{pdfLocked}}` screen instead of the document. Enter the PDF's own password to read it. This is the password whoever made the file set on it — it has nothing to do with your Notesnook account password or your [vault](/lock-notes-with-private-vault) password, and Notesnook cannot recover it for you. + +::: + +## Deleting an attachment + +Deleting an attachment removes it from your account **and** from every note that references it — attachments are not moved to [Trash](/trash) the way notes are. + +## What is an orphaned attachment? + +Deleting a note does not delete the files it contained — they stay in your account as **orphaned** attachments, listed under `{{orphaned}}` in the attachment manager. Delete the ones you no longer want the file for. + +## Why is my storage still full after I deleted attachments? + +Your plan's storage figure is a **monthly allowance**, not a measure of how much you are currently storing — that is why every plan is written as `50 MB/mo`, `1 GB/mo` and so on. Uploading a file spends part of that month's allowance, and deleting the file afterwards does not hand the allowance back. The allowance starts again at the beginning of the next month. + +So deleting attachments is worth doing to keep your account tidy, but it is not the way to get more room this month. If you are hitting the ceiling regularly, a plan with a larger monthly allowance is the fix — see [plans & limits](/plans-and-limits). + +<GetNotesnook action="pricing" title="Need more room for files?" text="The free plan gives you 50 MB a month and a 10 MB file size cap. Paid plans go up to 25 GB a month with 5 GB files — and every file stays end-to-end encrypted on all of them." /> + +## Related pages + +- [Plans & limits](/plans-and-limits) — the storage and file size limits for every plan +- [Trash](/trash) — why deleted notes leave their files behind +- [How is my data encrypted?](/how-is-my-data-encrypted) — how attachments are encrypted before upload +- [Private vault](/lock-notes-with-private-vault) — locking the notes your files live in +- [Backup and restore](/backup-and-restore-notes-in-notesnook) — including attachments in a backup +- [Why do I need to log in to upload attachments?](/faqs/login-to-upload-attachments) diff --git a/docs/help/contents/backup-and-restore-notes-in-notesnook.md b/docs/help/contents/backup-and-restore-notes-in-notesnook.md index d9d3c38f5..83efb2d92 100644 --- a/docs/help/contents/backup-and-restore-notes-in-notesnook.md +++ b/docs/help/contents/backup-and-restore-notes-in-notesnook.md @@ -1,111 +1,148 @@ --- title: Backup and restore -description: Notesnook allows you to backup all your notes data to a single backup file. Learn how you can backup your notes and restore them. +pageTitle: How do I back up and restore my notes in Notesnook? +description: Create an encrypted backup of everything in Notesnook, turn on automatic backups, and restore a backup without losing the work you have done since. +keywords: + - notesnook backup + - backup notes app + - restore notesnook backup + - notesnook automatic backups + - nnbackupz file +schema: howto --- -# Backup your notes +# How do I back up and restore my notes? -It is always a good practice to take regular backups of your data so you can easily recover your data in case of data corruption or losing access to your account. All backups are stored locally encrypted (unless you turn off backup encryption) on your device. +Taking regular backups means you can recover your notes if your data is corrupted or you lose access to your account. All backups are stored locally encrypted (unless you turn off backup encryption) on your device. -> error Store your password & recovery key safely -> -> Since all your data is end-to-end encrypted, we have no way to restore your account data if you forget your account password and lose your account recovery key. That's why we recommend that you store your password & recovery key in a password manager or some other safe place. +::: danger Store your password & recovery key safely +Since all your data is end-to-end encrypted, we have no way to restore your account data if you forget your account password and lose your account recovery key. That's why we recommend that you store your password & recovery key in a password manager or some other safe place. -# [Desktop/Web](#/tab/web) +::: -1. Go to Settings -2. Scroll down in the Settings navigation menu and click on `Backup & export` section -3. Click on `Create backup` under `Backup now` heading to create a new `.nnbackupz` file +:::tabs key:platform +== Desktop/Web -![](/create-backup-web.png) +1. Go to `{{settings}}`. +2. Open `{{backupExport}}` section +3. Click `Create backup` under `{{backupNow}}` heading to create a new `.nnbackupz` file -# [Mobile](#/tab/mobile) +![The Backup & export section of Notesnook settings on web, with the Create backup button](/create-backup-web.png) -1. Go to Settings from Sidebar -2. Scroll down to `Backup and Restore` -3. Tap on `Backups` -4. Press on `Backup now` to create a new `.nnbackupz` file +== Mobile -> info -> -> On **Android** when you take a backup for the first time, you will be asked to select a folder where you want to store all your backup files. You can always change your backup files location from `Backups > Select backup directory`. -> -> Regardless of the folder you select, Notesnook will create a folder "Notesnook/backups" inside it and store all backup files there. +1. Go to `{{settings}}`. +2. Open `{{backupRestore}}` +3. Tap `{{backups}}` +4. Tap `{{backupNow}}` to create a new `.nnbackupz` file ---- +::: info +On **Android** when you take a backup for the first time, you will be asked to select a folder where you want to store all your backup files. You can always change your backup files location from `Backups > Select backup directory`. -## Automatic Backups +Regardless of the folder you select, Notesnook will create a folder "Notesnook/backups" inside it and store all backup files there. + +::: + +## Turn on automatic backups For maximum safety against potential data loss, you can enable daily, weekly or monthly backups of your notes. Enabling automatic backups will ensure that all your data is safely backed up locally after a regular interval. -# [Desktop](#/tab/desktop) +:::tabs key:platform +== Desktop -1. Go to Settings -2. Scroll down in the Settings navigation menu and click on `Backup & export` section +1. Go to `{{settings}}`. +2. Open `{{backupExport}}` section 3. Select the Automatic backups interval from the dropdown -![](/auto-backups-desktop.png) +![The automatic backup interval dropdown in Notesnook desktop settings](/auto-backups-desktop.png) +== Web +::: info +On the **web** app there is no way to automatically save backups to a folder, that is why Notesnook only reminds the users when it's time to create a new backup. -# [Web](#/tab/web) +::: -> info -> -> On the **web** app there is no way to automatically save backups to a folder, that is why Notesnook only reminds the users when it's time to create a new backup. - -1. Go to Settings -2. Scroll down in the Settings navigation menu and click on `Backup & export` section +1. Go to `{{settings}}`. +2. Open `{{backupExport}}` section 3. Select the Backup reminders interval from the dropdown -![](/auto-backups-web.png) +![The backup reminder interval dropdown in Notesnook on the web](/auto-backups-web.png) -# [Mobile](#/tab/mobile) +== Mobile -1. Go to Settings > Backup & Restore -2. Press Backups -3. Select automatic backup frequency to enable automatic backups +1. Go to `{{settings}}` → `{{backupRestore}}`. +2. Tap `{{backups}}`. +3. Choose an automatic backup frequency. + : + ::: ---- +## Keep backups encrypted -## Encrypted Backups (Recommended) +To keep your backups secure & private, it is recommended that you enable encryption on your backup files instead of storing them as plaintext data. **Encrypted backups are on by default.** -To keep your backups secure & private, it is recommended that you enable encryption on your backup files instead of storing them as plaintext data. **Starting from v2.6.0, encrypted backups are enabled by default for all users.** +:::tabs key:platform +== Desktop/Web -# [Desktop/Web](#/tab/web) +1. Go to `{{settings}}`. +2. Open `{{backupExport}}` section +3. Click the toggle next to `{{backupEncryption}}` to enable/disable encrypted backups -1. Go to Settings -2. Scroll down in the Settings navigation menu and click on `Backup & export` section -3. Click on the toggle next to `Backup encryption` to enable/disable encrypted backups +== Mobile -# [Mobile](#/tab/mobile) +1. Go to `{{settings}}` → `{{backupRestore}}` +2. Tap `{{backups}}` +3. Tap the toggle next to `{{backupEncryption}}` to enable/disable encrypted backups -1. Go to `Settings` > `Backup & Restore` -2. Tap on `Backups` -3. Tap on the toggle next to `Backup encryption` to enable/disable encrypted backups +::: ---- +::: info +Backups are always encrypted with your account password. -> info -> -> Backups are always encrypted with your account password. +::: -# Restore a backup +## Restore a backup -At any point in time, you can restore a backup to recover lost data. However, **to restore a backup, you must be logged in to your Notesnook account.** Backups created on one account can be restored on another Notesnook account. +::: danger Restoring overwrites what you have now +Restoring a backup replaces your current content in-place. Anything that changed since that backup was taken is reverted to how it was in the backup. Entirely new content — notes you created after the backup — is not touched. -# [Desktop/Web](#/tab/web) +**Always create a backup before restoring one.** -1. Go to Settings -2. Scroll down in the Settings navigation menu and click on `Backup & export` section -3. Click on `Restore` button next to `Restore backup` heading +::: + +### Recover a few old notes without losing today's work + +If you only want something back from an old backup, don't restore it over your current data and hope for the best. Sandwich it: + +1. Create a **new backup** of your current data. +2. Restore the **old backup** and take out what you needed. +3. Restore the **new backup** from step 1 to put everything back as it was. + +That sequence means no recent change is lost. Be aware of one side effect: restoring an old backup can bring back notes you had deleted since, so check your trash and notes list afterwards. + +At any point in time, you can restore a backup to recover lost data. Backups created on one account can be restored on another Notesnook account. + +:::tabs key:platform +== Desktop/Web + +1. Go to `{{settings}}`. +2. Open `{{backupExport}}` section +3. Click `{{restore}}` button next to `{{restoreBackup}}` heading 4. Select the `.nnbackupz` or `.nnbackup` file from your PC that you want to restore. -# [Mobile](#/tab/mobile) +== Mobile -1. Go to Settings from Sidebar -2. Scroll down to `Backup & Restore` section -3. Tap on `Restore backup` -4. From `Restore backup` sheet, select the backup you want to restore. If your backup file is located in some other location, tap on `Restore from files` on top right corner of the sheet then select the backup file. +1. Go to `{{settings}}`. +2. Open `{{backupRestore}}` +3. Tap `{{restoreBackup}}` +4. From `{{restoreBackup}}` sheet, select the backup you want to restore. If your backup file is located in some other location, tap `{{restoreFromFiles}}` on top right corner of the sheet then select the backup file. -<img src="/restore-backup-mobile.png" height="700px"> +![The Restore backup sheet on Notesnook mobile, listing the backup files it found](/restore-backup-mobile.png) ---- +::: + +## Related pages + +- [Exporting notes](/export-notes-from-notesnook) — taking your notes to another app +- [Recovering your account](/recovering-your-account) — when you forget your password +- [Attachments & files](/attachments-and-files) — managing the files in your notes +- [Version history](/note-version-history) — going back to an earlier draft +- [Plans & limits](/plans-and-limits) — what each plan unlocks and the exact limits diff --git a/docs/help/contents/create-a-note-in-notesnook.md b/docs/help/contents/create-a-note-in-notesnook.md index 29ac2433e..5e84eaa4c 100644 --- a/docs/help/contents/create-a-note-in-notesnook.md +++ b/docs/help/contents/create-a-note-in-notesnook.md @@ -1,39 +1,52 @@ --- title: Create your first note -description: Notesnook let's you create unlimited notes for free. Learn how you can create your first note in Notesnook. +pageTitle: How do I create a note in Notesnook? +description: Create your first note in Notesnook on desktop, web or mobile. Notes save themselves as you type, and you can start one from anywhere in the app. +keywords: + - create a note notesnook + - how to use notesnook + - notesnook first note +schema: howto --- # Creating your first note You are in a note taking app, the first thing you'd want to do is create a note. -# [Desktop/Web](#/tab/web) +:::tabs key:platform +== Desktop/Web -1. Click on the `+` button on top right corner or click anywhere inside the editor to focus it. +1. Click the `+` button on top right corner or click anywhere inside the editor to focus it. 2. Start typing in the editor and a new note will be automatically created. 3. As you type, your note is saved automatically whenever you stop for a few seconds. -![First note web](/first-note-desktop.png) +![A new note being typed in the Notesnook desktop editor](/first-note-desktop.png) -> info -> -> The bottom right corner of the app will show the number of words of current note & the last saved time. -> -> ![Status bar desktop](/editor-status-bar-desktop.png) +::: info +The bottom right corner of the app will show the number of words of current note & the last saved time. -# [Mobile](#/tab/mobile) +![The editor status bar at the bottom right, showing the word count and last saved time](/editor-status-bar-desktop.png) + +== Mobile 1. On mobile regardless of what screen you are on, you can swipe from right to left to open the editor. 2. You can also press the `+` button on bottom right corner to open the editor (note: the `+` button is visible only on some screens). 3. Start typing in the editor and a new note will be automatically created. 4. As you type, your note is saved automatically whenever you stop for a few seconds. -![First note mobile](/first-note-mobile.png) +![A new note being typed in the Notesnook mobile editor](/first-note-mobile.png) -> info -> -> Below the note title is the editor status bar. It shows you the number of words in the note and last saved time. +::: info +Below the note title is the editor status bar. It shows you the number of words in the note and last saved time. ---- +::: And that is how you create your first private note in Notesnook! + +## Related pages + +- [Notebooks](/organizing-notes/organize-notes-using-notebooks) — nested notebooks for structure +- [Editor toolbar](/rich-text-editor/rich-text-editor-toolbar) — every formatting tool +- [Search & navigation](/search-and-navigation) — finding anything, fast +- [How sync works](/sync/how-sync-works) — when and how your notes travel +- [Plans & limits](/plans-and-limits) — what each plan unlocks and the exact limits diff --git a/docs/help/contents/custom-themes/README.md b/docs/help/contents/custom-themes/README.md deleted file mode 100644 index 8891dd6ac..000000000 --- a/docs/help/contents/custom-themes/README.md +++ /dev/null @@ -1 +0,0 @@ -# Custom themes diff --git a/docs/help/contents/custom-themes/create-a-theme-with-theme-builder.md b/docs/help/contents/custom-themes/create-a-theme-with-theme-builder.md index d26a8f565..e3f2ad137 100644 --- a/docs/help/contents/custom-themes/create-a-theme-with-theme-builder.md +++ b/docs/help/contents/custom-themes/create-a-theme-with-theme-builder.md @@ -1,35 +1,48 @@ +--- +title: Theme Builder +pageTitle: How do I create a custom Notesnook theme? +description: Build a Notesnook theme in the Theme Builder without writing JSON — pick a starter theme, set your colors and metadata, and export it as a theme file. +keywords: + - notesnook theme builder + - create notesnook theme + - custom theme notes app +schema: howto +--- + # Create a theme with the Theme Builder The Theme Builder provides an easy and accessible way to create themes for Notesnook without prior technical knowledge. The purpose of this tool is to allow anyone, especially a layman, to tweak Notesnook according to their liking. You can access the Theme Builder at [https://theme-builder.notesnook.com](https://theme-builder.notesnook.com). -> info -> -> The Theme Builder is the exact duplicate of the Notesnook Web application — just with the option to tweak the colors. You can use it to sign into your account, create notes, and everything else you do in the Notesnook app. +::: info +The Theme Builder is a full copy of the Notesnook web app, with an extra panel for tweaking the colors. You can use it to sign into your account, create notes, and everything else you do in the Notesnook app. + +::: Here's a look at the theme builder: -![Toolbar](/theme-builder.png) +![The Notesnook Theme Builder, with the colour panel beside a live copy of the app](/theme-builder.png) Now let's walk through the whole process of creating your own theme using the Theme Builder. ## 1. Select a starter theme -Before you can create your own theme, it is best to select a starter theme to build upon. This allows us to quickly visualize all the changes without have to build from scratch. +Before you can create your own theme, it is best to select a starter theme to build upon. That lets you see every change against a working app instead of building one from scratch. The Theme Builder makes this very easy: 1. Open the [Theme Builder](https://theme-builder.notesnook.com). 2. Go to `Settings > Appearance > Themes` and select any theme from the list. -> warn -> -> Keep in mind that a theme can only have one color scheme: `light` or `dark` so choose your starter theme accordingly. +::: warning +Keep in mind that a theme can only have one color scheme: `light` or `dark` so choose your starter theme accordingly. + +::: For our example, we are going to select "Notesnook Light" as our base theme. -![Toolbar](/theme-builder-select-starter-theme.png) +![Choosing Notesnook Light as the starter theme in the Theme Builder](/theme-builder-select-starter-theme.png) Once the theme is applied, you'll notice all the colors in the Theme Builder update with the colors of the Notesnook Light theme. @@ -37,47 +50,50 @@ Once the theme is applied, you'll notice all the colors in the Theme Builder upd Theme metadata allows better discoverability in search and gives users a quick idea of what the theme is. You can read about all the supported properties [here](/custom-themes/introduction#theme-metadata). -![Toolbar](/theme-builder-metadata.png) +![The theme metadata fields in the Theme Builder](/theme-builder-metadata.png) -> warn Theme ID conflicts -> -> Remember that the `id` for your custom theme should not conflict with other published themes on Notesnook. You can see the list of all published theme IDs [here](https://github.com/streetwriters/notesnook-themes/tree/main/themes). +::: warning Theme ID conflicts +Remember that the `id` for your custom theme should not conflict with other published themes on Notesnook. You can see the list of all published theme IDs [here](https://github.com/streetwriters/notesnook-themes/tree/main/themes). + +::: ## 3. Configuring base theme scope -> info -> -> Before you proceed, it is recommended that you [learn about how theming in Notesnook works](/custom-themes/introduction#what-is-a-theme), what scopes, variants & colors do etc. +::: info +Before you proceed, it is recommended that you [learn about how theming in Notesnook works](/custom-themes/introduction#what-is-a-theme), what scopes, variants & colors do etc. + +::: Every Notesnook theme must implement the base theme scope. Colors from the `base` theme scope are used as a fallback in all other scopes if a specific color is not defined. -![Toolbar](/theme-builder-base.png) +![The base theme scope expanded in the Theme Builder, showing its variants](/theme-builder-base.png) -For our example, we will be creating a Blue accented theme for Notesnook. In order to do that, we must replace all the occurences of the default green color (#008837) in the `base` theme scope with a nice blue color (#1d4ed8). +For our example, we will be creating a Blue accented theme for Notesnook. In order to do that, we must replace all the occurrences of the default green color (#008837) in the `base` theme scope with a nice blue color (#1d4ed8). Since we want to create a blue variant of our Notesnook light theme, we will replace the default green (#008837) in our base theme scope with blue(#1d4ed8). We have to go through all variants, primary, secondary, selected, disabled and replace the colors. -![Toolbar](/theme-builder-change-color.gif) +![Replacing the green accent colour with blue and seeing the app update live](/theme-builder-change-color.gif) -As you change each color, you will see the changes reflected in the app in real-time. How cool is that! +As you change each color, the app updates in real time. ## 4. Configuring optional scopes After configuring `base` theme scope, you can optionally set colors for other scopes, such as `navigationMenu`, to make them look a little different. -> info An example -> -> For example, in the default Notesnook Light theme, the background color of the navigation menu is grayish instead of pure white. -> -> ![Toolbar](/theme-builder-navigation-menu.png) -> -> This is because the default Notesnook Light theme has a different background color set for the `navigationMenu` scope. -> -> ![Toolbar](/theme-builder-navigation-menu-scope.png) +::: info An example +For example, in the default Notesnook Light theme, the background color of the navigation menu is grayish instead of pure white. -The sky is the limit here. In most cases, though, the `base` scope will suffice unless you want to get super creative like me. +![The Notesnook Light navigation menu, with a background slightly greyer than the rest of the app](/theme-builder-navigation-menu.png) -![Toolbar](/theme-builder-navigation-menu-modify.png) +This is because the default Notesnook Light theme has a different background color set for the `navigationMenu` scope. + +![The navigationMenu scope in the Theme Builder, showing its own background colour](/theme-builder-navigation-menu-scope.png) + +::: + +The sky is the limit here. In most cases, though, the `base` scope will suffice unless you want to get more adventurous. + +![The navigation menu restyled with a custom background colour](/theme-builder-navigation-menu-modify.png) And that's it! Your theme is ready to be exported. @@ -85,7 +101,7 @@ And that's it! Your theme is ready to be exported. Once you have finished working on your theme, you can export it by clicking the "Export theme" button at the top of Theme Builder pane. -![](/theme-builder-export-theme.png) +![The Export theme button at the top of the Theme Builder panel](/theme-builder-export-theme.png) You will get a JSON file containing your theme which you can either [install directly into the Notesnook app](/custom-themes/install-a-theme-from-file) for personal use or [publish it](/custom-themes/publish-a-theme) for others to use as well. @@ -93,3 +109,10 @@ You will get a JSON file containing your theme which you can either [install dir - [Publish your theme](/custom-themes/publish-a-theme) - [Install a theme directly from JSON file](/custom-themes/install-a-theme-from-file) + +## Related pages + +- [How themes work](/custom-themes/introduction) — scopes, variants and colors +- [Publish a theme](/custom-themes/publish-a-theme) — sharing a theme with everyone +- [Install from file](/custom-themes/install-a-theme-from-file) — loading a theme.json +- [Using themes](/custom-themes/using-themes) — light, dark and the theme store diff --git a/docs/help/contents/custom-themes/install-a-theme-from-file.md b/docs/help/contents/custom-themes/install-a-theme-from-file.md index c96310072..9be5eaffb 100644 --- a/docs/help/contents/custom-themes/install-a-theme-from-file.md +++ b/docs/help/contents/custom-themes/install-a-theme-from-file.md @@ -1,15 +1,33 @@ -## Install a theme directly from theme.json file +--- +title: Install from file +pageTitle: How do I install a Notesnook theme from a file? +description: Load a theme.json file directly into Notesnook on mobile, desktop or web, and set it as your default theme. +keywords: + - install notesnook theme + - theme.json notesnook + - load theme from file +schema: howto +--- + +# Install a theme directly from theme.json file In both mobile and desktop/web apps, you can install themes directly from a JSON theme file. -> info You cannot currently import CSS for a code block. -> -> [Themes must be published](/custom-themes/publish-a-theme) in order for you to use custom CSS for code blocks. +::: info You cannot currently import CSS for a code block. +[Themes must be published](/custom-themes/publish-a-theme) in order for you to use custom CSS for code blocks. + +::: 1. Open the Notesnook app 2. Go to Settings > Appearance > Themes -3. Click on "Load from file" button - ![Toolbar](/theme-load-file.png) +3. Click "Load from file" button + ![The Load from file button in the Notesnook theme settings](/theme-load-file.png) 4. Select the JSON file to load the theme from. -5. Click on "Set as default" - ![](/theme-set-as-default.png) +5. Click "Set as default" + ![The Set as default button on a theme loaded from a file](/theme-set-as-default.png) + +## Related pages + +- [Using themes](/custom-themes/using-themes) — light, dark and the theme store +- [Theme Builder](/custom-themes/create-a-theme-with-theme-builder) — building a theme visually +- [How themes work](/custom-themes/introduction) — scopes, variants and colors diff --git a/docs/help/contents/custom-themes/introduction.md b/docs/help/contents/custom-themes/introduction.md index fd4eb2339..5946664a9 100644 --- a/docs/help/contents/custom-themes/introduction.md +++ b/docs/help/contents/custom-themes/introduction.md @@ -1,8 +1,19 @@ +--- +title: Introduction +pageTitle: How Notesnook themes work — scopes, variants and colors +description: "How the Notesnook theme engine is built: the 11 scopes that split up the app, the 6 variants inside each one, and the 13 colors each variant defines." +keywords: + - notesnook theme spec + - notesnook theme scopes + - custom theme notes app +--- + # Introduction -> info -> -> This document reflects v1.0 of the Notesnook Theme specification. +::: info +This document reflects v1.0 of the Notesnook Theme specification. + +::: The goal of this document is to provide you with an exact idea of what each scope, variant & color in the theme does, how they all fit together, and how you can use them to create your own custom theme for Notesnook. This document will also serve as a descriptive guide for any `theme.json` file you may find online. @@ -17,13 +28,13 @@ Suffice it to say, you can change every part of Notesnook independently. This is ### 1. Scopes Scopes allow you to independently theme various parts of the Notesnook app. -Each scope represents a specific part of the app. For example, you can style the editor toolbar different than the rest of the UI. Since scopes never overlap with each other, you can style each part of Notesnook without worrying about the rest. +Each scope represents a specific part of the app. For example, you can style the editor toolbar differently from the rest of the UI. Since scopes never overlap with each other, you can style each part of Notesnook without worrying about the rest. Here's a quick schematic diagram of each scope used by the Notesnook Web app. -![](/custom-themes/theme-scopes-schema.png) +![A diagram of the Notesnook web app with each theme scope outlined and labelled](/custom-themes/theme-scopes-schema.png) -Currently, Notesnook has 10 scopes: +Currently, Notesnook has 11 scopes: #### 1. `base` @@ -42,55 +53,59 @@ This allows you to change only the colors you need without any duplication. The `navigationMenu` scope is used by the left-most side bar that contains the links to your Notes, Notebooks, Favorites etc. -![](/custom-themes/theme-scope-navigation-menu.png) +![The Notesnook side bar, the area covered by the navigationMenu scope](/custom-themes/theme-scope-navigation-menu.png) -#### 3. `statusBar` +#### 3. `titleBar` + +The `titleBar` scope is used by the title bar Notesnook draws along the top of the desktop window. It has no effect when you have switched to [your system's native titlebar](/desktop-integration/updates-and-advanced-settings). + +#### 4. `statusBar` The `statusBar` scope is used by the bottom most horizontal bar that contains your email address, the sync status etc. -![](/custom-themes/theme-scope-status-bar.png) +![The bar along the bottom of the desktop window, the area covered by the statusBar scope](/custom-themes/theme-scope-status-bar.png) -#### 4. `list` +#### 5. `list` The `list` scope is used by the list of notes, notebooks & everything else that is in the middle pane. -![](/custom-themes/theme-scope-list.png) +![The middle pane listing notes, the area covered by the list scope](/custom-themes/theme-scope-list.png) -#### 5. `editor` +#### 6. `editor` The `editor` scope is used by the editor and everything inside of it like task lists, outline lists, tables etc. This scope does not include the editor toolbar. -![](/custom-themes/theme-scope-editor.png) +![The note editing surface, the area covered by the editor scope](/custom-themes/theme-scope-editor.png) -#### 6. `editorToolbar` +#### 7. `editorToolbar` The `editorToolbar` scope is used specifically by the editor toolbar for styling all its icons, buttons & menus. -![](/custom-themes/theme-scope-editor-toolbar.png) +![The formatting toolbar above the editor, the area covered by the editorToolbar scope](/custom-themes/theme-scope-editor-toolbar.png) -#### 7. `editorSidebar` +#### 8. `editorSidebar` The `editorSidebar` scope is used by the right-most properties menu, and the PDF attachments preview. -![](/custom-themes/theme-scope-editor-sidebar.png) +![The note properties pane on the right, the area covered by the editorSidebar scope](/custom-themes/theme-scope-editor-sidebar.png) -#### 8. `dialog` +#### 9. `dialog` All the dialogs in the app, regardless of how they are triggered or what they contain, use the `dialog` scope. This includes the settings dialog, notebook creation dialog, reminder creation dialog etc. -![](/custom-themes/theme-scope-dialog.png) +![A Notesnook dialog, the area covered by the dialog scope](/custom-themes/theme-scope-dialog.png) -#### 9. `contextMenu` +#### 10. `contextMenu` All the context menus & drop down menus in the app use the `contextMenu` scope. This includes the menus in the `editor`, `list`, and other scopes. -![](/custom-themes/theme-scope-context-menu.png) +![A right click menu in Notesnook, the area covered by the contextMenu scope](/custom-themes/theme-scope-context-menu.png) -#### 10. `sheet` +#### 11. `sheet` The `sheet` scope is a mobile specific scope, and is not used by the web app. It is used by all the popup action sheets displayed in the mobile app. -<img src="/custom-themes/theme-scope-sheet.png" height="500px"/> +![A bottom sheet in the Notesnook mobile app, the area covered by the sheet scope](/custom-themes/theme-scope-sheet.png) --- @@ -100,39 +115,44 @@ Each scope is further broken down into Variants. Variants reflect either the state or importance of a UI element. Variants are NOT isolated and can be intermixed so it is important for a theme to have good contrast between the colors of each variant in order to avoid making some parts of Notesnook completely unreadable. -Currently, Notesnook has 5 variants: +Currently, Notesnook has 6 variants: 1. `primary` \ The `primary` variant is used by every element when it isn't in any of the other states. 2. `secondary` \ - The `secondary` variant is complimentary to the `primary` variant. It is used in places to show elements or text of less importance. For example, the text `12h ago` shown under each note item uses the `paragraph` color from the `secondary` variant. -3. `selected` + The `secondary` variant is complementary to the `primary` variant. It is used in places to show elements or text of less importance. For example, the text `12h ago` shown under each note item uses the `paragraph` color from the `secondary` variant. +3. `disabled` + \ + The `disabled` variant is used for elements that are present but not currently actionable — a greyed-out button, or a tool the editor has switched off for the current selection. +4. `selected` \ This variant is used throughout the app for all elements in selected, toggled, or focused state. -4. `error` +5. `error` \ The `error` variant contains colors for showing errored status anywhere inside the app. It is possible that the UI element using this variant may make use of colors from other variants. -5. `success` +6. `success` \ The `success` variant contains colors for showing success status anywhere inside the app. It is possible that the UI element using this variant may make use of colors from other variants. -Each variant further contains a total of 12 Colors: +Each variant further contains a total of 13 colors. The **Transparent** column shows which ones accept an alpha channel (`#dbdbdb99`) as well as plain hex: | Color | Description | Transparent | | ------------------ | ------------------------------------------------------------------------------------------------------------------ | ----------- | | `accent` | Color used to make something stand out (like the primary button in dialogs). Can be both background or foreground. | ❌ | | `accentForeground` | Color for icons & text on accent background | ❌ | -| `background` | Background color of elements | ❌ | +| `background` | Background color of elements | ✅ | | `paragraph` | Color of paragraphs and other text | ❌ | | `heading` | Color of headings & titles | ❌ | | `backdrop` | The color of the overlay shown behind dialogs & modals | ✅ | | `hover` | Background color when hovering over elements (that support it) | ✅ | | `border` | Border color | ❌ | | `separator` | Color of the separator line between items | ❌ | -| `placeholder` | Color of the placeholder in input fields | ❌ | +| `placeholder` | Color of the placeholder in input fields | ✅ | | `icon` | Color of icons | ❌ | +| `shade` | Tint laid over an element to shade it, usually derived from the accent color | ✅ | +| `textSelection` | Background color of selected text | ✅ | ### Theme Metadata @@ -150,3 +170,10 @@ Each variant further contains a total of 12 Colors: ## Further reading - [Build your own theme using the Theme Builder](/custom-themes/create-a-theme-with-theme-builder). + +## Related pages + +- [Using themes](/custom-themes/using-themes) — light, dark and the theme store +- [Theme Builder](/custom-themes/create-a-theme-with-theme-builder) — building a theme visually +- [Publish a theme](/custom-themes/publish-a-theme) — sharing a theme with everyone +- [Customizing the app](/customizing-notesnook) — home screen, sidebar, sorting and formats diff --git a/docs/help/contents/custom-themes/publish-a-theme.md b/docs/help/contents/custom-themes/publish-a-theme.md index 4bcfc1172..357835433 100644 --- a/docs/help/contents/custom-themes/publish-a-theme.md +++ b/docs/help/contents/custom-themes/publish-a-theme.md @@ -1,56 +1,74 @@ +--- +title: Publish a new theme +pageTitle: How do I publish a Notesnook theme? +description: Submit your Notesnook theme to the official themes repository through a GitHub pull request, and push updates to it afterwards. +keywords: + - publish notesnook theme + - notesnook themes repository + - share notesnook theme +schema: howto +--- + # Publish a new theme -## Prerequisites +## What you need 1. A [GitHub](https://github.com/) account 2. JSON file containing your theme (you can export the JSON file [using the Theme Builder](/custom-themes/create-a-theme-with-theme-builder)) -## Instructions +## Publish your theme 1. Go to [https://github.com/streetwriters/notesnook-themes](https://github.com/streetwriters/notesnook-themes) and "Fork" the repo. (Don't forget to "Star" it as well!)\ - ![Toolbar](/publish-theme-1.png) -2. Click on the "Create fork" button on the next page.\ - ![Toolbar](/publish-theme-2.png) + ![The Fork button on the notesnook-themes repository on GitHub](/publish-theme-1.png) +2. Click the "Create fork" button on the next page.\ + ![The Create fork page on GitHub](/publish-theme-2.png) 3. Once your fork has been created, go to the `themes/` directory and create a new file.\ - ![Toolbar](/publish-theme-3.png) + ![The themes directory in the forked repository, with the Add file button](/publish-theme-3.png) 4. Enter the path for your file as `{your-theme-id}/v1/theme.json`. (Pressing `/` will create a new directory.)\ - ![Toolbar](/publish-theme-4.png) -5. Paste the contents of the JSON theme file and click on "Commit changes". - ![Toolbar](/publish-theme-5.png) + ![Typing the theme file path so GitHub creates the nested directories](/publish-theme-4.png) +5. Paste the contents of the JSON theme file and click "Commit changes". + ![The theme JSON pasted into the new file, with the Commit changes button](/publish-theme-5.png) 6. Enter title of your commit as "add {your-theme-id} theme" -7. Click on "Commit changes" - ![Toolbar](/publish-theme-6.png) -8. On the next page, click on "Contribute" and then click on "Open pull request" from the popup. - ![Toolbar](/publish-theme-7.png) -9. Click on "Create pull request" - ![Toolbar](/publish-theme-8.png) -10. Click on "Create pull request" - ![Toolbar](/publish-theme-9.png) +7. Click "Commit changes" + ![The commit message dialog with the add theme message filled in](/publish-theme-6.png) +8. On the next page, click "Contribute" and then click "Open pull request" from the popup. + ![The Contribute menu on the fork, with Open pull request](/publish-theme-7.png) +9. Click "Create pull request" + ![The Create pull request button on the comparison page](/publish-theme-8.png) +10. Click "Create pull request" + ![The pull request form, ready to submit](/publish-theme-9.png) 11. And you are all done! - ![Toolbar](/publish-theme-10.png) + ![The submitted pull request for the new theme](/publish-theme-10.png) -# Updating your theme +## Update a published theme -Once your theme is published, you will probably need to push a new update for your theme to fix a color or change something. You can do this by [selecting your theme as the starter theme](/custom-themes/create-a-theme-with-theme-builder#1-select-a-starter-theme) in the Theme Builder and making the changes. Once everything is ready, just [export the changed theme](/custom-themes/create-a-theme-with-theme-builder#5-exporting-your-theme) as usual. +Once your theme is published, you will probably need to push a new update for your theme to fix a color or change something. You can do this by [selecting your theme as the starter theme](/custom-themes/create-a-theme-with-theme-builder#1-select-a-starter-theme) in the Theme Builder and making the changes. Once everything is ready, [export the changed theme](/custom-themes/create-a-theme-with-theme-builder#5-exporting-your-theme) as usual. -> warn -> -> Don't forget to increment the version of your theme; otherwise, no one will be able to see the changes. +::: warning +Don't forget to increment the version of your theme; otherwise, no one will be able to see the changes. + +::: To publish the updated theme, you will need to submit a new pull request in the same way as you did while publishing: -1. Go to your fork on GitHub. (Mine is at [https://github.com/ammarahm-ed/notesnook-themes](https://github.com/ammarahm-ed/notesnook-themes)). -2. Click on "Sync fork" and then click the "Update branch" button. - ![Toolbar](/update-theme-1.png) +1. Go to your fork on GitHub. +2. Click "Sync fork" and then click the "Update branch" button. + ![The Sync fork button on the forked repository](/update-theme-1.png) 3. Go to `themes/your-theme-id/v1` directory and open the `theme.json` file. -4. Click on the Edit button\ - ![Toolbar](/update-theme-2.png) -5. Paste your updated theme and click on "Commit changes". -6. Enter title of your commit as `update {your-theme-id} theme` and click on "Commit changes". - ![Toolbar](/update-theme-3.png) -7. Now go to the homepage of your fork and click on "Contribute" and then click on "Open pull request" in the popup. - ![Toolbar](/update-theme-4.png) -8. Click on "Create pull request" - ![Toolbar](/update-theme-5.png) +4. Click the Edit button\ + ![The Edit button on an existing theme.json file](/update-theme-2.png) +5. Paste your updated theme and click "Commit changes". +6. Enter title of your commit as `update {your-theme-id} theme` and click "Commit changes". + ![The commit message dialog with the update theme message filled in](/update-theme-3.png) +7. Now go to the homepage of your fork and click "Contribute" and then click "Open pull request" in the popup. + ![The Contribute menu on the fork, with Open pull request](/update-theme-4.png) +8. Click "Create pull request" + ![The Create pull request button for the theme update](/update-theme-5.png) 9. You are all done! - ![Toolbar](/update-theme-6.png) + ![The submitted pull request for the theme update](/update-theme-6.png) + +## Related pages + +- [Theme Builder](/custom-themes/create-a-theme-with-theme-builder) — building a theme visually +- [How themes work](/custom-themes/introduction) — scopes, variants and colors +- [Using themes](/custom-themes/using-themes) — light, dark and the theme store diff --git a/docs/help/contents/custom-themes/using-themes.md b/docs/help/contents/custom-themes/using-themes.md new file mode 100644 index 000000000..d8fadab94 --- /dev/null +++ b/docs/help/contents/custom-themes/using-themes.md @@ -0,0 +1,95 @@ +--- +title: Using themes +pageTitle: How do I change the theme in Notesnook? +description: Switch between light and dark mode, install a theme from the Notesnook theme store, set separate light and dark themes, or load a theme from a file. +keywords: + - notesnook dark mode + - notesnook themes + - change notesnook theme + - notesnook theme store +schema: howto +--- + +# How do I change the theme in Notesnook? + +Notesnook keeps two themes at once — one for light mode and one for dark mode — and switches between them based on your color scheme. You can pick both from the built-in theme store, or load a theme from a `theme.json` file. + +## Switch between light and dark + +:::tabs key:platform +== Desktop/Web + +1. Go to `{{settings}}`. +2. Open `{{customization}}` → `{{appearance}}`. +3. Under `{{themes}}`, set `{{colorScheme}}` to `{{light}}`, `{{dark}}` or `{{auto}}`. + +`{{auto}}` follows your operating system, so Notesnook flips with it. + +== Mobile + +1. Go to `{{settings}}`. +2. Open `{{customization}}` → `{{appearance}}`. +3. Turn on `{{useSystemTheme}}` to follow your phone's light/dark setting, or turn it off and use the `{{darkMode}}` switch to choose yourself. + +::: + +::: tip Faster switching on desktop +The side menu profile menu has a `{{toggleDarkLightMode}}` item, so you don't have to open settings. + +::: + +## Install a theme from the theme store + +Every theme in the store is fetched from `themes-api.notesnook.com` and installed on your device. The list only shows themes that are compatible with the version of Notesnook you're running. + +:::tabs key:platform +== Desktop/Web + +1. Go to `{{settings}}` → `{{customization}}` → `{{appearance}}`. +2. Scroll to `{{selectTheme}}`. +3. Type in the `{{searchThemes}}` box to search, or use the `{{all}}`, `{{dark}}` and `{{light}}` filters to narrow the list. +4. Click a theme to see its details, then confirm — or hover it and click `{{setAsDarkTheme}}` / `{{setAsLightTheme}}` directly. + +A checkmark marks the themes you currently have applied. + +== Mobile + +1. Go to `{{settings}}` → `{{customization}}` → `{{appearance}}`. +2. Tap `{{themes}}`. +3. Use the search box or the `{{all}}`, `{{dark}}` and `{{light}}` filters. +4. Tap a theme to open its details, then tap `{{setAsDarkTheme}}` or `{{setAsLightTheme}}`. + +An applied theme reads `{{appliedDark}}` or `{{appliedLight}}` on its details screen. + +::: + +<!-- TODO: screenshot — the theme store with the All/Dark/Light filters and a theme card --> + +## Set separate light and dark themes + +There is no separate "which theme goes where" setting — a theme's own color scheme decides it. Applying a dark theme replaces your dark theme; applying a light theme replaces your light theme. Your `{{colorScheme}}` setting then decides which of the two you see. + +So to have both: install a light theme, install a dark theme, and set `{{colorScheme}}` to `{{auto}}` (or `{{useSystemTheme}}` on mobile). + +## Load a theme from a file + +If you have a `theme.json` file — one you built with the [Theme Builder](/custom-themes/create-a-theme-with-theme-builder), or one that isn't published yet — you can apply it directly. + +1. Open the theme list as above. +2. Click or tap `{{loadFromFile}}`. +3. Pick the `.json` file. Notesnook validates it and shows the theme's details. +4. Confirm to apply it. + +If the file is missing required fields or isn't a valid theme, the app tells you instead of applying it. Full steps and caveats are on [install a theme from file](/custom-themes/install-a-theme-from-file). + +## Where do the themes come from? + +The theme store is an open collection. Themes are submitted as JSON files to the [notesnook-themes](https://github.com/streetwriters/notesnook-themes) repository, and once merged they appear in the store for everyone. If you have made a theme you like, you can [publish it](/custom-themes/publish-a-theme) the same way. + +## Related pages + +- [Publish a theme](/custom-themes/publish-a-theme) — get your theme into the store +- [Create a theme with the Theme Builder](/custom-themes/create-a-theme-with-theme-builder) — build one without writing JSON +- [Install a theme from file](/custom-themes/install-a-theme-from-file) — apply a `theme.json` directly +- [Theme engine introduction](/custom-themes/introduction) — how scopes, variants and colors fit together +- [Customizing the app](/customizing-notesnook) — home screen, side menu and list density diff --git a/docs/help/contents/customizing-notesnook.md b/docs/help/contents/customizing-notesnook.md new file mode 100644 index 000000000..9e840d42c --- /dev/null +++ b/docs/help/contents/customizing-notesnook.md @@ -0,0 +1,167 @@ +--- +title: Customizing the app +pageTitle: How do I customize the Notesnook app? +description: Choose which screen Notesnook opens on, reorder or hide side menu items, switch to compact lists, and change how dates, times and sorting work. +keywords: + - notesnook custom home screen + - notesnook default sidebar tab + - notesnook hide side menu items + - notesnook compact list view + - notesnook date format +schema: howto +--- + +# How do I customize the Notesnook app? + +Notesnook lets you decide what it opens on, what your side menu contains and in what order, how dense your note lists are, and how dates and times are written. Everything on this page is per-device — none of it changes the notes themselves. + +## Set your home screen <PlanTag plan="pro" /> + +The home screen is the screen Notesnook opens on when you launch it. By default that is your notes list, but you can point it at any side menu item, or at a specific notebook, tag or color. + +:::tabs key:platform +== Desktop/Web + +1. Right click the item you want as your home screen — a side menu item such as `Notes` or `Favorites`, a color, a shortcut, or a notebook or tag in the list. +2. Click `{{setAsHomepage}}`. +3. A checkmark appears next to `{{setAsHomepage}}`. Click it again to go back to the default home screen. + +== Mobile + +1. Long press the item you want as your home screen. +2. For a side menu item, tap `{{setAsHomepage}}` in the sheet that opens. For a notebook, tag or color, tap `{{setAsHomepage}}` in its properties sheet. +3. For a notebook, tag or color you can undo it by opening the same menu and tapping `{{unsetAsHomepage}}`. For a side menu item there is no reset — set a different item as your home screen instead. + +::: + +Next time you open Notesnook it lands on the screen you picked. + +::: info What happens if your plan expires +A custom home screen is a Pro feature. If your subscription ends, Notesnook resets the home screen to the default. See [plans & limits](/plans-and-limits). + +::: + +## Choose the default sidebar tab <PlanTag plan="pro" /> + +The sidebar has three tabs — notes, notebooks and tags. This setting decides which one is selected when the app starts. + +:::tabs key:platform +== Desktop/Web + +1. Go to `{{settings}}`. +2. Open `{{customization}}` → `{{behaviour}}`. +3. Under `{{general}}`, set `{{defaultSidebarTab}}` to `Notes`, `{{notebooks}}` or `Tags`. + +== Mobile + +1. Go to `{{settings}}`. +2. Open `{{customization}}` → `{{behavior}}`. +3. Tap `{{defaultSidebarTab}}` and pick `Home`, `{{notebooks}}` or `Tags`. + +::: + +## Reorder and hide side menu items <PlanTag plan="essential" /> + +You can drag the items in your side menu into the order you want, and hide the ones you never use. This covers the built-in items (`Notes`, `Favorites`, `{{reminders}}`, `{{monographs}}`, `{{trash}}`, `{{archive}}`) and your [colors](/organizing-notes/organize-notes-using-colors). `{{notebooks}}` and `Tags` are sidebar tabs rather than menu items, so they cannot be reordered or hidden. Hiding an item only removes it from the menu; nothing inside it is deleted. + +:::tabs key:platform +== Desktop/Web + +1. Drag a side menu item up or down to move it. +2. To hide items, right click any side menu item — the menu lists every item and color with a checkmark next to the visible ones. +3. Click an item to uncheck it and hide it. Click it again to bring it back. +4. To undo everything, right click a side menu item and click `{{resetSidebar}}`. + +== Mobile + +1. Long press a side menu item and tap `{{reorder}}`. +2. Drag items into the order you want. +3. Tap the **−** button beside an item to hide it, or the **+** button to show it again. Hidden items stay visible while you're reordering, dimmed. +4. Tap `{{done}}` at the bottom of the side menu to leave reorder mode. + +::: + +<!-- TODO: screenshot — the side menu right click menu on desktop showing checked/unchecked items and Reset sidebar --> + +::: info Shortcuts are separate +Pinning notebooks and tags to the side menu is a different feature — see [side menu shortcuts](/organizing-notes/side-menu-shortcuts). Free plans can keep 10 shortcuts; Essential and above are unlimited. + +::: + +## Switch between detailed and compact lists + +Compact mode strips a list down to one line per item, so more fits on screen. It is remembered per list type: on desktop and web there is one setting for notes (shared by the notes, favorites and search lists) and one for notebooks; on mobile, notes, notebooks and search results each have their own. + +:::tabs key:platform +== Desktop/Web + +1. Find the list view icon at the top right of the list, next to the sort icon. +2. Click it. The tooltip reads `Switch to compact view`, and `Switch to detailed view` once compact mode is on. + +== Mobile + +1. Tap the list view icon at the top right of the list, next to the sort icon. +2. Tap it again to go back to the detailed list. + +::: + +## Change how notes are sorted and grouped + +Sorting and grouping are stored per list, and separately for each notebook, tag and color you open — so your notebooks can be alphabetical while your notes stay newest-first. + +:::tabs key:platform +== Desktop/Web + +1. Click the sort icon at the top right of the list. The menu is titled `Group & sort`, or `{{sort}}` where grouping doesn't apply. +2. Use `{{orderBy}}` to flip the direction — `{{oldestToNewest}}` / `{{newestToOldest}}`, or `{{aToZ}}` / `{{zToA}}` when sorting by title. +3. Use `{{sortBy}}` to choose `Date created`, `Date edited`, `Date modified`, `Date deleted`, `Due date`, `{{title}}` or `Relevance`, depending on the list. +4. Use `{{groupBy}}` to choose `{{none}}`, `{{default}}`, `Year`, `{{month}}`, `Week` or `Abc`. + +== Mobile + +1. Tap the sort icon at the top right of the list. +2. Tap the button beside `{{sortBy}}` to flip the direction between ascending and descending. +3. Pick a field under `{{sortBy}}`, and a grouping under `{{groupBy}}`. + +::: + +Reminders and search results can be sorted but not grouped. + +## Change the date, time, day and week formats + +These settings control how every date in the app is written — in note lists, reminders and note properties. + +:::tabs key:platform +== Desktop/Web + +1. Go to `{{settings}}`. +2. Open `{{customization}}` → `{{behaviour}}`. +3. Under `{{dateAndTime}}`, set: + - `{{dateFormat}}` — day/month/year, month/day/year or year/month/day, each with `-`, `/` or `.` as the separator, plus `MMM D, YYYY`. Every option previews today's date beside it. + - `{{timeFormat}}` — `12h` or `24h`. + - `{{dayFormat}}` — `Short (Mon, Tue)` or `Long (Monday, Tuesday)`. + - `{{weekFormat}}` — whether the week starts on `Sunday` or `Monday`. + +== Mobile + +1. Go to `{{settings}}`. +2. Open `{{customization}}` → `{{behavior}}`. +3. Tap `{{dateFormat}}`, `{{timeFormat}}`, `{{dayFormat}}` or `{{weekFormat}}` and pick an option. + +::: + +## Mobile-only settings + +Three behaviour settings exist only in the mobile apps, under `{{settings}}` → `{{customization}}` → `{{behavior}}`: + +- `{{keepScreenOn}}` — stops the screen from dimming while you're in the app. +- `{{autoUpdateCheck}}` — turn off the update check on app start. +- `{{clearDefaultNotebook}}` — clears the notebook new notes are filed into by default. + +## Related pages + +- [Plans & limits](/plans-and-limits) — which customizations need Essential or Pro +- [Side menu shortcuts](/organizing-notes/side-menu-shortcuts) — pin notebooks and tags to the side menu +- [Using themes](/custom-themes/using-themes) — light, dark and themes from the theme store +- [Personalizing the editor](/rich-text-editor/personalizing-rich-text-editor) — font, size and line spacing while you write +- [Organize notes using colors](/organizing-notes/organize-notes-using-colors) — the colors that appear in your side menu diff --git a/docs/help/contents/deleting-your-account.md b/docs/help/contents/deleting-your-account.md index 37dd48017..2c86a3089 100644 --- a/docs/help/contents/deleting-your-account.md +++ b/docs/help/contents/deleting-your-account.md @@ -1,28 +1,46 @@ --- title: Deleting your account -description: No questions asked! You can delete your account anytime from mobile and desktop apps with a single click and delete all your data +pageTitle: How do I delete my Notesnook account? +description: Delete your Notesnook account and all its data from the app in a few taps. What gets removed, and why none of it can be recovered afterwards. +keywords: + - delete notesnook account + - remove notes app account + - notesnook data deletion +schema: faq +faqs: + - q: What information is deleted when I delete my Notesnook account? + a: "Everything: all your notes, notebooks, attachments and other data, your login credentials, your subscription and billing information, and the account itself. Your email address is no longer associated with Notesnook and cannot be used to log in." + - q: Can I recover my data after deleting my Notesnook account? + a: No. Deletion is immediate and permanent, and because your data is end-to-end encrypted there is no copy anyone can restore from. Take a backup or export your notes before you delete the account. --- # Deleting your account Notesnook allows you to delete your accounts and your data without any questions asked or keeping you waiting on email. -## [Web/Desktop](#/tab/web) +::: danger This cannot be undone +Deleting your account immediately and permanently erases all your notes, notebooks, attachments and other data. Because of end-to-end encryption, Notesnook cannot recover this data for you afterwards. Take a [backup](/backup-and-restore-notes-in-notesnook) or [export your notes](/export-notes-from-notesnook) first if you might need this data again. + +::: + +:::tabs key:platform +== Desktop/Web 1. Open Notesnook web or desktop app 2. Make sure you are logged in -3. Go to Settings -4. Click on `Delete account` button next to **Account removal** heading +3. Go to `{{settings}}`. +4. Go to `{{account}}` +5. Click `{{deleteAccount}}` -## [Mobile](#/tab/mobile) +== Mobile 1. Open the Notesnook app 2. Make sure you are logged in -3. Go to Settings -4. Go to `Account Settings` -5. Tap on `Delete account` +3. Go to `{{settings}}`. +4. Go to `{{account}}` then `{{manageAccount}}` +5. Tap `{{deleteAccount}}` ---- +::: ## FAQs @@ -40,3 +58,10 @@ After deletion, your email address will no longer be associated with Notesnook a ### Is there any way to recover deleted data? No. Once you delete your account, it's gone for good and there is no way for us or anyone else to recover it. If your data is important to you, make sure to take a [backup](/backup-and-restore-notes-in-notesnook) or [export your notes](/export-notes-from-notesnook) before deleting your account. + +## Related pages + +- [Backup and restore](/backup-and-restore-notes-in-notesnook) — keeping your own encrypted copy +- [Exporting notes](/export-notes-from-notesnook) — taking your notes to another app +- [Account settings](/account-settings) — email, password and profile +- [Plans & limits](/plans-and-limits) — what each plan unlocks and the exact limits diff --git a/docs/help/contents/desktop-integration/README.md b/docs/help/contents/desktop-integration/README.md deleted file mode 100644 index 7e52eba2e..000000000 --- a/docs/help/contents/desktop-integration/README.md +++ /dev/null @@ -1 +0,0 @@ -# Desktop integration diff --git a/docs/help/contents/desktop-integration/auto-start-on-system-startup.md b/docs/help/contents/desktop-integration/auto-start-on-system-startup.md index 0ffac552a..0259767a5 100644 --- a/docs/help/contents/desktop-integration/auto-start-on-system-startup.md +++ b/docs/help/contents/desktop-integration/auto-start-on-system-startup.md @@ -1,19 +1,37 @@ +--- +title: Auto start +pageTitle: Start Notesnook automatically when your computer boots +description: Configure the Notesnook desktop app to launch at system startup, and to start minimized so it stays out of your way. +keywords: + - notesnook auto start + - launch notes app on startup + - notesnook start minimized +schema: howto +--- + # Auto start on system startup If your workflow requires Notesnook to be always opened, it's a good idea to enable auto start on system startup: -1. Go to `Settings` -2. Click on `Desktop integration` -3. Click on `Auto start on system startup` to enable/disable it. +1. Go to `{{settings}}` +2. Click `{{desktopIntegration}}` +3. Click `{{autoStartOnSystemStartup}}` to enable/disable it. ## Start minimized -> info -> -> This only works when `Auto start on system startup` is enabled. +::: info +This only works when `{{autoStartOnSystemStartup}}` is enabled. + +::: Notesnook can also start minimized when it's opened on system startup: -1. Go to `Settings` -2. Click on `Desktop integration` -3. Click on `Start minimized` to enable/disable it. +1. Go to `{{settings}}` +2. Click `{{desktopIntegration}}` +3. Click `{{startMinimized}}` to enable/disable it. + +## Related pages + +- [System tray menu](/desktop-integration/system-tray-menu) — keeping Notesnook out of the way +- [Jumplist & dock menu](/desktop-integration/jumplist-and-dock-menu) — new note from the taskbar +- [Updates & advanced](/desktop-integration/updates-and-advanced-settings) — release track, DNS and zoom diff --git a/docs/help/contents/desktop-integration/jumplist-and-dock-menu.md b/docs/help/contents/desktop-integration/jumplist-and-dock-menu.md index c90e3c9bf..40e36d2ea 100644 --- a/docs/help/contents/desktop-integration/jumplist-and-dock-menu.md +++ b/docs/help/contents/desktop-integration/jumplist-and-dock-menu.md @@ -1,25 +1,37 @@ +--- +title: Jumplist & dock menu +pageTitle: The Notesnook jumplist and macOS dock menu +description: Start a new note or notebook straight from the Notesnook jumplist on Windows and Linux, or from the dock menu on macOS. +keywords: + - notesnook jumplist + - notesnook dock menu + - taskbar quick actions +--- + # Jumplist & dock menu Notesnook supports quick actions from the "jumplist" menu (dock menu on macOS): -## [Windows](#/tab/windows) +:::tabs key:platform +== Windows +![The Notesnook jumplist on the Windows taskbar](/static/desktop-integration/jumplist-menu-windows.png) +== Linux +![The Notesnook jumplist on Linux](/static/desktop-integration/jumplist-menu-linux.png) +== macOS +![The Notesnook dock menu on macOS](/static/desktop-integration/dock-menu-macos.png) -![](/static/desktop-integration/jumplist-menu-windows.png) - -## [Linux](#/tab/linux) - -![](/static/desktop-integration/jumplist-menu-linux.png) - -## [macOS](#/tab/macos) - -![](/static/desktop-integration/dock-menu-macos.png) - ---- +::: ## How does it work? Jumplist menu items are responsible for opening Notesnook at the specified page. For example: -1. Right click on the Notesnook icon in your taskbar/dock -2. Click on "New notebook" +1. Right click the Notesnook icon in your taskbar/dock +2. Click "New notebook" 3. Notice how the new notebook dialog is opened after the Notesnook app is focused + +## Related pages + +- [Auto start](/desktop-integration/auto-start-on-system-startup) — launching with your computer +- [System tray menu](/desktop-integration/system-tray-menu) — keeping Notesnook out of the way +- [Keyboard shortcuts](/keyboard-shortcuts) — every shortcut in one place diff --git a/docs/help/contents/desktop-integration/spell-checker.md b/docs/help/contents/desktop-integration/spell-checker.md index 265ca2e57..33c40b831 100644 --- a/docs/help/contents/desktop-integration/spell-checker.md +++ b/docs/help/contents/desktop-integration/spell-checker.md @@ -1,40 +1,60 @@ +--- +title: Spell checker +pageTitle: Turn on the spell checker in Notesnook desktop +description: Enable the built-in spell checker in the Notesnook desktop app and choose which languages it checks against, including multiple at once. +keywords: + - notesnook spell check + - notes app spell checker + - spell check languages +schema: howto +--- + # Spell checker -> error Desktop app only -> -> Configuring the spell checker is only available in the desktop app. +::: info Desktop app only +Configuring the spell checker is only available in the desktop app. + +::: ## Toggling the spell checker You can enable/disable the spell checker at any time from Settings: -1. Go to `Settings` -2. Click on `Editor Settings` -3. Click on the `Enable spellchecker` toggle to enable/disable the spell checker +1. Go to `{{settings}}` +2. Click `{{editor}}` +3. Click the `{{enableSpellChecker}}` toggle to enable/disable the spell checker ## Choosing languages -> info For macOS users -> -> On macOS it is not possible to choose custom languages. Instead the spell checker uses your system settings. +::: info For macOS users +On macOS it is not possible to choose custom languages. Instead the spell checker uses your system settings. -> warn Network activity notice -> -> Notesnook supports spell checking text in multiple languages at the same time. However, it doesn't ship all the supported languages but gives you the choice to enable the languages you want. -> -> Selecting a new language will **download the dictionary from `dictionaries.notesnook.com`**. +::: + +::: warning Network activity notice +Notesnook supports spell checking text in multiple languages at the same time. However, it doesn't ship all the supported languages but gives you the choice to enable the languages you want. + +Selecting a new language will **download the dictionary from `dictionaries.notesnook.com`**. + +::: To select new languages: -1. Go to `Settings` -2. Click on `Editor Settings` -3. Click on `Spellchecker languages` - ![Spell checker languages dialog](/static/spell-checker-languages.png) +1. Go to `{{settings}}` +2. Click `{{editor}}` +3. Click `{{languages}}` + ![The spell checker language picker in Notesnook desktop settings](/static/spell-checker-languages.png) 4. Select the languages you need -5. Click on `Done` and spell checking should now be working for the languages you selected. +5. Click `{{done}}` and spell checking should now be working for the languages you selected. ### My language is not included in the list While we'd love to include all the languages, we are dependent on Electron (which, in turn, depends on Chromium) for adding the required dictionaries. It might be possible in the future to implement a custom spell checker to support all the languages. + +## Related pages + +- [Personalizing the editor](/rich-text-editor/personalizing-rich-text-editor) — fonts, spacing and title formats +- [Updates & advanced](/desktop-integration/updates-and-advanced-settings) — release track, DNS and zoom +- [Customizing the app](/customizing-notesnook) — home screen, sidebar, sorting and formats diff --git a/docs/help/contents/desktop-integration/system-tray-menu.md b/docs/help/contents/desktop-integration/system-tray-menu.md index 9fc0f6541..ffd934979 100644 --- a/docs/help/contents/desktop-integration/system-tray-menu.md +++ b/docs/help/contents/desktop-integration/system-tray-menu.md @@ -1,3 +1,14 @@ +--- +title: System tray menu +pageTitle: The Notesnook system tray menu +description: Use the Notesnook system tray icon for quick actions, and set the app to minimize or close to the tray instead of the taskbar. +keywords: + - notesnook system tray + - minimize to tray + - close to tray notes app +schema: howto +--- + # System tray menu Notesnook features a system tray menu to give quick access to some common functions such as: @@ -8,20 +19,26 @@ Notesnook features a system tray menu to give quick access to some common functi See it in action here: -![The system tray menu](/static/desktop-integration/system-tray-menu.png) +![The Notesnook system tray menu, with New note and New notebook](/static/desktop-integration/system-tray-menu.png) ## Minimize to tray Instead of always taking space in your taskbar, you can hide Notesnook in your system tray on minimizing: -1. Go to `Settings` -2. Click on `Desktop integration` -3. Click on `Minimize to system tray` to enable/disable it. +1. Go to `{{settings}}` +2. Click `{{desktopIntegration}}` +3. Click `{{minimizeToSystemTray}}` to enable/disable it. ## Close to tray To prevent accidentally closing the Notesnook app, it is possible to always close it to the system tray: -1. Go to `Settings` -2. Click on `Desktop integration` -3. Click on `Close to system tray` to enable/disable it. +1. Go to `{{settings}}` +2. Click `{{desktopIntegration}}` +3. Click `{{closeToSystemTray}}` to enable/disable it. + +## Related pages + +- [Auto start](/desktop-integration/auto-start-on-system-startup) — launching with your computer +- [Jumplist & dock menu](/desktop-integration/jumplist-and-dock-menu) — new note from the taskbar +- [Updates & advanced](/desktop-integration/updates-and-advanced-settings) — release track, DNS and zoom diff --git a/docs/help/contents/desktop-integration/updates-and-advanced-settings.md b/docs/help/contents/desktop-integration/updates-and-advanced-settings.md new file mode 100644 index 000000000..2abddbc82 --- /dev/null +++ b/docs/help/contents/desktop-integration/updates-and-advanced-settings.md @@ -0,0 +1,113 @@ +--- +title: Updates & advanced +pageTitle: Notesnook desktop updates, release track and network settings +description: Control how the Notesnook desktop app updates, switch between the Stable and Beta release tracks, and change the titlebar, zoom, DNS, proxy and CORS proxy. +keywords: + - notesnook desktop update + - notesnook beta release track + - notesnook native titlebar + - notesnook proxy + - notesnook custom dns +--- + +# Updates and advanced settings + +::: info Mostly, but not only, the desktop app +`{{useNativeTitlebar}}`, `{{zoomFactor}}` and `{{useCustomDns}}` are desktop-only. The update controls, `{{releaseTrack}}`, `{{proxy}}` and the CORS proxy also appear in the web app, where an "update" means swapping the service worker rather than downloading an installer. + +::: + +## Keep the app updated automatically + +When automatic updates are on, the desktop app downloads new versions in the background. Updates are never installed silently on quit — you always trigger the install yourself, which avoids a half-written install directory if your machine shuts down mid-update. + +1. Go to `{{settings}}`. +2. Open `{{customization}}` → `{{behaviour}}`. +3. Under `{{desktopApp}}`, toggle `{{automaticUpdates}}`. + +## Check for updates manually + +1. Go to `{{settings}}`. +2. Open `{{other}}` → `{{about}}`. +3. The `{{version}}` row shows the version you're running. Click `{{checkForUpdates}}`. +4. If a new version is found the description changes to `New version (vX.X.X) is available for download.` and the button becomes `{{installUpdate}}`. Clicking it downloads the update; once the download finishes, the update button in the status bar installs it and restarts the app. + +::: info Flatpak, Snap and portable builds +These builds are updated by the system that installed them, so the `{{automaticUpdates}}` toggle, `{{checkForUpdates}}` and `{{installUpdate}}` buttons don't appear. Only `{{copy}}` (for the version number) is shown. + +::: + +## Switch between the Stable and Beta release track + +The release track decides which builds you receive. `{{beta}}` gets features earlier, with the usual caveat that they are less tested. + +1. Go to `{{settings}}`. +2. Open `{{other}}` → `{{about}}`. +3. Set `{{releaseTrack}}` to `{{stable}}` or `{{beta}}`. + +Switching from `{{beta}}` back to `{{stable}}` is allowed to downgrade you, but only if the build you are running is itself a prerelease. This setting is also hidden on Flatpak, Snap and portable builds. + +::: warning Beta builds are still beta +Keep [current backups](/backup-and-restore-notes-in-notesnook) before moving to the beta track. + +::: + +## Use your system's native titlebar + +By default Notesnook draws its own titlebar. You can switch to the one your operating system draws instead. + +1. Go to `{{settings}}`. +2. Open `{{customization}}` → `{{desktopIntegration}}`. +3. Toggle `{{useNativeTitlebar}}`. +4. A toast appears reading `{{restartAppToTakeEffect}}` — click `{{restartNow}}`, or restart later yourself. + +## Change the zoom factor + +Zoom scales the whole app, not only the editor text. + +1. Go to `{{settings}}`. +2. Open `{{customization}}` → `{{appearance}}`. +3. Under `{{general}}`, set `{{zoomFactor}}`. It accepts `0.5` to `3.0` in steps of `0.1`. + +## Use custom DNS + +Notesnook can resolve its own hostnames over DNS-over-HTTPS instead of using your system resolver. This sometimes gets around ISP-level blocking of Notesnook traffic. + +1. Go to `{{settings}}`. +2. Open `{{privacyAndSecurity}}` → `{{privacy}}`. +3. Under `{{advanced}}`, toggle `{{useCustomDns}}`. + +When it is on, the app resolves through **Cloudflare DNS** (`mozilla.cloudflare-dns.com`) and **Quad9** (`dns.quad9.net`). Turn it off to go back to your system's DNS settings. + +## Route the app through a proxy + +1. Go to `{{settings}}`. +2. Open `{{privacyAndSecurity}}` → `{{privacy}}`. +3. Under `{{advanced}}`, type your rules into `{{proxy}}`. + +HTTP, HTTPS and SOCKS proxies are supported, for example: + +``` +http://foobar:80 +socks4://proxy.example.com +http://username:password@foobar:80 +``` + +## Change the CORS proxy + +Remote content the editor has to fetch — images pasted by URL and YouTube embeds — is routed through a proxy so the browser's cross-origin rules don't block it. The default is `https://cors.notesnook.com`. You can point it at your own if you'd rather not use ours. + +1. Go to `{{settings}}`. +2. Open `{{privacyAndSecurity}}` → `{{privacy}}`. +3. Under `{{advanced}}`, next to `{{corsBypass}}`, click `{{changeProxy}}`. +4. Enter the URL and confirm. Only the scheme and hostname are kept; an unparseable URL is rejected with `{{invalidCors}}`. + +This setting exists in the web app too. + +## Related pages + +- [Auto start on system startup](/desktop-integration/auto-start-on-system-startup) — launch Notesnook when you log in +- [System tray menu](/desktop-integration/system-tray-menu) — quick actions and minimize-to-tray +- [Spell checker](/desktop-integration/spell-checker) — enable it and pick languages +- [Privacy mode](/privacy-mode) — hide the app window from screen capture +- [Backup and restore](/backup-and-restore-notes-in-notesnook) — before you switch release tracks diff --git a/docs/help/contents/docs.md b/docs/help/contents/docs.md new file mode 100644 index 000000000..38dbe249c --- /dev/null +++ b/docs/help/contents/docs.md @@ -0,0 +1,16 @@ +--- +title: All help topics +pageTitle: All Notesnook help topics +description: Every page in the Notesnook help site, grouped by task — getting started, organizing notes, the editor, importing, sync, privacy, plans and more. +aside: false +keywords: + - notesnook help + - notesnook documentation + - notesnook user guide +--- + +# All help topics + +Everything the Notesnook documentation covers. Use the search box (`Ctrl` `K`) if you already know what you're after. + +<DocsIndex /> diff --git a/docs/help/contents/export-notes-from-notesnook.md b/docs/help/contents/export-notes-from-notesnook.md index 6803cffe9..2035b39b3 100644 --- a/docs/help/contents/export-notes-from-notesnook.md +++ b/docs/help/contents/export-notes-from-notesnook.md @@ -1,69 +1,97 @@ --- title: Exporting notes -description: Notesnook is zero lock-in. You can always export and backup your notes to pdf, html, markdown and plain text files anytime from iOS, Android & Desktop. +pageTitle: Export notes from Notesnook as PDF, Markdown or HTML +description: Export one note or your whole Notesnook library as PDF, Markdown, HTML or plain text — on Windows, macOS, Linux, Android and iOS. +keywords: + - export notes to markdown + - export notes as pdf + - notes app no lock in +schema: howto --- # Exporting notes -You can export some or all your notes as PDF, HTML, Markdown and Plain text files on all Notesnook apps. +You can export some or all your notes as **PDF**, **HTML**, **Markdown**, **Markdown + Frontmatter** and **Plain text** files on all Notesnook apps. Notesnook is zero lock-in — your notes leave in open formats that any other app can read. + +::: info PDF is for one note at a time on desktop and web +On desktop and web, PDF is only offered when you export a **single note** — multi-select exports and "export all notes" produce a `.zip` in Markdown, Markdown + Frontmatter, HTML or plain text. To get a PDF of several notes there, export them one at a time, or print the note from the desktop app. On mobile, PDF is available for multi-select and "export all notes" as well. + +::: ## Exporting a single note -# [Desktop/Web](#/tab/web) +:::tabs key:platform +== Desktop/Web -1. Right click on a note -2. Click on `Export as` +1. Right click a note +2. Click `{{exportAs}}` 3. Select the desired format 4. Wait a few moments while your note is exported 5. Save the note at your desired location -# [Mobile](#/tab/mobile) +== Mobile 1. Tap the ![Three dot button](/three-dot-button.png) button on a note -2. Tap on `Export` +2. Tap `{{export}}` 3. Select the desired format 4. Wait a few moments while your note is exported 5. Exported notes are stored in `Notesnook/exported` folder. ---- +::: ## Exporting multiple notes -# [Desktop/Web](#/tab/web) +:::tabs key:platform +== Desktop/Web 1. Hold `Ctrl` & click on all the notes you want to export -2. Right click & click on `Export as` +2. Right click & click `{{exportAs}}` 3. Select your desired export format 4. Wait a few moments while your notes are exported 5. Save the `.zip` file at your desired location -# [Mobile](#/tab/mobile) +== Mobile -1. Long press on a note to enter multi selection mode -2. Tap on all the notes you want to export -3. Press on the Export button on top right corner +1. Long press a note to enter multi selection mode +2. Tap all the notes you want to export +3. Tap the Export button on top right corner 4. Select the desired format 5. Exported notes are stored in `Notesnook/exported` folder ---- +::: ## Exporting all your notes -# [Desktop/Web](#/tab/web) +:::tabs key:platform +== Desktop/Web -1. Go to Settings -2. Scroll down to `Import & export` section -3. Click on `Backup & export` -4. Click on `Select format` dropdown next to `Export all notes` heading +1. Go to `{{settings}}`. +2. Open `{{importExport}}` +3. Click `{{backupExport}}` +4. Click `Select format` dropdown next to `{{exportAllNotes}}` heading 5. Select the desired format 6. Enter account password for authentication 7. Save the `.zip` file at your desired location -# [Mobile](#/tab/mobile) +== Mobile -1. Go to Settings from Sidebar -2. Scroll down to `Backup and Restore` -3. Tap on `Export all notes` +1. Go to `{{settings}}`. +2. Open `{{backupRestore}}` +3. Tap `{{exportAllNotes}}` 4. Select the desired format 5. Enter account password for authentication 6. Exported notes are stored in `Notesnook/exported` folder as a single .zip file + +::: + +::: info Exporting everything needs your password +"Export all notes" asks for your account password before it runs. Locked notes are included only after you unlock the [vault](/lock-notes-with-private-vault) when prompted. + +::: + +## Related pages + +- [Backup and restore](/backup-and-restore-notes-in-notesnook) — encrypted backups you can restore into Notesnook, as opposed to exports for other apps +- [Importing notes](/importing-notes/) — moving notes in from another app +- [Publishing with monographs](/publish-notes-with-monographs) — sharing a single note as a link instead of a file +- [Attachments & files](/attachments-and-files) — what happens to files attached to exported notes diff --git a/docs/help/contents/faqs/README.md b/docs/help/contents/faqs/README.md deleted file mode 100644 index 95241a8b3..000000000 --- a/docs/help/contents/faqs/README.md +++ /dev/null @@ -1 +0,0 @@ -# FAQs diff --git a/docs/help/contents/faqs/is-there-an-eta.md b/docs/help/contents/faqs/is-there-an-eta.md index 957a37851..95af5c750 100644 --- a/docs/help/contents/faqs/is-there-an-eta.md +++ b/docs/help/contents/faqs/is-there-an-eta.md @@ -1,18 +1,35 @@ --- title: Is there an ETA for X feature? -description: We do not provide any ETAs. +pageTitle: When will a feature ship in Notesnook? +description: Notesnook doesn't publish ETAs for features. Here's where to see what's planned, how to follow a feature's progress, and why dates aren't promised. +keywords: + - notesnook roadmap + - notesnook feature request + - when will notesnook add --- # Is there an ETA for X feature? -![](https://imgs.xkcd.com/comics/estimating_time.png) +No — Notesnook doesn't publish dates for unreleased features. The [roadmap](https://notesnook.com/roadmap) lists everything being worked on and everything planned, but nothing on it carries a delivery date. -We maintain an up-to-date [roadmap](https://notesnook.com/roadmap) which lists everything we are working on and everything we plan on adding in the future. There is no certainty _when_ something might land, though. It can be days, months, or even years before a feature becomes generally available. Asking us for ETAs is annoying and distracts us from what really matters. +## Where to see what's planned -## Why we don't provide ETAs +- The [roadmap](https://notesnook.com/roadmap) is the current picture of what is being built and what is queued. +- [GitHub issues](https://github.com/streetwriters/notesnook/issues) track individual features and bugs. Subscribe to an issue and you'll be notified when it moves. +- Release notes go out with each version, so a feature you're waiting on shows up there the moment it ships. -In case you are still curious, a huge part of developing any software are **deadlines**. Giving any ETA means we want to be held accountable for when a feature might land. That is something we cannot afford because another huge part of developing any software are **delays**. As any engineer might tell you, "X will land in 1 month" almost always means "X will land in 4 months". +## Why we don't give ETAs -Users do not understand or tolerate delays, and developers do not like incessant pestering on why something didn't land on X date when we said it'll land on X date. To avoid all these headaches we simply do not give out any ETAs. Obviously, internally we do have timelines for each feature but disclosing these is unnecessary. +Software estimates are unreliable, and a date given in good faith becomes a promise the moment it's published. Rather than set expectations we can't reliably meet, we'd rather ship the feature and announce it when it's real. -In short, it'll land when it'll land. No promises. +Timelines do exist internally — they move too often to be useful to anyone outside the team. + +## Can I make a feature more likely to happen? + +Yes. Open or upvote an issue on [GitHub](https://github.com/streetwriters/notesnook/issues/new/choose) and describe the problem you're trying to solve rather than the solution you have in mind. What gets built is shaped heavily by how many people need it and how well we understand why. + +## Related pages + +- [Create your first note](/create-a-note-in-notesnook) — the two-minute version +- [Plans & limits](/plans-and-limits) — what each plan unlocks and the exact limits +- [Notesnook Circle](/notesnook-circle) — partner offers for subscribers diff --git a/docs/help/contents/faqs/login-to-restore-attachments-in-backup.md b/docs/help/contents/faqs/login-to-restore-attachments-in-backup.md index 13bddecfb..a57a1d384 100644 --- a/docs/help/contents/faqs/login-to-restore-attachments-in-backup.md +++ b/docs/help/contents/faqs/login-to-restore-attachments-in-backup.md @@ -1,8 +1,39 @@ --- -title: Login to restore attachments in backup. -description: We require users to be logged in to restore attachments in backup. +title: Login to restore attachments +pageTitle: Why do I need to log in to restore attachments from a backup? +description: A backup's attachments are encrypted with a key tied to your account, so Notesnook needs you signed in to decrypt them and re-upload them after a restore. +keywords: + - notesnook restore attachments backup + - notesnook backup attachments login +schema: faq +faqs: + - q: Why do I need to log in to restore attachments from a backup? + a: Attachments are encrypted with a sub-key derived from your account's data encryption key. Restoring them means decrypting them with that key and re-uploading them to your account, and neither is possible while you are signed out. + - q: Can I restore a backup without logging in? + a: You can restore the notes, notebooks and tags in it. The attachments in the backup cannot be restored until you sign in. --- -# Login to restore attachments in backup. +# Why do I need to log in to restore attachments from a backup? -We require users to be logged in to restore attachments in backup. This is because attachments are encrypted using a sub-key derived from your database encryption key. Without a login, we cannot encrypt/upload/sync attachments. +Attachments are encrypted with a sub-key derived from your account's data encryption key. Restoring them means decrypting them with that key and putting them back in your account — and while you are signed out, that key isn't available and there is no account to upload to. + +## What restores without an account, and what doesn't + +| In the backup | Restores while signed out? | +| --------------------------------------------- | -------------------------- | +| Notes, notebooks, tags, colors and reminders | Yes | +| Attachments — images, files, audio, web clips | No, sign in first | + +If you restore while signed out, your notes come back but the files inside them stay unavailable until you log in and run the restore again. + +::: tip Sign in before you restore +The simplest order is: log in, let the first sync finish, then restore the backup. That way notes and attachments come back in one pass. + +::: + +## Related pages + +- [Backup and restore](/backup-and-restore-notes-in-notesnook) — creating and restoring backups +- [Attachments & files](/attachments-and-files) — managing the files in your notes +- [How is my data encrypted?](/how-is-my-data-encrypted) — the keys this page is talking about +- [Why do I need to log in to upload attachments?](/faqs/login-to-upload-attachments) — the same question, for new files diff --git a/docs/help/contents/faqs/login-to-upload-attachments.md b/docs/help/contents/faqs/login-to-upload-attachments.md index 061049cf0..6d533aefb 100644 --- a/docs/help/contents/faqs/login-to-upload-attachments.md +++ b/docs/help/contents/faqs/login-to-upload-attachments.md @@ -1,8 +1,35 @@ --- -title: Login to upload attachments -description: We require users to be logged in to upload attachments. +title: Login to upload attachments +pageTitle: Why do I need to log in to upload attachments? +description: Attachments are encrypted with a key derived from your account's encryption key, so Notesnook needs you signed in before it can encrypt and upload a file. +keywords: + - notesnook login to upload attachments + - notesnook attachment requires account +schema: faq +faqs: + - q: Why do I need to log in to upload attachments in Notesnook? + a: Attachments are encrypted with a sub-key derived from your account's data encryption key. That key only exists once you are logged in, so while you are signed out there is nothing to encrypt the file with and no account to sync it to. + - q: Can I use Notesnook without an account? + a: Yes. Notes, notebooks, tags, the editor and search all work fully offline with no account. Attachments are the one exception, because they are stored on Notesnook's servers in encrypted form. --- -# Login to upload attachments +# Why do I need to log in to upload attachments? -We require users to be logged in to upload attachments. This is because attachments are encrypted using a sub-key derived from your database encryption key. Without a login, we cannot encrypt/upload/sync attachments. +Attachments are encrypted with a sub-key derived from your account's data encryption key. That key is created with your account and only exists once you are logged in, so while you are signed out there is nothing to encrypt the file with — and no account to sync it to. + +This is why the editor shows `Login to upload attachments.` instead of inserting the file. + +## What still works without an account + +Everything that lives on your device: notes, notebooks, tags, colors, the [editor](/rich-text-editor/rich-text-editor-toolbar) and search all work fully offline with no account at all. Attachments are the one exception, because they are stored on Notesnook's servers in encrypted form rather than only on your device. + +## What counts as an attachment + +Images, files, audio recordings and [web clips](/web-clipper/clipping-your-first-web-page-with-web-clipper) all go through the same pipeline, so all of them need you signed in. See [attachments and files](/attachments-and-files) for the size and storage limits on each plan. + +## Related pages + +- [Attachments & files](/attachments-and-files) — managing the files in your notes +- [How is my data encrypted?](/how-is-my-data-encrypted) — the keys this page is talking about +- [Plans & limits](/plans-and-limits) — file size and storage limits on each plan +- [Why do I need to log in to restore attachments?](/faqs/login-to-restore-attachments-in-backup) — the same question, for backups diff --git a/docs/help/contents/faqs/what-are-merge-conflicts.md b/docs/help/contents/faqs/what-are-merge-conflicts.md index 5aeb3ce72..776d55a18 100644 --- a/docs/help/contents/faqs/what-are-merge-conflicts.md +++ b/docs/help/contents/faqs/what-are-merge-conflicts.md @@ -1,25 +1,39 @@ --- title: What are merge conflicts? -description: Merge conflicts occur when two or more devices edit the same note and then attempt to sync these changes. Since each device has a different version of the note, Notesnook cannot automatically determine which version should take precedence, resulting in a merge conflict. +pageTitle: What is a merge conflict in Notesnook, and how do I fix it? +description: A merge conflict happens when the same note is edited on two devices before they sync. How to spot one, and how to keep the version you want. +keywords: + - notesnook merge conflict + - conflicted note + - notes app sync conflict +schema: faq +faqs: + - q: What is a merge conflict in Notesnook? + a: It happens when the same note is edited on two devices and both edits reach the server. Notesnook will not guess which one you want, so it marks the note conflicted and asks you to choose. + - q: Why doesn't Notesnook merge the two versions automatically? + a: Because automatic merging can silently lose text that only exists in one version. Notesnook shows you both and lets you keep one, discard one, or save both as separate notes. + - q: When does a merge conflict happen? + a: Only when the two edits are more than a minute apart. Editing on two devices at the same time, with sync working on both, does not create a conflict. --- # What are merge conflicts? -Merge conflicts occur when two or more devices edit the same note and then attempt to sync these changes. Since each device has a different version of the note, Notesnook cannot automatically determine which version should take precedence, resulting in a merge conflict. +A merge conflict happens when two devices edit the same note and then try to sync those changes. Since each device has a different version of the note, Notesnook cannot automatically determine which version should take precedence, resulting in a merge conflict. -### Example: +## An example Let’s say you’re using Notesnook on both your laptop and smartphone. You edit a note on your laptop making a lot of changes. Later, while commuting, you remember something important and edit the same note on your smartphone. When both devices eventually reconnect to the internet and sync, Notesnook detects that there are two different versions of the same note and triggers a merge conflict. ## Why do merge conflicts happen? -Merge conflicts happen because Notesnook cannot safely figure out which version of the name you want to keep. Unlike some apps that prioritize the most recent changes or attempt to merge content automatically (which can result in loss of important data or unwanted changes), Notesnook ensures you have full control over which version of a note you want to keep. +Merge conflicts happen because Notesnook cannot safely figure out which version of the note you want to keep. Unlike some apps that prioritize the most recent changes or attempt to merge content automatically (which can result in loss of important data or unwanted changes), Notesnook ensures you have full control over which version of a note you want to keep. -> info Both edits must be at least a minute apart -> -> The changes on both devices must be at least a minute apart for a merge conflict to occur. For example, if you are editing on both devices simultaneously (and both devices have a working sync), a merge conflict will NOT occur. +::: info Both edits must be at least a minute apart +The changes on both devices must be at least a minute apart for a merge conflict to occur. For example, if you are editing on both devices simultaneously (and both devices have a working sync), a merge conflict will NOT occur. -### Why doesn't Notesnook automatically resolve merge conflicts? +::: + +## Why doesn't Notesnook resolve merge conflicts automatically? 1. Automatic conflict resolution can lead to unintended data loss. For example, if both versions of a note contain unique but crucial information, merging them automatically might result in losing an important part of the information. 2. By allowing you to manually resolve conflicts, you can review each version of the note and decide which one is correct or if you want to keep both (i.e. both versions contain important information). @@ -33,35 +47,42 @@ Conflicted notes appear at the very top of your notes list. ## How to resolve merge conflicts -### [Desktop/Web](#/tab/web) - +:::tabs key:platform +== Desktop/Web To resolve a merge conflict on your desktop or web app, follow these steps: 1. Locate the conflicted note at the top of your notes list. -2. Click on the note to open the conflict resolution screen. +2. Click the note to open the conflict resolution screen. 3. On the conflict resolution screen, you’ll see two versions of your note side by side: 1. **Current Note** is the version from the device you are using. 2. **Incoming Note** is the version coming from the other device. - ![](/static/merge-conflicts-resolution-screen.png) + ![The desktop conflict resolution screen, with Current Note and Incoming Note side by side](/static/merge-conflicts-resolution-screen.png) 3. The red and green highlights on the left side show the changes you made. Red indicates deletions and green indicates additions. 4. Review both versions and decide which one you want to keep. 5. Click the **Keep** button on the version you want to retain. 6. Click the **Discard** button on the version you don’t want to keep, or press **Save a Copy** if you want to keep both versions. - ![](/static/merge-conflicts-resolution-screen-2.png) + ![The Keep, Discard and Save a Copy buttons on the desktop conflict resolution screen](/static/merge-conflicts-resolution-screen-2.png) -### [Mobile](#/tab/mobile) +== Mobile To resolve a merge conflict on your mobile device, follow these steps: 1. Locate the conflicted note at the top of your notes list. -2. Tap on the note to open the conflict resolution screen. +2. Tap the note to open the conflict resolution screen. 3. On the conflict resolution screen, you’ll see two versions of your note, one above the other: 1. **This Device** is the version from the device you are using. 2. **Incoming** is the version coming from the other device. - <p><img src="/static/merge-conflicts-resolution-screen-mobile.png" alt="drawing" height="414"/></p> + ![The mobile conflict resolution screen, with This Device above and Incoming below](/static/merge-conflicts-resolution-screen-mobile.png) 4. Review both versions and decide which one you want to keep. -5. Press the **Keep** button on the version you want to retain. -6. Press the **Discard** button on the version you don’t want to keep, or press **Save a Copy** if you want to keep both versions. - <p><img src="/static/merge-conflicts-resolution-screen-mobile-2.png" alt="drawing" height="414"/></p> +5. Tap the **Keep** button on the version you want to retain. +6. Tap the **Discard** button on the version you don’t want to keep, or press **Save a Copy** if you want to keep both versions. + ![The Keep, Discard and Save a Copy buttons on the mobile conflict resolution screen](/static/merge-conflicts-resolution-screen-mobile-2.png) ---- +::: + +## Related pages + +- [How sync works](/sync/how-sync-works) — when and how your notes travel +- [Troubleshooting sync](/sync/troubleshooting-sync) — when a note doesn't turn up +- [Version history](/note-version-history) — going back to an earlier draft +- [Sync settings](/sync/sync-settings) — offline mode and sync controls diff --git a/docs/help/contents/gift-cards.md b/docs/help/contents/gift-cards.md index 534b96940..b93914600 100644 --- a/docs/help/contents/gift-cards.md +++ b/docs/help/contents/gift-cards.md @@ -1,6 +1,21 @@ --- title: Gift cards -description: Gift your friends and family a Notesnook Pro subscription. +pageTitle: Notesnook gift cards — buying and redeeming a gift code +description: Buy a Notesnook gift card for one, three or five years, send the code to anyone, and redeem it on an account that is currently on the free plan. +keywords: + - notesnook gift card + - gift notesnook subscription + - redeem notesnook code +schema: faq +faqs: + - q: Who can redeem a Notesnook gift code? + a: Anyone whose account is currently on the free plan. You cannot redeem a gift code on an account with an active subscription, and a cancelled subscription counts as active until its billing period ends. + - q: Can I use a gift card to extend my existing subscription? + a: No. Your current subscription has to end completely before a gift code can be redeemed on that account. + - q: Do Notesnook gift codes expire? + a: Yes, one year from the date of purchase. + - q: Are Notesnook gift cards refundable or auto-renewing? + a: Neither. Gift codes are non-refundable and are a one-time purchase that never renews. --- # Gift cards @@ -19,39 +34,43 @@ You can purchase a gift card from [https://notesnook.com/giftcards](https://note - 3 years gift card - 5 years gift card -> info -> -> Gift cards are not attached to a user account and can be claimed by any Notesnook user. +::: info +Gift cards are not attached to a user account and can be claimed by any Notesnook user. + +::: ## Redeem a gift code -> info -> -> You can't redeem a gift code on an account with an active Notesnook subscription. A cancelled subscription is still active until its current billing period ends. +::: info +You can't redeem a gift code on an account with an active Notesnook subscription. A cancelled subscription is still active until its current billing period ends. -# [Desktop/Web](#/tab/web) +::: -1. Go to `Settings` -2. Go to `Subscription settings` -3. Click on `Redeem a gift code` button +:::tabs key:platform +== Desktop/Web + +1. Go to `{{settings}}` +2. Go to `{{subDetails}}` +3. Click `{{redeemGiftCode}}` button 4. Enter the gift code you received -5. Click on `Submit` and wait for the app to verify your gift code. +5. Click `{{submit}}` and wait for the app to verify your gift code. 6. Once the process succeeds, you should be upgraded to Pro. -# [Mobile](#/tab/mobile) +== Mobile -1. Go to `Settings` -2. Go to `Account settings` -3. Tap on `Redeem a gift code` +1. Go to `{{settings}}` +2. Go to `{{account}}` +3. Tap `{{redeemGiftCode}}` 4. Enter the gift code you received -5. Tap on `Redeem` and wait for the app to verify your gift code. +5. Tap `{{redeem}}` and wait for the app to verify your gift code. 6. Once the process succeeds, you should be upgraded to Pro. ---- +::: -> info -> -> Once you redeem a gift code, the person who purchased it will receive an email informing them that one of their gift codes was claimed. The email **does not** contain any information about who claimed the gift code. +::: info +Once you redeem a gift code, the person who purchased it will receive an email informing them that one of their gift codes was claimed. The email **does not** contain any information about who claimed the gift code. + +::: ## FAQs @@ -81,4 +100,9 @@ No. Gift cards are a one-time purchase. ### Can I use cryptocurrency to purchase a gift card? -Currently, no. But we are actively working on a solution to support this so stay tuned. +Yes! You can do so over at [Proxystore.](https://digitalgoods.proxysto.re/en) + +## Related pages + +- [Plans & limits](/plans-and-limits) — what each plan unlocks and the exact limits +- [Account settings](/account-settings) — email, password and profile diff --git a/docs/help/contents/how-is-my-data-encrypted.md b/docs/help/contents/how-is-my-data-encrypted.md index 39bdd13f5..b241c727b 100644 --- a/docs/help/contents/how-is-my-data-encrypted.md +++ b/docs/help/contents/how-is-my-data-encrypted.md @@ -1,27 +1,40 @@ --- title: How is my data encrypted? -description: Every byte of your notes data is encrypted with the strongest encryption algorithms on client with XChaCha-Poly1305-IETF & Argon2. +pageTitle: How does Notesnook encrypt my notes? +description: Every note is encrypted on your device with XChaCha20-Poly1305-IETF and a key derived with Argon2, before anything is sent. Here is exactly how it works. +keywords: + - notesnook encryption + - end to end encrypted notes app + - xchacha20 poly1305 notes + - zero knowledge note taking +schema: faq +faqs: + - q: How does Notesnook encrypt my notes? + a: Every item is encrypted on your device with XChaCha20-Poly1305-IETF before it is synced. The key comes from a data encryption key that is itself protected by a master key derived from your password with Argon2. The server only ever receives ciphertext. + - q: Can Notesnook read my notes? + a: No. Your password never leaves your device, and the keys that decrypt your notes never leave it either. The server stores encrypted blobs it has no way to open. + - q: What happens if I forget my password? + a: Your account recovery key is the only way back to your data. Without your password and without that key, nobody — including Notesnook — can decrypt your notes. --- # How is my data encrypted? -> warn Note -> -> This document is not a spec, only an explanation of the encryption process. +Everything you write is encrypted on your own device before it is sent anywhere. The Notesnook server stores ciphertext it cannot open, which is why nobody here can read your notes — and why nobody here can recover them for you if you lose both your password and your recovery key. + +::: info This is an explanation, not a specification +This page describes how the encryption works in practice. It is not a formal spec. + +::: ## Algorithms & cryptographic library -1. XChaCha-Poly1305-IETF (for encryption/decryption) -2. Argon2 (for password hashing & PKDF) - 1. `argon2i` for PKDF - 2. `argon2id` for password hashing -3. [**libsodium**](https://libsodium.org) +| Purpose | Algorithm | +| ------------------------------------------- | ----------------------- | +| Encrypting and decrypting your data | XChaCha20-Poly1305-IETF | +| Deriving your master key from your password | Argon2i | +| Hashing your password for the server | Argon2id | -On all three platforms we use the same exact library for all cryptographic functions. This ensures data integrity across platforms. - -> info Fun story -> -> When we first added encryption, we used AES-GCM-256 across platforms but the cross-platform compatibility was abyssmal. That is when I found out about the great libsodium. Written in C, wrappers available for all platforms...what more could I want? +All of it comes from [**libsodium**](https://libsodium.org). Web, desktop and mobile use the same library for every cryptographic operation, so a note encrypted on one platform decrypts identically on the others. ## Process @@ -31,9 +44,10 @@ When you sign up for an account, the app takes your password and hashes it using This predictable salt is generated using a `fixed client salt` + `your email`. -> info Your password never leaves your device -> -> Sending the hash over sending your plain text password ensures that there is no way for us (or anyone else) to get your password. +::: info Your password never leaves your device +Only the hash is sent, never the password itself, so there is no way for us — or anyone who intercepts the request — to learn your password. + +::: After the hash is generated, it is sent to the server. This hash is used as a `password` and is hashed again to mitigate password passthrough attacks. @@ -41,25 +55,25 @@ This process is repeated every time you sign in. ### 2. Key generation -When you first sign up for an account, your client generates two encryption keys. One is a unique data encryption key that encrypts all your notes and other data. The second is your master encryption key, this is derived by your password and predictable salt. This key protects all your encryption keys, like the aforementioned data encryption key. If you change your password, your client will re-encrypt your existing data encryption key with your new master key. +When you first sign up for an account, your client generates two encryption keys. One is a unique data encryption key that encrypts all your notes and other data. The second is your master encryption key, derived from your password and that predictable salt. This key protects all your encryption keys, like the aforementioned data encryption key. If you change your password, your client will re-encrypt your existing data encryption key with your new master key. ### 3. Encryption key storage -# [Desktop/Web](#/tab/web) - +:::tabs key:platform +== Desktop/Web Instead of storing the key as plain text (and allowing anyone to copy/move it), we use browser's `IndexedDB` to store the key as a `CryptoKey`. `CryptoKey` is stored securely by the browser and cannot be exported, viewed, or copied except by the app & browser. -# [Mobile](#/tab/mobile) +== Mobile On iOS and Android, the encryption key is stored in the phone's keychain. ---- +::: ### 4. Data encryption -Encryption only takes place when you sync. Each item in the database is encrypted separately using XChaCha-Poly1305-IETF. +Encryption takes place when you sync. Each item in the database is encrypted separately using XChaCha20-Poly1305-IETF. #### How it works @@ -72,14 +86,31 @@ Encryption only takes place when you sync. Each item in the database is encrypte 4. Algorithm id `alg` 5. ItemId `id` -> info -> -> See the whole process in action [here.](https://vericrypt.notesnook.com/) +::: info +See the whole process in action [here.](https://vericrypt.notesnook.com/) + +::: This object is then sent to the server for storage. The server performs no further operation on this data (because it can't). -## Faqs +## FAQs -### I am an old user of Notesnook, I don't have a data encryption key. +### Can Notesnook read my notes? -Your data encryption key will be created when you change your password. +No. Your notes are encrypted on your device with keys that never leave it, and the server only ever receives ciphertext. This is also why we cannot reset your password or recover your notes for you — see [recovering your account](/recovering-your-account). + +### What happens if I forget my password? + +Your [account recovery key](/recovering-your-account) is the only way back into your data. Without your password and without that key, your notes cannot be decrypted by anyone. + +### I am an old user of Notesnook and I don't have a data encryption key + +Your data encryption key is created the next time you change your password. + +## Related pages + +- [Private vault](/lock-notes-with-private-vault) — locking individual notes +- [Recovering your account](/recovering-your-account) — when you forget your password +- [Backup and restore](/backup-and-restore-notes-in-notesnook) — keeping your own encrypted copy +- [Two-factor authentication](/two-factor-authentication) — a second step at login +- [Self-hosting](/self-hosting) — running your own servers diff --git a/docs/help/contents/importing-notes/README.md b/docs/help/contents/importing-notes/README.md deleted file mode 100644 index 93d8cbd96..000000000 --- a/docs/help/contents/importing-notes/README.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -title: Importing notes ---- - -# Import notes from any notes app - -Notesnook supports importing from most of the popular note apps and common export formats such as markdown, html and text files. - -## Try it out - -You can try out the importer by opening the web or desktop app and going to `Settings > Notesnook Importer`. - -## Supported note apps and formats - -1. Plain text files -2. HTML files -3. Markdown (.md) files -4. EverNote -5. Simplenote -6. Google Keep -7. Joplin -8. Zoho Notebook -9. Obsidian -10. Skiff Pages - -**Don't see your notes app?** No worries, create an issue on [Github](https://github.com/streetwriters/notesnook/issues) - -## Is it safe to import? - -Not a single byte of your data from other apps is sent to our servers. Everything is processed 100% on the client side inside this browser. diff --git a/docs/help/contents/importing-notes/import-notes-from-colornote.md b/docs/help/contents/importing-notes/import-notes-from-colornote.md index eedb917eb..90012a69e 100644 --- a/docs/help/contents/importing-notes/import-notes-from-colornote.md +++ b/docs/help/contents/importing-notes/import-notes-from-colornote.md @@ -1,15 +1,33 @@ --- title: ColorNote +description: Move your notes from ColorNote into Notesnook by importing an encrypted ColorNote backup. +pageTitle: How to import ColorNote notes into Notesnook +keywords: + - import colornote + - colornote backup import + - colornote alternative +schema: howto --- # How to import notes from ColorNote notes app? -The following steps will help you import your notes from ColorNote easily. +Here is how to move your notes from ColorNote into Notesnook. 1. Download the ColorNote mobile app. 2. Go to `Settings > Backup` and create a backup. Make sure to remember the password you set while creating the backup as it will be needed during import. 3. Open the Notesnook app (web or desktop). -4. Go to `Settings > Notesnook Importer` and select `ColorNote` from list of apps. +4. Go to `Settings > Import & export > Notesnook Importer` and select `ColorNote` from list of apps. 5. Drop the backup file you exported earlier in the box or click anywhere to open system file picker to select the backup. -7. Click on "Start importing" and enter the password you used while creating the backup in the popup. -8. Once importing completes you should see all your notes in Notesnook. If you face any issues during importing, [report it on github](https://github.com/streetwriters/notesnook). \ No newline at end of file +6. Click "Start importing" and enter the password you used while creating the backup in the popup. +7. Once importing completes you should see all your notes in Notesnook. If you face any issues during importing, [report it on github](https://github.com/streetwriters/notesnook). + +<GetNotesnook title="Your notes, encrypted the moment they land" text="Notesnook imports run entirely on your device — not one byte of your ColorNote export is sent to our servers. Once imported, everything is end-to-end encrypted and syncs to all your devices for free." /> + +## Related pages + +- [Importing notes](/importing-notes/) — every app and file format Notesnook can import +- [Import from Evernote](/importing-notes/import-notes-from-evernote) — moving notes out of Evernote +- [Import from Google Keep](/importing-notes/import-notes-from-googlekeep) — moving notes out of Google Keep +- [Import from Joplin](/importing-notes/import-notes-from-joplin) — moving notes out of Joplin +- [Backup and restore](/backup-and-restore-notes-in-notesnook) — protecting your notes once they're in +- [How is my data encrypted?](/how-is-my-data-encrypted) — what happens to your notes after the import diff --git a/docs/help/contents/importing-notes/import-notes-from-evernote.md b/docs/help/contents/importing-notes/import-notes-from-evernote.md index f67f9ec3c..5e35b049a 100644 --- a/docs/help/contents/importing-notes/import-notes-from-evernote.md +++ b/docs/help/contents/importing-notes/import-notes-from-evernote.md @@ -1,33 +1,42 @@ --- title: Evernote +description: Export your Evernote notebooks as .enex files and import them into Notesnook — attachments, web clips, tags and notebooks included. +pageTitle: How to import Evernote notes into Notesnook (.enex) +keywords: + - import enex + - how to export evernote notes + - evernote to notesnook + - evernote alternative import +schema: howto --- # How do I import notes from Evernote? -The following steps will help you quickly import your notes from Evernote into Notesnook. +Here is how to move your notes from Evernote into Notesnook. ## Exporting your Evernote notebooks -> info -> -> If you are tech savvy and know your way around a computer, you can use a tool like [evernote-backup](https://github.com/vzhd1701/evernote-backup) to quickly export all your Evernote notes as .ENEX files. +::: info +If you are tech savvy and know your way around a computer, you can use a tool like [evernote-backup](https://github.com/vzhd1701/evernote-backup) to quickly export all your Evernote notes as .ENEX files. -1. Open the Evernote Desktop app (its not possible to export notes from the Evernote web app), and go to `Notebooks` from the side menu: - ![](/static/evernote-importer/1.png) -2. Click on the `three-dot` button on each notebook and click on `Export Notebook` - ![](/static/evernote-importer/2.png) -3. Choose `ENEX format` then click on `Export`, and save it to your desired location. Repeat this for all the Notebooks you want to import into Notesnook. - ![](/static/evernote-importer/3.png) +::: + +1. Open the Evernote desktop app — exporting is not possible from the Evernote web app — and go to `{{notebooks}}` in the side menu: + ![The Notebooks section in the Evernote desktop app side menu](/static/evernote-importer/1.png) +2. Click the three dot button on each notebook and click `Export Notebook` + ![The three dot menu on an Evernote notebook, showing Export Notebook](/static/evernote-importer/2.png) +3. Choose `ENEX format` then click `{{export}}`, and save it to your desired location. Repeat this for all the Notebooks you want to import into Notesnook. + ![The Evernote export dialog with ENEX chosen as the format](/static/evernote-importer/3.png) ## Importing .ENEX files into Notesnook -Once you have all the .ENEX files containing your Evernote notes, its time to import them into Notesnook. +Once you have the `.enex` files containing your Evernote notes, it is time to import them. 1. Open the Notesnook app (web or desktop) -2. Go to `Settings > Notesnook Importer` and select Evernote from the list of apps. - ![](/static/evernote-importer/4.png) -3. Drop (or select) the `.enex` files you exported earlier from Evernote, and click the "Start processing" button. - ![](/static/evernote-importer/5.png) +2. Go to `Settings > Import & export > Notesnook Importer` and select Evernote from the list of apps. + ![The Notesnook Importer app list with Evernote selected](/static/evernote-importer/4.png) +3. Drop (or select) the `.enex` files you exported earlier from Evernote, and click the "Start importing" button. + ![The Notesnook Importer drop zone, ready to accept the export file](/static/evernote-importer/5.png) 4. Once the importing completes you should see all your notes in Notesnook. If you face any issues during importing, feel free to [report them on GitHub](https://github.com/streetwriters/notesnook-importer). ## Supported formats @@ -44,3 +53,14 @@ Notesnook Importer is one of the most robust Evernote importers, supporting almo - [x] Internal note links (limitation: links only resolve correctly if the link text exactly matches the Evernote note title) - [x] Notebooks - [x] Tags + +<GetNotesnook title="Your notes, encrypted the moment they land" text="Notesnook imports run entirely on your device — not one byte of your Evernote export is sent to our servers. Once imported, everything is end-to-end encrypted and syncs to all your devices for free." /> + +## Related pages + +- [Importing notes](/importing-notes/) — every app and file format Notesnook can import +- [Import from Google Keep](/importing-notes/import-notes-from-googlekeep) — moving notes out of Google Keep +- [Import from Joplin](/importing-notes/import-notes-from-joplin) — moving notes out of Joplin +- [Import from Obsidian](/importing-notes/import-notes-from-obsidian) — moving notes out of Obsidian +- [Backup and restore](/backup-and-restore-notes-in-notesnook) — protecting your notes once they're in +- [How is my data encrypted?](/how-is-my-data-encrypted) — what happens to your notes after the import diff --git a/docs/help/contents/importing-notes/import-notes-from-fusebase.md b/docs/help/contents/importing-notes/import-notes-from-fusebase.md new file mode 100644 index 000000000..819937eea --- /dev/null +++ b/docs/help/contents/importing-notes/import-notes-from-fusebase.md @@ -0,0 +1,55 @@ +--- +title: Fusebase +pageTitle: How to import Fusebase (Nimbus Note) notes into Notesnook +description: Export your Fusebase — formerly Nimbus Note — workspace and import it into Notesnook, keeping folders, tags, colors and attachments. +keywords: + - import nimbus note + - fusebase export notes + - nimbus note alternative +schema: howto +--- + +# How do I import notes from Fusebase? + +Fusebase — the app formerly called **Nimbus Note** — can export your workspace as a `.zip` archive, and the Notesnook Importer reads it directly. + +## Exporting from Fusebase + +1. Open Fusebase on the web or desktop. +2. Export your workspace. The export arrives as a `.zip` file (for example `nimbus-export.zip`) containing one folder per note. +3. Save the file somewhere you can find it. + +## Importing into Notesnook + +:::tabs key:platform +== Desktop/Web + +1. Open the Notesnook web or desktop app. +2. Go to `Settings > Import & export > Notesnook Importer`. +3. Select `Fusebase (formerly Nimbus Note)` from the list of apps. +4. Drag and drop the `.zip` file, or click to browse for it. +5. Click `Start importing` and wait for the import to finish. + +== Mobile + +The Notesnook Importer runs in the **web and desktop apps only**. Import on a computer and the notes will sync down to your phone automatically. + +::: + +## Supported formats + +- [x] Notes, converted to Notesnook's rich text +- [x] Folders — each Fusebase parent folder becomes a notebook +- [x] Tags +- [x] Note colors, mapped to Notesnook's colors +- [x] Attachments and images embedded in a note + +## Related pages + +- [Importing notes](/importing-notes/) — every app and file format Notesnook can import +- [Import from Evernote](/importing-notes/import-notes-from-evernote) — moving notes out of Evernote +- [Import from Obsidian](/importing-notes/import-notes-from-obsidian) — moving a Markdown vault across +- [Organizing with notebooks](/organizing-notes/organize-notes-using-notebooks) — where your imported folders land +- [Backup and restore](/backup-and-restore-notes-in-notesnook) — protecting your notes once they're in + +<GetNotesnook title="Your notes, encrypted the moment they land" text="Notesnook imports run entirely on your device — not one byte of your Fusebase export is sent to our servers. Once imported, everything is end-to-end encrypted and syncs to all your devices for free." /> diff --git a/docs/help/contents/importing-notes/import-notes-from-googlekeep.md b/docs/help/contents/importing-notes/import-notes-from-googlekeep.md index 09209360e..5aa0d578c 100644 --- a/docs/help/contents/importing-notes/import-notes-from-googlekeep.md +++ b/docs/help/contents/importing-notes/import-notes-from-googlekeep.md @@ -1,5 +1,12 @@ --- title: Google Keep +description: Export Google Keep with Google Takeout and import the archive into Notesnook, keeping labels, images and checklists. +pageTitle: How to import Google Keep notes into Notesnook +keywords: + - import google keep notes + - google takeout notes + - google keep alternative +schema: howto --- # How do I import notes from Google Keep? @@ -9,22 +16,22 @@ The following steps will help you quickly import your notes from Google Keep int ## Exporting your Google Keep notes 1. Go to [Google Takeout](https://takeout.google.com/settings/takeout) and log into your Google account. -2. On the Google Takeout page, first deselect all the items by clicking on `Deselect all`, and then scroll down and select only `Keep` from the list. Once selected, click on `Next Step` by scrolling to the very bottom of the page. - ![](/static/google-keep-importer/1.png) -3. On the next section, leave everything as is and just click on the "Create export" button: - ![](/static/google-keep-importer/2.png) +2. On the Google Takeout page, first deselect all the items by clicking on `Deselect all`, and then scroll down and select only `{{keep}}` from the list. Once selected, click `Next Step` by scrolling to the very bottom of the page. + ![The Google Takeout page with every product deselected except Keep](/static/google-keep-importer/1.png) +3. Leave everything in the next section as it is and click the "Create export" button: + ![The Google Takeout export options, with the Create export button at the bottom](/static/google-keep-importer/2.png) 4. Download the exported .zip file once it becomes available: - ![](/static/google-keep-importer/3.png) + ![The finished Google Takeout export, ready to download as a .zip file](/static/google-keep-importer/3.png) ## Importing Google Takeout into Notesnook Once you have the Google Takeout containing your Google Keep notes, its time to import them into Notesnook. 1. Open the Notesnook app (web or desktop) -2. Go to `Settings > Notesnook Importer` and select `Google Keep` from list of apps. - ![](/static/google-keep-importer/4.png) +2. Go to `Settings > Import & export > Notesnook Importer` and select `Google Keep` from list of apps. + ![The Notesnook Importer app list with Google Keep selected](/static/google-keep-importer/4.png) 3. Drop the .zip backup file(s) you exported earlier from Google Takeout in the box or click anywhere to open system file picker to select the backup. - ![](/static/google-keep-importer/5.png) + ![The Notesnook Importer drop zone, ready to accept the export file](/static/google-keep-importer/5.png) 4. Once the importing completes you should see all your notes in Notesnook. If you face any issues during importing, feel free to [report them on GitHub](https://github.com/streetwriters/notesnook-importer). ## Supported formats @@ -38,3 +45,14 @@ Notesnook Importer is one of the most robust Google Keep importers around suppor - [x] Tags/Labels - [x] Pinned status - [x] Colors + +<GetNotesnook title="Your notes, encrypted the moment they land" text="Notesnook imports run entirely on your device — not one byte of your Google Keep export is sent to our servers. Once imported, everything is end-to-end encrypted and syncs to all your devices for free." /> + +## Related pages + +- [Importing notes](/importing-notes/) — every app and file format Notesnook can import +- [Import from Evernote](/importing-notes/import-notes-from-evernote) — moving notes out of Evernote +- [Import from Joplin](/importing-notes/import-notes-from-joplin) — moving notes out of Joplin +- [Import from Obsidian](/importing-notes/import-notes-from-obsidian) — moving notes out of Obsidian +- [Backup and restore](/backup-and-restore-notes-in-notesnook) — protecting your notes once they're in +- [How is my data encrypted?](/how-is-my-data-encrypted) — what happens to your notes after the import diff --git a/docs/help/contents/importing-notes/import-notes-from-html-files.md b/docs/help/contents/importing-notes/import-notes-from-html-files.md index 269cad555..706ef47a0 100644 --- a/docs/help/contents/importing-notes/import-notes-from-html-files.md +++ b/docs/help/contents/importing-notes/import-notes-from-html-files.md @@ -1,12 +1,29 @@ --- title: HTML files +description: Import .html files into Notesnook and keep their formatting, links and images. +pageTitle: How to import HTML files into Notesnook +keywords: + - import html files notes + - html to notes app +schema: howto --- # How do I import notes from HTML files? 1. Open the Notesnook app (web or desktop) -2. Go to `Settings > Notesnook Importer` and select `HTML` from list of apps. - ![](/static/html/1.png) -3. Drop your .html files, or click anywhere inside the box to browse and select your .html files. You can also provide a .zip file containing all your .html files. Then click "Start processing". - ![](/static/html/2.png) +2. Go to `Settings > Import & export > Notesnook Importer` and select `HTML` from list of apps. + ![The Notesnook Importer app list with HTML selected](/static/html/1.png) +3. Drop your .html files, or click anywhere inside the box to browse and select your .html files. You can also provide a .zip file containing all your .html files. Then click "Start importing". + ![The Notesnook Importer drop zone, ready to accept the export file](/static/html/2.png) 4. Once the importing completes you should see all your notes in Notesnook. If you face any issues during importing, feel free to [report them on GitHub](https://github.com/streetwriters/notesnook-importer). + +<GetNotesnook title="Your notes, encrypted the moment they land" text="Notesnook imports run entirely on your device — not one byte of your HTML files export is sent to our servers. Once imported, everything is end-to-end encrypted and syncs to all your devices for free." /> + +## Related pages + +- [Importing notes](/importing-notes/) — every app and file format Notesnook can import +- [Import from Evernote](/importing-notes/import-notes-from-evernote) — moving notes out of Evernote +- [Import from Google Keep](/importing-notes/import-notes-from-googlekeep) — moving notes out of Google Keep +- [Import from Joplin](/importing-notes/import-notes-from-joplin) — moving notes out of Joplin +- [Backup and restore](/backup-and-restore-notes-in-notesnook) — protecting your notes once they're in +- [How is my data encrypted?](/how-is-my-data-encrypted) — what happens to your notes after the import diff --git a/docs/help/contents/importing-notes/import-notes-from-joplin.md b/docs/help/contents/importing-notes/import-notes-from-joplin.md index b6887e19a..caac10ef3 100644 --- a/docs/help/contents/importing-notes/import-notes-from-joplin.md +++ b/docs/help/contents/importing-notes/import-notes-from-joplin.md @@ -1,19 +1,26 @@ --- title: Joplin +description: Export your Joplin notebooks and import them into Notesnook without losing notebooks, tags or attachments. +pageTitle: How to import Joplin notes into Notesnook +keywords: + - import joplin notes + - joplin to notesnook + - joplin jex import +schema: howto --- # How do I import notes from Joplin notes app? -The following steps will help you import your notes from Joplin easily. +Here is how to move your notes from Joplin into Notesnook. 1. Open the Joplin Desktop app. -2. Click on `File > Export All -> JEX - Joplin Export File` and save the .JEX file at your desired location. - ![](/static/joplin-importer/1.png) +2. Click `File > Export All -> JEX - Joplin Export File` and save the .JEX file at your desired location. + ![The Joplin export menu, with JEX chosen as the export format](/static/joplin-importer/1.png) 3. Open the Notesnook app (web or desktop) -4. Go to `Settings > Notesnook Importer` and select `Joplin` from list of apps. - ![](/static/joplin-importer/2.png) +4. Go to `Settings > Import & export > Notesnook Importer` and select `Joplin` from list of apps. + ![The Notesnook Importer app list with Joplin selected](/static/joplin-importer/2.png) 5. Drop (or select) the .jex backup file you exported earlier from Joplin: - ![](/static/joplin-importer/3.png) + ![The Notesnook Importer drop zone, ready to accept the export file](/static/joplin-importer/3.png) 6. Once the importing completes you should see all your notes in Notesnook. If you face any issues during importing, feel free to [report them on GitHub](https://github.com/streetwriters/notesnook-importer). ## Supported formats @@ -23,3 +30,14 @@ The following steps will help you import your notes from Joplin easily. - [x] Tags - [x] Folders (currently only 2 levels of nesting is supported) - [ ] Internal links to other notes + +<GetNotesnook title="Your notes, encrypted the moment they land" text="Notesnook imports run entirely on your device — not one byte of your Joplin export is sent to our servers. Once imported, everything is end-to-end encrypted and syncs to all your devices for free." /> + +## Related pages + +- [Importing notes](/importing-notes/) — every app and file format Notesnook can import +- [Import from Evernote](/importing-notes/import-notes-from-evernote) — moving notes out of Evernote +- [Import from Google Keep](/importing-notes/import-notes-from-googlekeep) — moving notes out of Google Keep +- [Import from Obsidian](/importing-notes/import-notes-from-obsidian) — moving notes out of Obsidian +- [Backup and restore](/backup-and-restore-notes-in-notesnook) — protecting your notes once they're in +- [How is my data encrypted?](/how-is-my-data-encrypted) — what happens to your notes after the import diff --git a/docs/help/contents/importing-notes/import-notes-from-markdown-files.md b/docs/help/contents/importing-notes/import-notes-from-markdown-files.md index 76cd4bc2b..e60cf763b 100644 --- a/docs/help/contents/importing-notes/import-notes-from-markdown-files.md +++ b/docs/help/contents/importing-notes/import-notes-from-markdown-files.md @@ -1,14 +1,21 @@ --- title: Markdown files +description: Import .md files from any app or folder into Notesnook — headings, lists, code blocks and links are preserved. +pageTitle: How to import Markdown files into Notesnook +keywords: + - import markdown files + - markdown notes app import + - md files to notes +schema: howto --- # How do I import notes from Markdown files? 1. Open the Notesnook app (web or desktop) -2. Go to `Settings > Notesnook Importer` and select "Markdown". - ![](/static/markdown-importer/1.png) -3. Drop your .md files, or click anywhere inside the box to browse and select your .md files. You can also provide a .zip file containing all your .md files. Then click "Start processing". - ![](/static/markdown-importer/2.png) +2. Go to `Settings > Import & export > Notesnook Importer` and select "Markdown". + ![The Notesnook Importer app list with Markdown selected](/static/markdown-importer/1.png) +3. Drop your .md files, or click anywhere inside the box to browse and select your .md files. You can also provide a .zip file containing all your .md files. Then click "Start importing". + ![The Notesnook Importer drop zone, ready to accept the export file](/static/markdown-importer/2.png) 4. Once the importing completes you should see all your notes in Notesnook. If you face any issues during importing, feel free to [report them on GitHub](https://github.com/streetwriters/notesnook-importer). ## Supported formats @@ -21,3 +28,14 @@ title: Markdown files - [x] Images and links (links that point to files get added as attachments) > Note: For best results, it is recommended to ZIP all your .md files and their attachments so they can be found by the importer. + +<GetNotesnook title="Your notes, encrypted the moment they land" text="Notesnook imports run entirely on your device — not one byte of your Markdown files export is sent to our servers. Once imported, everything is end-to-end encrypted and syncs to all your devices for free." /> + +## Related pages + +- [Importing notes](/importing-notes/) — every app and file format Notesnook can import +- [Import from Evernote](/importing-notes/import-notes-from-evernote) — moving notes out of Evernote +- [Import from Google Keep](/importing-notes/import-notes-from-googlekeep) — moving notes out of Google Keep +- [Import from Joplin](/importing-notes/import-notes-from-joplin) — moving notes out of Joplin +- [Backup and restore](/backup-and-restore-notes-in-notesnook) — protecting your notes once they're in +- [How is my data encrypted?](/how-is-my-data-encrypted) — what happens to your notes after the import diff --git a/docs/help/contents/importing-notes/import-notes-from-obsidian.md b/docs/help/contents/importing-notes/import-notes-from-obsidian.md index 75d241d50..5b612bf9a 100644 --- a/docs/help/contents/importing-notes/import-notes-from-obsidian.md +++ b/docs/help/contents/importing-notes/import-notes-from-obsidian.md @@ -1,21 +1,39 @@ --- title: Obsidian +description: Import an Obsidian vault into Notesnook — your Markdown files, folders and attachments become encrypted notes. +pageTitle: How to import an Obsidian vault into Notesnook +keywords: + - import obsidian vault + - obsidian to notesnook + - obsidian markdown import +schema: howto --- # How do I import notes from Obsidian? 1. Open the Notesnook app (web or desktop) -2. Go to `Settings > Notesnook Importer` and select "Obsidian". - ![](/static/obsidian-importer/1.png) -3. Drop your .md files from your Obsidian Vault, or click anywhere inside the box to browse and select your .md files. You can also provide a .zip file containing all your Obsidian .md files. Then click "Start processing". - ![](/static/obsidian-importer/2.png) +2. Go to `Settings > Import & export > Notesnook Importer` and select "Obsidian". + ![The Notesnook Importer app list with Obsidian selected](/static/obsidian-importer/1.png) +3. Drop your .md files from your Obsidian Vault, or click anywhere inside the box to browse and select your .md files. You can also provide a .zip file containing all your Obsidian .md files. Then click "Start importing". + ![The Notesnook Importer drop zone, ready to accept the export file](/static/obsidian-importer/2.png) 4. Once the importing completes you should see all your notes in Notesnook. If you face any issues during importing, feel free to [report them on GitHub](https://github.com/streetwriters/notesnook-importer). ## Supported formats - [ ] Internal links -- [x] Embedded files (supporting both `![[path-to-file]]` and `![](path/to/image.png)`) +- [x] Embedded files (supporting both `![[path-to-file]]` and `![Image in Notesnook](path/to/image.png)`) - [x] Full CommonMark Markdown syntax - [ ] Callouts - [x] Metadata (tags etc.) - [x] Comments (block & inline both get removed) + +<GetNotesnook title="Your notes, encrypted the moment they land" text="Notesnook imports run entirely on your device — not one byte of your Obsidian export is sent to our servers. Once imported, everything is end-to-end encrypted and syncs to all your devices for free." /> + +## Related pages + +- [Importing notes](/importing-notes/) — every app and file format Notesnook can import +- [Import from Evernote](/importing-notes/import-notes-from-evernote) — moving notes out of Evernote +- [Import from Google Keep](/importing-notes/import-notes-from-googlekeep) — moving notes out of Google Keep +- [Import from Joplin](/importing-notes/import-notes-from-joplin) — moving notes out of Joplin +- [Backup and restore](/backup-and-restore-notes-in-notesnook) — protecting your notes once they're in +- [How is my data encrypted?](/how-is-my-data-encrypted) — what happens to your notes after the import diff --git a/docs/help/contents/importing-notes/import-notes-from-plaintext-files.md b/docs/help/contents/importing-notes/import-notes-from-plaintext-files.md index 476cbee53..32f22e3d7 100644 --- a/docs/help/contents/importing-notes/import-notes-from-plaintext-files.md +++ b/docs/help/contents/importing-notes/import-notes-from-plaintext-files.md @@ -1,12 +1,29 @@ --- title: Plaintext files +description: Import .txt files into Notesnook, one note per file. +pageTitle: How to import plain text files into Notesnook +keywords: + - import txt files notes + - plain text notes import +schema: howto --- # How do I import notes from Plaintext files? 1. Open the Notesnook app (web or desktop) -2. Go to `Settings > Notesnook Importer` and select "Text". - ![](/static/plaintext-importer/1.png) -3. Drop your .txt files, or click anywhere inside the box to browse and select your .txt files. You can also provide a .zip file containing all your .txt files. Then click "Start processing". - ![](/static/plaintext-importer/2.png) +2. Go to `Settings > Import & export > Notesnook Importer` and select "Text". + ![The Notesnook Importer app list with Text selected](/static/plaintext-importer/1.png) +3. Drop your .txt files, or click anywhere inside the box to browse and select your .txt files. You can also provide a .zip file containing all your .txt files. Then click "Start importing". + ![The Notesnook Importer drop zone, ready to accept the export file](/static/plaintext-importer/2.png) 4. Once the importing completes you should see all your notes in Notesnook. If you face any issues during importing, feel free to [report them on GitHub](https://github.com/streetwriters/notesnook-importer). + +<GetNotesnook title="Your notes, encrypted the moment they land" text="Notesnook imports run entirely on your device — not one byte of your Plaintext files export is sent to our servers. Once imported, everything is end-to-end encrypted and syncs to all your devices for free." /> + +## Related pages + +- [Importing notes](/importing-notes/) — every app and file format Notesnook can import +- [Import from Evernote](/importing-notes/import-notes-from-evernote) — moving notes out of Evernote +- [Import from Google Keep](/importing-notes/import-notes-from-googlekeep) — moving notes out of Google Keep +- [Import from Joplin](/importing-notes/import-notes-from-joplin) — moving notes out of Joplin +- [Backup and restore](/backup-and-restore-notes-in-notesnook) — protecting your notes once they're in +- [How is my data encrypted?](/how-is-my-data-encrypted) — what happens to your notes after the import diff --git a/docs/help/contents/importing-notes/import-notes-from-simplenote.md b/docs/help/contents/importing-notes/import-notes-from-simplenote.md index bc8a3465b..a6c4c047a 100644 --- a/docs/help/contents/importing-notes/import-notes-from-simplenote.md +++ b/docs/help/contents/importing-notes/import-notes-from-simplenote.md @@ -1,22 +1,29 @@ --- title: Simplenote +description: Export your Simplenote notes and import them into Notesnook, keeping tags and note history intact where possible. +pageTitle: How to import Simplenote notes into Notesnook +keywords: + - import simplenote notes + - simplenote to notesnook + - simplenote alternative +schema: howto --- # How to import notes from Simplenote notes app? -The following steps will help you import your notes from Simplenote easily. +Here is how to move your notes from Simplenote into Notesnook. 1. Open Simplenote app on Desktop or Login to [https://app.simplenote.com](https://app.simplenote.com). -2. Go to sidebar and click on Settings. - ![](/static/simplenote-importer/1.png) +2. Go to sidebar and click Settings. + ![The Settings entry in the Simplenote sidebar](/static/simplenote-importer/1.png) 3. Go to `Tools` tab in Settings - ![](/static/simplenote-importer/2.png) -4. Click on `Export notes` to download your notes as a .zip file. + ![The Tools tab in Simplenote settings, where Export notes lives](/static/simplenote-importer/2.png) +4. Click `Export notes` to download your notes as a .zip file. 5. Open the Notesnook app (web or desktop) -6. Go to `Settings > Notesnook Importer` and select `Simplenote` from list of apps. - ![](/static/simplenote-importer/3.png) -7. Drop the .zip backup file you exported earlier from Simplenote in the box or click anywhere to open system file picker to select the backup and click "Start processing". - ![](/static/simplenote-importer/4.png) +6. Go to `Settings > Import & export > Notesnook Importer` and select `Simplenote` from list of apps. + ![The Notesnook Importer app list with Simplenote selected](/static/simplenote-importer/3.png) +7. Drop the .zip backup file you exported earlier from Simplenote in the box or click anywhere to open system file picker to select the backup and click "Start importing". + ![The Notesnook Importer drop zone, ready to accept the export file](/static/simplenote-importer/4.png) 8. Once importing completes you should see all your notes in Notesnook. If you face any issues during importing, [report it on github](https://github.com/streetwriters/notesnook). ## Supported formats @@ -28,3 +35,14 @@ Simplenote's export is, well, pretty simple and the Notesnook Importer supports ### Some of my notes have weird whitespacing and broken formatting after import. What do I do? This can happen in notes for which you have enabled Markdown in Simplenote. Notesnook Importer follows this flag during processing and respects Markdown rules during the conversion to HTML. If you want to preserve the formatting of your notes, it is best that you disable the Markdown formatting for all your notes in Simplenote. This will force the Notesnook Importer to import all your notes as plaintext. + +<GetNotesnook title="Your notes, encrypted the moment they land" text="Notesnook imports run entirely on your device — not one byte of your Simplenote export is sent to our servers. Once imported, everything is end-to-end encrypted and syncs to all your devices for free." /> + +## Related pages + +- [Importing notes](/importing-notes/) — every app and file format Notesnook can import +- [Import from Evernote](/importing-notes/import-notes-from-evernote) — moving notes out of Evernote +- [Import from Google Keep](/importing-notes/import-notes-from-googlekeep) — moving notes out of Google Keep +- [Import from Joplin](/importing-notes/import-notes-from-joplin) — moving notes out of Joplin +- [Backup and restore](/backup-and-restore-notes-in-notesnook) — protecting your notes once they're in +- [How is my data encrypted?](/how-is-my-data-encrypted) — what happens to your notes after the import diff --git a/docs/help/contents/importing-notes/import-notes-from-skiff-pages.md b/docs/help/contents/importing-notes/import-notes-from-skiff-pages.md index 50b034de7..0035778b0 100644 --- a/docs/help/contents/importing-notes/import-notes-from-skiff-pages.md +++ b/docs/help/contents/importing-notes/import-notes-from-skiff-pages.md @@ -1,5 +1,12 @@ --- title: Skiff Pages +description: Skiff is gone — export your Skiff Pages and import them into Notesnook so your notes survive the shutdown. +pageTitle: How to import Skiff Pages into Notesnook +keywords: + - import skiff pages + - skiff shut down notes + - skiff alternative +schema: howto --- # How do I import notes from Skiff Pages? @@ -9,21 +16,21 @@ The following steps will help you quickly import your notes from Skiff Pages int ## Exporting your Skiff Pages 1. Open the [Skiff Pages](https://app.skiff.com) app -2. Open Settings > Export or just go directly to [https://app.skiff.com/dashboard/?settingTab=export](https://app.skiff.com/dashboard/?settingTab=export) - ![](/static/skiff-importer/1.png) -3. Click on the Export button next to `Pages and Files` — this might take a few minutes depending on how many pages you have. +2. Open Settings > Export, or go straight to [https://app.skiff.com/dashboard/?settingTab=export](https://app.skiff.com/dashboard/?settingTab=export) + ![The Export tab in Skiff settings](/static/skiff-importer/1.png) +3. Click the Export button next to `Pages and Files` — this might take a few minutes depending on how many pages you have. 4. Once the export is complete, save the `Skiff.zip` file at your preferred location. - ![](/static/skiff-importer/2.png) + ![The finished Skiff export, ready to save as Skiff.zip](/static/skiff-importer/2.png) ## Importing Skiff.zip file into Notesnook Once you have the `Skiff.zip` file containing your Skiff pages, its time to import them into Notesnook. 1. Open the Notesnook app (web or desktop) -2. Go to `Settings > Notesnook Importer` and select "Skiff Pages". - ![](/static/skiff-importer/3.png) -3. Drop your Skiff.zip file, or click anywhere inside the box to browse and select your Skiff.zip file. Then click "Start processing". - ![](/static/skiff-importer/4.png) +2. Go to `Settings > Import & export > Notesnook Importer` and select "Skiff Pages". + ![The Notesnook Importer app list with Skiff Pages selected](/static/skiff-importer/3.png) +3. Drop your Skiff.zip file, or click anywhere inside the box to browse and select your Skiff.zip file. Then click "Start importing". + ![The Notesnook Importer drop zone, ready to accept the export file](/static/skiff-importer/4.png) 4. Once the importing completes you should see all your notes in Notesnook. If you face any issues during importing, feel free to [report them on GitHub](https://github.com/streetwriters/notesnook-importer). ## Supported formats @@ -34,3 +41,14 @@ Once you have the `Skiff.zip` file containing your Skiff pages, its time to impo - [x] Tables - [x] Rich text (bold, italic, headings, lists etc.) - [x] Task lists + +<GetNotesnook title="Your notes, encrypted the moment they land" text="Notesnook imports run entirely on your device — not one byte of your Skiff Pages export is sent to our servers. Once imported, everything is end-to-end encrypted and syncs to all your devices for free." /> + +## Related pages + +- [Importing notes](/importing-notes/) — every app and file format Notesnook can import +- [Import from Evernote](/importing-notes/import-notes-from-evernote) — moving notes out of Evernote +- [Import from Google Keep](/importing-notes/import-notes-from-googlekeep) — moving notes out of Google Keep +- [Import from Joplin](/importing-notes/import-notes-from-joplin) — moving notes out of Joplin +- [Backup and restore](/backup-and-restore-notes-in-notesnook) — protecting your notes once they're in +- [How is my data encrypted?](/how-is-my-data-encrypted) — what happens to your notes after the import diff --git a/docs/help/contents/importing-notes/import-notes-from-standardnotes.md b/docs/help/contents/importing-notes/import-notes-from-standardnotes.md index 121e40240..8824b327a 100644 --- a/docs/help/contents/importing-notes/import-notes-from-standardnotes.md +++ b/docs/help/contents/importing-notes/import-notes-from-standardnotes.md @@ -1,23 +1,60 @@ --- title: Standard Notes +description: Moving from Standard Notes to Notesnook — export a decrypted backup and import it with the Markdown or plaintext importer. +pageTitle: How to import Standard Notes into Notesnook +keywords: + - import standard notes + - standard notes to notesnook + - standard notes alternative +schema: howto --- # How do I import notes from Standard Notes? -The following steps will help you import your notes from Standard notes easily. +Export a **decrypted backup** from Standard Notes, unzip it, and bring the files in with Notesnook's Markdown or plaintext importer. -1. Open Standard Notes app on Desktop or visit [https://app.standardnotes.org](https://app.standardnotes.org) and login to your account. -2. Select all your notes, right click, and select `Export`. -3. Open the Notesnook (app or desktop). -4. Go to `Settings > Notesnook Importer` and select `Standard Notes` from list of apps. - ![](/static/standard-notes-importer/3.png) -5. Drop the .zip file you exported earlier from Standard Notes in the box or click anywhere to open system file picker to select the backup. - ![](/static/standard-notes-importer/4.png) -6. Once importing completes you should see all your notes in Notesnook. If you face any issues during importing, [report it on github](https://github.com/streetwriters/notesnook). +::: warning There is no longer a Standard Notes importer +Recent versions of the Notesnook Importer don't list Standard Notes as a source app, so you import the files it exports rather than the backup itself. The steps below take that route. -## Supported formats +::: -- [x] Text files -- [x] Authentication notes -- [x] Spreadsheets -- [ ] Tags +## Export a decrypted backup from Standard Notes + +1. Open the Standard Notes desktop app, or go to [https://app.standardnotes.com](https://app.standardnotes.com) and sign in. +2. Select all your notes, right click, and choose `{{export}}`. +3. Choose the **decrypted** backup option. An encrypted backup can only be read by Standard Notes, so nothing can import it. +4. Save the `.zip` file somewhere you can find it. + +## Import the files into Notesnook + +1. Unzip the backup. Inside it, your notes are plain text and Markdown files. +2. Open Notesnook on web or desktop. +3. Go to `Settings > Import & export > Notesnook Importer`. +4. Choose **Markdown** for `.md` files, or **Text** for `.txt` files. Run the importer once for each type you have. +5. Drop the files in, or click the box to pick them, and start the import. + +Full steps for each importer are on [import Markdown files](/importing-notes/import-notes-from-markdown-files) and [import plaintext files](/importing-notes/import-notes-from-plaintext-files). + +## What carries across + +| | Imported | +| ----------------------------- | -------- | +| Note titles and content | Yes | +| Plain text and Markdown notes | Yes | +| Tags | No | +| Notebooks or folders | No | + +Your notes arrive as a flat list, so plan to re-file them into [notebooks](/organizing-notes/organize-notes-using-notebooks) and re-apply [tags](/organizing-notes/organize-notes-using-tags) afterwards. + +If you'd like a proper Standard Notes importer back, [open an issue](https://github.com/streetwriters/notesnook/issues/new/choose) — that is where importer requests are tracked. + +<GetNotesnook title="Your notes, encrypted the moment they land" text="Notesnook imports run entirely on your device — not one byte of your Standard Notes export is sent to our servers. Once imported, everything is end-to-end encrypted and syncs to all your devices for free." /> + +## Related pages + +- [Importing notes](/importing-notes/) — every app and file format Notesnook can import +- [Import Markdown files](/importing-notes/import-notes-from-markdown-files) — the importer this page routes you to +- [Import plaintext files](/importing-notes/import-notes-from-plaintext-files) — for `.txt` exports +- [Import from Joplin](/importing-notes/import-notes-from-joplin) — moving notes out of Joplin +- [Backup and restore](/backup-and-restore-notes-in-notesnook) — protecting your notes once they're in +- [How is my data encrypted?](/how-is-my-data-encrypted) — what happens to your notes after the import diff --git a/docs/help/contents/importing-notes/import-notes-from-textbundle-files.md b/docs/help/contents/importing-notes/import-notes-from-textbundle-files.md new file mode 100644 index 000000000..aee47eec1 --- /dev/null +++ b/docs/help/contents/importing-notes/import-notes-from-textbundle-files.md @@ -0,0 +1,61 @@ +--- +title: TextBundle files +pageTitle: How to import TextBundle and TextPack files into Notesnook +description: Import .textbundle and .textpack files into Notesnook — the portable note format used by Bear, Ulysses, iA Writer and other Markdown editors. +keywords: + - import textbundle + - textpack import notes + - bear notes export import +schema: howto +--- + +# How do I import TextBundle files? + +TextBundle is an open format for moving a note and its images between apps as a single package. Editors such as Bear, Ulysses and iA Writer export it, and the Notesnook Importer reads both `.textbundle` folders and their zipped form, `.textpack`. + +## Exporting a TextBundle + +Export from your current app as **TextBundle** or **TextPack**. Each package holds the note's text plus an `assets` folder with its images and files. + +If your app offers both, `.textpack` is easier to move around because it's a single file. + +## Importing into Notesnook + +:::tabs key:platform +== Desktop/Web + +1. Open the Notesnook web or desktop app. +2. Go to `Settings > Import & export > Notesnook Importer`. +3. Select `TextBundle` from the list of apps. +4. Drag and drop your `.textbundle` or `.textpack` files, or click to browse for them. You can add as many as you like. +5. Click `Start importing` and wait for the import to finish. + +== Mobile + +The Notesnook Importer runs in the **web and desktop apps only**. Import on a computer and the notes will sync down to your phone automatically. + +::: + +## Supported formats + +The importer reads whichever text file the package contains, so a TextBundle written as Markdown, HTML or plain text all import correctly. + +- [x] Markdown notes, including headings, lists, code blocks, tables and links +- [x] HTML notes +- [x] Plain text notes +- [x] Images and attachments stored in the package + +::: info macOS export folders +Files inside a `__MACOSX` folder — the metadata macOS adds when zipping — are ignored automatically, so you can import an archive straight from Finder. + +::: + +## Related pages + +- [Importing notes](/importing-notes/) — every app and file format Notesnook can import +- [Import Markdown files](/importing-notes/import-notes-from-markdown-files) — loose `.md` files instead of packages +- [Import HTML files](/importing-notes/import-notes-from-html-files) — for `.html` exports +- [Markdown shortcuts](/rich-text-editor/markdown-notes-editing) — writing Markdown once your notes are in +- [Backup and restore](/backup-and-restore-notes-in-notesnook) — protecting your notes once they're in + +<GetNotesnook title="Your notes, encrypted the moment they land" text="Notesnook imports run entirely on your device — not one byte of your TextBundle is sent to our servers. Once imported, everything is end-to-end encrypted and syncs to all your devices for free." /> diff --git a/docs/help/contents/importing-notes/import-notes-from-upnote.md b/docs/help/contents/importing-notes/import-notes-from-upnote.md index eb5817289..2a6ef7f92 100644 --- a/docs/help/contents/importing-notes/import-notes-from-upnote.md +++ b/docs/help/contents/importing-notes/import-notes-from-upnote.md @@ -1,22 +1,40 @@ --- title: UpNote +description: Export your UpNote notebooks and import them into Notesnook, keeping formatting, images and attachments. +pageTitle: How to import UpNote notes into Notesnook +keywords: + - import upnote notes + - upnote to notesnook + - upnote alternative +schema: howto --- # How to import notes from UpNote notes app? -The following steps will help you import your notes from UpNote easily. +Here is how to move your notes from UpNote into Notesnook. 1. Download the UpNote desktop app. -2. Click on settings icon on the header. -3. Go to `General` tab in Settings -4. Click on `Export All Notes`. +2. Click settings icon on the header. +3. Go to `{{general}}` tab in Settings +4. Click `Export All Notes`. 5. Export from the `Export to HTML` option to download your notes. 6. Create a `.zip` file of the exported folder. 7. Open the Notesnook app (web or desktop). -8. Go to `Settings > Notesnook Importer` and select `UpNote` from list of apps. -9. Drop the `.zip` file you exported earlier in the box or click anywhere to open system file picker to select the backup and click "Start processing". +8. Go to `Settings > Import & export > Notesnook Importer` and select `UpNote` from list of apps. +9. Drop the `.zip` file you exported earlier in the box or click anywhere to open system file picker to select the backup and click "Start importing". 10. Once importing completes you should see all your notes in Notesnook. If you face any issues during importing, [report it on github](https://github.com/streetwriters/notesnook). ## Supported formats UpNote's export is a folder with HTML files for each note and a folder for attachments. Make sure to create a `.zip` of the exported folder before importing to Notesnook. The Notesnook Importer preserves all formatting, images, and attachments in the imported notes. + +<GetNotesnook title="Your notes, encrypted the moment they land" text="Notesnook imports run entirely on your device — not one byte of your UpNote export is sent to our servers. Once imported, everything is end-to-end encrypted and syncs to all your devices for free." /> + +## Related pages + +- [Importing notes](/importing-notes/) — every app and file format Notesnook can import +- [Import from Evernote](/importing-notes/import-notes-from-evernote) — moving notes out of Evernote +- [Import from Google Keep](/importing-notes/import-notes-from-googlekeep) — moving notes out of Google Keep +- [Import from Joplin](/importing-notes/import-notes-from-joplin) — moving notes out of Joplin +- [Backup and restore](/backup-and-restore-notes-in-notesnook) — protecting your notes once they're in +- [How is my data encrypted?](/how-is-my-data-encrypted) — what happens to your notes after the import diff --git a/docs/help/contents/importing-notes/import-notes-from-zoho-notebook.md b/docs/help/contents/importing-notes/import-notes-from-zoho-notebook.md index 21ac56b84..fd02c9601 100644 --- a/docs/help/contents/importing-notes/import-notes-from-zoho-notebook.md +++ b/docs/help/contents/importing-notes/import-notes-from-zoho-notebook.md @@ -1,22 +1,39 @@ --- title: Zoho notebook +description: Export your Zoho Notebook notecards and import them into Notesnook in a few steps. +pageTitle: How to import Zoho Notebook notes into Notesnook +keywords: + - import zoho notebook + - zoho notebook to notesnook +schema: howto --- # How do I import notes from Zoho notebook? -The following steps will help you import your notes from Zoho notebook easily. +Here is how to move your notes from Zoho Notebook into Notesnook. -1. Go to Zoho notebook and click on account icon on top right corner. - ![](/static/zoho-importer/1.png) +1. Go to Zoho notebook and click account icon on top right corner. + ![The account icon at the top right of Zoho Notebook](/static/zoho-importer/1.png) 2. From the Side menu, go to Settings. - ![](/static/zoho-importer/2.png) + ![The Settings entry in the Zoho Notebook side menu](/static/zoho-importer/2.png) 3. In the Migration section, select "Export". - ![](/static/zoho-importer/3.png) + ![The Export option in the Migration section of Zoho Notebook settings](/static/zoho-importer/3.png) 4. Wait while your notes are exported. Once export completes, download exported .zip file - ![](/static/zoho-importer/4.png) + ![The Zoho Notebook export finishing, with a link to download the .zip file](/static/zoho-importer/4.png) 5. Open the Notesnook app (web or desktop) -6. Go to `Settings > Notesnook Importer` and select `Zoho notebook` from the list of apps. - ![](/static/zoho-importer/5.png) -7. Drop the .zip backup file(s) you exported earlier in the box or click anywhere to open system file picker to select the backup then click start processing. - ![](/static/zoho-importer/6.png) +6. Go to `Settings > Import & export > Notesnook Importer` and select `Zoho Notebook` from the list of apps. + ![The Notesnook Importer app list with Zoho Notebook selected](/static/zoho-importer/5.png) +7. Drop the .zip backup file(s) you exported earlier in the box or click anywhere to open system file picker to select the backup then click "Start importing". + ![The Notesnook Importer drop zone, ready to accept the export file](/static/zoho-importer/6.png) 8. Once importing completes you should see all your notes in Notesnook. If you face any issues during importing, feel free to [report them on GitHub](https://github.com/streetwriters/notesnook-importer). + +<GetNotesnook title="Your notes, encrypted the moment they land" text="Notesnook imports run entirely on your device — not one byte of your Zoho Notebook export is sent to our servers. Once imported, everything is end-to-end encrypted and syncs to all your devices for free." /> + +## Related pages + +- [Importing notes](/importing-notes/) — every app and file format Notesnook can import +- [Import from Evernote](/importing-notes/import-notes-from-evernote) — moving notes out of Evernote +- [Import from Google Keep](/importing-notes/import-notes-from-googlekeep) — moving notes out of Google Keep +- [Import from Joplin](/importing-notes/import-notes-from-joplin) — moving notes out of Joplin +- [Backup and restore](/backup-and-restore-notes-in-notesnook) — protecting your notes once they're in +- [How is my data encrypted?](/how-is-my-data-encrypted) — what happens to your notes after the import diff --git a/docs/help/contents/importing-notes/index.md b/docs/help/contents/importing-notes/index.md new file mode 100644 index 000000000..d68afa5fa --- /dev/null +++ b/docs/help/contents/importing-notes/index.md @@ -0,0 +1,74 @@ +--- +title: Importing notes +pageTitle: Import notes into Notesnook from any app +description: Move your notes into Notesnook from Evernote, Google Keep, Obsidian, Simplenote, Joplin, UpNote and more — or from Markdown, HTML and text files. +keywords: + - import notes to notesnook + - migrate notes app + - notesnook importer +schema: faq +faqs: + - q: Is it safe to import my notes into Notesnook? + a: Yes. The Notesnook Importer runs entirely on your device. Not a single byte of your export file is sent to Notesnook's servers — the notes are encrypted on your device before anything is synced. + - q: Which apps can I import from? + a: Evernote, Simplenote, Google Keep, Joplin, Obsidian, ColorNote, UpNote, Zoho Notebook, Fusebase (Nimbus Note) and Skiff Pages, plus plain text, HTML, Markdown and TextBundle files. + - q: Can I import notes on my phone? + a: No. The Notesnook Importer runs in the web and desktop apps only. Import there, and your notes sync to your phone automatically. + - q: Will my notebooks and tags survive the import? + a: In most cases yes. Notebooks, tags, attachments and formatting are carried over where the source app's export format includes them; the page for each app lists exactly what is supported. +--- + +# Import notes from any notes app + +Notesnook supports importing from most of the popular note apps and common export formats such as markdown, html and text files. Imports run **on your device** — your old notes are never uploaded to us in the clear. + +## Try it out + +You can try out the importer by opening the web or desktop app and going to `Settings > Import & export > Notesnook Importer`. + +::: info Import from a computer +The Notesnook Importer is available in the **web and desktop apps only**. Import on a computer and your notes will sync down to your phone and tablet automatically. + +::: + +## Supported note apps and formats + +| App or format | Guide | +| --------------------------------------- | ------------------------------------------------------------------------------ | +| Evernote (`.enex`) | [Import from Evernote](/importing-notes/import-notes-from-evernote) | +| Google Keep | [Import from Google Keep](/importing-notes/import-notes-from-googlekeep) | +| Simplenote | [Import from Simplenote](/importing-notes/import-notes-from-simplenote) | +| Joplin | [Import from Joplin](/importing-notes/import-notes-from-joplin) | +| Obsidian | [Import from Obsidian](/importing-notes/import-notes-from-obsidian) | +| ColorNote | [Import from ColorNote](/importing-notes/import-notes-from-colornote) | +| UpNote | [Import from UpNote](/importing-notes/import-notes-from-upnote) | +| Zoho Notebook | [Import from Zoho Notebook](/importing-notes/import-notes-from-zoho-notebook) | +| Skiff Pages | [Import from Skiff Pages](/importing-notes/import-notes-from-skiff-pages) | +| Fusebase (Nimbus Note) | [Import from Fusebase](/importing-notes/import-notes-from-fusebase) | +| TextBundle (`.textbundle`, `.textpack`) | [Import TextBundle files](/importing-notes/import-notes-from-textbundle-files) | +| Markdown (`.md`) files | [Import Markdown files](/importing-notes/import-notes-from-markdown-files) | +| HTML files | [Import HTML files](/importing-notes/import-notes-from-html-files) | +| Plain text (`.txt`) files | [Import plaintext files](/importing-notes/import-notes-from-plaintext-files) | + +**Don't see your notes app?** No worries, create an issue on [Github](https://github.com/streetwriters/notesnook/issues) + +## Is it safe to import? + +Not a single byte of your data from other apps is sent to our servers. Everything is processed 100% on the client side inside this browser. + +Once the import finishes, your notes are [end-to-end encrypted](/how-is-my-data-encrypted) like everything else in Notesnook, and they sync to every device you sign in on. + +## What happens after the import + +- Imported notebooks and tags appear alongside your existing ones — see [organizing with notebooks](/organizing-notes/organize-notes-using-notebooks). +- Attachments count towards your [storage limit](/plans-and-limits), so a large Evernote library may need a paid plan. +- Take a [backup](/backup-and-restore-notes-in-notesnook) once you're happy with the result. + +<GetNotesnook title="Bring your notes somewhere private" text="Notesnook is free, open source, and encrypts every note on your device before it syncs. Import once and your notes are readable only by you — on every device you own." /> + +## Related pages + +- [Exporting notes](/export-notes-from-notesnook) — leaving with your notes takes the same few steps as arriving +- [Backup and restore](/backup-and-restore-notes-in-notesnook) — your safety net after a big import +- [Attachments & files](/attachments-and-files) — what imported images and files count against +- [How is my data encrypted?](/how-is-my-data-encrypted) — what protects your notes once they're in diff --git a/docs/help/contents/inbox-api/README.md b/docs/help/contents/inbox-api/README.md deleted file mode 100644 index 98414d3ad..000000000 --- a/docs/help/contents/inbox-api/README.md +++ /dev/null @@ -1 +0,0 @@ -# Inbox API \ No newline at end of file diff --git a/docs/help/contents/inbox-api/getting-started.md b/docs/help/contents/inbox-api/getting-started.md index b5f1db12e..eaf97dd4f 100644 --- a/docs/help/contents/inbox-api/getting-started.md +++ b/docs/help/contents/inbox-api/getting-started.md @@ -1,6 +1,13 @@ --- title: Getting Started -description: Learn about Notesnook's Inbox API. +pageTitle: Getting started with the Notesnook Inbox API +description: Send notes into your Notesnook account from other apps and services with the Inbox API — enabling it, creating keys, and posting your first note. +keywords: + - notesnook inbox api + - notesnook api + - send note to notesnook + - notesnook zapier + - notesnook inbox api html --- # Getting started with the Inbox API @@ -22,38 +29,43 @@ Some common use cases include: ### 1. Enable Inbox API from settings. -# [Desktop/Web](#/tab/web) +:::tabs key:platform +== Desktop/Web -1. Go to Settings > Inbox -2. Turn on the `Enable Inbox API` toggle +1. Go to Settings > Account > Inbox +2. Turn on the `{{enableInboxAPI}}` toggle 3. Choose whether you want to use your own PGP keypair or let Notesnook autogenerate one for you -# [Mobile](#/tab/mobile) +== Mobile -`Settings > Inbox > Enable Inbox API`. +`Settings > Account > Inbox API > Enable Inbox API`. ---- +::: -> info -> -> The PGP keys are validated (round-trip encrypt/decrypt) before being saved. +::: info +The PGP keys are validated (round-trip encrypt/decrypt) before being saved. + +::: ### 2. Create your Inbox API Key -A default API key is created automatically when you enable the Inbox API. You can create up to 10 API keys and revoke them individually. +You create your own API keys — none is generated for you when you turn the Inbox API on. You can hold up to **10 keys at a time** and revoke them individually, so each service you connect can have its own. -# [Desktop/Web](#/tab/web) +Each key gets an expiry: `{{expiryOneDay}}`, `{{expiryOneWeek}}`, `{{expiryOneMonth}}` (the default), `{{expiryOneYear}}`, or `{{never}}`. -1. Go to Settings > Inbox -2. Click `Create Key` in the `API Keys` section +:::tabs key:platform +== Desktop/Web + +1. Go to Settings > Account > Inbox +2. Click `{{createKey}}` in the `{{viewAPIKeys}}` section 3. Set a name for the API Key (e.g. Zapier) 4. Set an expiry date -# [Mobile](#/tab/mobile) +== Mobile -`Settings > Inbox > View API Keys > +`. +`Settings > Account > Inbox API > API Keys > Create Key`. ---- +::: ### 3. Send data to the Inbox @@ -84,9 +96,38 @@ A default API key is created automatically when you enable the Inbox API. You ca | `notebookIds` | string[] | Optional | Array of notebook IDs to assign the note to. | | `tagIds` | string[] | Optional | Array of tag IDs to apply to the note. | -> info Notebook & Tag IDs -> -> Notebook and Tag IDs can be found by right-clicking on a notebook/tag and selecting `Copy ID`. +::: info Notebook & Tag IDs +Notebook and Tag IDs can be found by right clicking on a notebook/tag and selecting `{{copyId}}`. + +::: + +#### What HTML can I send? + +`content.data` is an HTML string, and `content.type` must be `"html"` — it is the only content format the Inbox API accepts. There is no `"text"` or `"markdown"` type, but you can send plain text with no tags in it at all and it becomes a paragraph. + +You don't have to send a fragment. A whole document works too: a `<!doctype>`, `<html>`, `<head>` or `<body>` wrapper is unwrapped for you and only the body content is kept, so you can pipe an email body or a scraped page straight through. + +The HTML is sanitized on your own device, after decryption and before the note is saved. Ordinary document markup survives: + +- headings, paragraphs, lists, tables, blockquotes and preformatted text +- inline formatting — `<strong>`, `<em>`, `<u>`, `<s>`, `<code>`, `<sub>`, `<sup>` +- links with an `http` or `https` address +- images +- `<iframe>` with a safe `src`, so embeds are not stripped + +Anything that could run code is removed, and the surrounding text is kept: + +- `<script>` tags and their contents +- inline event handlers — `onclick`, `onerror`, `onmouseover` and the rest +- `javascript:` and `data:` addresses in `href` and `src` +- `<object>`, `<embed>` and `<base>` + +::: warning Unbalanced tags turn the whole note into a code block +Your HTML is checked for balanced tags before anything else. An unclosed or mismatched tag anywhere in the payload is **not** repaired — the entire string is escaped and stored as one code block, so the note arrives showing your raw markup instead of formatted text. If a note lands looking like source code, that is why. Close every tag before you post. + +::: + +Notesnook stores the result in its own editor format, so markup is kept to the extent that it maps onto something the editor can represent. Presentational details that have no equivalent — most inline `style` attributes and layout scaffolding, for example — are dropped, and the text and structure remain. #### Limits @@ -157,9 +198,10 @@ This Zap sends every new email you receive in your Gmail inbox to your Notesnook | Data — `content__data` | _(Gmail)_ Body HTML | | Headers — `Authorization` | `<your-inbox-api-key>` | -> info -> -> In Zapier's nested JSON syntax, use double underscores (`__`) to represent nested keys. `content__type` maps to `content.type` and `content__data` maps to `content.data` in the JSON body. +::: info +In Zapier's nested JSON syntax, use double underscores (`__`) to represent nested keys. `content__type` maps to `content.type` and `content__data` maps to `content.data` in the JSON body. + +::: **4. Test and activate the Zap.** Zapier will POST a note to your Notesnook inbox for every matching email. The note will appear after your next sync. @@ -178,13 +220,13 @@ This Applet sends any email you forward to your IFTTT trigger address into your **3. Configure the Webhooks action:** -| Field | Value | -| ------------------ | ------------------------------------ | -| URL | `https://inbox.notesnook.com/` | -| Method | `POST` | -| Content Type | `application/json` | -| Additional Headers | `Authorization: <your-inbox-api-key> | -| Body | _(see below)_ | +| Field | Value | +| ------------------ | ------------------------------------- | +| URL | `https://inbox.notesnook.com/` | +| Method | `POST` | +| Content Type | `application/json` | +| Additional Headers | `Authorization: <your-inbox-api-key>` | +| Body | _(see below)_ | Use the following JSON body template, substituting IFTTT ingredients: @@ -214,14 +256,50 @@ Inbox uses OpenPGP asymmetric encryption to ensure your data is encrypted before 1. **When you enable Inbox from settings:** - The client generates an OpenPGP public/private keypair (or you provide your own). The public key is stored on Notesnook's servers. The private key is encrypted with your account's master key before being stored. Notesnook never sees it in plaintext. - - You can now generate API keys for the inbox endpoint. These are short tokens (with a fixed lifetime) you paste into Zapier, IFTTT, or your own code. They tell the inbox server which account to deliver the note to. You can create multiple keys (one per service) and revoke them individually without affecting your account. + - You can now generate API keys for the inbox endpoint. These are tokens you paste into Zapier, IFTTT, or your own code — each with the expiry you chose, or none at all if you picked `{{never}}`. They tell the inbox server which account to deliver the note to. You can create multiple keys (one per service) and revoke them individually without affecting your account. 2. **When data is posted to the Inbox API:** - The inbox server fetches your PGP public key from Notesnook's API using the provided API key. - Your payload is encrypted using your PGP public key (`alg: pgp-aes256`). The result is an armored PGP ciphertext blob. - - The encrypted payload is forwarded to Notesnook's servers and stored in the database. The inbox server never stores your data in plaintext or encrypted. It just acts as a relay. + - The encrypted payload is forwarded to Notesnook's servers and stored in the database. The inbox server never stores your data in plaintext or encrypted. It only acts as a relay. 3. **When your client syncs:** - Encrypted inbox items are pushed to all your connected clients (web, desktop, and mobile) via sync. - Your device decrypts the payload using your PGP private key (decrypted from the master key on-device) and adds the note to your database. + +## When an item fails to arrive + +Every item the Inbox API processes is recorded, and anything that fails is kept with the reason it failed — a decryption failure, invalid JSON, or a payload that didn't match the schema, with the offending field named. + +:::tabs key:platform +== Desktop/Web + +1. Go to `{{settings}}`. +2. Open `{{account}}` > `Inbox`. +3. Next to `{{failedInboxItems}}`, click `{{show}}`. + +== Mobile + +1. Go to `{{settings}}`. +2. Open `{{account}}` > `{{inboxAPI}}`. +3. Tap `{{failedInboxItems}}`. + +::: + +You can delete individual entries or clear the whole list. If a service keeps failing, check that `type` is `"note"`, `version` is `1`, and `content.type` is `"html"`. + +A note that arrives as a **code block** full of raw markup is not a failure and won't show up in this list — it means the HTML you sent had an unclosed or mismatched tag. See [what HTML can I send?](#what-html-can-i-send). + +## Turning the Inbox API off + +::: danger Disabling revokes every key +Turning off the Inbox API **deletes all your unsynced inbox items and revokes every API key you have created**. Any service still posting to your inbox will start getting `401 unauthorized`, and you will have to create new keys and update every integration if you turn it back on. + +::: + +## Related pages + +- [Self-hosting the Inbox API](/inbox-api/self-hosting-inbox-api) — running the relay yourself +- [Account settings](/account-settings) — email, password and profile +- [How is my data encrypted?](/how-is-my-data-encrypted) — the encryption behind every note diff --git a/docs/help/contents/inbox-api/self-hosting-inbox-api.md b/docs/help/contents/inbox-api/self-hosting-inbox-api.md index d8430489b..50c57cea6 100644 --- a/docs/help/contents/inbox-api/self-hosting-inbox-api.md +++ b/docs/help/contents/inbox-api/self-hosting-inbox-api.md @@ -1,6 +1,11 @@ --- title: Self-Hosting Inbox API -description: Learn about self-hosting Notesnook's Inbox API. +pageTitle: Self-host the Notesnook Inbox API +description: Run your own Notesnook Inbox API server so inbound notes never touch Notesnook's infrastructure, and point the apps at it. +keywords: + - self host inbox api + - notesnook inbox server + - notesnook self hosting --- # Self-Hosting Inbox API @@ -18,9 +23,10 @@ The inbox server is a lightweight proxy: it fetches your PGP public key from Not The source code and setup instructions are available in the [notesnook-sync-server](https://github.com/streetwriters/notesnook-sync-server/tree/master/Notesnook.Inbox.API) repository. Once running, replace `https://inbox.notesnook.com/` with your own instance URL in any API calls or automation tools. -> info -> -> Even on Notesnook's hosted instance, your payload is encrypted with your PGP public key before it leaves the server — it cannot be read in transit or at rest. +::: info +Even on Notesnook's hosted instance, your payload is encrypted with your PGP public key before it leaves the server — it cannot be read in transit or at rest. + +::: ## Option 2: Encrypt locally and post directly @@ -124,6 +130,13 @@ Usage: ./send-to-notesnook.sh "Meeting notes" "<p>Discussed the Q4 roadmap.</p>" ``` -> info -> -> After rotating your PGP keys in Notesnook settings, re-fetch the public key (Step 1) and re-import it before encrypting new payloads. +::: info +After rotating your PGP keys in Notesnook settings, re-fetch the public key (Step 1) and re-import it before encrypting new payloads. + +::: + +## Related pages + +- [Inbox API](/inbox-api/getting-started) — sending notes in from other services +- [Self-hosting](/self-hosting) — running your own servers +- [How is my data encrypted?](/how-is-my-data-encrypted) — the encryption behind every note diff --git a/docs/help/contents/index.md b/docs/help/contents/index.md new file mode 100644 index 000000000..1dc371f71 --- /dev/null +++ b/docs/help/contents/index.md @@ -0,0 +1,73 @@ +--- +layout: home +title: Notesnook Help +description: Your complete and free resource to using Notesnook as a daily note taking app to organize your work and life while safeguarding your privacy. + +hero: + name: Notesnook Help + tagline: Helping you discover everything you can do with Notesnook + image: + src: /logo.png + alt: Notesnook + actions: + - theme: brand + text: Go to docs + link: /docs + - theme: alt + text: Create your first note + link: /create-a-note-in-notesnook + - theme: alt + text: Download Notesnook + link: https://notesnook.com/downloads + +features: + - title: Organize your notes + details: Notebooks, tags, colors, favorites, pins and the side menu — pick the structure that fits your work. + link: /organizing-notes/organize-notes-using-notebooks + linkText: Start with notebooks + - title: Write and format + details: The editor toolbar, markdown shortcuts, tables and task lists, on every platform. + link: /rich-text-editor/rich-text-editor-toolbar + linkText: Open the editor guide + - title: Bring your notes over + details: Import from Evernote, Google Keep, Obsidian, Joplin, Simplenote and plain markdown or HTML files. + link: /importing-notes/ + linkText: Import your notes + - title: Keep your notes safe + details: Backups, restore, the private vault, app lock and how your data is encrypted end-to-end. + link: /backup-and-restore-notes-in-notesnook + linkText: Back up your notes + - title: Recover your account + details: What to do when you forget your password, and what your recovery key protects. + link: /recovering-your-account + linkText: Recover an account + - title: Publish with Monographs + details: Share a note as a link — optionally encrypted with a password only your reader knows. + link: /publish-notes-with-monographs + linkText: Publish a note +--- + +<div class="vp-doc nn-home-note"> + +Notesnook is a free and open source note taking app focused on user privacy and ease of use. Everything is encrypted on your device with `XChaCha20-Poly1305` and `Argon2` before it ever leaves it — which also means nobody at Notesnook can read your notes, or recover them for you. + +Can't find what you're looking for? [Contact us](https://notesnook.com/contact-us) or [open an issue](https://github.com/streetwriters/notesnook/issues/new/choose). + +</div> + +<style> +.nn-home-note { + max-width: 768px; + margin: 64px auto 0; + padding: 32px 24px 72px; + border-top: 1px solid var(--vp-c-divider); + color: var(--vp-c-text-2); +} + +@media (max-width: 640px) { + .nn-home-note { + margin-top: 40px; + padding-bottom: 56px; + } +} +</style> diff --git a/docs/help/contents/keyboard-shortcuts.md b/docs/help/contents/keyboard-shortcuts.md index 9a5a85818..c89a152d8 100644 --- a/docs/help/contents/keyboard-shortcuts.md +++ b/docs/help/contents/keyboard-shortcuts.md @@ -1,86 +1,99 @@ --- -title: Keyboard Shortcuts -description: Keyboard shortcuts for Notesnook +title: Keyboard shortcuts +pageTitle: Every keyboard shortcut in Notesnook +description: The complete list of Notesnook keyboard shortcuts for web, Windows, Linux and macOS — navigation, the editor, formatting and note actions. +keywords: + - notesnook keyboard shortcuts + - notesnook hotkeys + - notes app shortcuts --- # Keyboard shortcuts -The following keyboard shortcuts will help you navigate Notesnook faster. +These are all the keyboard shortcuts the Notesnook desktop and web apps respond to, grouped by what they do. Press `Ctrl` `/` (`⌘` `/` on macOS) inside the app to bring the same list up. -### General +## General -| Description | Web | Windows/Linux | Mac | -| --- | --- | --- | --- | -| Search in notes list view if editor is not focused | Ctrl F | Ctrl F | ⌘ F | -| Settings | Ctrl , | Ctrl , | ⌘ , | -| Keyboard shortcuts | Ctrl / | Ctrl / | ⌘ / | -| New note | - | Ctrl N | ⌘ N | +| Description | Web | Windows/Linux | Mac | +| -------------------------------------------------- | ------ | ------------- | --- | +| Search in notes list view if editor is not focused | Ctrl F | Ctrl F | ⌘ F | +| Settings | Ctrl , | Ctrl , | ⌘ , | +| Keyboard shortcuts | Ctrl / | Ctrl / | ⌘ / | +| New note | - | Ctrl N | ⌘ N | -### Navigation +## Navigation -| Description | Web | Windows/Linux | Mac | -| --- | --- | --- | --- | -| Next tab | Ctrl Alt → / Ctrl Alt ⇧ → | Ctrl tab | ⌘ tab | -| Previous tab | Ctrl Alt ← / Ctrl Alt ⇧ ← | Ctrl ⇧ tab | ⌘ ⇧ tab | -| Command palette | Ctrl ⇧ P / Ctrl ⇧ : | Ctrl ⇧ P / Ctrl ⇧ : | ⌘ ⇧ P / ⌘ ⇧ : | -| Quick open | Ctrl P | Ctrl P | ⌘ P | -| New tab | - | Ctrl T | ⌘ T | -| Close active tab | - | Ctrl W | ⌘ W | -| Close all tabs | - | Ctrl ⇧ W | ⌘ ⇧ W | +| Description | Web | Windows/Linux | Mac | +| ---------------- | ------------------------- | ------------------- | ------------- | +| Next tab | Ctrl Alt → / Ctrl Alt ⇧ → | Ctrl tab | ⌘ tab | +| Previous tab | Ctrl Alt ← / Ctrl Alt ⇧ ← | Ctrl ⇧ tab | ⌘ ⇧ tab | +| Command palette | Ctrl ⇧ P / Ctrl ⇧ : | Ctrl ⇧ P / Ctrl ⇧ : | ⌘ ⇧ P / ⌘ ⇧ : | +| Quick open | Ctrl P | Ctrl P | ⌘ P | +| New tab | - | Ctrl T | ⌘ T | +| Close active tab | - | Ctrl W | ⌘ W | +| Close all tabs | - | Ctrl ⇧ W | ⌘ ⇧ W | -### Editor +## Editor -| Description | Web | Windows/Linux | Mac | -| --- | --- | --- | --- | -| Add attachment | Ctrl ⇧ A | Ctrl ⇧ A | ⌘ ⇧ A | -| Insert blockquote | Ctrl ⇧ B | Ctrl ⇧ B | ⌘ ⇧ B | -| Toggle bold | Ctrl B | Ctrl B | ⌘ B | -| Toggle bullet list | Ctrl ⇧ 8 | Ctrl ⇧ 8 | ⌘ ⇧ 8 | -| Toggle check list | Ctrl ⇧ 9 | Ctrl ⇧ 9 | ⌘ ⇧ 9 | -| Split list item | ↵ | ↵ | ↵ | -| Lift list item | ⇧ Tab | ⇧ Tab | ⇧ Tab | -| Sink list item | Ctrl ⇧ Down | Ctrl ⇧ Down | ⌘ ⇧ Down | -| Toggle code | Ctrl E | Ctrl E | ⌘ E | -| Toggle code block | Ctrl ⇧ C | Ctrl ⇧ C | ⌘ ⇧ C | -| Insert date | Alt D | Alt D | ⌥ D | -| Insert time | Alt T | Alt T | ⌥ T | -| Insert date and time | Ctrl Alt D | Ctrl Alt D | ⌘ ⌥ D | -| Insert date and time with timezone | Ctrl Alt Z | Ctrl Alt Z | ⌘ ⌥ Z | -| Increase font size | Ctrl [ | Ctrl [ | ⌘ [ | -| Decrease font size | Ctrl ] | Ctrl ] | ⌘ ] | -| Insert paragraph | Ctrl Alt 0 | Ctrl Alt 0 | ⌘ ⌥ 0 | -| Insert heading 1 | Ctrl Alt 1 | Ctrl Alt 1 | ⌘ ⌥ 1 | -| Insert heading 2 | Ctrl Alt 2 | Ctrl Alt 2 | ⌘ ⌥ 2 | -| Insert heading 3 | Ctrl Alt 3 | Ctrl Alt 3 | ⌘ ⌥ 3 | -| Insert heading 4 | Ctrl Alt 4 | Ctrl Alt 4 | ⌘ ⌥ 4 | -| Insert heading 5 | Ctrl Alt 5 | Ctrl Alt 5 | ⌘ ⌥ 5 | -| Insert heading 6 | Ctrl Alt 6 | Ctrl Alt 6 | ⌘ ⌥ 6 | -| Undo | Ctrl Z | Ctrl Z | ⌘ Z | -| Redo | Ctrl ⇧ Z / Ctrl Y | Ctrl ⇧ Z / Ctrl Y | ⌘ ⇧ Z / ⌘ Y | -| Add image | Ctrl ⇧ I | Ctrl ⇧ I | ⌘ ⇧ I | -| Toggle italic | Ctrl I | Ctrl I | ⌘ I | -| Remove formatting in selection | Ctrl \ | Ctrl \ | ⌘ \ | -| Insert internal link | Ctrl ⇧ K | Ctrl ⇧ K | ⌘ ⇧ K | -| Insert link | Ctrl K | Ctrl K | ⌘ K | -| Insert math block | Ctrl ⇧ M | Ctrl ⇧ M | ⌘ ⇧ M | -| Toggle ordered list | Ctrl ⇧ 7 | Ctrl ⇧ 7 | ⌘ ⇧ 7 | -| Toggle outline list | Ctrl ⇧ O | Ctrl ⇧ O | ⌘ ⇧ O | -| Toggle outline list expand | Ctrl Space | Ctrl Space | ⌘ Space | -| Open search | Ctrl F | Ctrl F | ⌘ F | -| Open search and replace | Ctrl Alt F | Ctrl Alt F | ⌘ ⌥ F | -| Toggle strike | Ctrl ⇧ S | Ctrl ⇧ S | ⌘ ⇧ S | -| Toggle subscript | Ctrl , | Ctrl , | ⌘ , | -| Toggle superscript | Ctrl . | Ctrl . | ⌘ . | -| Toggle task list | Ctrl ⇧ T | Ctrl ⇧ T | ⌘ ⇧ T | -| Text align center | Ctrl ⇧ E | Ctrl ⇧ E | ⌘ ⇧ E | -| Text align justify | Ctrl ⇧ J | Ctrl ⇧ J | ⌘ ⇧ J | -| Text align left | Ctrl ⇧ L | Ctrl ⇧ L | ⌘ ⇧ L | -| Text align right | Ctrl ⇧ R | Ctrl ⇧ R | ⌘ ⇧ R | -| Underline | Ctrl U | Ctrl U | ⌘ U | -| Toggle highlight | Ctrl Alt H | Ctrl Alt H | ⌘ ⌥ H | -| Toggle text color | Ctrl Alt C | Ctrl Alt C | ⌘ ⌥ C | -| Move line up | Alt ↑ | Alt ↑ | ⌥ ↑ | -| Move line down | Alt ↓ | Alt ↓ | ⌥ ↓ | -| Move parent node up | Alt ⇧ ↑ | Alt ⇧ ↑ | ⌥ ⇧ ↑ | -| Move parent node down | Alt ⇧ ↓ | Alt ⇧ ↓ | ⌥ ⇧ ↓ | -| Clear current line | Ctrl L | Ctrl L | ⌘ L | \ No newline at end of file +| Description | Web | Windows/Linux | Mac | +| ---------------------------------- | ----------------- | ----------------- | ----------- | +| Add attachment | Ctrl ⇧ A | Ctrl ⇧ A | ⌘ ⇧ A | +| Insert blockquote | Ctrl ⇧ B | Ctrl ⇧ B | ⌘ ⇧ B | +| Toggle bold | Ctrl B | Ctrl B | ⌘ B | +| Toggle bullet list | Ctrl ⇧ 8 | Ctrl ⇧ 8 | ⌘ ⇧ 8 | +| Toggle check list | Ctrl ⇧ 9 | Ctrl ⇧ 9 | ⌘ ⇧ 9 | +| Split list item | ↵ | ↵ | ↵ | +| Lift list item | ⇧ Tab | ⇧ Tab | ⇧ Tab | +| Sink list item | Tab | Tab | Tab | +| Toggle code | Ctrl E | Ctrl E | ⌘ E | +| Toggle code block | Ctrl ⇧ C | Ctrl ⇧ C | ⌘ ⇧ C | +| Insert date | Alt D | Alt D | ⌥ D | +| Insert time | Alt T | Alt T | ⌥ T | +| Insert date and time | Ctrl Alt D | Ctrl Alt D | ⌘ ⌥ D | +| Insert date and time with timezone | Ctrl Alt Z | Ctrl Alt Z | ⌘ ⌥ Z | +| Increase font size | Ctrl [ | Ctrl [ | ⌘ [ | +| Decrease font size | Ctrl ] | Ctrl ] | ⌘ ] | +| Insert paragraph | Ctrl Alt 0 | Ctrl Alt 0 | ⌘ ⌥ 0 | +| Insert heading 1 | Ctrl Alt 1 | Ctrl Alt 1 | ⌘ ⌥ 1 | +| Insert heading 2 | Ctrl Alt 2 | Ctrl Alt 2 | ⌘ ⌥ 2 | +| Insert heading 3 | Ctrl Alt 3 | Ctrl Alt 3 | ⌘ ⌥ 3 | +| Insert heading 4 | Ctrl Alt 4 | Ctrl Alt 4 | ⌘ ⌥ 4 | +| Insert heading 5 | Ctrl Alt 5 | Ctrl Alt 5 | ⌘ ⌥ 5 | +| Insert heading 6 | Ctrl Alt 6 | Ctrl Alt 6 | ⌘ ⌥ 6 | +| Undo | Ctrl Z | Ctrl Z | ⌘ Z | +| Redo | Ctrl ⇧ Z / Ctrl Y | Ctrl ⇧ Z / Ctrl Y | ⌘ ⇧ Z / ⌘ Y | +| Add image | Ctrl ⇧ I | Ctrl ⇧ I | ⌘ ⇧ I | +| Toggle italic | Ctrl I | Ctrl I | ⌘ I | +| Remove formatting in selection | Ctrl \ | Ctrl \ | ⌘ \ | +| Insert internal link | Ctrl ⇧ K | Ctrl ⇧ K | ⌘ ⇧ K | +| Insert link | Ctrl K | Ctrl K | ⌘ K | +| Insert math block | Ctrl ⇧ M | Ctrl ⇧ M | ⌘ ⇧ M | +| Toggle ordered list | Ctrl ⇧ 7 | Ctrl ⇧ 7 | ⌘ ⇧ 7 | +| Toggle outline list | Ctrl ⇧ O | Ctrl ⇧ O | ⌘ ⇧ O | +| Toggle outline list expand | Ctrl Space | Ctrl Space | ⌘ Space | +| Open search | Ctrl F | Ctrl F | ⌘ F | +| Open search and replace | Ctrl Alt F | Ctrl Alt F | ⌘ ⌥ F | +| Toggle strike | Ctrl ⇧ S | Ctrl ⇧ S | ⌘ ⇧ S | +| Toggle subscript | Ctrl , | Ctrl , | ⌘ , | +| Toggle superscript | Ctrl . | Ctrl . | ⌘ . | +| Toggle task list | Ctrl ⇧ T | Ctrl ⇧ T | ⌘ ⇧ T | +| Text align center | Ctrl ⇧ E | Ctrl ⇧ E | ⌘ ⇧ E | +| Text align justify | Ctrl ⇧ J | Ctrl ⇧ J | ⌘ ⇧ J | +| Text align left | Ctrl ⇧ L | Ctrl ⇧ L | ⌘ ⇧ L | +| Text align right | Ctrl ⇧ R | Ctrl ⇧ R | ⌘ ⇧ R | +| Underline | Ctrl U | Ctrl U | ⌘ U | +| Toggle highlight | Ctrl Alt H | Ctrl Alt H | ⌘ ⌥ H | +| Toggle text color | Ctrl Alt C | Ctrl Alt C | ⌘ ⌥ C | +| Move line up | Alt ↑ | Alt ↑ | ⌥ ↑ | +| Move line down | Alt ↓ | Alt ↓ | ⌥ ↓ | +| Move parent node up | Alt ⇧ ↑ | Alt ⇧ ↑ | ⌥ ⇧ ↑ | +| Move parent node down | Alt ⇧ ↓ | Alt ⇧ ↓ | ⌥ ⇧ ↓ | +| Clear current line | Ctrl L | Ctrl L | ⌘ L | + +## Related pages + +- [Editor toolbar](/rich-text-editor/rich-text-editor-toolbar) — the same actions as buttons, and how to rearrange them +- [Markdown shortcuts](/rich-text-editor/markdown-notes-editing) — formatting that triggers as you type +- [Find & replace](/rich-text-editor/search-and-replace) — searching inside the note you are editing +- [Search & navigation](/search-and-navigation) — the command palette and quick open +- [Tabs & panes](/rich-text-editor/editor-tabs-and-panes) — moving between open notes diff --git a/docs/help/contents/lock-notes-with-private-vault.md b/docs/help/contents/lock-notes-with-private-vault.md index 4a0c22850..b9d1e0e74 100644 --- a/docs/help/contents/lock-notes-with-private-vault.md +++ b/docs/help/contents/lock-notes-with-private-vault.md @@ -1,51 +1,65 @@ --- title: Locking notes with private vault -description: Password protect your most important and sensitive notes with private vault and store them encrypted even on your device. +pageTitle: How do I password protect a note in Notesnook? +description: Lock individual notes behind a second password with the Notesnook private vault, unlock with biometrics, and change or clear the vault. +keywords: + - password protect notes + - notesnook vault + - lock a note + - private notes app +schema: howto --- # Locking notes -Notesnook is a private notes app. All your notes are encrypted and secure by default. We can not read your notes even if we want to on our servers. However you can still add an extra layer of security and encrypt your most important and sensitive notes by adding them to a vault. +Notesnook is a private notes app: every note is encrypted by default, and nobody here can read your notes on our servers even if we wanted to. However you can still add an extra layer of security and encrypt your most important and sensitive notes by adding them to a vault. Adding notes to private vault is useful when you do not want anyone to read your notes, _even if they have access to your phone_. ## Creating a vault -# [Desktop/Web](#/tab/web) +:::tabs key:platform +== Desktop/Web -1. Go to Settings -2. Go to `Vault` in `Security & privacy` section -3. Click on `Create` button +1. Go to `{{settings}}`. +2. Go to `{{vault}}` in `{{privacyAndSecurity}}` section +3. Click `{{create}}` button 4. Enter the password for your vault (this password will be used to open all locked notes) -5. Click on `Create` in the dialog to create the vault. +5. Click `{{create}}` in the dialog to create the vault. -# [Mobile](#/tab/mobile) +== Mobile -1. Go to Settings from Sidebar -2. Scroll down to `Privacy and Security` section -3. Tap on `Create vault` +1. Go to `{{settings}}`. +2. Open `{{privacyAndSecurity}}` +3. Tap `{{createVault}}` 4. Enter password for the vault (this password will be used to open all locked notes) -5. Tap on `Create` button to create the vault. +5. Tap `{{create}}` button to create the vault. ---- +::: ## Lock a note -# [Desktop/Web](#/tab/web) +:::tabs key:platform +== Desktop/Web -1. Right click on any note -2. Select `Lock` from the context menu +1. Right click any note +2. Select `{{lock}}` from the context menu 3. Enter the password for the vault 4. Press `Enter` key to lock the note -# [Mobile](#/tab/mobile) +== Mobile 1. Tap the ![Three dot button](/three-dot-button.png) button on a note -2. Tap on `Lock` button in the note properties +2. Tap `{{lock}}` button in the note properties 3. Enter password for the vault -4. Press on `Lock` to add note to vault. +4. Tap `{{lock}}` to add note to vault. ---- +::: + +::: danger Locking a note deletes its history +When a note moves into the vault, every stored [version of that note](/note-version-history) is deleted. Restore or copy anything you still need from history **before** you lock it. + +::: ## Open/edit/delete a locked note @@ -53,79 +67,126 @@ To open, edit or delete a locked note, you must provide the password for the vau ## Unlock a note permanently -# [Desktop/Web](#/tab/web) +:::tabs key:platform +== Desktop/Web -1. Right click on any note -2. Select `Unlock` from the context menu +1. Right click any note +2. Click `{{lock}}` again — while a note is locked, a checkmark shows next to it 3. Enter the password for the vault in dialog. -4. Click on Unlock to remove note from vault +4. Click `{{unlock}}` to remove note from vault -# [Mobile](#/tab/mobile) +== Mobile 1. Tap the ![Three dot button](/three-dot-button.png) button on a note -2. Tap on `Unlock` button in the note properties +2. Tap `{{unlock}}` button in the note properties 3. Enter password for the vault -4. Tap on `Unlock` to remove note from vault. +4. Tap `{{unlock}}` to remove note from vault. ---- +::: + +## How long the vault stays unlocked + +Once you enter your vault password, the vault stays unlocked for a while so you aren't retyping it for every note. You choose how long. + +:::tabs key:platform +== Desktop/Web + +1. Go to `{{settings}}`. +2. Open `{{vault}}`. +3. Set `{{lockVaultAfter}}` to `1`, `5`, `10`, `15`, `30`, `45` minutes, `1 hour` or `Never`. + +== Mobile + +1. Go to `{{settings}}`. +2. Open `{{privacyAndSecurity}}` > `{{vault}}`. +3. Set `{{lockVaultAfter}}`. + +::: + +`{{never}}` keeps the vault open until you close the app or lock it yourself. The setting only appears once a vault exists. + +## Unlock with biometrics + +On mobile you can open locked notes with your fingerprint or face instead of typing the vault password. Turn on `{{biometricUnlock}}` in `{{settings}}` > `{{privacyAndSecurity}}` > `{{vault}}` — you unlock with your password once, and it is then stored in the device's own secure keystore, tied to that device. The toggle only appears if the device has biometrics available. + +::: warning Biometrics are per device +Turning biometrics on doesn't replace your vault password, and it doesn't travel with your account. On a new device you'll be asked for the password again — so don't rely on biometrics as your only copy of it. + +::: ## Change vault password -# [Desktop/Web](#/tab/web) +:::tabs key:platform +== Desktop/Web -1. Go to Settings -2. Go to `Vault` in `Security & privacy` section -3. Click on `Change` button next to `Change vault password` heading +1. Go to `{{settings}}`. +2. Go to `{{vault}}` in `{{privacyAndSecurity}}` section +3. Click `{{change}}` button next to `{{changeVaultPassword}}` heading 4. Enter the old and new password for the vault -5. Click on `Change password` to update the password +5. Click `{{changePassword}}` to update the password -# [Mobile](#/tab/mobile) +== Mobile -1. Go to Settings from Sidebar. -2. Scroll down to `Privacy and Security` section -3. Tap on `Vault` -4. Press on `Change vault password` +1. Go to `{{settings}}`. +2. Open `{{privacyAndSecurity}}` +3. Tap `{{vault}}` +4. Tap `{{changeVaultPassword}}` 5. Enter the old and new password for the vault -6. Click on Change to update password +6. Tap `{{change}}` to update the password ---- +::: ## Clear vault -# [Desktop/Web](#/tab/web) +:::tabs key:platform +== Desktop/Web -1. Go to Settings -2. Go to `Vault` in `Security & privacy` section -3. Click on `Clear` button next to `Clear vault` heading -4. Enter your vault password and click on clear vault. All notes in the vault will be deleted. +1. Go to `{{settings}}`. +2. Go to `{{vault}}` in `{{privacyAndSecurity}}` section +3. Click `{{clear}}` button next to `{{clearVault}}` heading +4. Enter your vault password and click clear vault. All notes in the vault will be deleted. -# [Mobile](#/tab/mobile) +== Mobile -1. Go to Settings from Sidebar. -2. Scroll down to `Privacy and Security` section -3. Tap on `Vault` -4. Tap on `Clear vault` -5. Enter your vault password and tap on `Clear`. All notes in the vault will be deleted. +1. Go to `{{settings}}`. +2. Open `{{privacyAndSecurity}}` +3. Tap `{{vault}}` +4. Tap `{{clearVault}}` +5. Enter your vault password and tap `{{clear}}`. All notes in the vault will be deleted. ---- +::: ## Delete vault In the event that you have forgotten your vault password, you can delete the vault and (optionally) delete all the notes in it. -# [Desktop/Web](#/tab/web) +::: danger Permanent data loss +Deleting the vault only requires your account password, but if you also choose to delete all the notes in it, those notes are permanently and irrecoverably destroyed. Because of end-to-end encryption, there is no way for Notesnook to recover a forgotten vault password or restore deleted vault notes afterwards. -1. Go to Settings -2. Go to `Vault` in `Security & privacy` section -3. Click on `Delete` button next to `Delete vault` heading -4. Enter your account password and click on `Delete vault` to delete the vault +::: -# [Mobile](#/tab/mobile) +:::tabs key:platform +== Desktop/Web -1. Go to Settings from Sidebar. -2. Scroll down to `Privacy and Security` section -3. Tap on `Vault` -4. Tap on `Delete vault` -5. Enter your account password and tap on `Delete` to delete the vault +1. Go to `{{settings}}`. +2. Go to `{{vault}}` in `{{privacyAndSecurity}}` section +3. Click `{{delete}}` button next to `{{deleteVault}}` heading +4. Enter your account password and click `{{deleteVault}}` to delete the vault ---- +== Mobile + +1. Go to `{{settings}}`. +2. Open `{{privacyAndSecurity}}` +3. Tap `{{vault}}` +4. Tap `{{deleteVault}}` +5. Enter your account password and tap `{{delete}}` to delete the vault + +::: + +## Related pages + +- [App lock](/app-lock) — locking the whole app +- [How is my data encrypted?](/how-is-my-data-encrypted) — the encryption behind every note +- [Version history](/note-version-history) — going back to an earlier draft +- [Privacy mode](/privacy-mode) — blocking screenshots and screen sharing +- [Recovering your account](/recovering-your-account) — when you forget your password diff --git a/docs/help/contents/mobile-integration/README.md b/docs/help/contents/mobile-integration/README.md deleted file mode 100644 index f51629e41..000000000 --- a/docs/help/contents/mobile-integration/README.md +++ /dev/null @@ -1 +0,0 @@ -# Mobile integration diff --git a/docs/help/contents/mobile-integration/android-quick-actions.md b/docs/help/contents/mobile-integration/android-quick-actions.md new file mode 100644 index 000000000..57b8e59d5 --- /dev/null +++ b/docs/help/contents/mobile-integration/android-quick-actions.md @@ -0,0 +1,67 @@ +--- +title: Android quick actions +pageTitle: Notesnook quick actions on Android +description: Start a note from the Android quick settings tile or the share sheet, and pin notes, notebooks and tags to your launcher. +keywords: + - notesnook android quick settings tile + - notesnook android shortcut + - notesnook make note share + - pin note to android home screen +--- + +# Quick actions on Android + +::: info This page is Android only. +The iOS app has its own share extension — see [share things from other apps.](/mobile-integration/share-things-from-other-apps) + +::: + +Android gives Notesnook three ways to start writing without opening the app first, plus a way to pin any note, notebook, tag or color to your launcher. + +## Add the quick settings tile + +Notesnook ships a quick settings tile labelled `{{newNote}}`. Tapping it collapses the shade and opens the same quick-compose screen the `Make Note` share target uses. + +1. Pull down the notification shade twice to show the full quick settings panel. +2. Tap the edit (pencil) button to see the available tiles. +3. Drag the `{{newNote}}` tile into your active tiles. +4. Tap it any time to start a note. + +The tile requires Android 7.0 or newer. + +<!-- TODO: screenshot — the New note tile in the Android quick settings editor --> + +## Send text and files to Notesnook with "Make Note" + +Notesnook registers as a share target under the name **Make Note**, for text, images, video and other files, including multiple items at once. + +1. In any app, tap `{{share}}`. +2. Choose `Make Note` from the share sheet. +3. Edit the note that opens, then save it. + +The same **Make Note** action appears in the text selection menu: highlight text anywhere in Android, tap the overflow (⋮) in the selection toolbar, and choose `Make Note` to drop the selection into a new note. + +Details on what gets saved are on [share things from other apps](/mobile-integration/share-things-from-other-apps). + +## Pin a note, notebook or tag to your launcher <PlanTag plan="pro" note="Android only" /> + +You can put a note, notebook, tag or color on your home screen as its own icon. Tapping it opens that item directly in Notesnook. + +1. Long press the note, notebook, tag or color — or open its ⋮ menu. +2. Tap `{{addToHome}}`. +3. Android asks whether to add the shortcut. Confirm it. + +The shortcut gets a generated icon based on the item's title and color, and its long label is the note headline or the notebook description. Pinned shortcuts need Android 8.0 or newer. + +::: info What happens if your plan expires +Launcher shortcuts are a Pro feature. See [plans & limits](/plans-and-limits) for everything each plan unlocks. + +::: + +## Related pages + +- [Share things from other apps](/mobile-integration/share-things-from-other-apps) — what the Make Note share target saves +- [Quick notes from notifications](/mobile-integration/quick-note-from-notification) — write from the notification shade +- [Home screen widgets](/mobile-integration/home-screen-widgets) — the quick note, note preview and reminder widgets +- [Pin notes to notifications](/mobile-integration/pin-notes-to-notifications) — keep a note in your notification shade +- [Plans & limits](/plans-and-limits) — which of these need a paid plan diff --git a/docs/help/contents/mobile-integration/home-screen-widgets.md b/docs/help/contents/mobile-integration/home-screen-widgets.md index 1c4645a1e..f54f014ee 100644 --- a/docs/help/contents/mobile-integration/home-screen-widgets.md +++ b/docs/help/contents/mobile-integration/home-screen-widgets.md @@ -1,25 +1,83 @@ +--- +title: Home screen widgets +pageTitle: Notesnook home screen widgets on Android and iOS +description: Add the Notesnook quick note, note preview and reminders widgets to your Android or iOS home screen, and pick which note a widget shows. +keywords: + - notesnook widget + - android notes widget + - ios notes widget + - quick note widget +schema: howto +--- + # Home screen widgets -Basic home screen widgets are availble on both Android & iOS for quick note taking. +Basic home screen widgets are available on both Android and iOS for quick note taking. -# [iOS](#/tab/ios) +:::tabs key:platform +== iOS -1. Long press on home screen -2. Tap on the + button on top left +1. Long press home screen +2. Tap the + button on top left 3. Select Notesnook Quick Note widget and add it to home screen -![Home widget](/static/mobile-integration/ios-quick-note-widget.png) +![The Notesnook Quick Note widget on an iOS home screen](/static/mobile-integration/ios-quick-note-widget.png) -4. Tap on the widget to directly launch the editor in the app. +4. Tap the widget to directly launch the editor in the app. -# [Android](#/tab/android) +== Android -1. Long press on home screen -2. Tap on widgets +1. Long press home screen +2. Tap widgets 3. Add Notesnook widget to home screen -![Home widget](/static/mobile-integration/android-quick-note-widget.png) +![The Notesnook quick note widget on an Android home screen](/static/mobile-integration/android-quick-note-widget.png) -4. Tap on the widget to quickly take a note without launching the app. +4. Tap the widget to quickly take a note without launching the app. ---- +::: + +## Which widgets are available? + +Android ships three widgets; iOS ships one. + +| Widget | Android | iOS | What it does | +| ------------------------------------------ | ------- | --- | ----------------------------------------------------------------------------------- | +| `{{quickNoteTitle}}` (`Quick Note` on iOS) | Yes | Yes | Opens a small note-taking screen straight from the home screen. | +| `{{note}}` | Yes | No | Shows the title and first line of a note you pick, and opens that note when tapped. | +| `{{reminders}}` | Yes | No | Lists your upcoming reminders and lets you add a new one. | + +### Quick note + +On Android the widget is listed as `{{quickNoteTitle}}`, described as `Take a quick note.` in the widget picker, and appears as a single-line bar. Tapping it opens Notesnook's lightweight note screen without starting the full app. + +On iOS the widget is listed as `Quick Note`, described as `A widget to add notes quickly.`, and shows a plus icon over `Add a quick note`. Tapping it launches the app straight into the editor with a new note. + +### Note _(Android only)_ + +The `{{note}}` widget — `Add a note to home screen` in the widget picker — pins one specific note to your home screen and shows its title and headline. It updates whenever you edit the note. + +1. Long press the home screen and open the widget picker. +2. Drag the Notesnook `{{note}}` widget onto your home screen. +3. The `Select a note` screen opens — pick the note you want on the widget. +4. Tap the widget to open that note in the app. + +Because the widget is reconfigurable, you can long press it later and choose a different note. + +<!-- TODO: screenshot — the Android note preview widget on a home screen --> + +### Reminders _(Android only)_ + +The `{{reminders}}` widget — `Quick overview of upcoming reminders` in the widget picker — shows a scrollable list of your upcoming [reminders](/reminders). + +1. Long press the home screen and open the widget picker. +2. Drag the Notesnook `{{reminders}}` widget onto your home screen. +3. Tap a reminder in the list to open it in the app, or tap the `+` button on the widget to create a new reminder. + +<!-- TODO: screenshot — the Android reminders widget on a home screen --> + +## Related pages + +- [Android quick actions](/mobile-integration/android-quick-actions) — tiles, shortcuts and the share sheet +- [Quick notes](/mobile-integration/quick-note-from-notification) — writing without opening the app +- [Reminders](/reminders) — getting notified about a note diff --git a/docs/help/contents/mobile-integration/pin-notes-to-notifications.md b/docs/help/contents/mobile-integration/pin-notes-to-notifications.md index 35bec619e..cbe2fe100 100644 --- a/docs/help/contents/mobile-integration/pin-notes-to-notifications.md +++ b/docs/help/contents/mobile-integration/pin-notes-to-notifications.md @@ -1,11 +1,28 @@ -# Pin to notifications +--- +title: Pin to notifications +pageTitle: Pin a note to your Android notifications +description: Keep a Notesnook note in your Android notification shade so it is always one swipe away, and unpin it when you no longer need it there. +keywords: + - pin note to notification + - android sticky note + - notesnook notification +schema: howto +--- -> error This feature is Android only. +# Pin to notifications <PlanTag plan="pro" note="Android only" /> -Android allows you to add sticky/on-going notifications to the System Notifications drawer. In Notesnook we use this feature to allow you to pin notes in notifications. +Android lets apps keep an ongoing notification in the shade. Notesnook uses that to keep a note one swipe away — useful for a shopping list, a door code, or anything you keep reaching for during the day. -![Pinned notifications](/static/mobile-integration/android-pin-notification.png) +Pinning a note to your notifications needs a Pro plan and is Android only — see [Plans & limits](/plans-and-limits). -1. Tap on the ![Three dot button](/three-dot-button.png) on a note -2. Select `Pin to notifications` -3. The pinned note will appear in notifications permanently until you `Unpin` it. +![A note pinned to the Android notification shade](/static/mobile-integration/android-pin-notification.png) + +1. Tap the ![Three dot button](/three-dot-button.png) on a note +2. Select `{{pinToNotifications}}` +3. The pinned note will appear in notifications permanently until you select `{{unpinFromNotifications}}` on it. + +## Related pages + +- [Quick notes](/mobile-integration/quick-note-from-notification) — writing without opening the app +- [Home screen widgets](/mobile-integration/home-screen-widgets) — notes and reminders on your home screen +- [Plans & limits](/plans-and-limits) — what each plan unlocks and the exact limits diff --git a/docs/help/contents/mobile-integration/quick-note-from-notification.md b/docs/help/contents/mobile-integration/quick-note-from-notification.md index 854b39602..2d0b023b0 100644 --- a/docs/help/contents/mobile-integration/quick-note-from-notification.md +++ b/docs/help/contents/mobile-integration/quick-note-from-notification.md @@ -1,12 +1,29 @@ -# Quick notes from notifications +--- +title: Quick notes +pageTitle: Write a note from the Android notification drawer +description: Turn on the Notesnook quick note notification so you can write a note straight from your Android notification shade without opening the app. +keywords: + - quick note android + - note from notification + - notesnook quick note +schema: howto +--- -> error This feature is Android only. +# Quick notes from notifications <PlanTag plan="pro" note="Android only" /> + +Taking a note from the notification drawer requires a Pro plan and is available on Android only — see [Plans & limits](/plans-and-limits). A simple, quick and convenient way to take notes on your phone from notifications. This works the same way as a messaging/chat app allows you to reply to messages from notifications. -![Notes in notifications](/static/mobile-integration/android-quick-note-notifications.png) +![The Notesnook notification with a Take note button in the Android shade](/static/mobile-integration/android-quick-note-notifications.png) 1. Go to Settings from Side Menu -2. Scroll down to `Productivity` section -3. Enable `Notes in notifications` option -4. Open notifications drawer, you should see a notification with button `Take note`. +2. Open `{{productivity}}` +3. Enable `{{quickNoteNotification}}` +4. Open notifications drawer, you should see a notification with button `{{takeNote}}`. + +## Related pages + +- [Pin to notifications](/mobile-integration/pin-notes-to-notifications) — a note that lives in your shade +- [Android quick actions](/mobile-integration/android-quick-actions) — tiles, shortcuts and the share sheet +- [Plans & limits](/plans-and-limits) — what each plan unlocks and the exact limits diff --git a/docs/help/contents/mobile-integration/share-things-from-other-apps.md b/docs/help/contents/mobile-integration/share-things-from-other-apps.md index fbe49ca1c..22a9e32a3 100644 --- a/docs/help/contents/mobile-integration/share-things-from-other-apps.md +++ b/docs/help/contents/mobile-integration/share-things-from-other-apps.md @@ -1,52 +1,66 @@ +--- +title: Share from other apps +pageTitle: Share text, links and files into Notesnook +description: Send text, links, images and files from any Android or iOS app into a Notesnook note using the share sheet, or clip a whole web page. +keywords: + - share to notesnook + - android share sheet notes + - ios share extension notes +schema: howto +--- + # Share things from other apps -Basic web clipping support is available on both Android & iOS apps via share extensions. +Both the Android and iOS apps register a share extension, so you can send text, links and files from any other app straight into a note. -We are going to use browser app as an example to demonstrate how you can clip information from webpages and other apps on your iPhone. +The examples below use a browser, but the same share sheet works from any app that can share text, links or files. -1. Select some text on a webpage then Tap on "Share" on the context menu. +1. Select some text on a web page, then tap `{{share}}` in the context menu. -# [iOS](#/tab/ios) +:::tabs key:platform +== iOS +![Sharing selected text from a web page on iOS](/static/mobile-integration/clip-selection-ios.png) +== Android +![Sharing selected text from a web page on Android](/static/mobile-integration/clip-selection-android.png) -![Clip selection](/static/mobile-integration/clip-selection-ios.png) +::: -# [Android](#/tab/android) +2. Choose Notesnook from the list of apps. -![Clip selection](/static/mobile-integration/clip-selection-android.png) +:::tabs key:platform +== iOS +![Choosing Notesnook from the iOS share sheet](/static/mobile-integration/select-notesnook-ios.png) +== Android +![Choosing Notesnook from the Android share sheet](/static/mobile-integration/select-notesnook-android.png) ---- +::: -2. Select Notesnook from the list of apps. +3. Tap the save button at the bottom right. The clip is saved as a new note in Notesnook. -# [iOS](#/tab/ios) - -![Select Notesnook](/static/mobile-integration/select-notesnook-ios.png) - -# [Android](#/tab/android) - -![Select Notesnook](/static/mobile-integration/select-notesnook-android.png) - ---- - -3. Tap on the Save button on bottom right corner to save the web clip. This will save the web clip as a new note in Notesnook. - -![Save web clip](/static/mobile-integration/save-clip-ios.png) +![The Save button in the Notesnook share extension](/static/mobile-integration/save-clip-ios.png) ## Append to note -1. Tap on Append to note on the Share extension +1. Tap Append to note on the Share extension 2. Search for a note to append the web clip to and select it 3. Save the web clip. -> info -> -> Share extension will save the note you selected so in future web clips, it will be selected by default until you reset it. +::: info +The share extension remembers the note you picked, so later clips default to the same one until you change it. + +::: ## Clipping full webpage content -1. Share the webpage link to Notesnook share extension -2. Select "Web clip" on bottom left corner +1. Share the web page link to the Notesnook share extension. +2. Tap `Web clip` at the bottom left. -![clip-webpage](/static/mobile-integration/clip-webpage.png) +![The Web clip button in the Notesnook share extension, which saves the whole page](/static/mobile-integration/clip-webpage.png) 3. Save the web clip. + +## Related pages + +- [Android quick actions](/mobile-integration/android-quick-actions) — tiles, shortcuts and the share sheet +- [Clipping your first page](/web-clipper/clipping-your-first-web-page-with-web-clipper) — areas, modes and organizing clips +- [Notebooks](/organizing-notes/organize-notes-using-notebooks) — nested notebooks for structure diff --git a/docs/help/contents/note-links-and-backlinks.md b/docs/help/contents/note-links-and-backlinks.md new file mode 100644 index 000000000..583774db9 --- /dev/null +++ b/docs/help/contents/note-links-and-backlinks.md @@ -0,0 +1,139 @@ +--- +title: Note links +pageTitle: How to link one note to another in Notesnook +description: Link a note to another note in Notesnook, link to a specific paragraph inside it, and see every note that links back to yours in Linked notes and Referenced in. +keywords: + - notesnook note links + - notesnook backlinks + - link notes together + - bi-directional note link +schema: howto +--- + +# How do I link one note to another? + +Put the cursor where you want the link, press `Ctrl+Shift+K` (`⌘+Shift+K` on macOS), pick the note you want, and Notesnook inserts a link to it. The link works in both directions: the note you linked to lists your note under `{{referencedIn}}`, so you never have to maintain a back-link by hand. + +Note links are internal links. They use the `nn://` scheme instead of `http://`, they never leave your device unencrypted, and they keep working after you rename or move a note because they point at the note's internal ID, not its title. + +## Link a note to another note + +:::tabs key:platform +== Desktop/Web + +1. Open the note and place the cursor where the link should go. Selecting some text first turns that text into the link. +2. Press `Ctrl+Shift+K`, or click `{{noteLink}}` in the editor toolbar — it sits next to `{{link}}`. +3. In the `{{newInternalLink}}` dialog, use the `{{searchNoteToLinkPlaceholder}}` box to find the note. +4. Click the note to select it. +5. Click `{{insertLink}}`. + +== Mobile + +1. Open the note and place the cursor where the link should go. +2. Tap `{{noteLink}}` in the editor toolbar. +3. Use the `{{searchNoteToLinkPlaceholder}}` box to find the note. +4. Tap the note to select it. +5. Tap `{{createLink}}`. + +::: + +The link appears as the note's title (or as the text you had selected). Tapping or clicking it opens that note. + +## Link to a specific section inside a note <PlanTag plan="essential" /> + +Every block in a note — paragraph, heading, list, table, callout, code block, image, math block, web clip or embed — carries its own ID, so a link can point at one specific block rather than the top of the note. Opening the link scrolls straight to that block. + +Block-level note links are part of the [Essential plan and above](/plans-and-limits). On the free plan you can still link to whole notes. + +:::tabs key:platform +== Desktop/Web + +1. Press `Ctrl+Shift+K` and select the note, as above. +2. The dialog now lists every block in that note, each tagged with its block type. +3. Use the search box to narrow the list. Type `#` first to search headings only — the placeholder reads `Type # to search for headings`. +4. Click the block you want. The link is inserted immediately, without pressing `{{insertLink}}`. + +To pick a different note, click the `{{linkNoteSelectedNote}}` button at the top of the dialog to deselect it. + +== Mobile + +1. Tap `{{noteLink}}` and select the note, as above. +2. Under `{{linkNoteToSection}}` the sheet lists every block in that note, each tagged with its block type. +3. Use the search box to narrow the list. Type `#` first to search headings only. +4. Tap the block you want. The link is created immediately. + +To pick a different note, tap the selected note at the top of the sheet to deselect it. + +::: + +Blocks with no text show as `{{linkNoteEmptyBlock}}`. If the note you picked is empty you'll see `{{noBlocksOnNote}}` + +::: info Locked notes +A note in your [private vault](/lock-notes-with-private-vault) can be linked to as a whole, but not block by block — its content is encrypted, so Notesnook can't list its blocks. The dialog says `Linking to a specific block is not available for locked notes.` + +::: + +## See which notes link to this one + +Every note keeps two lists: + +- **`{{linkedNotes}}`** — notes that this note links _out_ to. +- **`{{referencedIn}}`** — notes that link _in_ to this note. These are your backlinks, and they're built automatically. + +:::tabs key:platform +== Desktop/Web + +1. Open the note. +2. Click `{{properties}}` in the action bar at the top right of the editor. +3. At the top of the panel, switch between the two lists with the two icon buttons. The count and the current list name are shown on the right. +4. Click any note in the list to open it. +5. Click the arrow next to an entry to expand it — under `{{linkedNotes}}` you get the exact blocks you linked to, and under `{{referencedIn}}` you get each sentence containing the link, with the link text highlighted. Click one to open the note scrolled to that spot. + +== Mobile + +1. Tap the ![Three dot button](/three-dot-button.png) button on a note. +2. Tap `{{references}}`. +3. Switch between the `{{linkedNotes}}` and `{{referencedIn}}` tabs. +4. Tap an entry to open the note, or expand it to see the individual blocks and jump straight to them. + +::: + +When a note has nothing to show you'll see `{{notLinked}}` or `{{notReferenced}}` + +<!-- TODO: screenshot — the Linked notes / Referenced in panel in note properties, with one entry expanded --> + +## Copy a note's link + +Every note has a permanent internal link of the form `nn://note/<note id>`. A block link adds the block to it: `nn://note/<note id>?blockId=<block id>`. Paste it into any other note to create a link by hand, or keep it somewhere as a stable pointer to that note. + +:::tabs key:platform +== Desktop/Web + +1. Right click a note to open the `Note properties` menu. +2. Click `{{copyLink}}`. + +A `{{linkCopied}}` toast confirms it. The link is copied as plain text, as HTML and as Markdown, so pasting into another note produces a ready-made link. + +== Mobile + +1. Tap the ![Three dot button](/three-dot-button.png) button on a note. +2. Tap `{{copyLink}}`. + +A `{{linkCopied}}` toast shows the copied link. + +::: + +Notebooks, tags and colors have internal links too — `nn://notebook/<id>`, `nn://tag/<id>` and `nn://color/<id>` — copied the same way from their own menus. + +::: tip Opening links from outside the app +Internal links only resolve inside Notesnook. A `nn://` link pasted into a browser or another app will open the Notesnook app. To share a note with someone who doesn't use Notesnook, [publish it as a monograph](/publish-notes-with-monographs) instead. + +::: + +## Related pages + +- [Plans and limits](/plans-and-limits) — which plan unlocks block-level note links +- [Editor toolbar](/rich-text-editor/rich-text-editor-toolbar) — where the link tools live and how to rearrange them +- [Note actions](/notes/note-actions) — copying, duplicating and the rest of the per-note menu +- [Search and navigation](/search-and-navigation) — finding the note you want to link to +- [Organize notes using notebooks](/organizing-notes/organize-notes-using-notebooks) — the other way to connect notes together diff --git a/docs/help/contents/note-version-history.md b/docs/help/contents/note-version-history.md index 3e6810d1b..a055f1305 100644 --- a/docs/help/contents/note-version-history.md +++ b/docs/help/contents/note-version-history.md @@ -1,11 +1,24 @@ --- title: Note version history -description: A log of all your notes edit sessions. Preview and go back to older version of a note whenever needed in case of a mishap. +pageTitle: Restore an earlier version of a note +description: Notesnook keeps earlier versions of every note so you can preview and restore them. How it works, how many versions each plan keeps, and how to clear them. +keywords: + - restore previous version of note + - note history notes app + - undo changes to a note +schema: faq +faqs: + - q: Is note version history synced across my devices? + a: No. Version history is kept on the device it was created on. Logging out clears the stored versions for all your notes on that device. + - q: Does note version history count against my storage? + a: No. Storage limits apply to attachments only. Note versions are stored on your device, not on the server. + - q: What happens to a note's history when I delete the note? + a: It goes with the note. Moving a note to trash and then deleting it permanently removes its versions too. --- # Note version history -Notesnook keeps a constant log of all your edit sessions. These are stored as "versions" of a particular notes which you can view & restore to in case of data loss. +Notesnook keeps a log of your editing sessions. Each one is stored as a "version" of the note, so if you delete a paragraph you needed or paste over something important, you can look at an earlier copy and bring it back. ## How it works @@ -13,8 +26,78 @@ Every time you create a new note or open an existing note, Notesnook creates a " In short, if you open a note and edit it at 10 different times during the day, you'll have 10 previous versions of that note. +## View and restore an earlier version + +:::tabs key:platform +== Desktop/Web + +1. Open the note. +2. Open the `{{properties}}` panel from the editor's action bar. +3. Scroll to `{{noteHistory}}` and click a session to preview it. +4. Click `{{restoreThisVersion}}` to bring it back, or `{{saveACopy}}` to keep both. + +== Mobile + +1. Open the note. +2. Tap the three dot button to open `Note properties`. +3. Tap `{{history}}` and choose a session to preview it. +4. Tap `{{restore}}` to bring it back. (`{{saveACopy}}` is desktop and web only.) + +::: + +Restoring replaces the note's current content with the version you picked. To compare instead, `{{saveACopy}}` creates a new note from the old version and leaves the original untouched. + +## How many versions are kept + +Version history is capped by plan, and versions past the cap are **deleted permanently** — they are not hidden or archived. + +| Plan | Versions kept per note | +| ---------------- | ---------------------- | +| Free | 100 | +| Essential | 1,000 | +| Pro and Believer | Unlimited | + +See [plans and limits](/plans-and-limits) for the full comparison. + +## Clear the history of a note + +:::tabs key:platform +== Desktop/Web +There is no button to clear a single note's history on desktop or web. History is cleared when the note is locked, trashed and deleted, or when you log out. + +== Mobile + +1. Open the note. +2. Tap the three dot button to open `Note properties`. +3. Tap `{{history}}`. +4. Tap `{{clearHistory}}` and confirm. + +::: + +Clearing is permanent — once cleared, earlier versions of that note are gone. + +::: danger Locking a note erases its history +Moving a note into the [private vault](/lock-notes-with-private-vault) deletes every stored version of it. Old unencrypted copies of a note you have chosen to lock would defeat the point of locking it. Restore anything you still need **before** you lock the note. + +::: + ## FAQs ### Is note history synced to all my devices? No, at the moment we have decided to keep note version history local only. If you logout from your account, previous versions of all your notes will be cleared. + +### Does version history count against my storage? + +No. Storage limits apply to [attachments](/attachments-and-files) only. Note versions are stored on your device. + +### What happens to history when I delete a note? + +It goes with the note. Moving a note to [trash](/trash) and then deleting it permanently removes its versions too. + +## Related pages + +- [Backup and restore](/backup-and-restore-notes-in-notesnook) — the safety net that does cover every device +- [Private vault](/lock-notes-with-private-vault) — locking notes, and what that does to their history +- [Trash](/trash) — recovering a note you deleted entirely +- [Plans & limits](/plans-and-limits) — how many versions your plan keeps diff --git a/docs/help/contents/notes/note-actions.md b/docs/help/contents/notes/note-actions.md new file mode 100644 index 000000000..083a2550a --- /dev/null +++ b/docs/help/contents/notes/note-actions.md @@ -0,0 +1,288 @@ +--- +title: Note actions +pageTitle: Every per-note action in Notesnook and where to find it +description: Pin, duplicate, print, copy, make read-only, or stop a single note from syncing — every per-note action in Notesnook, on desktop and mobile. +keywords: + - notesnook read only note + - duplicate a note + - copy note as markdown + - notesnook note menu +schema: howto +--- + +# What can I do with a single note? + +Every note has a menu of actions on it. Right click a note on desktop or web, or press the ![Three dot button](/three-dot-button.png) button on mobile. This page covers the actions that aren't documented elsewhere — making a note read-only, duplicating it, copying it, printing it, fixing its creation date, keeping it off sync, and seeing what links to it. + +## Open the note menu + +:::tabs key:platform +== Desktop/Web + +1. Right click a note in the list to open the `Note properties` menu. + +Some of the same switches also live in the editor: open a note, then click `{{properties}}` in the action bar at the top right. + +== Mobile + +1. Tap the ![Three dot button](/three-dot-button.png) button on a note. + +The sheet that opens holds every action for that note. + +::: + +## Open a note in a new tab + +Opening a note in a new tab puts it in its own editor tab instead of replacing whatever is already open, so you can keep two notes on the go at once. + +:::tabs key:platform +== Desktop/Web + +1. Right click the note. +2. Click `{{openInNewTab}}`. It is the first item in the note menu. + +== Mobile + +1. Tap the ![Three dot button](/three-dot-button.png) button on a note. +2. Tap the open-in-new icon at the top right of the properties sheet, beside the note's title. + +The button only appears for notes, and it has no text label. On a phone, tapping it also takes you straight to the editor; on a tablet the note opens in a new tab beside the list you are already looking at. + +::: + +## Unlink a note from all its notebooks + +`{{unlinkFromAll}}` removes the note from every [notebook](/organizing-notes/organize-notes-using-notebooks) it belongs to in one step, without deleting the note or the notebooks. It works on a multiple selection too. + +:::tabs key:platform +== Desktop/Web + +1. Right click the note, or select several notes and right click. +2. Open `{{notebooks}}`. +3. Click `{{unlinkFromAll}}`. + +The action only appears when at least one of the selected notes is already in a notebook. + +== Mobile + +There is no single action that unlinks a note from *every* notebook at once. Two ways round it: + +- **One note** — tap the ![Three dot button](/three-dot-button.png) button, tap `{{addToNotebook}}`, and unselect the notebooks one by one. +- **Several notes, one notebook** — open the notebook, long press a note to start selecting, tap the rest, then tap `{{unlinkNotebook}}` in the header. That removes every selected note from the notebook you are viewing. The action only appears while you are inside a notebook. + +::: + +## Remove all tags from a note + +`{{removeFromAll}}` strips every [tag](/organizing-notes/organize-notes-using-tags) off the note. The tags themselves are not deleted — they stay in your tags list and on your other notes. It works on a multiple selection too. + +:::tabs key:platform +== Desktop/Web + +1. Right click the note, or select several notes and right click. +2. Open `Tags`. +3. Click `{{removeFromAll}}`. + +The action only appears when at least one of the selected notes already has a tag. + +== Mobile + +There is no single action that strips *every* tag at once, but tags can be removed from several notes together: + +1. Long press a note to start selecting, then tap the other notes you want. +2. Tap `{{manageTags}}` in the header. +3. Tap a tag that is currently applied to remove it from every selected note. Tap it again to put it back. + +For a single note, tap the ![Three dot button](/three-dot-button.png) button and `{{addTags}}` instead. + +::: + +## Make a note read-only + +`{{readOnly}}` locks the note against editing. The content stays visible and searchable — you cannot type into it. It is a toggle: turn it off and the note becomes editable again. + +:::tabs key:platform +== Desktop/Web + +1. Right click the note. +2. Click `{{readOnly}}`. + +The editor's `{{properties}}` panel has the same `{{readOnly}}` switch, and it applies to any note tab that is already open. + +== Mobile + +1. Tap the ![Three dot button](/three-dot-button.png) button on the note. +2. Tap `{{readOnly}}`. + +::: + +A read-only note shows a small pencil-lock icon in the notes list. + +## Duplicate a note + +`{{duplicate}}` makes a full copy of the note — title, content and formatting — as a new, separate note. Editing the copy does not touch the original. + +:::tabs key:platform +== Desktop/Web + +1. Right click the note. +2. Click `{{duplicate}}`. + +`{{duplicate}}` also works on a multiple selection: select several notes first and every one of them is copied. + +== Mobile + +1. Tap the ![Three dot button](/three-dot-button.png) button on the note. +2. Tap `{{duplicate}}`. + +A `{{noteDuplicated}}` toast confirms it. + +::: + +## Copy a note's link + +`{{copyLink}}` copies the note's internal `nn://` link to the clipboard, so you can paste it into another note and have a working [note link](/note-links-and-backlinks). On desktop and web the link is copied as plain text, HTML and Markdown at the same time, so pasting into an editor produces a proper link rather than raw text. + +:::tabs key:platform +== Desktop/Web + +1. Right click the note. +2. Click `{{copyLink}}`. + +== Mobile + +1. Tap the ![Three dot button](/three-dot-button.png) button on the note. +2. Tap `{{copyLink}}`. + +::: + +Either way a `{{linkCopied}}` toast confirms it. + +## Copy a note as text or Markdown + +This copies the note's _content_ to the clipboard, not a link to it — for pasting into an email, a chat, or another app. + +:::tabs key:platform +== Desktop/Web + +1. Right click the note. +2. Open `{{copyAs}}`. +3. Choose `Text` for plain text, or `Markdown` to keep headings, lists, bold and links as Markdown syntax. + +A `{{noteCopied}}` toast confirms it. + +== Mobile + +1. Tap the ![Three dot button](/three-dot-button.png) button on the note. +2. Tap `{{copy}}`. + +Mobile copies the note as plain text. There is no Markdown option in the copy action — use `{{export}}` and pick `Markdown` if you need Markdown, or use `{{share}}` to hand the text to another app. + +::: + +If the note is in your [private vault](/lock-notes-with-private-vault) you'll be asked for your vault password first. + +## Print a note + +:::tabs key:platform +== Desktop/Web + +1. Right click the note. +2. Click `{{print}}`. + +The note is rendered as a PDF and handed to your system print dialog, so you can send it to a printer or save it as a PDF file. + +== Mobile + +There is no print action on mobile. Press the ![Three dot button](/three-dot-button.png) button, press `{{export}}`, choose `PDF`, and print or share the resulting file from there. + +::: + +## Change a note's creation date + +Useful after an import, when notes arrive stamped with the day you imported them rather than the day you wrote them. + +:::tabs key:platform +== Desktop/Web + +1. Open the note. +2. Click `{{properties}}` in the action bar at the top right. +3. Next to `{{createdAt}}`, click the pencil icon. +4. In the `{{editCreationDate}}` dialog set the `{{date}}` and `{{time}}` fields — the expected formats are shown under each field, and the calendar icon opens a day picker. +5. Click `{{save}}`. + +The creation date cannot be later than the note's last edited date. If you pick a later one, Notesnook refuses with `{{creationDateCannotBeAfterLastEditedDate}}`. + +== Mobile + +1. Tap the ![Three dot button](/three-dot-button.png) button on a note. +2. Scroll to the dates at the bottom of the properties sheet. +3. Tap the date beside `Created at` — it has a pencil icon after it. +4. Pick a date and time in the picker, then confirm. + +The picker sets the date and the time together, and uses whichever 12- or 24-hour format you have set in [your date and time settings](/customizing-notesnook). There is no separate save step — confirming the picker saves the change. + +The picker won't let you choose anything later than the note's last edited date; those days are unselectable rather than rejected with an error. + +::: + +The pencil only appears on notes. Notebooks, tags and reminders show their dates read-only. + +## Keep a note off sync + +`{{syncOff}}` marks a single note as local-only, independently of your global [sync settings](/sync/sync-settings). It stays on the device you're using and stops syncing; future changes to it never leave that device. + +::: warning This removes the note from your other devices +Turning `{{syncOff}}` on for a note deletes it from every other device you're signed in on, and any changes you make to it afterwards will not sync. This is exactly what the confirmation asks you: `Prevent note from syncing`. Make sure the device you're keeping it on is the one you want it on, and that you have a [backup](/backup-and-restore-notes-in-notesnook). + +::: + +:::tabs key:platform +== Desktop/Web + +1. Right click the note. +2. Click `{{syncOff}}`. +3. Confirm `Prevent note from syncing` with `{{yes}}`. + +Turning it off syncs the note again from that device. The editor `{{properties}}` panel carries the same switch, labelled `{{disableSync}}`. The action only appears when you're logged in. + +== Mobile + +1. Tap the ![Three dot button](/three-dot-button.png) button on the note. +2. Tap `{{syncOff}}`. + +The action only does anything when you're logged in. + +::: + +A local-only note shows a crossed-out sync icon in the notes list. + +## See what links to a note + +`{{references}}` lists the notes on both sides of a note link: the ones this note links out to, and the ones that link back to it. + +:::tabs key:platform +== Desktop/Web + +1. Open the note. +2. Click `{{properties}}` in the action bar at the top right. +3. Switch between `{{linkedNotes}}` and `{{referencedIn}}` at the top of the panel. + +== Mobile + +1. Tap the ![Three dot button](/three-dot-button.png) button on the note. +2. Tap `{{references}}`. +3. Switch between the `{{linkedNotes}}` and `{{referencedIn}}` tabs. + +::: + +See [note links](/note-links-and-backlinks) for what these lists contain and how to jump to an individual paragraph. + +## Related pages + +- [Note links](/note-links-and-backlinks) — linking notes together and reading backlinks +- [Expiring notes](/notes/note-expiry) — have a note delete itself on a date you choose +- [Export notes](/export-notes-from-notesnook) — saving notes as PDF, Markdown, HTML or text files +- [Note version history](/note-version-history) — recovering an earlier version of a note +- [Sync settings](/sync/sync-settings) — the app-wide controls behind per-note `{{syncOff}}` +- [Archive notes](/organizing-notes/archive-notes) — moving a note out of the way without deleting it diff --git a/docs/help/contents/notes/note-expiry.md b/docs/help/contents/notes/note-expiry.md new file mode 100644 index 000000000..ca81a5f30 --- /dev/null +++ b/docs/help/contents/notes/note-expiry.md @@ -0,0 +1,112 @@ +--- +title: Expiring notes +pageTitle: How to make a note delete itself on a date — Notesnook +description: Set an expiry date on a Notesnook note and it moves itself to trash on that day. How to set, change and remove an expiry date, and exactly when it runs. +keywords: + - notesnook expiring notes + - self destructing note + - note expiry date + - auto delete note +schema: howto +--- + +# Expiring notes <PlanTag plan="pro" /> + +An expiring note deletes itself. You pick a date, and on that date Notesnook moves the note to trash for you — useful for a temporary password, a one-off address, or anything you don't want sitting in your notes forever. + +Expiring notes are part of the [Pro plan and above](/plans-and-limits). + +::: warning This deletes your notes +An expiry date is a scheduled deletion. On the day it falls due the note leaves your notes list on every device without asking you again. It lands in [trash](/trash) first, so you have a window to restore it — but once trash is emptied, either by you or by automatic trash cleanup, the note is gone. Notesnook cannot recover deleted notes for you. + +::: + +## Set a note to expire + +:::tabs key:platform +== Desktop/Web + +1. Right click a note to open the `Note properties` menu. +2. Click `{{setExpiry}}`. +3. In the `{{setExpiry}}` dialog, type a date into the `{{date}}` field — the format shown under the field is your own date format from settings — or click the calendar icon and pick a day. +4. Click `{{done}}`. + +The earliest date you can choose is tomorrow, and the latest is one year from today. Notesnook refuses anything else with `{{expiryDateMustBeInTheFuture}}` or `{{expiryDateCannotBeMoreThan1YearInTheFuture}}`. + +== Mobile + +1. Tap the ![Three dot button](/three-dot-button.png) button on a note. +2. Tap `{{setExpiry}}`. +3. Scroll the date picker to the day you want. It opens one week ahead by default, and the earliest date you can choose is tomorrow. +4. Tap `{{setExpiry}}`. + +::: + +An `{{expiryDateSet}}` toast confirms it, and the note now carries an expiry badge in the notes list. + +## Spot a note that is going to expire + +:::tabs key:platform +== Desktop/Web +In the detailed notes list the note shows a bomb icon followed by the expiry date. In compact view only the bomb icon is shown. + +== Mobile + +The note shows a bomb icon with the expiry date next to it, in the same row as its tags and notebooks. + +::: + +<!-- TODO: screenshot — a note in the list showing the expiry badge --> + +## Change or remove an expiry date + +:::tabs key:platform +== Desktop/Web + +1. Right click the note. The menu entry now reads `{{expiryDate}}` instead of `{{setExpiry}}`. +2. Open `{{expiryDate}}` and choose: + - `{{change}}` — reopens the date dialog with the current date filled in. + - `{{remove}}` — clears the expiry date and leaves the note alone. + +== Mobile + +1. Tap the ![Three dot button](/three-dot-button.png) button on the note. The entry now reads `{{unsetExpiry}}`. +2. Tap `{{unsetExpiry}}` to clear the date. + +To move the date instead, clear it with `{{unsetExpiry}}` and then set a new one with `{{setExpiry}}`. + +::: + +Removing an expiry date takes effect immediately — the badge disappears and the note will not be deleted. + +## What happens on the day a note expires + +The note is **moved to trash**, not erased. It is recorded as having been deleted because it expired, and it sits in trash under your normal trash retention rules until it is cleaned up or you delete it permanently. Restoring it from trash brings it back with its content intact, and without an expiry date. + +Notesnook checks for expired notes on your device — there is no server-side job, because the server can't read your notes. + +:::tabs key:platform +== Desktop/Web +The check runs when the app starts and then once a day at midnight, for as long as the app is running. + +== Mobile + +The check runs when the app starts, and again whenever the app notices that the calendar day has changed while it is open. + +::: + +Because the check is local, a note whose date has passed while the app was closed is cleared out the next time you open Notesnook on that device, and the deletion then syncs to your other devices. + +::: info Expired notes and sync +Deletion syncs like any other change. If a note is set to expire and you are offline, nothing happens until a device with the note on it runs the check and then syncs. + +::: + +## Related pages + +- [Plans and limits](/plans-and-limits) — which plan unlocks expiring notes +- [Note actions](/notes/note-actions) — the rest of the per-note menu, including read-only and per-note sync +- [Trash](/trash) — restoring an expired note, and how long trash keeps things +- [Archive notes](/organizing-notes/archive-notes) — get a note out of the way without deleting it +- [Backup and restore](/backup-and-restore-notes-in-notesnook) — keeping a copy before a note deletes itself +- [Reminders](/reminders) — be told about a note on a date instead of deleting it diff --git a/docs/help/contents/notesnook-circle.md b/docs/help/contents/notesnook-circle.md new file mode 100644 index 000000000..14c6f7322 --- /dev/null +++ b/docs/help/contents/notesnook-circle.md @@ -0,0 +1,51 @@ +--- +title: Notesnook Circle +pageTitle: Notesnook Circle — partner discounts for subscribers +description: Notesnook Circle gives paying subscribers discount codes from privacy-focused partner products. How to find it, who can redeem, and how codes work. +keywords: + - notesnook circle + - privacy app discounts + - notesnook partner offers +--- + +# Notesnook Circle <PlanTag plan="essential" /> + +Notesnook Circle brings together trusted partners who share our commitment to privacy, transparency, and user freedom. If you subscribe to Notesnook, you can redeem a discount code from each partner. + +It is not a family plan or a shared workspace — it is a list of partner products with an offer attached to each. + +## Where to find it + +:::tabs key:platform +== Desktop/Web + +1. Go to `{{settings}}`. +2. Open `{{account}}` > `{{notesnookCircle}}`. +3. Pick a partner and redeem its code. + +== Mobile + +1. Go to `{{settings}}`. +2. Open `{{account}}` > `{{notesnookCircle}}`. +3. Pick a partner and redeem its code. + +::: + +## Who can redeem + +Circle is part of the [Essential plan and above](/plans-and-limits), and it needs an **active, confirmed subscription**: + +- **Free plan** — the partner list is visible, but codes cannot be redeemed until you subscribe. +- **During a free trial** — codes unlock once the trial ends and the subscription is confirmed. +- **Expired subscription** — treated the same as the free plan. + +::: info Codes come from the partner, not from Notesnook +Each code is issued by the partner and redeemed on their site under their terms. If a code doesn't work, contact that partner — Notesnook cannot reissue someone else's discount. + +::: + +## Related pages + +- [Plans & limits](/plans-and-limits) — what each plan unlocks, including Circle +- [Gift cards](/gift-cards) — buying and redeeming a Notesnook gift +- [Account settings](/account-settings) — managing your subscription and profile diff --git a/docs/help/contents/notesnook-wrapped.md b/docs/help/contents/notesnook-wrapped.md new file mode 100644 index 000000000..ed8b1f61f --- /dev/null +++ b/docs/help/contents/notesnook-wrapped.md @@ -0,0 +1,61 @@ +--- +title: Notesnook Wrapped +pageTitle: What is Notesnook Wrapped? +description: Notesnook Wrapped is your year of writing summed up — notes, words, busiest month and more — calculated entirely on your own device, every December. +keywords: + - notesnook wrapped + - notesnook year in review + - notesnook writing stats +--- + +# What is Notesnook Wrapped? + +Notesnook Wrapped is a year-in-review of your writing: how many notes you wrote, how many words that came to, the month you were most productive, and what you filed it all under. It is calculated **entirely on your own device** from the notes already stored there — nothing is sent to a server, and nobody at Notesnook can see it. + +## When does Wrapped appear? + +Wrapped covers the current calendar year — 1 January to 31 December — and shows up in December. + +:::tabs key:platform +== Desktop/Web +A `🎉 Wrapped <year>` button appears at the bottom of the side menu during December, while the `Notes` tab is selected and the side menu is not collapsed. Visiting the Wrapped page outside December sends you back to your notes. + +== Mobile + +A `Wrapped <year> 🎉` button replaces the upgrade button at the bottom of the side menu during December. Tap it to open your Wrapped. + +::: + +<!-- TODO: screenshot — the Wrapped button at the bottom of the side menu --> + +## What does Wrapped show? + +Wrapped scrolls through a few slides and finishes on a summary card. Between them you get: + +- **Notes written** this year, and the **total words** across them. +- **Your most productive month** and **your favorite day to write**, each with the number of notes. +- **Notebooks, tags and colors** you created, and how many **attachments** you added. +- **Monographs** you published. +- **Notes per month**, drawn as a bar chart. +- Fun facts: your longest note in words, and your largest attachment. + +Anything you have none of is skipped — if you didn't write any words this year, that slide doesn't appear. + +## Share your Wrapped + +On mobile, the summary card has a `Share with friends` button. It captures the card as an image and hands it to the Android or iOS share sheet, so you can post it or send it to someone. + +On desktop and web there is no share button — the summary card is on screen for you to screenshot. + +::: info It really is local +There is no other way for it to work. Encryption means Notesnook has no idea how many notes you have written or how many words are in them, so the only machine that can count them is yours. + +::: + +## Related pages + +- [How is my data encrypted?](/how-is-my-data-encrypted) — why we can't see your notes or your stats +- [Publish notes with monographs](/publish-notes-with-monographs) — the monographs counted in your Wrapped +- [Attachments and files](/attachments-and-files) — the files Wrapped totals up +- [Organize notes using notebooks](/organizing-notes/organize-notes-using-notebooks) — the notebooks Wrapped ranks +- [Customizing the app](/customizing-notesnook) — the side menu the Wrapped button lives in diff --git a/docs/help/contents/organizing-notes/README.md b/docs/help/contents/organizing-notes/README.md deleted file mode 100644 index d40f9c457..000000000 --- a/docs/help/contents/organizing-notes/README.md +++ /dev/null @@ -1 +0,0 @@ -# Organizing notes diff --git a/docs/help/contents/organizing-notes/archive-notes.md b/docs/help/contents/organizing-notes/archive-notes.md index c32cda892..f60c9258b 100644 --- a/docs/help/contents/organizing-notes/archive-notes.md +++ b/docs/help/contents/organizing-notes/archive-notes.md @@ -1,41 +1,57 @@ --- title: Archive +pageTitle: How do I archive a note in Notesnook? +description: Archive a note in Notesnook to move it out of your notes list without deleting it, then find it again in the Archive section and restore it. +keywords: + - notesnook archive + - archive notes app + - hide notes without deleting +schema: howto --- # Archive notes -Archiving lets you declutter your notes list without permanently deleting notes. Archived notes are moved out of your main `Notes` view and stored in the `Archive` section, which is accessible from the side menu. +Archiving lets you declutter your notes list without permanently deleting notes. Archived notes are moved out of your main `Notes` view and stored in the `{{archive}}` section, which is accessible from the side menu. ## Archive a note -# [Desktop/Web](#/tab/web) +:::tabs key:platform +== Desktop/Web -1. Right click on a note to open `Note properties` menu -2. Click on `Archive` -3. The note will be moved to the `Archive` section +1. Right click a note to open `Note properties` menu +2. Click `{{archive}}` +3. The note will be moved to the `{{archive}}` section -# [Mobile](#/tab/mobile) +== Mobile -1. Press the ![Three dot button](/three-dot-button.png) button on a note -2. Press `Archive` -3. The note will be moved to the `Archive` section +1. Tap the ![Three dot button](/three-dot-button.png) button on a note +2. Tap `{{archive}}` +3. The note will be moved to the `{{archive}}` section ---- +::: ## Unarchive a note -# [Desktop/Web](#/tab/web) +:::tabs key:platform +== Desktop/Web -1. Go to `Archive` from the side menu -2. Right click on a note to open `Note properties` menu -3. Untoggle `Archive` +1. Go to `{{archive}}` from the side menu +2. Right click a note to open `Note properties` menu +3. Click `{{archive}}` again — the checkmark next to it clears 4. The note will be restored to your main `Notes` view -# [Mobile](#/tab/mobile) +== Mobile -1. Go to `Archive` from the side menu -2. Press the ![Three dot button](/three-dot-button.png) button on a note -3. Press `Unarchive` +1. Go to `{{archive}}` from the side menu +2. Tap the ![Three dot button](/three-dot-button.png) button on a note +3. Tap `{{unarchive}}` 4. The note will be restored to your main `Notes` view ---- +::: + +## Related pages + +- [Trash](/trash) — restoring and permanently deleting +- [Pins](/organizing-notes/pin-notes) — keeping a note at the top +- [Notebooks](/organizing-notes/organize-notes-using-notebooks) — nested notebooks for structure +- [Search & navigation](/search-and-navigation) — finding anything, fast diff --git a/docs/help/contents/organizing-notes/organize-notes-using-colors.md b/docs/help/contents/organizing-notes/organize-notes-using-colors.md index 5cb1f6f64..0e4b64da6 100644 --- a/docs/help/contents/organizing-notes/organize-notes-using-colors.md +++ b/docs/help/contents/organizing-notes/organize-notes-using-colors.md @@ -1,85 +1,106 @@ --- title: Colors +pageTitle: How do I color-code notes in Notesnook? +description: Assign colors to notes in Notesnook, rename them, and show or hide color shortcuts in the side menu on desktop and mobile. +keywords: + - notesnook colors + - color code notes + - organize notes by color +schema: howto --- # Organize notes with colors Colors are a simple and quick way to organize your notes. +Free accounts can create up to 7 colors. Essential raises the cap to 20, and Pro and Believer are unlimited — see [Plans & limits](/plans-and-limits). + ## Assign color to a note -# [Desktop/Web](#/tab/web) +:::tabs key:platform +== Desktop/Web -1. Right click on a note -2. Click on `Assign colors` +1. Right click a note +2. Click `{{assignColor}}` 3. Assign a color to the note. -4. You can click on the color again to remove note from that color +4. You can click the color again to remove note from that color -# [Mobile](#/tab/mobile) +== Mobile -1. Press the ![Three dot button](/three-dot-button.png) button +1. Tap the ![Three dot button](/three-dot-button.png) button 2. Assign a color to a note from the color strip. 3. You can press on the color again to remove note from the color ---- +::: -> info -> -> After you assign a color to a note, the note will adapt to that color. -> -> ![Colored note](/colored-note.png) +::: info +After you assign a color to a note, the note will adapt to that color. + +![A note in the list tinted with the colour assigned to it](/colored-note.png) + +::: ## Color Shortcuts By default, all created colors are displayed in the side menu. -![Colored note](/colored-note-sidemenu.png) +![The side menu listing every colour you have created](/colored-note-sidemenu.png) ### Hiding Shortcuts Shortcuts can be hidden on mobile and desktop/web. -# [Desktop/Web](#/tab/web) +:::tabs key:platform +== Desktop/Web -1. Right click on the side menu. +1. Right click the side menu. 2. Select the color you wish to hide. -# [Mobile](#/tab/mobile) +== Mobile 1. Hold down on a color in the menu. A pop-up menu will appear. -2. Select `Reorder`. +2. Select `{{reorder}}`. 3. Select the minus (`-`) button for each color you wish to hide. ---- +::: ### Bringing Back Hidden Shortcuts -# [Desktop/Web](#/tab/web) +:::tabs key:platform +== Desktop/Web -1. Right click on the side menu. +1. Right click the side menu. 2. Select the color you wish to unhide. -# [Mobile](#/tab/mobile) +== Mobile 1. Hold down on an item in the menu. A pop-up menu will appear. -2. Select `Reorder`. +2. Select `{{reorder}}`. 3. Select the plus (`+`) button for each color you wish to unhide. ---- +::: ## Renaming a color Colors can be renamed to anything you want. -# [Desktop/Web](#/tab/web) +:::tabs key:platform +== Desktop/Web -1. Right click on a color in side menu -2. Click on "Rename color" +1. Right click a color in side menu +2. Click "Rename color" 3. Edit the color and click "Save" -# [Mobile](#/tab/mobile) +== Mobile -1. Long press on a color in the side menu +1. Long press a color in the side menu 2. Edit the color name and tap "Save" ---- +::: + +## Related pages + +- [Tags](/organizing-notes/organize-notes-using-tags) — cross-cutting labels +- [Side menu shortcuts](/organizing-notes/side-menu-shortcuts) — pinning notebooks and tags to the sidebar +- [Customizing the app](/customizing-notesnook) — home screen, sidebar, sorting and formats +- [Plans & limits](/plans-and-limits) — what each plan unlocks and the exact limits diff --git a/docs/help/contents/organizing-notes/organize-notes-using-favorites.md b/docs/help/contents/organizing-notes/organize-notes-using-favorites.md index 76a5c2f17..127542a9a 100644 --- a/docs/help/contents/organizing-notes/organize-notes-using-favorites.md +++ b/docs/help/contents/organizing-notes/organize-notes-using-favorites.md @@ -1,5 +1,12 @@ --- title: Favorites +pageTitle: How do I favorite a note in Notesnook? +description: Add a note to favorites in Notesnook for one-tap access from the side menu, and remove it again from the same menu. +keywords: + - notesnook favorites + - favorite a note + - bookmark notes app +schema: howto --- # Add notes to favorites @@ -8,28 +15,36 @@ While you organize your notes with all different types of notebooks, tags and co ## Add a note to favorites -# [Desktop/Web](#/tab/web) +:::tabs key:platform +== Desktop/Web -1. Right click on a note or click on the three-dot more button to open the `Note properties` menu. -2. Toggle `Favorite`. +1. Right click a note or click the three dot more button to open the `Note properties` menu. +2. Toggle `{{favorite}}`. -# [Mobile](#/tab/mobile) +== Mobile -1. Press the ![Three dot button](/three-dot-button.png) button -2. Press `Favorite`. If you do not see the option, scroll the bar left. +1. Tap the ![Three dot button](/three-dot-button.png) button +2. Tap `{{favorite}}`. If you do not see the option, scroll the bar left. ---- +::: ## Removing a note from favorites -# [Desktop/Web](#/tab/web) +:::tabs key:platform +== Desktop/Web -1. Right click on a note or click on the three-dot more button to open the `Note properties` menu. -2. Untoggle `Favorite`. +1. Right click a note or click the three dot more button to open the `Note properties` menu. +2. Click `{{favorite}}` again — the checkmark next to it clears. -# [Mobile](#/tab/mobile) +== Mobile -1. Press the ![Three dot button](/three-dot-button.png) button -2. Press `Unfavorite`. If you do not see the option, scroll the bar left. +1. Tap the ![Three dot button](/three-dot-button.png) button +2. Tap `{{unfavorite}}`. If you do not see the option, scroll the bar left. ---- +::: + +## Related pages + +- [Pins](/organizing-notes/pin-notes) — keeping a note at the top +- [Tags](/organizing-notes/organize-notes-using-tags) — cross-cutting labels +- [Search & navigation](/search-and-navigation) — finding anything, fast diff --git a/docs/help/contents/organizing-notes/organize-notes-using-notebooks.md b/docs/help/contents/organizing-notes/organize-notes-using-notebooks.md index 6f7a7cb51..5ffe2f593 100644 --- a/docs/help/contents/organizing-notes/organize-notes-using-notebooks.md +++ b/docs/help/contents/organizing-notes/organize-notes-using-notebooks.md @@ -1,5 +1,12 @@ --- title: Notebooks +pageTitle: How do I organize notes with notebooks in Notesnook? +description: Create nested notebooks in Notesnook, add one note to several notebooks at once, set a default notebook, and move a notebook out of its parent. +keywords: + - notesnook notebooks + - nested notebooks notes app + - organize notes notebooks +schema: howto --- # Organizing notes with notebooks @@ -8,147 +15,211 @@ Notebooks are a quick and easy way for nested organization of notes. In Notesnook, one note can belong to multiple notebooks. This allows for very flexible organization structures. For example, an author can "link" the character list to all the chapters instead of duplicating it for each chapter. Similarly, a user can link common notes between multiple notebooks without any duplication. +Free accounts can keep up to 50 notebooks. Essential raises the cap to 500, and Pro and Believer are unlimited — see [Plans & limits](/plans-and-limits). + ## Creating a notebook -# [Desktop/Web](#/tab/web) +:::tabs key:platform +== Desktop/Web -1. Click on the Notebook icon at the top of the side menu. -2. Click on the `+` button on top right corner of the side menu. +1. Click the Notebook icon at the top of the side menu. +2. Click the `+` button on top right corner of the side menu. 3. Add a title for your notebook, and optionally, a description. -4. Click on the `Create` button +4. Click the `{{create}}` button 5. You have created your first notebook in Notesnook -# [Mobile](#/tab/mobile) +== Mobile -1. Tap on the Notebook icon at the bottom of the side menu. -2. Press the `+` button on the bottom right corner +1. Tap the Notebook icon at the bottom of the side menu. +2. Tap the `+` button on the bottom right corner 3. Add a title for your notebook, and optionally, a description. -4. Press the `Add` button. +4. Tap the `{{add}}` button. 5. You have created your first notebook in Notesnook. ---- +::: -> info -> -> Starting from v3, you can create new Notebooks inside existing notebooks. Simply go to any notebook's properties and click on "Add notebook". +::: info +You can create notebooks inside other notebooks. Open any notebook's properties and click `{{addNotebook}}`. + +::: ## Editing a notebook -# [Desktop/Web](#/tab/web) +:::tabs key:platform +== Desktop/Web -1. Click on the Notebook icon at the top of the side menu. -2. Right click on the Notebook you want to edit and select "Edit" from dropdown. +1. Click the Notebook icon at the top of the side menu. +2. Right click the Notebook you want to edit and select "Edit" from dropdown. 3. Edit your notebook. -4. Click on `Save` button to save the changes. +4. Click `{{save}}` button to save the changes. -# [Mobile](#/tab/mobile) +== Mobile -1. Tap on the Notebook icon at the bottom of the side menu. +1. Tap the Notebook icon at the bottom of the side menu. 2. Hold down on the notebook you wish to edit. -3. Press on `Edit notebook` +3. Tap `{{editNotebook}}` 4. Edit your notebook -5. Press `Save` button to save changes +5. Tap `{{save}}` button to save changes ---- +::: ## Creating a new note in a notebook -# [Desktop/Web](#/tab/web) +:::tabs key:platform +== Desktop/Web 1. Go to the notebooks section by clicking on the notebook icon, and open a notebook -2. Click on the ![Three dot button](/plus-button-desktop.png) button on the top left corner of the note editor. +2. Click the ![Add a note](/plus-button-desktop.png) button at the top right of the notebook. 3. Start writing in editor to create a note in the notebook -# [Mobile](#/tab/mobile) +== Mobile 1. Go to the notebooks section by tapping on the notebook icon, and open a notebook -2. Tap on the ![Three dot button](/plus-button-desktop.png) button on bottom right corner to open the editor or just **swipe from right to left** to open editor +2. Tap the ![Add a note](/plus-button-desktop.png) button at the bottom right to open the editor, or **swipe from right to left**. 3. Start writing in editor to create a note in the notebook ---- +::: -> info -> -> Once a note is added to a notebook, you will see its path on the bottom of the note in the list. Clicking on it will take you to the respective notebook. Tags are always displayed first. -> -> ![Notebook reference on a note](/notebook-ref.png) +::: info +Once a note is added to a notebook, you will see its path on the bottom of the note in the list. Clicking on it will take you to the respective notebook. Tags are always displayed first. + +![A note in the list showing the notebook it belongs to along the bottom of the row](/notebook-ref.png) + +::: ## Linking an existing note to a notebook -# [Desktop/Web](#/tab/web) +:::tabs key:platform +== Desktop/Web -1. Right click on a note -2. Click on `Notebooks` > `Link to...` +1. Right click a note +2. Click `{{notebooks}}` > `{{linkNotebooks}}` 3. Select the notebook you want to link the note to (you can select multiple) -4. Click `Done` to save your changes. +4. Click `{{done}}` to save your changes. -# [Mobile](#/tab/mobile) +== Mobile 1. Tap the ![Three dot button](/three-dot-button.png) button -2. Tap on `Add to notebook` button. +2. Tap `{{addToNotebook}}` button. 3. Select the notebook you want to link the note to (you can select multiple) 4. Tap the checkmark button in the bottom right to save your changes. ---- +::: -> info -> -> In Notesnook a single note can exist in multiple Notebooks. However, a note will show only one reference on top. +::: info +In Notesnook a single note can exist in multiple Notebooks. However, a note will show only one reference on top. + +::: ## Linking multiple notes to a notebook -# [Desktop/Web](#/tab/web) +:::tabs key:platform +== Desktop/Web 1. Hold `Ctrl` key and click on all the notes you want to link -2. Right click on selected notes -3. Click on `Notebooks` > `Link to...` +2. Right click selected notes +3. Click `{{notebooks}}` > `{{linkNotebooks}}` 4. Select the notebook you want to link the note to (you can select multiple) -5. Click `Done` to save your changes. +5. Click `{{done}}` to save your changes. -# [Mobile](#/tab/mobile) +== Mobile -1. Long press on a note to enter multi selection mode. -2. Tap on all the notes you want to link to select them +1. Long press a note to enter multi selection mode. +2. Tap all the notes you want to link to select them 3. Tap the `+` button in top header 4. Select the notebook you want to link the note to (you can select multiple) -5. Tap the `Save` button at the top right corner to save your changes. +5. Tap the `{{save}}` button at the top right corner to save your changes. ---- +::: ## Remove note from a notebook -# [Desktop/Web](#/tab/web) +:::tabs key:platform +== Desktop/Web -1. Right click on a note -2. Click on `Notebooks` in the context menu -3. Click on the notebook you want to remove the note from +1. Right click a note +2. Click `{{notebooks}}` in the context menu +3. Click the notebook you want to remove the note from -# [Mobile](#/tab/mobile) +== Mobile -1. Press the ![Three dot button](/three-dot-button.png) button -2. Tap on `Add to notebook`. +1. Tap the ![Three dot button](/three-dot-button.png) button +2. Tap `{{addToNotebook}}`. 3. Unselect the notebooks you wish to remove this note from, and press the checkmark in the bottom right corner. -> warn You can only add or remove a note from a notebook. -> -> Attempting to do both at the same time will not work, and the note will not be removed from _any_ notebook. +::: ---- +::: warning You can only add or remove a note from a notebook. +Attempting to do both at the same time will not work, and the note will not be removed from _any_ notebook. +::: -## Move a notebook to trash +## Set a default notebook <PlanTag plan="pro" /> -# [Desktop/Web](#/tab/web) +Every new note you create outside a notebook is added to your default notebook automatically, so quick notes don't pile up in an unsorted list. Only one notebook can be the default at a time. + +:::tabs key:platform +== Desktop/Web 1. Go to the notebooks section by clicking on the notebook icon. -2. Right click on the notebook -3. Click on `Move to trash`. -4. Select whether you also want to move the notes inside this notebook to the trash. +2. Right click the notebook. +3. Click `{{setAsDefault}}`. -# [Mobile](#/tab/mobile) +A checkmark appears next to `{{setAsDefault}}` for the notebook that is currently the default. Click it again to clear the default. + +== Mobile 1. Go to the notebooks section by tapping on the notebook icon. 2. Hold down on the notebook. -3. Press `Move to trash` to delete the notebook. +3. Tap `{{setAsDefault}}`. + +The action reads `{{removeAsDefault}}` on the notebook that is already the default — tap it to clear the default. + +::: + +Setting a default notebook requires a Pro plan. See [Plans & limits](/plans-and-limits). + +## Move a notebook to top + +A notebook nested inside another notebook can be pulled back out to the top level of the notebooks list. + +:::tabs key:platform +== Desktop/Web + +1. Open the parent notebook so the nested notebook is visible. +2. Right click the nested notebook. +3. Click `{{moveToTop}}`. + +The notebook is unlinked from its parent and appears at the root of the notebooks list. The action is hidden for notebooks that are already at the root. + +== Mobile + +1. Hold down on the nested notebook and tap `{{moveNotebookFix}}`. +2. On the `{{moveNotebookFix}}` screen, tap `{{moveToTop}}`. + +::: + +## Move a notebook to trash + +:::tabs key:platform +== Desktop/Web + +1. Go to the notebooks section by clicking on the notebook icon. +2. Right click the notebook +3. Click `{{moveToTrash}}`. 4. Select whether you also want to move the notes inside this notebook to the trash. ---- +== Mobile + +1. Go to the notebooks section by tapping on the notebook icon. +2. Hold down on the notebook. +3. Tap `{{moveToTrash}}` to delete the notebook. +4. Select whether you also want to move the notes inside this notebook to the trash. + +::: + +## Related pages + +- [Tags](/organizing-notes/organize-notes-using-tags) — cross-cutting labels +- [Side menu shortcuts](/organizing-notes/side-menu-shortcuts) — pinning notebooks and tags to the sidebar +- [Note actions](/notes/note-actions) — pin, duplicate, read-only, print and more +- [Plans & limits](/plans-and-limits) — what each plan unlocks and the exact limits diff --git a/docs/help/contents/organizing-notes/organize-notes-using-tags.md b/docs/help/contents/organizing-notes/organize-notes-using-tags.md index ea3f4b63e..ef3c1eb7e 100644 --- a/docs/help/contents/organizing-notes/organize-notes-using-tags.md +++ b/docs/help/contents/organizing-notes/organize-notes-using-tags.md @@ -1,43 +1,83 @@ --- title: Tags +pageTitle: How do I tag notes in Notesnook? +description: Add tags to notes in Notesnook from the editor or the note menu, browse every tag from the side menu, and set a tag that applies to new notes automatically. +keywords: + - notesnook tags + - tag notes app + - organize notes with tags +schema: howto --- # Tags Tags are a quick and simple way to organize your notes. +Free accounts can keep up to 50 tags. Essential raises the cap to 500, and Pro and Believer are unlimited — see [Plans & limits](/plans-and-limits). + ## Tagging a note -# [Desktop/Web](#/tab/web) +:::tabs key:platform +== Desktop/Web -1. Click on the note you want to add tags to and open it in the editor -2. Under the note title, focus the `Add a tag` input. +1. Click the note you want to add tags to and open it in the editor +2. Under the note title, focus the `{{addATag}}` input. 3. Type the tag name & press enter to add it. The input supports auto complete for existing tags -> info -> -> Added tags appear at the bottom of each note item in the notes list. Clicking on the tag takes you to the respective tag. -> -> ![Tagged note](/tagged-note.png) +::: info +Added tags appear at the bottom of each note item in the notes list. Clicking on the tag takes you to the respective tag. -# [Mobile](#/tab/mobile) +![A note in the desktop list showing its tags along the bottom of the row](/tagged-note.png) -1. Press on the ![Three dot button](/three-dot-button.png) button on a note. -2. Tap on `Add tags` button under the title +== Mobile + +1. Tap the ![Three dot button](/three-dot-button.png) button on a note. +2. Tap `{{addTags}}` button under the title 3. Type the tag name then press enter to add it -> info -> -> When you open a note in editor, tags will appear on top of title on mobile. Tapping on a tag will take you to the manage tags screen. -> -> ![Tags in editor mobile](/tags-in-editor.png) -> -> Added tags also appear at the bottom of each note item in the notes list. -> -> ![Tagged note](/tagged-note-mobile.png) +::: info +When you open a note in editor, tags will appear on top of title on mobile. Tapping on a tag will take you to the manage tags screen. ---- +![Tags shown above the note title in the mobile editor](/tags-in-editor.png) + +Added tags also appear at the bottom of each note item in the notes list. + +![A note in the mobile list showing its tags along the bottom of the row](/tagged-note-mobile.png) + +::: ## Accessing your tags You can access all your tags by opening the tag section from the side menu. You can do this by selecting the `#` icon at the very top (bottom on mobile) of the side menu. Clicking on any tag will show you all the notes that are using that tag. + +## Set a default tag <PlanTag plan="pro" /> + +Every new note you create outside a tag gets your default tag applied automatically. Only one tag can be the default at a time. + +:::tabs key:platform +== Desktop/Web + +1. Open the tags section from the side menu. +2. Right click the tag. +3. Click `{{setAsDefault}}`. + +A checkmark marks the tag that is currently the default. Click it again to clear the default. + +== Mobile + +1. Open the tags section from the side menu. +2. Hold down on the tag. +3. Tap `{{setAsDefault}}`. + +The action reads `{{removeAsDefault}}` on the tag that is already the default — tap it to clear the default. + +::: + +Setting a default tag requires a Pro plan. See [Plans & limits](/plans-and-limits). + +## Related pages + +- [Notebooks](/organizing-notes/organize-notes-using-notebooks) — nested notebooks for structure +- [Colors](/organizing-notes/organize-notes-using-colors) — color-coding notes +- [Search & navigation](/search-and-navigation) — finding anything, fast +- [Plans & limits](/plans-and-limits) — what each plan unlocks and the exact limits diff --git a/docs/help/contents/organizing-notes/pin-notes.md b/docs/help/contents/organizing-notes/pin-notes.md index 837e6a8a3..cfbdc80c1 100644 --- a/docs/help/contents/organizing-notes/pin-notes.md +++ b/docs/help/contents/organizing-notes/pin-notes.md @@ -1,5 +1,12 @@ --- title: Pins +pageTitle: How do I pin a note in Notesnook? +description: Pin a note or notebook in Notesnook to keep it at the top of every list, and unpin it when you no longer need it there. +keywords: + - notesnook pin note + - pin note to top + - notesnook pinned notes +schema: howto --- # Pin notes @@ -8,32 +15,40 @@ You can pin an unlimited amount of notes. Pinning enables you to keep important ## Pinning a note/notebook -# [Desktop/Web](#/tab/web) +:::tabs key:platform +== Desktop/Web 1. Go to `Notes` -2. Right click on a note -3. Click on `Pin` to pin a note on top +2. Right click a note +3. Click `{{pin}}` to pin a note on top -# [Mobile](#/tab/mobile) +== Mobile 1. Go to `Notes` -2. Press on the ![Three dot button](/three-dot-button.png) button -3. Press on `Pin` to pin a note on top. If you do not see the option, scroll the top bar left. +2. Tap the ![Three dot button](/three-dot-button.png) button +3. Tap `{{pin}}` to pin a note on top. If you do not see the option, scroll the top bar left. ---- +::: ## Unpinning a note/notebook -# [Desktop/Web](#/tab/web) +:::tabs key:platform +== Desktop/Web 1. Go to `Notes` -2. Right click on a note -3. Untoggle `Pin` to unpin a note. +2. Right click a note +3. Click `{{pin}}` again — the checkmark next to it clears. -# [Mobile](#/tab/mobile) +== Mobile 1. Go to `Notes` -2. Press on the ![Three dot button](/three-dot-button.png) button -3. Press on `Unpin` to unpin the note. If you do not see the option, scroll the top bar left. +2. Tap the ![Three dot button](/three-dot-button.png) button +3. Tap `{{unpin}}` to unpin the note. If you do not see the option, scroll the top bar left. ---- +::: + +## Related pages + +- [Favorites](/organizing-notes/organize-notes-using-favorites) — quick access to the notes you use most +- [Archive](/organizing-notes/archive-notes) — clearing the clutter without deleting +- [Side menu shortcuts](/organizing-notes/side-menu-shortcuts) — pinning notebooks and tags to the sidebar diff --git a/docs/help/contents/organizing-notes/side-menu-shortcuts.md b/docs/help/contents/organizing-notes/side-menu-shortcuts.md index 6e1754764..afe8a50e8 100644 --- a/docs/help/contents/organizing-notes/side-menu-shortcuts.md +++ b/docs/help/contents/organizing-notes/side-menu-shortcuts.md @@ -1,55 +1,78 @@ +--- +title: Side menu shortcuts +pageTitle: How do I add a notebook or tag to the Notesnook side menu? +description: Add shortcuts for the notebooks and tags you use most to the Notesnook side menu, and remove them when they stop being useful. +keywords: + - notesnook shortcuts + - pin notebook to sidebar + - notesnook side menu +schema: howto +--- + # Side menu shortcuts Unlike most note taking apps, you might have noticed that when you add a tag or create a notebook, they are not added automatically to the side menu for quick access. We have seen people with 100's of tags, all on the side menu. Managing those tags from there and finding what you are looking for becomes a pain as your notes collection grows. To tackle this, we have added shortcuts which give you control of what you want to see on your side menu. You can add shortcuts of tags and notebooks to the side menu. +Free accounts can keep up to 10 shortcuts. Essential, Pro and Believer are all unlimited — see [Plans & limits](/plans-and-limits). + ## Creating a shortcut for a notebook -# [Desktop/Web](#/tab/web) +:::tabs key:platform +== Desktop/Web 1. Go to the notebooks section. You can do this by selecting the notebook icon at the top of the side menu. -2. Right click on a notebook -3. Click on `Add shortcut` +2. Right click a notebook +3. Click `{{addShortcut}}` 4. The notebook will appear on the home screen of the side menu. -# [Mobile](#/tab/mobile) +== Mobile 1. Go to the notebooks section. You can do this by selecting the notebook icon at the bottom of the side menu. 2. Hold down on the notebook. -3. Tap on `Add shortcut` +3. Tap `{{addShortcut}}` 4. The notebook will appear on the home screen of the side menu. ---- +::: ## Creating shortcut for a tag -# [Desktop/Web](#/tab/web) +:::tabs key:platform +== Desktop/Web 1. Go to the tags section. You can do this by selecting the `#` icon at the top of the side menu. -2. Right click on a tag -3. Click on `Add shortcut` +2. Right click a tag +3. Click `{{addShortcut}}` 4. The tag will appear on the home screen of the side menu. -# [Mobile](#/tab/mobile) +== Mobile 1. Go to the tags section. You can do this by selecting the `#` icon at the bottom of the side menu. 2. Hold down on the tag. -3. Tap on `Add shortcut` +3. Tap `{{addShortcut}}` 4. The tag will appear on the home screen of the side menu. ---- +::: ## Removing a shortcut -# [Desktop/Web](#/tab/web) +:::tabs key:platform +== Desktop/Web -1. On the home screen of the side menu, right click on a shortcut -2. Click on `Remove shortcut` to remove it from side menu +1. On the home screen of the side menu, right click a shortcut +2. Click `{{removeShortcut}}` to remove it from side menu -# [Mobile](#/tab/mobile) +== Mobile 1. On the home screen of the side menu, long press on any shortcut -2. Press on `Remove shortcut` to remove it from side menu +2. Tap `{{removeShortcut}}` to remove it from side menu ---- +::: + +## Related pages + +- [Notebooks](/organizing-notes/organize-notes-using-notebooks) — nested notebooks for structure +- [Customizing the app](/customizing-notesnook) — home screen, sidebar, sorting and formats +- [Colors](/organizing-notes/organize-notes-using-colors) — color-coding notes +- [Plans & limits](/plans-and-limits) — what each plan unlocks and the exact limits diff --git a/docs/help/contents/plans-and-limits.md b/docs/help/contents/plans-and-limits.md new file mode 100644 index 000000000..19759c7b0 --- /dev/null +++ b/docs/help/contents/plans-and-limits.md @@ -0,0 +1,170 @@ +--- +title: Plans & limits +pageTitle: Notesnook plans, limits and what's free +description: What Free, Essential, Pro and Believer include in Notesnook — storage, file size, notebooks, tags, reminders and every paid feature, with the exact limits. +keywords: + - notesnook free plan limits + - notesnook pro vs essential + - notesnook believer plan + - notesnook storage limit + - notesnook attachment size limit +schema: faq +faqs: + - q: Can I use Notesnook for free? + a: Yes. Notesnook is free to use with unlimited notes, unlimited devices, end-to-end encryption, sync, backups, the private vault and monographs. Paid plans raise storage and file size limits and unlock extras such as task lists, callouts, outline lists, markdown shortcuts and app lock. + - q: Does the Pro plan include everything in Essential? + a: Yes. Plans are cumulative. Every feature unlocked by Essential is also available on Pro and Believer, and everything in Pro is available on the Believer plan. + - q: How much storage do I get on the free plan? + a: The free plan gives you 50 MB of attachment storage per month and a maximum file size of 10 MB. Notes themselves are not counted against storage. + - q: What happens to my notes if my subscription expires? + a: Nothing is deleted. Your notes stay readable and syncable. You return to free-plan limits, so you cannot create new items above the free caps, and paid-only settings such as app lock are automatically switched off. + - q: Does Notesnook offer regional pricing? + a: Yes. Notesnook applies a regional price automatically, based on the country of the payment method you check out with. There is no code to enter. + - q: Can I get a refund? + a: Yes, you can request a refund within 14 days of your purchase. Refunds are requested from inside the app on subscriptions bought through Notesnook web/desktop apps. +--- + +# Notesnook plans and limits + +Notesnook has four plans — **Free**, **Essential**, **Pro** and **Believer** — plus an **Education** plan and a grandfathered **Pro (legacy)** plan for long-time subscribers. + +Everything that makes Notesnook _Notesnook_ is on the free plan: unlimited notes, unlimited devices, end-to-end encryption, sync, backups, the [private vault](/lock-notes-with-private-vault), and [publishing with monographs](/publish-notes-with-monographs). Paid plans raise the storage limits and unlock conveniences on top. + +::: tip Plans are cumulative +Each plan includes everything from the plans below it. A feature marked <PlanTag plan="essential" /> works on Essential, Pro **and** Believer. A feature marked <PlanTag plan="pro" /> works on Pro **and** Believer. + +::: + +## What each plan gives you + +| | Free | Essential | Pro | Believer | +| ------------------- | --------- | --------- | --------- | --------- | +| Notes | Unlimited | Unlimited | Unlimited | Unlimited | +| Devices | Unlimited | Unlimited | Unlimited | Unlimited | +| Storage per month | 50 MB | 1 GB | 10 GB | 25 GB | +| Maximum file size | 10 MB | 100 MB | 1 GB | 5 GB | +| Notebooks | 50 | 500 | Unlimited | Unlimited | +| Tags | 50 | 500 | Unlimited | Unlimited | +| Colors | 7 | 20 | Unlimited | Unlimited | +| Active reminders | 10 | 50 | Unlimited | Unlimited | +| Side menu shortcuts | 10 | Unlimited | Unlimited | Unlimited | +| Note versions kept | 100 | 1,000 | Unlimited | Unlimited | + +Storage counts **attachments only**, meaning images, files, audio and web clips. Your notes themselves never count against it, however many you write. + +## Features unlocked by Essential + +- [Task lists](/rich-text-editor/task-and-todo-lists) — checkable, sortable to-do blocks inside a note +- [Outline lists](/rich-text-editor/outline-lists) — collapsible nested bullets +- [Callouts](/rich-text-editor/callouts) — colored info, tip, warning and quote blocks +- [Block-level note links](/note-links-and-backlinks) — link to a specific paragraph in another note +- [Markdown shortcuts](/rich-text-editor/markdown-notes-editing) — turn `**bold**`, `# heading` and `- list` into formatting as you type +- [Recurring reminders](/reminders) — daily, weekly, monthly and yearly +- [Full offline mode](/sync/sync-settings) — keep every attachment downloaded on your device +- [Customizable side menu](/organizing-notes/side-menu-shortcuts) — reorder and hide items +- Links and embeds inside [published monographs](/publish-notes-with-monographs) +- Notesnook Circle — discounts from privacy-focused partner products + +## Features unlocked by Pro + +- [App lock](/app-lock) — lock the whole app with a PIN, password, biometrics or a security key +- [Expiring notes](/notes/note-expiry) — have a note delete itself on a date you choose +- [Set a default notebook and tag](/organizing-notes/organize-notes-using-notebooks) — send every new note somewhere automatically +- [Custom home screen](/customizing-notesnook) and default sidebar tab +- [Full-quality images](/attachments-and-files) — upload without compression +- [Sync controls](/sync/sync-settings) — turn off automatic, realtime or all syncing +- [Import and export tables as CSV](/rich-text-editor/tables) +- [Monograph view counts](/publish-notes-with-monographs) +- [Two-factor authentication by SMS](/two-factor-authentication) +- Disable [automatic trash cleanup](/trash) +- Font ligatures in the editor +- Save a custom [editor toolbar](/rich-text-editor/rich-text-editor-toolbar) layout +- On Android: [pin a note to your notifications](/mobile-integration/pin-notes-to-notifications), [write notes from the notification drawer](/mobile-integration/quick-note-from-notification), and pin notes to your launcher + +## Believer + +Believer includes everything above and exists for people who want to fund private, open source software. Like Pro, it is sold monthly and yearly as well as a one-time 5-year purchase. + +## Education plan + +The Education plan gives students and teachers **Pro features and Pro limits**. It is not sold from the plan grid. You can [apply for the discount here](https://notesnook.com/education). Education plans do not include a trial. + +## Pro (legacy) + +If you subscribed before the current plans existed, you keep a grandfathered **Pro (legacy)** plan. It gives you everything in the current Pro plan, with two differences: + +- **Unlimited storage** instead of 10 GB a month +- A **512 MB** maximum file size instead of 1 GB + +You keep it for as long as the subscription stays active. + +## Regional pricing + +Paid plans are sold at a regional price, applied automatically from the country of the payment method you check out with. There is no code to enter and nothing to apply for. When a regional price applies to you, the plan shows the original price struck through with the percentage off beside it. + +## Free trials + +You can trial **each plan only once**, and a valid payment method is required to start one — your card is not charged until the trial ends. The trial length is shown on the plan before you start it, and the app tells you the date it ends. + +A trial works like a short subscription: a feature you unlock during it stops working when the trial ends, unless you subscribe. You can cancel a trial at any time. The Education plan has no trial. + +## Refunds + +Refunds are self-service inside the app on subscriptions bought through Notesnook's own checkout, within the window for the billing period you bought: + +| Billing period | Refund window | +| -------------- | --------------------- | +| Monthly | 14 days from purchase | +| Yearly | 14 days from purchase | +| 5-year | 14 days from purchase | + +Requesting a refund downgrades your account to the free plan immediately, and eligible funds are returned within 24 hours. Subscriptions bought through Google Play or the App Store are refunded by that store, not by Notesnook. + +## Changing or cancelling your plan + +:::tabs key:platform +== Desktop/Web + +1. Go to `{{settings}}`. +2. Open `{{subDetails}}`. +3. Choose `{{changePlan}}` to move up or down a tier — the difference is prorated — or turn off `Auto renew` to stop the subscription at the end of the period. + +Your `{{billingHistory}}` on the same screen lists every payment with a downloadable receipt. + +== Mobile + +Subscriptions bought on mobile are managed by the store that sold them. + +1. Go to `{{settings}}`. +2. Open `{{account}}`. +3. Tap your subscription. If it was bought on the store you are using, this opens Google Play or App Store subscription management; otherwise Notesnook tells you where the subscription was bought so you can manage it there. + +::: + +## What happens when a subscription ends + +**Nothing is deleted, and nothing becomes unreadable.** Your notes, notebooks, tags and attachments stay exactly where they are and keep syncing. + +You go back to free-plan limits, which means: + +- you can't create _new_ items above the free caps, but everything you already have stays; +- paid-only settings are switched off — app lock is disabled, a custom home screen resets to the default, and a custom toolbar layout returns to the standard one; +- attachments you already uploaded stay downloadable, even if you're over the free storage limit. + +::: warning Before you let a subscription lapse +If you rely on app lock, take a moment to set up your device's own lock screen first — Notesnook will turn app lock off when the plan expires. + +::: + +## Redeeming a gift or promo code + +Gift codes can only be redeemed on an account that is **currently on the free plan**. See [gift cards](/gift-cards) for the full process. + +<GetNotesnook action="pricing" title="Not sure which plan you need?" text="Start on the free plan — it has unlimited notes and full end-to-end encryption. Upgrade only when you hit a limit that matters to you." /> + +## Related pages + +- [Gift cards](/gift-cards) — buying and redeeming a Notesnook gift +- [How is my data encrypted?](/how-is-my-data-encrypted) — what your subscription is protecting +- [Backup and restore](/backup-and-restore-notes-in-notesnook) — keeping your own copy, on any plan +- [Attachments and files](/attachments-and-files) — what counts against your storage diff --git a/docs/help/contents/privacy-mode.md b/docs/help/contents/privacy-mode.md index ae6071c46..e1059b805 100644 --- a/docs/help/contents/privacy-mode.md +++ b/docs/help/contents/privacy-mode.md @@ -1,36 +1,69 @@ --- title: Privacy mode -description: Privacy mode enables some OS specific settings to enhance your privacy while working in Notesnook. +pageTitle: Block screenshots and screen sharing in Notesnook +description: Privacy mode stops screenshots, screen recording and remote-desktop tools from capturing Notesnook, and hides your notes from the app switcher. +keywords: + - block screenshots notes app + - hide notes from screen share + - private notes screen capture --- # Privacy mode -> error Not available on Linux -> -> Privacy mode is not available on Linux. +Privacy mode stops other software from seeing what's on your screen while Notesnook is open — screenshots, screen recorders and remote-desktop tools get a blank window instead of your notes. + +::: warning Not available on Linux +Privacy mode is not available on Linux. + +::: Privacy mode enables some OS specific settings to enhance your privacy while working in Notesnook. This includes: 1. Disable screen capture 2. Disabling window previews -## [Desktop](#/tab/desktop) +:::tabs key:platform +== Desktop -1. Go to `Settings` -2. Scroll down to `Security & privacy` section -3. Click on `Privacy` -4. Click on toggle next to `Privacy mode` to enable/disable privacy mode. +1. Go to `{{settings}}` +2. Open `{{privacyAndSecurity}}` +3. Click `{{privacy}}` +4. Click toggle next to `{{privacyMode}}` to enable/disable privacy mode. -## [Mobile](#/tab/mobile) +== Mobile -1. Go to `Settings` -2. Scroll down to `Privacy and Security` -3. Tap on `Privacy mode` to enable/disable it +1. Go to `{{settings}}` +2. Open `{{privacyAndSecurity}}` +3. Tap `{{privacyMode}}` to enable/disable it ---- +::: -> info -> -> Privacy mode will prevent all screen capturing software from capturing Notesnook. This includes softwares like TeamViewer, AnyDesk & RustDesk etc. -> -> On Android, it'll also show a blank screen in the Activity Switcher & taking a screenshot will show an error. +::: info +Privacy mode prevents screen capturing software from capturing Notesnook. That includes tools like TeamViewer, AnyDesk and RustDesk. + +On Android, it'll also show a blank screen in the Activity Switcher & taking a screenshot will show an error. + +::: + +## Hide note titles from your window title + +Separately from privacy mode, the desktop and web apps can keep the open note's title out of the browser tab and the window title bar, so a note called "Divorce lawyer" doesn't appear in a screen share or on a projector. + +:::tabs key:platform +== Desktop/Web + +1. Go to `{{settings}}`. +2. Open `{{privacyAndSecurity}}` > `{{privacy}}`. +3. Turn on `{{hideNoteTitle}}`. + +== Mobile + +Mobile hides note content from the app switcher as part of privacy mode above; there is no separate title setting. + +::: + +## Related pages + +- [App lock](/app-lock) — require a PIN, password or biometrics to open Notesnook +- [Private vault](/lock-notes-with-private-vault) — encrypt individual notes behind a second password +- [How is my data encrypted?](/how-is-my-data-encrypted) — what protects your notes in transit and at rest diff --git a/docs/help/contents/public/_redirects b/docs/help/contents/public/_redirects new file mode 100644 index 000000000..53e8b8912 --- /dev/null +++ b/docs/help/contents/public/_redirects @@ -0,0 +1,28 @@ +# Cloudflare Pages redirects. This file is copied to the root of the deployed +# site by VitePress along with everything else in contents/public/. +# +# The legacy docgen site gave every section directory a landing page, generated +# from a README.md that contained nothing but an H1. The VitePress rewrite +# dropped those stubs, so their URLs started 404ing. Every *article* slug came +# across unchanged — only these section indexes moved — so each one is sent to +# the page that now leads its cluster (see STYLE.md, "Internal linking +# clusters") rather than to the home page, which would be a soft 404. +# +# 301 = permanent, so search engines transfer the old URL's ranking to the target. + +/organizing-notes /organizing-notes/organize-notes-using-notebooks 301 +/organizing-notes/ /organizing-notes/organize-notes-using-notebooks 301 +/rich-text-editor /rich-text-editor/rich-text-editor-toolbar 301 +/rich-text-editor/ /rich-text-editor/rich-text-editor-toolbar 301 +/custom-themes /custom-themes/using-themes 301 +/custom-themes/ /custom-themes/using-themes 301 +/mobile-integration /mobile-integration/home-screen-widgets 301 +/mobile-integration/ /mobile-integration/home-screen-widgets 301 +/desktop-integration /desktop-integration/auto-start-on-system-startup 301 +/desktop-integration/ /desktop-integration/auto-start-on-system-startup 301 +/web-clipper /web-clipper/installation 301 +/web-clipper/ /web-clipper/installation 301 +/inbox-api /inbox-api/getting-started 301 +/inbox-api/ /inbox-api/getting-started 301 +/faqs /docs 301 +/faqs/ /docs 301 diff --git a/docs/help/contents/_include/app-lock-setting-on-off.png b/docs/help/contents/public/app-lock-setting-on-off.png similarity index 100% rename from docs/help/contents/_include/app-lock-setting-on-off.png rename to docs/help/contents/public/app-lock-setting-on-off.png diff --git a/docs/help/contents/_include/app-lock-setting-time-out.png b/docs/help/contents/public/app-lock-setting-time-out.png similarity index 100% rename from docs/help/contents/_include/app-lock-setting-time-out.png rename to docs/help/contents/public/app-lock-setting-time-out.png diff --git a/docs/help/contents/_include/app-lock-setting.png b/docs/help/contents/public/app-lock-setting.png similarity index 100% rename from docs/help/contents/_include/app-lock-setting.png rename to docs/help/contents/public/app-lock-setting.png diff --git a/docs/help/contents/_include/auto-backups-desktop.png b/docs/help/contents/public/auto-backups-desktop.png similarity index 100% rename from docs/help/contents/_include/auto-backups-desktop.png rename to docs/help/contents/public/auto-backups-desktop.png diff --git a/docs/help/contents/_include/auto-backups-web.png b/docs/help/contents/public/auto-backups-web.png similarity index 100% rename from docs/help/contents/_include/auto-backups-web.png rename to docs/help/contents/public/auto-backups-web.png diff --git a/docs/help/contents/_include/cell-properties.png b/docs/help/contents/public/cell-properties.png similarity index 100% rename from docs/help/contents/_include/cell-properties.png rename to docs/help/contents/public/cell-properties.png diff --git a/docs/help/contents/_include/change-remove-app-lock-pin.png b/docs/help/contents/public/change-remove-app-lock-pin.png similarity index 100% rename from docs/help/contents/_include/change-remove-app-lock-pin.png rename to docs/help/contents/public/change-remove-app-lock-pin.png diff --git a/docs/help/contents/_include/clear-task-icon.png b/docs/help/contents/public/clear-task-icon.png similarity index 100% rename from docs/help/contents/_include/clear-task-icon.png rename to docs/help/contents/public/clear-task-icon.png diff --git a/docs/help/contents/_include/colored-note-sidemenu.png b/docs/help/contents/public/colored-note-sidemenu.png similarity index 100% rename from docs/help/contents/_include/colored-note-sidemenu.png rename to docs/help/contents/public/colored-note-sidemenu.png diff --git a/docs/help/contents/_include/colored-note.png b/docs/help/contents/public/colored-note.png similarity index 100% rename from docs/help/contents/_include/colored-note.png rename to docs/help/contents/public/colored-note.png diff --git a/docs/help/contents/_include/config-toolbar-desktop.png b/docs/help/contents/public/config-toolbar-desktop.png similarity index 100% rename from docs/help/contents/_include/config-toolbar-desktop.png rename to docs/help/contents/public/config-toolbar-desktop.png diff --git a/docs/help/contents/_include/create-backup-web.png b/docs/help/contents/public/create-backup-web.png similarity index 100% rename from docs/help/contents/_include/create-backup-web.png rename to docs/help/contents/public/create-backup-web.png diff --git a/docs/help/contents/_include/create-table.png b/docs/help/contents/public/create-table.png similarity index 100% rename from docs/help/contents/_include/create-table.png rename to docs/help/contents/public/create-table.png diff --git a/docs/help/contents/_include/custom-themes/Screenshot_20230808-173716.png b/docs/help/contents/public/custom-themes/Screenshot_20230808-173716.png similarity index 100% rename from docs/help/contents/_include/custom-themes/Screenshot_20230808-173716.png rename to docs/help/contents/public/custom-themes/Screenshot_20230808-173716.png diff --git a/docs/help/contents/_include/custom-themes/theme-scope-context-menu.png b/docs/help/contents/public/custom-themes/theme-scope-context-menu.png similarity index 100% rename from docs/help/contents/_include/custom-themes/theme-scope-context-menu.png rename to docs/help/contents/public/custom-themes/theme-scope-context-menu.png diff --git a/docs/help/contents/_include/custom-themes/theme-scope-dialog.png b/docs/help/contents/public/custom-themes/theme-scope-dialog.png similarity index 100% rename from docs/help/contents/_include/custom-themes/theme-scope-dialog.png rename to docs/help/contents/public/custom-themes/theme-scope-dialog.png diff --git a/docs/help/contents/_include/custom-themes/theme-scope-editor-sidebar.png b/docs/help/contents/public/custom-themes/theme-scope-editor-sidebar.png similarity index 100% rename from docs/help/contents/_include/custom-themes/theme-scope-editor-sidebar.png rename to docs/help/contents/public/custom-themes/theme-scope-editor-sidebar.png diff --git a/docs/help/contents/_include/custom-themes/theme-scope-editor-toolbar.png b/docs/help/contents/public/custom-themes/theme-scope-editor-toolbar.png similarity index 100% rename from docs/help/contents/_include/custom-themes/theme-scope-editor-toolbar.png rename to docs/help/contents/public/custom-themes/theme-scope-editor-toolbar.png diff --git a/docs/help/contents/_include/custom-themes/theme-scope-editor.png b/docs/help/contents/public/custom-themes/theme-scope-editor.png similarity index 100% rename from docs/help/contents/_include/custom-themes/theme-scope-editor.png rename to docs/help/contents/public/custom-themes/theme-scope-editor.png diff --git a/docs/help/contents/_include/custom-themes/theme-scope-list.png b/docs/help/contents/public/custom-themes/theme-scope-list.png similarity index 100% rename from docs/help/contents/_include/custom-themes/theme-scope-list.png rename to docs/help/contents/public/custom-themes/theme-scope-list.png diff --git a/docs/help/contents/_include/custom-themes/theme-scope-navigation-menu.png b/docs/help/contents/public/custom-themes/theme-scope-navigation-menu.png similarity index 100% rename from docs/help/contents/_include/custom-themes/theme-scope-navigation-menu.png rename to docs/help/contents/public/custom-themes/theme-scope-navigation-menu.png diff --git a/docs/help/contents/_include/custom-themes/theme-scope-sheet.png b/docs/help/contents/public/custom-themes/theme-scope-sheet.png similarity index 100% rename from docs/help/contents/_include/custom-themes/theme-scope-sheet.png rename to docs/help/contents/public/custom-themes/theme-scope-sheet.png diff --git a/docs/help/contents/_include/custom-themes/theme-scope-status-bar.png b/docs/help/contents/public/custom-themes/theme-scope-status-bar.png similarity index 100% rename from docs/help/contents/_include/custom-themes/theme-scope-status-bar.png rename to docs/help/contents/public/custom-themes/theme-scope-status-bar.png diff --git a/docs/help/contents/_include/custom-themes/theme-scopes-schema.png b/docs/help/contents/public/custom-themes/theme-scopes-schema.png similarity index 100% rename from docs/help/contents/_include/custom-themes/theme-scopes-schema.png rename to docs/help/contents/public/custom-themes/theme-scopes-schema.png diff --git a/docs/help/contents/_include/delete-table.png b/docs/help/contents/public/delete-table.png similarity index 100% rename from docs/help/contents/_include/delete-table.png rename to docs/help/contents/public/delete-table.png diff --git a/docs/help/contents/_include/desktop-enable-app-lock.png b/docs/help/contents/public/desktop-enable-app-lock.png similarity index 100% rename from docs/help/contents/_include/desktop-enable-app-lock.png rename to docs/help/contents/public/desktop-enable-app-lock.png diff --git a/docs/help/contents/_include/desktop-lock-app-after.png b/docs/help/contents/public/desktop-lock-app-after.png similarity index 100% rename from docs/help/contents/_include/desktop-lock-app-after.png rename to docs/help/contents/public/desktop-lock-app-after.png diff --git a/docs/help/contents/_include/desktop-password-key.png b/docs/help/contents/public/desktop-password-key.png similarity index 100% rename from docs/help/contents/_include/desktop-password-key.png rename to docs/help/contents/public/desktop-password-key.png diff --git a/docs/help/contents/_include/drag-drop.gif b/docs/help/contents/public/drag-drop.gif similarity index 100% rename from docs/help/contents/_include/drag-drop.gif rename to docs/help/contents/public/drag-drop.gif diff --git a/docs/help/contents/_include/editor-status-bar-desktop.png b/docs/help/contents/public/editor-status-bar-desktop.png similarity index 100% rename from docs/help/contents/_include/editor-status-bar-desktop.png rename to docs/help/contents/public/editor-status-bar-desktop.png diff --git a/docs/help/contents/_include/favicon.ico b/docs/help/contents/public/favicon.ico similarity index 100% rename from docs/help/contents/_include/favicon.ico rename to docs/help/contents/public/favicon.ico diff --git a/docs/help/contents/_include/first-note-desktop.png b/docs/help/contents/public/first-note-desktop.png similarity index 100% rename from docs/help/contents/_include/first-note-desktop.png rename to docs/help/contents/public/first-note-desktop.png diff --git a/docs/help/contents/_include/first-note-mobile.png b/docs/help/contents/public/first-note-mobile.png similarity index 100% rename from docs/help/contents/_include/first-note-mobile.png rename to docs/help/contents/public/first-note-mobile.png diff --git a/docs/help/contents/public/fonts/Inter-Bold.woff2 b/docs/help/contents/public/fonts/Inter-Bold.woff2 new file mode 100644 index 000000000..b9e3cb3b1 Binary files /dev/null and b/docs/help/contents/public/fonts/Inter-Bold.woff2 differ diff --git a/docs/help/contents/public/fonts/Inter-BoldItalic.woff2 b/docs/help/contents/public/fonts/Inter-BoldItalic.woff2 new file mode 100644 index 000000000..31cd05221 Binary files /dev/null and b/docs/help/contents/public/fonts/Inter-BoldItalic.woff2 differ diff --git a/docs/help/contents/public/fonts/Inter-Italic.woff2 b/docs/help/contents/public/fonts/Inter-Italic.woff2 new file mode 100644 index 000000000..9a1ad2167 Binary files /dev/null and b/docs/help/contents/public/fonts/Inter-Italic.woff2 differ diff --git a/docs/help/contents/public/fonts/Inter-Medium.woff2 b/docs/help/contents/public/fonts/Inter-Medium.woff2 new file mode 100644 index 000000000..fdfdcc699 Binary files /dev/null and b/docs/help/contents/public/fonts/Inter-Medium.woff2 differ diff --git a/docs/help/contents/public/fonts/Inter-MediumItalic.woff2 b/docs/help/contents/public/fonts/Inter-MediumItalic.woff2 new file mode 100644 index 000000000..0dc5a3068 Binary files /dev/null and b/docs/help/contents/public/fonts/Inter-MediumItalic.woff2 differ diff --git a/docs/help/contents/public/fonts/Inter-Regular.woff2 b/docs/help/contents/public/fonts/Inter-Regular.woff2 new file mode 100644 index 000000000..2bcd222ec Binary files /dev/null and b/docs/help/contents/public/fonts/Inter-Regular.woff2 differ diff --git a/docs/help/contents/public/fonts/Inter-SemiBold.woff2 b/docs/help/contents/public/fonts/Inter-SemiBold.woff2 new file mode 100644 index 000000000..fbae113d2 Binary files /dev/null and b/docs/help/contents/public/fonts/Inter-SemiBold.woff2 differ diff --git a/docs/help/contents/public/fonts/Inter-SemiBoldItalic.woff2 b/docs/help/contents/public/fonts/Inter-SemiBoldItalic.woff2 new file mode 100644 index 000000000..d67d01c6c Binary files /dev/null and b/docs/help/contents/public/fonts/Inter-SemiBoldItalic.woff2 differ diff --git a/docs/help/contents/_include/fonts/fira-code-v21-latin-regular.woff2 b/docs/help/contents/public/fonts/fira-code-v21-latin-regular.woff2 similarity index 100% rename from docs/help/contents/_include/fonts/fira-code-v21-latin-regular.woff2 rename to docs/help/contents/public/fonts/fira-code-v21-latin-regular.woff2 diff --git a/docs/help/contents/_include/insert-row-table.gif b/docs/help/contents/public/insert-row-table.gif similarity index 100% rename from docs/help/contents/_include/insert-row-table.gif rename to docs/help/contents/public/insert-row-table.gif diff --git a/docs/help/contents/_include/install-macos.png b/docs/help/contents/public/install-macos.png similarity index 100% rename from docs/help/contents/_include/install-macos.png rename to docs/help/contents/public/install-macos.png diff --git a/docs/help/contents/_include/logo.png b/docs/help/contents/public/logo.png similarity index 100% rename from docs/help/contents/_include/logo.png rename to docs/help/contents/public/logo.png diff --git a/docs/help/contents/_include/markdown-editing.gif b/docs/help/contents/public/markdown-editing.gif similarity index 100% rename from docs/help/contents/_include/markdown-editing.gif rename to docs/help/contents/public/markdown-editing.gif diff --git a/docs/help/contents/_include/notebook-ref.png b/docs/help/contents/public/notebook-ref.png similarity index 100% rename from docs/help/contents/_include/notebook-ref.png rename to docs/help/contents/public/notebook-ref.png diff --git a/docs/help/contents/_include/plus-button-desktop.png b/docs/help/contents/public/plus-button-desktop.png similarity index 100% rename from docs/help/contents/_include/plus-button-desktop.png rename to docs/help/contents/public/plus-button-desktop.png diff --git a/docs/help/contents/_include/plus-button-mobile.png b/docs/help/contents/public/plus-button-mobile.png similarity index 100% rename from docs/help/contents/_include/plus-button-mobile.png rename to docs/help/contents/public/plus-button-mobile.png diff --git a/docs/help/contents/_include/plus-button.png b/docs/help/contents/public/plus-button.png similarity index 100% rename from docs/help/contents/_include/plus-button.png rename to docs/help/contents/public/plus-button.png diff --git a/docs/help/contents/_include/plus-reminder-icon.png b/docs/help/contents/public/plus-reminder-icon.png similarity index 100% rename from docs/help/contents/_include/plus-reminder-icon.png rename to docs/help/contents/public/plus-reminder-icon.png diff --git a/docs/help/contents/_include/publish-theme-1.png b/docs/help/contents/public/publish-theme-1.png similarity index 100% rename from docs/help/contents/_include/publish-theme-1.png rename to docs/help/contents/public/publish-theme-1.png diff --git a/docs/help/contents/_include/publish-theme-10.png b/docs/help/contents/public/publish-theme-10.png similarity index 100% rename from docs/help/contents/_include/publish-theme-10.png rename to docs/help/contents/public/publish-theme-10.png diff --git a/docs/help/contents/_include/publish-theme-2.png b/docs/help/contents/public/publish-theme-2.png similarity index 100% rename from docs/help/contents/_include/publish-theme-2.png rename to docs/help/contents/public/publish-theme-2.png diff --git a/docs/help/contents/_include/publish-theme-3.png b/docs/help/contents/public/publish-theme-3.png similarity index 100% rename from docs/help/contents/_include/publish-theme-3.png rename to docs/help/contents/public/publish-theme-3.png diff --git a/docs/help/contents/_include/publish-theme-4.png b/docs/help/contents/public/publish-theme-4.png similarity index 100% rename from docs/help/contents/_include/publish-theme-4.png rename to docs/help/contents/public/publish-theme-4.png diff --git a/docs/help/contents/_include/publish-theme-5.png b/docs/help/contents/public/publish-theme-5.png similarity index 100% rename from docs/help/contents/_include/publish-theme-5.png rename to docs/help/contents/public/publish-theme-5.png diff --git a/docs/help/contents/_include/publish-theme-6.png b/docs/help/contents/public/publish-theme-6.png similarity index 100% rename from docs/help/contents/_include/publish-theme-6.png rename to docs/help/contents/public/publish-theme-6.png diff --git a/docs/help/contents/_include/publish-theme-7.png b/docs/help/contents/public/publish-theme-7.png similarity index 100% rename from docs/help/contents/_include/publish-theme-7.png rename to docs/help/contents/public/publish-theme-7.png diff --git a/docs/help/contents/_include/publish-theme-8.png b/docs/help/contents/public/publish-theme-8.png similarity index 100% rename from docs/help/contents/_include/publish-theme-8.png rename to docs/help/contents/public/publish-theme-8.png diff --git a/docs/help/contents/_include/publish-theme-9.png b/docs/help/contents/public/publish-theme-9.png similarity index 100% rename from docs/help/contents/_include/publish-theme-9.png rename to docs/help/contents/public/publish-theme-9.png diff --git a/docs/help/contents/_include/resize-table-mobile.gif b/docs/help/contents/public/resize-table-mobile.gif similarity index 100% rename from docs/help/contents/_include/resize-table-mobile.gif rename to docs/help/contents/public/resize-table-mobile.gif diff --git a/docs/help/contents/_include/resize-table.gif b/docs/help/contents/public/resize-table.gif similarity index 100% rename from docs/help/contents/_include/resize-table.gif rename to docs/help/contents/public/resize-table.gif diff --git a/docs/help/contents/_include/restore-backup-mobile.png b/docs/help/contents/public/restore-backup-mobile.png similarity index 100% rename from docs/help/contents/_include/restore-backup-mobile.png rename to docs/help/contents/public/restore-backup-mobile.png diff --git a/docs/help/contents/public/robots.txt b/docs/help/contents/public/robots.txt new file mode 100644 index 000000000..e72e74c63 --- /dev/null +++ b/docs/help/contents/public/robots.txt @@ -0,0 +1,5 @@ +# https://www.robotstxt.org/robotstxt.html +User-agent: * +Allow: / + +Sitemap: https://help.notesnook.com/sitemap.xml diff --git a/docs/help/contents/public/screenshots/editor-code-block.png b/docs/help/contents/public/screenshots/editor-code-block.png new file mode 100644 index 000000000..2961be884 Binary files /dev/null and b/docs/help/contents/public/screenshots/editor-code-block.png differ diff --git a/docs/help/contents/public/screenshots/editor-insert-block-menu.png b/docs/help/contents/public/screenshots/editor-insert-block-menu.png new file mode 100644 index 000000000..e94a04241 Binary files /dev/null and b/docs/help/contents/public/screenshots/editor-insert-block-menu.png differ diff --git a/docs/help/contents/public/screenshots/editor-insert-callout-submenu.png b/docs/help/contents/public/screenshots/editor-insert-callout-submenu.png new file mode 100644 index 000000000..4327bb4e6 Binary files /dev/null and b/docs/help/contents/public/screenshots/editor-insert-callout-submenu.png differ diff --git a/docs/help/contents/public/screenshots/editor-insert-table-menu.png b/docs/help/contents/public/screenshots/editor-insert-table-menu.png new file mode 100644 index 000000000..333882fe4 Binary files /dev/null and b/docs/help/contents/public/screenshots/editor-insert-table-menu.png differ diff --git a/docs/help/contents/public/screenshots/editor-toolbar-more-menu.png b/docs/help/contents/public/screenshots/editor-toolbar-more-menu.png new file mode 100644 index 000000000..e08620bd0 Binary files /dev/null and b/docs/help/contents/public/screenshots/editor-toolbar-more-menu.png differ diff --git a/docs/help/contents/_include/setup-app-lock-pin.png b/docs/help/contents/public/setup-app-lock-pin.png similarity index 100% rename from docs/help/contents/_include/setup-app-lock-pin.png rename to docs/help/contents/public/setup-app-lock-pin.png diff --git a/docs/help/contents/_include/sidemenu.png b/docs/help/contents/public/sidemenu.png similarity index 100% rename from docs/help/contents/_include/sidemenu.png rename to docs/help/contents/public/sidemenu.png diff --git a/docs/help/contents/_include/sort-task-icon.png b/docs/help/contents/public/sort-task-icon.png similarity index 100% rename from docs/help/contents/_include/sort-task-icon.png rename to docs/help/contents/public/sort-task-icon.png diff --git a/docs/help/contents/_include/static/account-recovery/recovery_email.png b/docs/help/contents/public/static/account-recovery/recovery_email.png similarity index 100% rename from docs/help/contents/_include/static/account-recovery/recovery_email.png rename to docs/help/contents/public/static/account-recovery/recovery_email.png diff --git a/docs/help/contents/_include/static/account-recovery/step-1.png b/docs/help/contents/public/static/account-recovery/step-1.png similarity index 100% rename from docs/help/contents/_include/static/account-recovery/step-1.png rename to docs/help/contents/public/static/account-recovery/step-1.png diff --git a/docs/help/contents/_include/static/account-recovery/step-2.png b/docs/help/contents/public/static/account-recovery/step-2.png similarity index 100% rename from docs/help/contents/_include/static/account-recovery/step-2.png rename to docs/help/contents/public/static/account-recovery/step-2.png diff --git a/docs/help/contents/_include/static/account-recovery/step-3.png b/docs/help/contents/public/static/account-recovery/step-3.png similarity index 100% rename from docs/help/contents/_include/static/account-recovery/step-3.png rename to docs/help/contents/public/static/account-recovery/step-3.png diff --git a/docs/help/contents/_include/static/account-recovery/step-4.png b/docs/help/contents/public/static/account-recovery/step-4.png similarity index 100% rename from docs/help/contents/_include/static/account-recovery/step-4.png rename to docs/help/contents/public/static/account-recovery/step-4.png diff --git a/docs/help/contents/_include/static/account-recovery/step-5.png b/docs/help/contents/public/static/account-recovery/step-5.png similarity index 100% rename from docs/help/contents/_include/static/account-recovery/step-5.png rename to docs/help/contents/public/static/account-recovery/step-5.png diff --git a/docs/help/contents/_include/static/account-recovery/step-6.png b/docs/help/contents/public/static/account-recovery/step-6.png similarity index 100% rename from docs/help/contents/_include/static/account-recovery/step-6.png rename to docs/help/contents/public/static/account-recovery/step-6.png diff --git a/docs/help/contents/_include/static/account-recovery/step-7.png b/docs/help/contents/public/static/account-recovery/step-7.png similarity index 100% rename from docs/help/contents/_include/static/account-recovery/step-7.png rename to docs/help/contents/public/static/account-recovery/step-7.png diff --git a/docs/help/contents/_include/static/color_note_desktop.png b/docs/help/contents/public/static/color_note_desktop.png similarity index 100% rename from docs/help/contents/_include/static/color_note_desktop.png rename to docs/help/contents/public/static/color_note_desktop.png diff --git a/docs/help/contents/_include/static/color_note_step_1.jpg b/docs/help/contents/public/static/color_note_step_1.jpg similarity index 100% rename from docs/help/contents/_include/static/color_note_step_1.jpg rename to docs/help/contents/public/static/color_note_step_1.jpg diff --git a/docs/help/contents/_include/static/color_note_step_2.jpg b/docs/help/contents/public/static/color_note_step_2.jpg similarity index 100% rename from docs/help/contents/_include/static/color_note_step_2.jpg rename to docs/help/contents/public/static/color_note_step_2.jpg diff --git a/docs/help/contents/_include/static/color_pinned_side_desktop.png b/docs/help/contents/public/static/color_pinned_side_desktop.png similarity index 100% rename from docs/help/contents/_include/static/color_pinned_side_desktop.png rename to docs/help/contents/public/static/color_pinned_side_desktop.png diff --git a/docs/help/contents/_include/static/desktop-integration/dock-menu-macos.png b/docs/help/contents/public/static/desktop-integration/dock-menu-macos.png similarity index 100% rename from docs/help/contents/_include/static/desktop-integration/dock-menu-macos.png rename to docs/help/contents/public/static/desktop-integration/dock-menu-macos.png diff --git a/docs/help/contents/_include/static/desktop-integration/jumplist-menu-linux.png b/docs/help/contents/public/static/desktop-integration/jumplist-menu-linux.png similarity index 100% rename from docs/help/contents/_include/static/desktop-integration/jumplist-menu-linux.png rename to docs/help/contents/public/static/desktop-integration/jumplist-menu-linux.png diff --git a/docs/help/contents/_include/static/desktop-integration/jumplist-menu-windows.png b/docs/help/contents/public/static/desktop-integration/jumplist-menu-windows.png similarity index 100% rename from docs/help/contents/_include/static/desktop-integration/jumplist-menu-windows.png rename to docs/help/contents/public/static/desktop-integration/jumplist-menu-windows.png diff --git a/docs/help/contents/_include/static/desktop-integration/system-tray-menu.png b/docs/help/contents/public/static/desktop-integration/system-tray-menu.png similarity index 100% rename from docs/help/contents/_include/static/desktop-integration/system-tray-menu.png rename to docs/help/contents/public/static/desktop-integration/system-tray-menu.png diff --git a/docs/help/contents/_include/static/evernote-importer/1.png b/docs/help/contents/public/static/evernote-importer/1.png similarity index 100% rename from docs/help/contents/_include/static/evernote-importer/1.png rename to docs/help/contents/public/static/evernote-importer/1.png diff --git a/docs/help/contents/_include/static/evernote-importer/2.png b/docs/help/contents/public/static/evernote-importer/2.png similarity index 100% rename from docs/help/contents/_include/static/evernote-importer/2.png rename to docs/help/contents/public/static/evernote-importer/2.png diff --git a/docs/help/contents/_include/static/evernote-importer/3.png b/docs/help/contents/public/static/evernote-importer/3.png similarity index 100% rename from docs/help/contents/_include/static/evernote-importer/3.png rename to docs/help/contents/public/static/evernote-importer/3.png diff --git a/docs/help/contents/_include/static/evernote-importer/4.png b/docs/help/contents/public/static/evernote-importer/4.png similarity index 100% rename from docs/help/contents/_include/static/evernote-importer/4.png rename to docs/help/contents/public/static/evernote-importer/4.png diff --git a/docs/help/contents/_include/static/evernote-importer/5.png b/docs/help/contents/public/static/evernote-importer/5.png similarity index 100% rename from docs/help/contents/_include/static/evernote-importer/5.png rename to docs/help/contents/public/static/evernote-importer/5.png diff --git a/docs/help/contents/_include/static/evernote-importer/6.png b/docs/help/contents/public/static/evernote-importer/6.png similarity index 100% rename from docs/help/contents/_include/static/evernote-importer/6.png rename to docs/help/contents/public/static/evernote-importer/6.png diff --git a/docs/help/contents/_include/static/favorite_note.jpg b/docs/help/contents/public/static/favorite_note.jpg similarity index 100% rename from docs/help/contents/_include/static/favorite_note.jpg rename to docs/help/contents/public/static/favorite_note.jpg diff --git a/docs/help/contents/_include/static/favorites_page.png b/docs/help/contents/public/static/favorites_page.png similarity index 100% rename from docs/help/contents/_include/static/favorites_page.png rename to docs/help/contents/public/static/favorites_page.png diff --git a/docs/help/contents/_include/static/google-keep-importer/1.png b/docs/help/contents/public/static/google-keep-importer/1.png similarity index 100% rename from docs/help/contents/_include/static/google-keep-importer/1.png rename to docs/help/contents/public/static/google-keep-importer/1.png diff --git a/docs/help/contents/_include/static/google-keep-importer/2.png b/docs/help/contents/public/static/google-keep-importer/2.png similarity index 100% rename from docs/help/contents/_include/static/google-keep-importer/2.png rename to docs/help/contents/public/static/google-keep-importer/2.png diff --git a/docs/help/contents/_include/static/google-keep-importer/3.png b/docs/help/contents/public/static/google-keep-importer/3.png similarity index 100% rename from docs/help/contents/_include/static/google-keep-importer/3.png rename to docs/help/contents/public/static/google-keep-importer/3.png diff --git a/docs/help/contents/_include/static/google-keep-importer/4.png b/docs/help/contents/public/static/google-keep-importer/4.png similarity index 100% rename from docs/help/contents/_include/static/google-keep-importer/4.png rename to docs/help/contents/public/static/google-keep-importer/4.png diff --git a/docs/help/contents/_include/static/google-keep-importer/5.png b/docs/help/contents/public/static/google-keep-importer/5.png similarity index 100% rename from docs/help/contents/_include/static/google-keep-importer/5.png rename to docs/help/contents/public/static/google-keep-importer/5.png diff --git a/docs/help/contents/_include/static/google-keep-importer/6.png b/docs/help/contents/public/static/google-keep-importer/6.png similarity index 100% rename from docs/help/contents/_include/static/google-keep-importer/6.png rename to docs/help/contents/public/static/google-keep-importer/6.png diff --git a/docs/help/contents/_include/static/html/1.png b/docs/help/contents/public/static/html/1.png similarity index 100% rename from docs/help/contents/_include/static/html/1.png rename to docs/help/contents/public/static/html/1.png diff --git a/docs/help/contents/_include/static/html/2.png b/docs/help/contents/public/static/html/2.png similarity index 100% rename from docs/help/contents/_include/static/html/2.png rename to docs/help/contents/public/static/html/2.png diff --git a/docs/help/contents/_include/static/joplin-importer/1.png b/docs/help/contents/public/static/joplin-importer/1.png similarity index 100% rename from docs/help/contents/_include/static/joplin-importer/1.png rename to docs/help/contents/public/static/joplin-importer/1.png diff --git a/docs/help/contents/_include/static/joplin-importer/2.png b/docs/help/contents/public/static/joplin-importer/2.png similarity index 100% rename from docs/help/contents/_include/static/joplin-importer/2.png rename to docs/help/contents/public/static/joplin-importer/2.png diff --git a/docs/help/contents/_include/static/joplin-importer/3.png b/docs/help/contents/public/static/joplin-importer/3.png similarity index 100% rename from docs/help/contents/_include/static/joplin-importer/3.png rename to docs/help/contents/public/static/joplin-importer/3.png diff --git a/docs/help/contents/_include/static/joplin-importer/4.png b/docs/help/contents/public/static/joplin-importer/4.png similarity index 100% rename from docs/help/contents/_include/static/joplin-importer/4.png rename to docs/help/contents/public/static/joplin-importer/4.png diff --git a/docs/help/contents/_include/static/markdown-importer/1.png b/docs/help/contents/public/static/markdown-importer/1.png similarity index 100% rename from docs/help/contents/_include/static/markdown-importer/1.png rename to docs/help/contents/public/static/markdown-importer/1.png diff --git a/docs/help/contents/_include/static/markdown-importer/2.png b/docs/help/contents/public/static/markdown-importer/2.png similarity index 100% rename from docs/help/contents/_include/static/markdown-importer/2.png rename to docs/help/contents/public/static/markdown-importer/2.png diff --git a/docs/help/contents/_include/static/merge-conflicts-resolution-screen-2.png b/docs/help/contents/public/static/merge-conflicts-resolution-screen-2.png similarity index 100% rename from docs/help/contents/_include/static/merge-conflicts-resolution-screen-2.png rename to docs/help/contents/public/static/merge-conflicts-resolution-screen-2.png diff --git a/docs/help/contents/_include/static/merge-conflicts-resolution-screen-mobile-2.png b/docs/help/contents/public/static/merge-conflicts-resolution-screen-mobile-2.png similarity index 100% rename from docs/help/contents/_include/static/merge-conflicts-resolution-screen-mobile-2.png rename to docs/help/contents/public/static/merge-conflicts-resolution-screen-mobile-2.png diff --git a/docs/help/contents/_include/static/merge-conflicts-resolution-screen-mobile.png b/docs/help/contents/public/static/merge-conflicts-resolution-screen-mobile.png similarity index 100% rename from docs/help/contents/_include/static/merge-conflicts-resolution-screen-mobile.png rename to docs/help/contents/public/static/merge-conflicts-resolution-screen-mobile.png diff --git a/docs/help/contents/_include/static/merge-conflicts-resolution-screen.png b/docs/help/contents/public/static/merge-conflicts-resolution-screen.png similarity index 100% rename from docs/help/contents/_include/static/merge-conflicts-resolution-screen.png rename to docs/help/contents/public/static/merge-conflicts-resolution-screen.png diff --git a/docs/help/contents/_include/static/mobile-integration/android-pin-notification.png b/docs/help/contents/public/static/mobile-integration/android-pin-notification.png similarity index 100% rename from docs/help/contents/_include/static/mobile-integration/android-pin-notification.png rename to docs/help/contents/public/static/mobile-integration/android-pin-notification.png diff --git a/docs/help/contents/_include/static/mobile-integration/android-quick-note-notifications.png b/docs/help/contents/public/static/mobile-integration/android-quick-note-notifications.png similarity index 100% rename from docs/help/contents/_include/static/mobile-integration/android-quick-note-notifications.png rename to docs/help/contents/public/static/mobile-integration/android-quick-note-notifications.png diff --git a/docs/help/contents/_include/static/mobile-integration/android-quick-note-widget.png b/docs/help/contents/public/static/mobile-integration/android-quick-note-widget.png similarity index 100% rename from docs/help/contents/_include/static/mobile-integration/android-quick-note-widget.png rename to docs/help/contents/public/static/mobile-integration/android-quick-note-widget.png diff --git a/docs/help/contents/_include/static/mobile-integration/clip-selection-android.png b/docs/help/contents/public/static/mobile-integration/clip-selection-android.png similarity index 100% rename from docs/help/contents/_include/static/mobile-integration/clip-selection-android.png rename to docs/help/contents/public/static/mobile-integration/clip-selection-android.png diff --git a/docs/help/contents/_include/static/mobile-integration/clip-selection-ios.png b/docs/help/contents/public/static/mobile-integration/clip-selection-ios.png similarity index 100% rename from docs/help/contents/_include/static/mobile-integration/clip-selection-ios.png rename to docs/help/contents/public/static/mobile-integration/clip-selection-ios.png diff --git a/docs/help/contents/_include/static/mobile-integration/clip-webpage.png b/docs/help/contents/public/static/mobile-integration/clip-webpage.png similarity index 100% rename from docs/help/contents/_include/static/mobile-integration/clip-webpage.png rename to docs/help/contents/public/static/mobile-integration/clip-webpage.png diff --git a/docs/help/contents/_include/static/mobile-integration/ios-quick-note-widget.png b/docs/help/contents/public/static/mobile-integration/ios-quick-note-widget.png similarity index 100% rename from docs/help/contents/_include/static/mobile-integration/ios-quick-note-widget.png rename to docs/help/contents/public/static/mobile-integration/ios-quick-note-widget.png diff --git a/docs/help/contents/_include/static/mobile-integration/save-clip-ios.png b/docs/help/contents/public/static/mobile-integration/save-clip-ios.png similarity index 100% rename from docs/help/contents/_include/static/mobile-integration/save-clip-ios.png rename to docs/help/contents/public/static/mobile-integration/save-clip-ios.png diff --git a/docs/help/contents/_include/static/mobile-integration/select-notesnook-android.png b/docs/help/contents/public/static/mobile-integration/select-notesnook-android.png similarity index 100% rename from docs/help/contents/_include/static/mobile-integration/select-notesnook-android.png rename to docs/help/contents/public/static/mobile-integration/select-notesnook-android.png diff --git a/docs/help/contents/_include/static/mobile-integration/select-notesnook-ios.png b/docs/help/contents/public/static/mobile-integration/select-notesnook-ios.png similarity index 100% rename from docs/help/contents/_include/static/mobile-integration/select-notesnook-ios.png rename to docs/help/contents/public/static/mobile-integration/select-notesnook-ios.png diff --git a/docs/help/contents/_include/static/obsidian-importer/1.png b/docs/help/contents/public/static/obsidian-importer/1.png similarity index 100% rename from docs/help/contents/_include/static/obsidian-importer/1.png rename to docs/help/contents/public/static/obsidian-importer/1.png diff --git a/docs/help/contents/_include/static/obsidian-importer/2.png b/docs/help/contents/public/static/obsidian-importer/2.png similarity index 100% rename from docs/help/contents/_include/static/obsidian-importer/2.png rename to docs/help/contents/public/static/obsidian-importer/2.png diff --git a/docs/help/contents/_include/static/onenote-importer/1.png b/docs/help/contents/public/static/onenote-importer/1.png similarity index 100% rename from docs/help/contents/_include/static/onenote-importer/1.png rename to docs/help/contents/public/static/onenote-importer/1.png diff --git a/docs/help/contents/_include/static/onenote-importer/2.png b/docs/help/contents/public/static/onenote-importer/2.png similarity index 100% rename from docs/help/contents/_include/static/onenote-importer/2.png rename to docs/help/contents/public/static/onenote-importer/2.png diff --git a/docs/help/contents/_include/static/onenote-importer/3.png b/docs/help/contents/public/static/onenote-importer/3.png similarity index 100% rename from docs/help/contents/_include/static/onenote-importer/3.png rename to docs/help/contents/public/static/onenote-importer/3.png diff --git a/docs/help/contents/_include/static/onenote-importer/4.png b/docs/help/contents/public/static/onenote-importer/4.png similarity index 100% rename from docs/help/contents/_include/static/onenote-importer/4.png rename to docs/help/contents/public/static/onenote-importer/4.png diff --git a/docs/help/contents/_include/static/onenote-importer/5.png b/docs/help/contents/public/static/onenote-importer/5.png similarity index 100% rename from docs/help/contents/_include/static/onenote-importer/5.png rename to docs/help/contents/public/static/onenote-importer/5.png diff --git a/docs/help/contents/_include/static/plaintext-importer/1.png b/docs/help/contents/public/static/plaintext-importer/1.png similarity index 100% rename from docs/help/contents/_include/static/plaintext-importer/1.png rename to docs/help/contents/public/static/plaintext-importer/1.png diff --git a/docs/help/contents/_include/static/plaintext-importer/2.png b/docs/help/contents/public/static/plaintext-importer/2.png similarity index 100% rename from docs/help/contents/_include/static/plaintext-importer/2.png rename to docs/help/contents/public/static/plaintext-importer/2.png diff --git a/docs/help/contents/_include/static/simplenote-importer/1.png b/docs/help/contents/public/static/simplenote-importer/1.png similarity index 100% rename from docs/help/contents/_include/static/simplenote-importer/1.png rename to docs/help/contents/public/static/simplenote-importer/1.png diff --git a/docs/help/contents/_include/static/simplenote-importer/2.png b/docs/help/contents/public/static/simplenote-importer/2.png similarity index 100% rename from docs/help/contents/_include/static/simplenote-importer/2.png rename to docs/help/contents/public/static/simplenote-importer/2.png diff --git a/docs/help/contents/_include/static/simplenote-importer/3.png b/docs/help/contents/public/static/simplenote-importer/3.png similarity index 100% rename from docs/help/contents/_include/static/simplenote-importer/3.png rename to docs/help/contents/public/static/simplenote-importer/3.png diff --git a/docs/help/contents/_include/static/simplenote-importer/4.png b/docs/help/contents/public/static/simplenote-importer/4.png similarity index 100% rename from docs/help/contents/_include/static/simplenote-importer/4.png rename to docs/help/contents/public/static/simplenote-importer/4.png diff --git a/docs/help/contents/_include/static/simplenote-importer/5.png b/docs/help/contents/public/static/simplenote-importer/5.png similarity index 100% rename from docs/help/contents/_include/static/simplenote-importer/5.png rename to docs/help/contents/public/static/simplenote-importer/5.png diff --git a/docs/help/contents/_include/static/skiff-importer/1.png b/docs/help/contents/public/static/skiff-importer/1.png similarity index 100% rename from docs/help/contents/_include/static/skiff-importer/1.png rename to docs/help/contents/public/static/skiff-importer/1.png diff --git a/docs/help/contents/_include/static/skiff-importer/2.png b/docs/help/contents/public/static/skiff-importer/2.png similarity index 100% rename from docs/help/contents/_include/static/skiff-importer/2.png rename to docs/help/contents/public/static/skiff-importer/2.png diff --git a/docs/help/contents/_include/static/skiff-importer/3.png b/docs/help/contents/public/static/skiff-importer/3.png similarity index 100% rename from docs/help/contents/_include/static/skiff-importer/3.png rename to docs/help/contents/public/static/skiff-importer/3.png diff --git a/docs/help/contents/_include/static/skiff-importer/4.png b/docs/help/contents/public/static/skiff-importer/4.png similarity index 100% rename from docs/help/contents/_include/static/skiff-importer/4.png rename to docs/help/contents/public/static/skiff-importer/4.png diff --git a/docs/help/contents/_include/static/spell-checker-languages.png b/docs/help/contents/public/static/spell-checker-languages.png similarity index 100% rename from docs/help/contents/_include/static/spell-checker-languages.png rename to docs/help/contents/public/static/spell-checker-languages.png diff --git a/docs/help/contents/_include/static/standard-notes-importer/1.png b/docs/help/contents/public/static/standard-notes-importer/1.png similarity index 100% rename from docs/help/contents/_include/static/standard-notes-importer/1.png rename to docs/help/contents/public/static/standard-notes-importer/1.png diff --git a/docs/help/contents/_include/static/standard-notes-importer/2.png b/docs/help/contents/public/static/standard-notes-importer/2.png similarity index 100% rename from docs/help/contents/_include/static/standard-notes-importer/2.png rename to docs/help/contents/public/static/standard-notes-importer/2.png diff --git a/docs/help/contents/_include/static/standard-notes-importer/3.png b/docs/help/contents/public/static/standard-notes-importer/3.png similarity index 100% rename from docs/help/contents/_include/static/standard-notes-importer/3.png rename to docs/help/contents/public/static/standard-notes-importer/3.png diff --git a/docs/help/contents/_include/static/standard-notes-importer/4.png b/docs/help/contents/public/static/standard-notes-importer/4.png similarity index 100% rename from docs/help/contents/_include/static/standard-notes-importer/4.png rename to docs/help/contents/public/static/standard-notes-importer/4.png diff --git a/docs/help/contents/_include/static/standard-notes-importer/5.png b/docs/help/contents/public/static/standard-notes-importer/5.png similarity index 100% rename from docs/help/contents/_include/static/standard-notes-importer/5.png rename to docs/help/contents/public/static/standard-notes-importer/5.png diff --git a/docs/help/contents/_include/static/web-clipper/assign-a-tag.gif b/docs/help/contents/public/static/web-clipper/assign-a-tag.gif similarity index 100% rename from docs/help/contents/_include/static/web-clipper/assign-a-tag.gif rename to docs/help/contents/public/static/web-clipper/assign-a-tag.gif diff --git a/docs/help/contents/_include/static/web-clipper/chrome-dev-mode.png b/docs/help/contents/public/static/web-clipper/chrome-dev-mode.png similarity index 100% rename from docs/help/contents/_include/static/web-clipper/chrome-dev-mode.png rename to docs/help/contents/public/static/web-clipper/chrome-dev-mode.png diff --git a/docs/help/contents/_include/static/web-clipper/chrome-pin-to-toolbar.gif b/docs/help/contents/public/static/web-clipper/chrome-pin-to-toolbar.gif similarity index 100% rename from docs/help/contents/_include/static/web-clipper/chrome-pin-to-toolbar.gif rename to docs/help/contents/public/static/web-clipper/chrome-pin-to-toolbar.gif diff --git a/docs/help/contents/_include/static/web-clipper/clipping-area.png b/docs/help/contents/public/static/web-clipper/clipping-area.png similarity index 100% rename from docs/help/contents/_include/static/web-clipper/clipping-area.png rename to docs/help/contents/public/static/web-clipper/clipping-area.png diff --git a/docs/help/contents/_include/static/web-clipper/firefox-pin-to-toolbar.gif b/docs/help/contents/public/static/web-clipper/firefox-pin-to-toolbar.gif similarity index 100% rename from docs/help/contents/_include/static/web-clipper/firefox-pin-to-toolbar.gif rename to docs/help/contents/public/static/web-clipper/firefox-pin-to-toolbar.gif diff --git a/docs/help/contents/_include/static/web-clipper/organize-web-clip.png b/docs/help/contents/public/static/web-clipper/organize-web-clip.png similarity index 100% rename from docs/help/contents/_include/static/web-clipper/organize-web-clip.png rename to docs/help/contents/public/static/web-clipper/organize-web-clip.png diff --git a/docs/help/contents/_include/static/web-clipper/selected-nodes-popup.png b/docs/help/contents/public/static/web-clipper/selected-nodes-popup.png similarity index 100% rename from docs/help/contents/_include/static/web-clipper/selected-nodes-popup.png rename to docs/help/contents/public/static/web-clipper/selected-nodes-popup.png diff --git a/docs/help/contents/_include/static/web-clipper/web-clip-embed.gif b/docs/help/contents/public/static/web-clipper/web-clip-embed.gif similarity index 100% rename from docs/help/contents/_include/static/web-clipper/web-clip-embed.gif rename to docs/help/contents/public/static/web-clipper/web-clip-embed.gif diff --git a/docs/help/contents/_include/static/zoho-importer/1.png b/docs/help/contents/public/static/zoho-importer/1.png similarity index 100% rename from docs/help/contents/_include/static/zoho-importer/1.png rename to docs/help/contents/public/static/zoho-importer/1.png diff --git a/docs/help/contents/_include/static/zoho-importer/2.png b/docs/help/contents/public/static/zoho-importer/2.png similarity index 100% rename from docs/help/contents/_include/static/zoho-importer/2.png rename to docs/help/contents/public/static/zoho-importer/2.png diff --git a/docs/help/contents/_include/static/zoho-importer/3.png b/docs/help/contents/public/static/zoho-importer/3.png similarity index 100% rename from docs/help/contents/_include/static/zoho-importer/3.png rename to docs/help/contents/public/static/zoho-importer/3.png diff --git a/docs/help/contents/_include/static/zoho-importer/4.png b/docs/help/contents/public/static/zoho-importer/4.png similarity index 100% rename from docs/help/contents/_include/static/zoho-importer/4.png rename to docs/help/contents/public/static/zoho-importer/4.png diff --git a/docs/help/contents/_include/static/zoho-importer/5.png b/docs/help/contents/public/static/zoho-importer/5.png similarity index 100% rename from docs/help/contents/_include/static/zoho-importer/5.png rename to docs/help/contents/public/static/zoho-importer/5.png diff --git a/docs/help/contents/_include/static/zoho-importer/6.png b/docs/help/contents/public/static/zoho-importer/6.png similarity index 100% rename from docs/help/contents/_include/static/zoho-importer/6.png rename to docs/help/contents/public/static/zoho-importer/6.png diff --git a/docs/help/contents/_include/static/zoho-importer/7.png b/docs/help/contents/public/static/zoho-importer/7.png similarity index 100% rename from docs/help/contents/_include/static/zoho-importer/7.png rename to docs/help/contents/public/static/zoho-importer/7.png diff --git a/docs/help/contents/_include/table-delete-column.png b/docs/help/contents/public/table-delete-column.png similarity index 100% rename from docs/help/contents/_include/table-delete-column.png rename to docs/help/contents/public/table-delete-column.png diff --git a/docs/help/contents/_include/table-example-22.png b/docs/help/contents/public/table-example-22.png similarity index 100% rename from docs/help/contents/_include/table-example-22.png rename to docs/help/contents/public/table-example-22.png diff --git a/docs/help/contents/_include/table-insert-column.gif b/docs/help/contents/public/table-insert-column.gif similarity index 100% rename from docs/help/contents/_include/table-insert-column.gif rename to docs/help/contents/public/table-insert-column.gif diff --git a/docs/help/contents/_include/table-merge-cells.gif b/docs/help/contents/public/table-merge-cells.gif similarity index 100% rename from docs/help/contents/_include/table-merge-cells.gif rename to docs/help/contents/public/table-merge-cells.gif diff --git a/docs/help/contents/_include/table-move-column.gif b/docs/help/contents/public/table-move-column.gif similarity index 100% rename from docs/help/contents/_include/table-move-column.gif rename to docs/help/contents/public/table-move-column.gif diff --git a/docs/help/contents/_include/table-move-row.gif b/docs/help/contents/public/table-move-row.gif similarity index 100% rename from docs/help/contents/_include/table-move-row.gif rename to docs/help/contents/public/table-move-row.gif diff --git a/docs/help/contents/_include/table-row-delete.png b/docs/help/contents/public/table-row-delete.png similarity index 100% rename from docs/help/contents/_include/table-row-delete.png rename to docs/help/contents/public/table-row-delete.png diff --git a/docs/help/contents/_include/table-split-cell.gif b/docs/help/contents/public/table-split-cell.gif similarity index 100% rename from docs/help/contents/_include/table-split-cell.gif rename to docs/help/contents/public/table-split-cell.gif diff --git a/docs/help/contents/_include/tagged-note-mobile.png b/docs/help/contents/public/tagged-note-mobile.png similarity index 100% rename from docs/help/contents/_include/tagged-note-mobile.png rename to docs/help/contents/public/tagged-note-mobile.png diff --git a/docs/help/contents/_include/tagged-note.png b/docs/help/contents/public/tagged-note.png similarity index 100% rename from docs/help/contents/_include/tagged-note.png rename to docs/help/contents/public/tagged-note.png diff --git a/docs/help/contents/_include/tags-in-editor.png b/docs/help/contents/public/tags-in-editor.png similarity index 100% rename from docs/help/contents/_include/tags-in-editor.png rename to docs/help/contents/public/tags-in-editor.png diff --git a/docs/help/contents/_include/task-drag-drop.png b/docs/help/contents/public/task-drag-drop.png similarity index 100% rename from docs/help/contents/_include/task-drag-drop.png rename to docs/help/contents/public/task-drag-drop.png diff --git a/docs/help/contents/_include/task-header-title.png b/docs/help/contents/public/task-header-title.png similarity index 100% rename from docs/help/contents/_include/task-header-title.png rename to docs/help/contents/public/task-header-title.png diff --git a/docs/help/contents/_include/theme-builder-actions.png b/docs/help/contents/public/theme-builder-actions.png similarity index 100% rename from docs/help/contents/_include/theme-builder-actions.png rename to docs/help/contents/public/theme-builder-actions.png diff --git a/docs/help/contents/_include/theme-builder-base.png b/docs/help/contents/public/theme-builder-base.png similarity index 100% rename from docs/help/contents/_include/theme-builder-base.png rename to docs/help/contents/public/theme-builder-base.png diff --git a/docs/help/contents/_include/theme-builder-change-color.gif b/docs/help/contents/public/theme-builder-change-color.gif similarity index 100% rename from docs/help/contents/_include/theme-builder-change-color.gif rename to docs/help/contents/public/theme-builder-change-color.gif diff --git a/docs/help/contents/_include/theme-builder-export-theme.png b/docs/help/contents/public/theme-builder-export-theme.png similarity index 100% rename from docs/help/contents/_include/theme-builder-export-theme.png rename to docs/help/contents/public/theme-builder-export-theme.png diff --git a/docs/help/contents/_include/theme-builder-metadata.png b/docs/help/contents/public/theme-builder-metadata.png similarity index 100% rename from docs/help/contents/_include/theme-builder-metadata.png rename to docs/help/contents/public/theme-builder-metadata.png diff --git a/docs/help/contents/_include/theme-builder-navigation-menu-modify.png b/docs/help/contents/public/theme-builder-navigation-menu-modify.png similarity index 100% rename from docs/help/contents/_include/theme-builder-navigation-menu-modify.png rename to docs/help/contents/public/theme-builder-navigation-menu-modify.png diff --git a/docs/help/contents/_include/theme-builder-navigation-menu-scope.png b/docs/help/contents/public/theme-builder-navigation-menu-scope.png similarity index 100% rename from docs/help/contents/_include/theme-builder-navigation-menu-scope.png rename to docs/help/contents/public/theme-builder-navigation-menu-scope.png diff --git a/docs/help/contents/_include/theme-builder-navigation-menu.png b/docs/help/contents/public/theme-builder-navigation-menu.png similarity index 100% rename from docs/help/contents/_include/theme-builder-navigation-menu.png rename to docs/help/contents/public/theme-builder-navigation-menu.png diff --git a/docs/help/contents/_include/theme-builder-select-starter-theme.png b/docs/help/contents/public/theme-builder-select-starter-theme.png similarity index 100% rename from docs/help/contents/_include/theme-builder-select-starter-theme.png rename to docs/help/contents/public/theme-builder-select-starter-theme.png diff --git a/docs/help/contents/_include/theme-builder.png b/docs/help/contents/public/theme-builder.png similarity index 100% rename from docs/help/contents/_include/theme-builder.png rename to docs/help/contents/public/theme-builder.png diff --git a/docs/help/contents/_include/theme-load-file.png b/docs/help/contents/public/theme-load-file.png similarity index 100% rename from docs/help/contents/_include/theme-load-file.png rename to docs/help/contents/public/theme-load-file.png diff --git a/docs/help/contents/_include/theme-set-as-default.png b/docs/help/contents/public/theme-set-as-default.png similarity index 100% rename from docs/help/contents/_include/theme-set-as-default.png rename to docs/help/contents/public/theme-set-as-default.png diff --git a/docs/help/contents/_include/three-dot-button.png b/docs/help/contents/public/three-dot-button.png similarity index 100% rename from docs/help/contents/_include/three-dot-button.png rename to docs/help/contents/public/three-dot-button.png diff --git a/docs/help/contents/_include/toolbar-blocks.png b/docs/help/contents/public/toolbar-blocks.png similarity index 100% rename from docs/help/contents/_include/toolbar-blocks.png rename to docs/help/contents/public/toolbar-blocks.png diff --git a/docs/help/contents/_include/toolbar-editor.png b/docs/help/contents/public/toolbar-editor.png similarity index 100% rename from docs/help/contents/_include/toolbar-editor.png rename to docs/help/contents/public/toolbar-editor.png diff --git a/docs/help/contents/_include/toolbar-plus.png b/docs/help/contents/public/toolbar-plus.png similarity index 100% rename from docs/help/contents/_include/toolbar-plus.png rename to docs/help/contents/public/toolbar-plus.png diff --git a/docs/help/contents/_include/update-theme-1.png b/docs/help/contents/public/update-theme-1.png similarity index 100% rename from docs/help/contents/_include/update-theme-1.png rename to docs/help/contents/public/update-theme-1.png diff --git a/docs/help/contents/_include/update-theme-2.png b/docs/help/contents/public/update-theme-2.png similarity index 100% rename from docs/help/contents/_include/update-theme-2.png rename to docs/help/contents/public/update-theme-2.png diff --git a/docs/help/contents/_include/update-theme-3.png b/docs/help/contents/public/update-theme-3.png similarity index 100% rename from docs/help/contents/_include/update-theme-3.png rename to docs/help/contents/public/update-theme-3.png diff --git a/docs/help/contents/_include/update-theme-4.png b/docs/help/contents/public/update-theme-4.png similarity index 100% rename from docs/help/contents/_include/update-theme-4.png rename to docs/help/contents/public/update-theme-4.png diff --git a/docs/help/contents/_include/update-theme-5.png b/docs/help/contents/public/update-theme-5.png similarity index 100% rename from docs/help/contents/_include/update-theme-5.png rename to docs/help/contents/public/update-theme-5.png diff --git a/docs/help/contents/_include/update-theme-6.png b/docs/help/contents/public/update-theme-6.png similarity index 100% rename from docs/help/contents/_include/update-theme-6.png rename to docs/help/contents/public/update-theme-6.png diff --git a/docs/help/contents/publish-notes-with-monographs.md b/docs/help/contents/publish-notes-with-monographs.md index d871aea29..212494992 100644 --- a/docs/help/contents/publish-notes-with-monographs.md +++ b/docs/help/contents/publish-notes-with-monographs.md @@ -1,39 +1,50 @@ --- title: Monographs -description: Anonymous, secure and encrypted note sharing with password protection. Share a note with anyone on the internet even if they do not use Notesnook. +pageTitle: Share a note as an encrypted link with Monographs +description: Publish any Notesnook note as a public link, optionally password-protected or set to self-destruct after one read. Your reader needs no account and no app. +keywords: + - share encrypted note link + - password protected note sharing + - publish note to web +schema: howto --- # Publish notes with monographs -Sharing a note with someone can be such a tedious task. You have to copy/download/export it to a file and then attach it in an email or upload it to some cloud storage. +A monograph turns any note into a link you can send to anyone. Your reader needs no account, no app and no Notesnook — they open the URL and read the note, and you can protect it with a password or have it self-destruct after one read. Once a note is published as a monograph, you get a public URL which you can share with anyone. They don't need to download Notesnook or install any extra software — it works like a blog, only simpler. -With Notesnook, you don't need to do that anymore. Monographs enable you to share your notes with anyone in a single click. Once a note is published as a monograph, you get a public URL which you can share with anyone. They don't need to download Notesnook or install any extra software — it's just like a blog, only simpler. +::: warning Size limit +Currently, monographs are limited to 15 MB in size. This also includes attachments, like images. If you try to publish a note larger than 15 MB, you'll get an error. -> warn Size limit -> -> Currently, monographs are limited to 15 MB in size. This includes attachments as well. If you try to publish a note larger than 15 MB, you'll get an error. +::: ## How to publish a note? -# [Desktop/Web](#/tab/web) +::: warning A monograph is a public URL +Anyone with the link can open a monograph unless you set a password. Notesnook cannot tell who has opened it, and an unprotected monograph can be indexed if the link is posted publicly. Use password protection for anything sensitive, and unpublish when you are done. -1. Right click on a note -2. Click on `Publish` from Note properties to open publish note dialog. -3. Click on `Publish` button to publish note. -4. Copy the URL and send it to respective person. +::: -# [Mobile](#/tab/mobile) +:::tabs key:platform +== Desktop/Web -1. Tap on ![Three dot button](/three-dot-button.png) button on a note. -2. Tap on `Publish` to open Publish note sheet -3. Tap on `Publish` button to publish note. -4. Copy the URL and send it to respective person. +1. Right click a note +2. Click `{{publish}}` from Note properties to open publish note dialog. +3. Click `{{publish}}` button to publish note. +4. Copy the URL and send it to the person you are sharing with. ---- +== Mobile + +1. Tap ![Three dot button](/three-dot-button.png) button on a note. +2. Tap `{{publish}}` to open Publish note sheet +3. Tap `{{publish}}` button to publish note. +4. Copy the URL and send it to the person you are sharing with. + +::: ## Password protection -When you are sharing sensitive information with someone, you can encrypt the monograph with a password. Only someone who has the password can decrypt and read the contents of the note. While you are on the Publish note dialog, turn on password protection and enter a password for the monograph. Then click publish to publish the note. +When you are sharing sensitive information with someone, you can encrypt the monograph with a password. Only someone who has the password can decrypt and read the contents of the note. While you are on the Publish note dialog, enter a password for the monograph. Then click publish to publish the note. ## Self destruct @@ -41,16 +52,48 @@ Self destruct means that the published note can be viewed only once. Once someon ## Unpublish a monograph -# [Desktop/Web](#/tab/web) +:::tabs key:platform +== Desktop/Web -1. Right click on a note -2. Click on `Publish` to open publish note popup -3. Click on `Unpublish` button to unpublish note +1. Right click a note +2. Click `{{publish}}` to open publish note popup +3. Click `{{unpublish}}` button to unpublish note -# [Mobile](#/tab/mobile) +== Mobile -1. Tap on ![Three dot button](/three-dot-button.png) button on a published note -2. Tap on `Publish` to open Publish note sheet -3. Tap on `Unpublish` button to unpublish note +1. Tap ![Three dot button](/three-dot-button.png) button on a published note +2. Tap `{{publish}}` to open Publish note sheet +3. Tap `{{unpublish}}` button to unpublish note ---- +::: + +## Once a note is published + +:::warning +**Published notes cannot be deleted while published.** + +::: + +Opening `{{publish}}` on a note that is already published gives you the full set of actions rather than a single toggle: + +- **Open** — view the monograph as your reader sees it +- **Copy link** — copy the public URL, as plain text, HTML or Markdown on desktop and web +- **Update** — push the note's latest edits to the published copy +- **Unpublish** — take it offline + +Edits you make after publishing are **not** live until you choose `{{update}}`. + +## View counts <PlanTag plan="pro" /> + +The publish view shows how many times a monograph has been opened. View counts are part of the [Pro plan and above](/plans-and-limits); on desktop and web the counter is replaced by an upgrade link on other plans, and on mobile it is hidden. View counts are not shown for self-destructing monographs. + +## Links and embeds in a published note <PlanTag plan="essential" /> + +Links and embedded content inside a note are preserved in the published monograph on the [Essential plan and above](/plans-and-limits). + +## Related pages + +- [Exporting notes](/export-notes-from-notesnook) — sharing a note as a file instead of a link +- [Private vault](/lock-notes-with-private-vault) — locking notes you don't want to share +- [How is my data encrypted?](/how-is-my-data-encrypted) — how password-protected monographs are encrypted +- [Plans & limits](/plans-and-limits) — what Essential and Pro add to monographs diff --git a/docs/help/contents/recovering-your-account.md b/docs/help/contents/recovering-your-account.md index 9501afdc2..68ede4ad3 100644 --- a/docs/help/contents/recovering-your-account.md +++ b/docs/help/contents/recovering-your-account.md @@ -1,91 +1,127 @@ --- title: Recovering your account -description: Notesnook is one of the few end-to-end encrypted software that allows users to recovery their account in case they forget their passwords. Here is a detailed step-by-step guide into how you can recover your Notesnook account. +pageTitle: I forgot my Notesnook password — how do I recover my account? +description: Recover a Notesnook account with your data recovery key or a backup file, or reset it and start over. What each option keeps, and what it costs you. +keywords: + - notesnook forgot password + - notesnook account recovery + - notesnook data recovery key + - reset notesnook account +schema: howto --- # Recovering your account -Notesnook is one of the few end-to-end encrypted software that allows users to recovery their account in case they forget their passwords. Here is a detailed step-by-step guide into how you can recover your Notesnook account. +Notesnook is one of the few end-to-end encrypted apps that lets you recover your account after forgetting your password. Which of your notes survive depends on what you have kept: your **data recovery key**, a **backup file**, or neither. -> warn You will be logged out -> -> For account recovery to work reliably, you will be force logged out from all your other devices. It is recommended that you save & backup all your data on your other devices before continuing. +::: danger You will be logged out +For account recovery to work reliably, you will be force logged out from all your other devices. It is recommended that you save & backup all your data on your other devices before continuing. + +::: ## Requesting an account recovery link The first step to recovering your account consists of requesting an account recovery link. Notesnook sends the recovery link on your registered email. Here's how you can do that: -> info The new login flow -> -> The recent versions of Notesnook have updated the login flow. It is now **mandatory to verify your 2FA** before you can request an account recovery link. +::: info The new login flow +The recent versions of Notesnook have updated the login flow. It is now **mandatory to verify your 2FA** before you can request an account recovery link. -### [Web](#/tab/web) +::: + +:::tabs key:platform +== Desktop/Web 1. Go to [Notesnook Login page](https://app.notesnook.com/login) 2. Enter your email & continue 3. Verify your 2FA & continue -4. On the next page, click on `Forgot password?` - ![](/static/account-recovery/step-1.png) +4. On the next page, click `{{forgotPassword}}` + +![The Forgot password link on the Notesnook login page](/static/account-recovery/step-1.png) + 5. On the next page, your email should be prefilled. If it isn't, fill it out. - ![](/static/account-recovery/step-2.png) -6. Click on `Send recovery email` + +![The account recovery page with the email address prefilled](/static/account-recovery/step-2.png) + +6. Click `{{sendRecoveryEmail}}` 7. If everything goes well, you should receive an email from Notesnook in your inbox: - ![](/static/account-recovery/recovery_email.png) - > info What if I didn't receive an email? - > - > _Check your spam/junk folder if you haven't received one & [contact us](mailto:support@streetwriters.co) if you still don't find it._ -8. Click on `Reset your password` button in the email. This will take you to the account recovery page. -### [Mobile](#/tab/mobile) +![Recovery email in Notesnook](/static/account-recovery/recovery_email.png) -1. Open the Notesnook app -2. Go to the Login page +8. Click the `Reset your password` button in the email. This takes you to the account recovery page. ---- +== Mobile + +You can request the recovery email from the mobile app, but the recovery itself happens on the web page the email links to. + +1. Open the Notesnook app and go to the login screen. +2. Enter your email and continue. +3. Verify your 2FA and continue. +4. Tap `{{forgotPassword}}` under the password field. +5. Confirm your email in the sheet that opens and send the recovery email. You should see `{{recoveryEmailSent}}`. +6. Open the email on any device and click `Reset your password` to continue in a browser. + +::: + +::: info What if I didn't receive an email? +_Check your spam/junk folder if you haven't received one & [contact us](mailto:support@streetwriters.co) if you still don't find it._ +::: ## Choosing an account recovery method Notesnook gives its users a variety of recovery methods depending on the data they have: -![](/static/account-recovery/step-3.png) +![The Choose a recovery method screen, listing the recovery key, backup file and reset options](/static/account-recovery/step-3.png) + +There are three, and they are listed in order of how much you keep: + +| Method | What it does | Your notes | +| ----------------------------- | ----------------------------------------------------------------------------- | ----------------------------------- | +| `{{recoveryKeyMethod}}` | Decrypts your data with your old key and re-encrypts it with the new password | Kept | +| `{{backupFileMethod}}` | Restores your data from a `.nnbackup` file you saved earlier | Kept, up to the date of that backup | +| `{{clearDataAndResetMethod}}` | Wipes the account and starts it over | **Deleted** | ### Use recovery key -This is the safest method of recovering your account because it just decrypts your data using your old key & then re-encrypts it using the new password. +This is the safest method, because it decrypts your data with your old key and then re-encrypts it with your new password. Nothing is lost. -> warn Don't have a recovery key? -> -> If you don't have your data recovery key, you can skip to the next section. - -1. Click on the first option (the button that says `Use recovery key`) if you haven't already -2. Enter your recovery key in the input field & click on `Start account recovery` - ![](/static/account-recovery/step-4.png) -3. Click on `Download backup file` once you data has been downloaded. **_Don't forget to save the file in a safe place._** - ![](/static/account-recovery/step-5.png) +1. Click the first option (the button that says `{{recoveryKeyMethod}}`) if you haven't already +2. Enter your recovery key in the input field & click `{{startAccountRecovery}}` + ![The recovery key field on the account recovery page](/static/account-recovery/step-4.png) +3. Click `{{downloadBackupFile}}` once your data has been downloaded. **_Don't forget to save the file in a safe place._** + ![The account recovery screen offering a download of your decrypted backup file](/static/account-recovery/step-5.png) 4. For next steps, see [Resetting account password](#resetting-account-password) section +### Use a backup file + +If you don't have your recovery key but you do have a [backup file](/backup-and-restore-notes-in-notesnook), you can recover from that instead. You get back everything that was in the account when the backup was taken; anything written after it is not in the file and cannot be recovered. + +1. Click the second option (the button that says `{{backupFileMethod}}`). +2. Select the `.nnbackup` file you saved. +3. For next steps, see the [Resetting account password](#resetting-account-password) section. + ### Clear data & reset account -> error RISK OF LOSING DATA -> -> This method will clear all your data including your notes, notebooks, reminders, tags etc. **Proceed with caution.** +::: danger This deletes everything in the account +This method clears all your data — notes, notebooks, reminders, tags and attachments. It is irreversible, and because your data is end-to-end encrypted, **Notesnook cannot restore any of it afterwards.** Only use it if you have neither a recovery key nor a backup file, and you accept starting from scratch. -1. Click on the third option (the button that says `Clear data & reset account`) -2. For next steps, see [Resetting account password](#resetting-account-password) section +::: + +1. Click the third option (the button that says `{{clearDataAndResetMethod}}`). +2. For next steps, see the [Resetting account password](#resetting-account-password) section. ## Resetting account password Once you have selected the appropriate account recovery method, you'll be asked to choose a new password. -![](/static/account-recovery/step-7.png) +![The new password screen at the end of account recovery](/static/account-recovery/step-7.png) 1. Choose a strong & memorable password. _We recommend using a password manager like 1Password or Bitwarden so you never lose your password again._ -2. Click on `Continue` and wait until the process finishes. +2. Click `{{continue}}` and wait until the process finishes. 3. Save the new recovery key when prompted in a safe place. --- -And that's it. You have now successfully recovered your account. Feel free to relogin on all your devices so you can sync & access your notes. +That's it — your account is recovered. Log back in on your other devices to sync and read your notes again. ## Troubleshooting @@ -99,4 +135,11 @@ The only way to recover from this corruption is to reset your account. The main cause of this error is our server getting timed out when clearing your data. If you have _a lot_ of data (in GBs) then you might face this. -As a work around, try again from a laptop using Google Chrome or Mozilla Firefox. However, there's a very low chance that it'll work. Unfortunately, there's no easy way around this. We are working on mitigating this ASAP. +As a workaround, try again from a laptop using Google Chrome or Mozilla Firefox. If it still fails, [contact us](mailto:support@streetwriters.co) — a very large account may need to be cleared server-side. + +## Related pages + +- [Account settings](/account-settings) — email, password and profile +- [Two-factor authentication](/two-factor-authentication) — a second step at login +- [How is my data encrypted?](/how-is-my-data-encrypted) — the encryption behind every note +- [Backup and restore](/backup-and-restore-notes-in-notesnook) — keeping your own encrypted copy diff --git a/docs/help/contents/reminders.md b/docs/help/contents/reminders.md index f1efd26c4..015b74ed5 100644 --- a/docs/help/contents/reminders.md +++ b/docs/help/contents/reminders.md @@ -1,29 +1,38 @@ --- title: Setting reminders on notes -description: Learn how to create reminders on your notes in Notesnook. Set one-time or recurring reminders with custom notification preferences. +pageTitle: How do I set a reminder on a note in Notesnook? +description: Set one-time, recurring and permanent reminders on your Notesnook notes, snooze them from the notification, and change the sound and snooze time. +keywords: + - notesnook reminders + - reminder on a note + - recurring reminders notes app +schema: howto --- # Creating reminders Reminders help you stay on top of your important notes. You can create one-time or recurring reminders with custom notification settings. +Free accounts can have up to 10 active reminders at a time. Essential raises the cap to 50, and Pro and Believer are unlimited — see [Plans & limits](/plans-and-limits). Deactivated reminders, and one-time reminders whose time has already passed, don't count towards the cap. + ## Adding a reminder to a note -# [Desktop/Web](#/tab/web) +:::tabs key:platform +== Desktop/Web -1. Right click on a note to open the `Note properties` menu -2. Click on `Remind me` to open the add reminder dialog +1. Right click a note to open the `Note properties` menu +2. Click `{{remindMe}}` to open the add reminder dialog 3. Enter a title for the reminder and description (optional) 4. Choose your reminder type: - **Once**: Set a specific date and time - **Repeat** (paid plans only): Create a recurring reminder (daily, weekly, monthly, or yearly) 5. Select your notification preference (Silent, Vibrate, or Urgent) -6. Click `Add` to save the reminder +6. Click `{{add}}` to save the reminder -# [Mobile](#/tab/mobile) +== Mobile -1. Press the ![Three dot button](/three-dot-button.png) button on a note -2. Tap `Remind me` to open the add reminder dialog +1. Tap the ![Three dot button](/three-dot-button.png) button on a note +2. Tap `{{remindMe}}` to open the add reminder dialog 3. Enter a title for the reminder and description (optional) 4. Choose your reminder type: - **Once**: Set a specific date and time @@ -32,37 +41,39 @@ Reminders help you stay on top of your important notes. You can create one-time 5. Select your notification preference (Silent, Vibrate, or Urgent) 6. Tap the checkmark button on top right to save the reminder ---- +::: ## Creating a standalone reminder You can also create reminders without attaching them to a specific note. This is useful for general tasks or events. -# [Desktop/Web](#/tab/web) +:::tabs key:platform +== Desktop/Web -1. Go to the `Reminders` screen from the side menu +1. Go to the `{{reminders}}` screen from the side menu 2. Click the add reminder button (![Plus icon](/plus-reminder-icon.png)) on top right 3. Enter a title for the reminder and description (optional) 4. Choose your reminder type (Once or Repeat) 5. Select your notification preference (Silent, Vibrate, or Urgent) -6. Click `Add` to save the reminder +6. Click `{{add}}` to save the reminder -# [Mobile](#/tab/mobile) +== Mobile -1. Go to the `Reminders` screen from the side menu -2. Tap the add reminder button (![Plus icon](/plus-icon.png)) on bottom right +1. Go to the `{{reminders}}` screen from the side menu +2. Tap the add reminder button (![Plus icon](/plus-button-desktop.png)) on bottom right 3. Enter a title for the reminder and description (optional) 4. Choose your reminder type (Once, Repeat, or Permanent on Android) 5. Select your notification preference (Silent, Vibrate, or Urgent) 6. Tap the checkmark button on top right to save the reminder ---- +::: -## Configuring recurring reminders +## Configuring recurring reminders <PlanTag plan="essential" /> -> info Recurring reminders are a paid feature -> -> Recurring reminders can only be used if you are on a paid plan. +::: info Recurring reminders are a paid feature +Recurring reminders can only be used if you are on a paid plan — Essential, Pro or Believer. See [Plans & limits](/plans-and-limits). + +::: When you select **Repeat** mode, you can customize how often you want to be reminded: @@ -71,8 +82,6 @@ When you select **Repeat** mode, you can customize how often you want to be remi - **Monthly**: Pick specific dates of the month - **Yearly**: Choose the month and day for your yearly reminder ---- - ## Notification preferences Choose how you want to be notified: @@ -81,20 +90,78 @@ Choose how you want to be notified: - **Vibrate**: Get a notification with vibration - **Urgent**: Receive a notification with sound and vibration -> info -> -> Reminders require notification permissions. You'll be asked to enable notifications when you create your first reminder. +::: info +Reminders require notification permissions. You'll be asked to enable notifications when you create your first reminder. ---- +::: ## Editing or viewing reminders -To edit an existing reminder, go to `Reminders` screen from the side menu and select the reminder you want to edit. You can change all reminder settings, including the date, time, and recurrence pattern. +To edit an existing reminder, go to `{{reminders}}` screen from the side menu and select the reminder you want to edit. You can change all reminder settings, including the date, time, and recurrence pattern. -To see all reminders attached to a note, open the note properties go to `Reminders`. This will show you a list of all reminders associated with that note. +To see all reminders attached to a note, open the note properties go to `{{reminders}}`. This will show you a list of all reminders associated with that note. ---- +## Activate or deactivate a reminder -## Permanent reminders (Android only) +Deactivating a reminder stops it from notifying you without deleting it, so you can turn it back on later. A deactivated reminder is labelled `{{disabled}}` in the reminders list and stops counting towards your active reminder cap. + +:::tabs key:platform +== Desktop/Web + +1. Go to the `{{reminders}}` screen from the side menu. +2. Right click the reminder. +3. Click `{{deactivate}}` to switch it off, or `{{activate}}` to switch it back on. + +== Mobile + +1. Go to the `{{reminders}}` screen from the side menu. +2. Tap the ![Three dot button](/three-dot-button.png) button on the reminder. +3. Tap `{{turnOffReminder}}` to switch it off, or `{{turnOnReminder}}` to switch it back on. + +::: + +## Snooze a reminder + +When a reminder fires you can push it back instead of dismissing it. + +:::tabs key:platform +== Desktop/Web + +1. Click the reminder notification. The reminder preview opens. +2. Under `{{remindMeIn}}`, click `5 minutes`, `10 minutes`, `15 minutes` or `1 hour`. + +The reminder fires again after the interval you picked. + +== Mobile + +1. Expand the reminder notification in your notification shade. +2. Tap the snooze action on it — `Remind in 5 min` on Android, `Remind me in 5 min` on iOS. Both labels show your default snooze time. + +The action uses your default snooze time, which is 5 minutes until you change it. Recurring reminders also get a `{{disable}}` action on the notification, which deactivates the reminder. + +::: + +### Change the default snooze time _(mobile)_ + +1. Go to `{{settings}}` > `{{productivity}}` > `{{reminders}}`. +2. Tap `{{defaultSnoozeTime}}` and enter the number of minutes. + +The default is `5` minutes. This is the interval the snooze button on a reminder notification uses. + +### Change the reminder notification sound _(Android only)_ + +1. Go to `{{settings}}` > `{{productivity}}` > `{{reminders}}`. +2. Tap `{{changeNotificationSound}}`. + +On Android 8 and above this opens the system notification channel settings for Notesnook's urgent reminder channel, where the sound is set. On older Android versions you pick the sound from a list inside the app. There is no sound setting on iOS. + +## Permanent reminders <PlanTag plan="essential" note="Android only"/> **Permanent reminders** are available only on Android devices. Unlike one-time or recurring reminders, permanent reminders persist every day and won't disappear after triggering. This is useful for important daily tasks or notes you want constant access to. + +## Related pages + +- [Note actions](/notes/note-actions) — pin, duplicate, read-only, print and more +- [Pin to notifications](/mobile-integration/pin-notes-to-notifications) — a note that lives in your shade +- [Task lists](/rich-text-editor/task-and-todo-lists) — to-do lists inside a note +- [Plans & limits](/plans-and-limits) — what each plan unlocks and the exact limits diff --git a/docs/help/contents/rich-text-editor/README.md b/docs/help/contents/rich-text-editor/README.md deleted file mode 100644 index 068f68b3c..000000000 --- a/docs/help/contents/rich-text-editor/README.md +++ /dev/null @@ -1 +0,0 @@ -# Editor diff --git a/docs/help/contents/rich-text-editor/callouts.md b/docs/help/contents/rich-text-editor/callouts.md new file mode 100644 index 000000000..2683a62f0 --- /dev/null +++ b/docs/help/contents/rich-text-editor/callouts.md @@ -0,0 +1,111 @@ +--- +title: Callouts +pageTitle: How do I add a callout box to a note in Notesnook? +description: Add colored, collapsible callout boxes — info, tip, warning, error, quote and more — to any note in Notesnook, from the toolbar or with a markdown shortcut. +keywords: + - notesnook callout + - admonition notes app + - info box in notes +schema: howto +--- + +# Callouts <PlanTag plan="essential" /> + +A callout is a colored, titled box that pulls one part of a note out of the flow — a warning, a tip, a definition you keep forgetting. Each callout has a heading you can rename and a body that can hold paragraphs, lists, code and other blocks, and it can be collapsed down to its title alone. + +Callouts are part of the [Essential plan and above](/plans-and-limits). + +## Insert a callout + +:::tabs key:platform +== Desktop/Web + +1. Place the cursor where you want the callout, or select the text you want to put inside it. +2. Click the `+` (Insert) button in the toolbar. +3. Hover `{{callout}}` in the menu. +4. Pick a type from the submenu. + +== Mobile + +1. Place the cursor where you want the callout, or select the text you want to put inside it. +2. Tap the `+` (Insert) button in the bottom toolbar. +3. Tap `{{callout}}` in the `{{chooseBlockToInsert}}` sheet. +4. Pick a type from the list. + +::: + +The new callout is titled with the type name in capitals — `INFO`, `WARN` — and the cursor lands in that title so you can type a real one straight away. If you had text selected, that text becomes the callout's body. + +![The insert block menu in the Notesnook editor; Callout opens a submenu of callout types](/screenshots/editor-insert-block-menu.png) + +### The eight types in the menu + +| Type | Use it for | +| ----------- | -------------------------------------------- | +| `Abstract` | a summary at the top of a long note | +| `Hint` | an aside that helps but isn't required | +| `Info` | neutral context | +| `Success` | something that worked, or a confirmed result | +| `Warn` | something that can go wrong | +| `{{error}}` | something that failed or must not be done | +| `Example` | a worked example | +| `{{quote}}` | a quotation or citation | + +## Write a callout with a markdown shortcut <PlanTag plan="essential" /> + +On an empty line, type `>` immediately followed by the callout type — no space — then press `Enter`: + +``` +>warning +``` + +To give it a title in the same step, add the title after the type: + +``` +>warning Back up before you upgrade +``` + +The first form titles the callout `WARNING`; the second titles it `Back up before you upgrade`. Either way the cursor ends up in the body, ready for content. + +::: info Markdown shortcuts need Essential too +This is a [Markdown shortcut](/rich-text-editor/markdown-notes-editing), so it needs the same [Essential plan](/plans-and-limits) as callouts themselves, plus the setting switched on. Markdown shortcuts are **off by default on web and desktop** — turn on `{{mardownShortcuts}}` in `{{settings}}` → `{{customization}}` → `{{editor}}`. On mobile they are on by default. Typing `>` followed by a _space_ still makes a plain blockquote, on any plan. + +::: + +### Types the shortcut accepts + +The shortcut understands far more type names than the menu offers — many of them aliases that map onto the same styling, so you can write whichever word comes naturally: + +`note`, `abstract`, `summary`, `tldr`, `info`, `todo`, `tip`, `hint`, `important`, `success`, `check`, `done`, `question`, `help`, `faq`, `warning`, `warn`, `caution`, `attention`, `failure`, `fail`, `missing`, `danger`, `error`, `bug`, `example`, `quote`, `cite` + +So `>tldr`, `>faq`, `>caution` and `>bug` all work even though none of them appear in the insert menu. + +## Collapse and expand a callout + +Callouts fold away to a single title line, which is useful for long asides you only need occasionally. + +:::tabs key:platform +== Desktop/Web + +1. Move the pointer to the right-hand end of the callout's title row. +2. Click the collapse control there. + +Click it again to expand. The collapsed state is saved with the note content, so a callout you collapsed is still collapsed the next time you open the note, on any device. + +== Mobile + +1. Tap the right-hand end of the callout's title row. + +Tap again to expand. + +::: + +<!-- TODO: screenshot — a collapsed callout showing only its title --> + +## Related pages + +- [Editor toolbar](/rich-text-editor/rich-text-editor-toolbar) — every block you can insert into a note +- [Outline lists](/rich-text-editor/outline-lists) — the other collapsible block in the editor +- [Markdown shortcuts](/rich-text-editor/markdown-notes-editing) — the full shortcut list and how to switch it on +- [Tasks and todo lists](/rich-text-editor/task-and-todo-lists) — checkable to-do blocks inside a note +- [Plans & limits](/plans-and-limits) — what Essential unlocks, and everything else diff --git a/docs/help/contents/rich-text-editor/code-blocks.md b/docs/help/contents/rich-text-editor/code-blocks.md new file mode 100644 index 000000000..3b9f872a9 --- /dev/null +++ b/docs/help/contents/rich-text-editor/code-blocks.md @@ -0,0 +1,111 @@ +--- +title: Code blocks +pageTitle: How do I add a code block to a note in Notesnook? +description: Insert syntax-highlighted code blocks in Notesnook, pick from 297 languages, switch between spaces and tabs, and copy the whole block in one click. +keywords: + - notesnook code block + - syntax highlighting notes app + - notes app for code snippets +schema: howto +--- + +# Code blocks + +A code block keeps code as code: monospaced, syntax highlighted, indentation preserved, and never touched by spellcheck or autocorrect. Insert one from the toolbar's `+` button, with `Ctrl+Shift+C`, or by typing ` ``` ` on an empty line. + +## Insert a code block + +:::tabs key:platform +== Desktop/Web + +1. Place the cursor on an empty line. +2. Click the `+` (Insert) button in the toolbar. +3. Choose `Code block`. + +You can also press `Ctrl+Shift+C` (`⌘+Shift+C` on macOS). If you press it with text selected, the selected text becomes the code block's contents, line breaks and all. Pressing it again while the cursor is inside a code block turns the block back into normal paragraphs. + +== Mobile + +1. Place the cursor on an empty line. +2. Tap the `+` (Insert) button in the bottom toolbar. +3. Choose `Code block` from the `Choose a block to insert` sheet. + +::: + +![The insert block menu in the Notesnook editor, with Code block listed alongside Task list, Outline list, Math & formulas and Callout](/screenshots/editor-insert-block-menu.png) + +### Type ` ``` ` instead <PlanTag plan="essential"/> + +On an empty line, type three backticks followed by a space or Enter — ` ``` ` — and the line becomes a code block. Add a language name straight after the backticks to set the language at the same time: ` ```javascript `. The name has to be plain lowercase letters, so ` ```c++ ` and ` ```objective-c ` won't trigger it — pick those from the language menu instead. Three tildes (`~~~`) work the same way. + +::: info Markdown shortcuts need to be enabled. +Typing ` ``` ` relies on [Markdown shortcuts.](/rich-text-editor/markdown-notes-editing) They are **off by default on web and desktop** — turn on `{{mardownShortcuts}}` in `{{settings}}` → `{{customization}}` → `{{editor}}` first. On mobile they are on by default. The toolbar button and `Ctrl+Shift+C` work on every plan. + +::: + +## Choose the language + +![A code block in the Notesnook editor showing the footer bar with the caret position, indentation mode, language and copy button](/screenshots/editor-code-block.png) + +Every code block has a language button in the bar along its bottom edge showing the current language. The default is `Plaintext` until you change the language once. + +:::tabs key:platform +== Desktop/Web + +1. Click the language name at the bottom of the code block. +2. Type in the `{{searchLanguages}}` box to filter the list — it matches both language names and their aliases (searching `js` finds JavaScript). +3. Click the language you want, or press `Enter` to take the first result. + +== Mobile + +1. Tap the language name at the bottom of the code block. +2. In the `{{selectLanguage}}` sheet, type in `{{searchLanguages}}` to filter the list. +3. Tap the language you want. + +::: + +There are **297 languages** to choose from, each highlighted with its own grammar. + +::: tip The last language becomes the default +The language you pick is remembered on that device and used for every code block you create afterwards, so you only have to set your usual language once. + +::: + +<!-- TODO: screenshot — the language picker with the search languages field --> + +## Read the line and column indicator + +The bar along the bottom of a code block shows `Line 1, Column 1` for wherever the cursor is. When you select code, the count of selected characters is appended — `Line 4, Column 12 (37 selected)`. + +## Switch between spaces and tabs + +Next to the line indicator is a button reading `Spaces: 2` or `Tabs: 2` — this is the `{{toggleIndentationMode}}` control. + +1. Click (or tap) the `{{spaces}}` / `{{tabs}}` button. +2. Every indented line in that block is rewritten to use the other character. + +The setting is per code block, so one block can use tabs while another uses spaces. Inside a block, `Tab` inserts one indent level at the cursor, or indents every line when you have several selected, and `Shift+Tab` removes one level from the start of each selected line. + +## Copy a code block + +Once a code block has content, a `{{copy}}` button appears in its bottom bar. Click it and the label changes to `{{copied}}` for a second. It copies the code only — no surrounding note text. + +## Paste code from VS Code or GitHub + +Paste code copied out of VS Code or from a GitHub file view and Notesnook creates a code block for it automatically, using the language the source reported. Indentation is normalized to the block's own indentation settings, and carriage returns are stripped. + +Short single-line snippets are treated as [inline code](/rich-text-editor/rich-text-editor-toolbar) instead of a full block. Pasting into an existing code block always inserts plain text, so highlighting stays intact. + +::: tip Leaving a code block +Press `Enter` three times at the end of a block, or press the down arrow at the very bottom of the last block in a note, and the cursor moves out into a new paragraph. `Ctrl+A` inside a code block selects that block's code rather than the whole note. + +::: + +## Related pages + +- [Editor toolbar](/rich-text-editor/rich-text-editor-toolbar) — every block you can insert into a note +- [Markdown shortcuts](/rich-text-editor/markdown-notes-editing) — the full list of shortcuts, and how to switch them on +- [Math & formulas](/rich-text-editor/math-and-formulas) — LaTeX expressions inline and as blocks +- [Personalizing the editor](/rich-text-editor/personalizing-rich-text-editor) — change the fonts the editor uses +- [Plans & limits](/plans-and-limits) — which editor features need a paid plan +- [Keyboard shortcuts](/keyboard-shortcuts) — the complete shortcut reference diff --git a/docs/help/contents/rich-text-editor/editor-tabs-and-panes.md b/docs/help/contents/rich-text-editor/editor-tabs-and-panes.md new file mode 100644 index 000000000..6fd5ef13c --- /dev/null +++ b/docs/help/contents/rich-text-editor/editor-tabs-and-panes.md @@ -0,0 +1,202 @@ +--- +title: Tabs & panes +pageTitle: Editor tabs, split panes and focus mode in Notesnook +description: Open notes in editor tabs, pin them, split the editor with the table of contents, properties or a PDF preview, and use focus mode, zoom and word counts. +keywords: + - notesnook editor tabs + - notesnook focus mode + - notesnook table of contents + - notesnook word count +--- + +# Editor tabs and panes + +The Notesnook editor keeps every note you open in a tab, so you can jump between notes without losing your place. Beside the editor you can open a table of contents, a note's properties or a PDF preview, and you can strip the app back to the writing surface alone with focus mode. + +<!-- TODO: screenshot — the editor tab strip on desktop with three tabs, one pinned and one with unsaved changes --> + +## Open a note in a new tab + +:::tabs key:platform +== Desktop/Web + +1. Right click a note in the list and choose `{{openInNewTab}}`. Middle-clicking the note does the same thing. +2. Or click the `{{newTab}}` button in the editor's top bar to open an empty tab, then start writing. + +You can also drag a note from the list onto the tab strip to open it in a new tab, or drop it **onto an existing tab** to open it in that tab. Double-clicking the empty part of the tab strip opens a new tab. + +In the desktop app there are keyboard shortcuts for all of this: + +| Action | Shortcut | +| -------------------- | ---------------- | +| New tab | `Ctrl+T` | +| Close the active tab | `Ctrl+W` | +| Close all tabs | `Ctrl+Shift+W` | +| Next tab | `Ctrl+Tab` | +| Previous tab | `Ctrl+Shift+Tab` | + +In the web app the browser owns most of those combinations, so only tab switching is bound: `Ctrl+Alt+→` for the next tab and `Ctrl+Alt+←` for the previous one. On macOS use `Command` wherever the table says `Ctrl`. + +== Mobile + +1. Open a note. It takes over the current tab. +2. To keep it and start another note, tap the **number badge** in the editor header — it shows how many tabs are open — and then tap `+` in the `Tabs` sheet. + +Every open tab is listed in that sheet. Tap one to switch to it, tap the close icon to close it, or use the close-all button beside `+` to close everything at once. + +To open a **specific note** in its own tab rather than a blank one, tap the ![Three dot button](/three-dot-button.png) button on that note and then the open-in-new icon at the top right of the properties sheet. See [note actions](/notes/note-actions) for the rest of that menu. + +::: + +## Manage tabs from the tab menu + +:::tabs key:platform +== Desktop/Web +Right click any tab for its menu: + +- `{{save}}` — only shown when that tab has unsaved changes +- `{{close}}` +- `{{closeOthers}}` +- `{{closeToRight}}` +- `{{closeToLeft}}` +- `{{closeAll}}` +- `{{revealInList}}` — scrolls the notes list to the note in this tab, and highlights it +- `{{pin}}` + +::: info Pinned tabs survive every "close" command +`{{closeOthers}}`, `{{closeToRight}}`, `{{closeToLeft}}` and `{{closeAll}}` all skip pinned tabs. `{{revealInList}}` is unavailable while focus mode is on, because the notes list is hidden. + +::: + +Middle-clicking a tab closes it, and tabs can be dragged left and right to reorder them. + +== Mobile + +The `{{tabs}}` sheet gives you a pin button and a close button on each tab, plus a close-all button and `+` in its header. There is no equivalent of `Close others`, `Close to the right`, `Close to the left` or `Reveal in list` on mobile. + +::: + +## Pin a tab + +Pinning keeps a note where you put it. A pinned tab: + +- moves to the front of the tab strip and stays there; +- shows a pin icon in place of its close button, so it can't be closed by accident; +- is skipped by every bulk close command; +- never gets replaced — while a pinned tab is active, opening another note always opens a **new** tab. + +:::tabs key:platform +== Desktop/Web +Right click the tab and choose `{{pin}}`. Click the pin icon on the tab to unpin it again. + +== Mobile + +Tap the number badge in the editor header, then tap the pin icon on the tab you want to pin. Tap it again to unpin. + +::: + +## Move back and forward inside a tab + +Each tab remembers the notes you opened in it, exactly like browser history — useful when you follow a [note link](/note-links-and-backlinks) and want to get back. + +:::tabs key:platform +== Desktop/Web +Use the back and forward arrows to the left of the tab strip. They're greyed out when there is nothing to go back or forward to. + +== Mobile + +Tap the `⋮` menu in the editor header. The back and forward arrows are in the row at the top of that menu. + +::: + +::: info +Back and forward are disabled in a pinned tab — a pinned tab is meant to stay on the note you pinned it to. + +::: + +## Split the editor with a side pane + +:::tabs key:platform +== Desktop/Web +Three panes can open to the right of the editor: + +- **Table of contents** — click the table-of-contents button in the top bar. It lists every heading in the note as a tree; click a heading to scroll to it, and use the chevrons to collapse a branch. If the note has no headings it says `{{noHeadingsFound}}`. +- **Properties** — click the `{{properties}}` button in the top bar for tags, notebooks, colors, reminders, attachments, `{{noteHistory}}` and note settings. +- **PDF preview** — opens by itself when you preview a PDF [attachment](/attachments-and-files) in the note, so you can read the PDF and write at the same time. See [reading a PDF](/attachments-and-files#read-a-pdf-without-downloading-it) for the pane's own toolbar. + +Drag the divider between two panes to resize them; the widths are remembered for next time. The table of contents and the properties pane share the same space, so opening one closes the other. + +== Mobile + +There are no side panes on a phone. The same information is available as sheets from the `⋮` menu in the editor header: + +- `{{toc}}` — listed only when the note actually has headings +- `{{properties}}` + +Previewing a PDF attachment opens it in a full-screen viewer instead of a pane. + +::: + +## Write without distractions + +:::tabs key:platform +== Desktop/Web +Click the sunglasses in the status bar at the bottom of the window. The side menu and the notes list disappear and only the editor is left. Click the glasses again to bring them back. + +While focus mode is on, a second button appears next to it: `{{enterFullScreen}}`. That one hands the whole screen to Notesnook; `{{exitFullScreen}}` or the `Esc` key returns you to the window. + +== Mobile + +Phones have no focus mode — the editor is already full screen. On a tablet, where the editor sits beside the notes list, tap the expand icon in the editor header to make the editor full screen. + +::: + +## Change the editor width and text size + +:::tabs key:platform +== Desktop/Web +The status bar at the bottom of the window holds both controls: + +- `{{enableEditorMargins}}` / `{{disableEditorMargins}}` — switch between a comfortable centered column and using the full width of the pane. +- The `−` and `+` buttons zoom the editor text between **30%** and **500%** in steps of 10%. Click the percentage itself to reset it to 100%. + +![The editor status bar at the bottom right, showing the word count and last saved time](/editor-status-bar-desktop.png) + +== Mobile + +Editor margins and zoom aren't available on mobile. Set your preferred text size instead in `{{settings}}` > `{{customization}}` > `{{editor}}`, as described in [personalizing the editor](/rich-text-editor/personalizing-rich-text-editor). + +::: + +## Check the word and character count + +:::tabs key:platform +== Desktop/Web +The status bar always shows the total word count for the note, plus a count of the words in your selection when you have text selected. + +Click that word count to open the full statistics popup: + +- `{{words}}` +- `{{characters}}` +- `{{paragraphs}}` +- `{{spaces}}` + +Each one shows the total, and how many are inside your current selection. + +::: warning Very long notes stop saving automatically +Above **100,000 words** the status bar shows `{{autoSaveOff}}`. From then on the note is saved only when you ask it to — press `Ctrl+S`, or click the save indicator at the right of the status bar (`{{clickToSave}}`). The same indicator tells you whether the current note is saved. +Even when autosave is off, notes are still saved when you switch away from the current editor tab. + +== Mobile + +Word statistics are shown at the top left of the editor. Tapping the count flips the view to the current character count. + +::: + +## Related pages + +- [Editor toolbar](/rich-text-editor/rich-text-editor-toolbar) — every formatting tool and how to customize the toolbar +- [Headings](/rich-text-editor/headings-and-collapsible-sections) — what feeds the table of contents, and how to collapse a section +- [Find & replace](/rich-text-editor/search-and-replace) — searching inside the note that's open in a tab +- [Personalizing the editor](/rich-text-editor/personalizing-rich-text-editor) — fonts, spacing and title formats +- [Keyboard shortcuts](/keyboard-shortcuts) — the full list for desktop and web diff --git a/docs/help/contents/rich-text-editor/headings-and-collapsible-sections.md b/docs/help/contents/rich-text-editor/headings-and-collapsible-sections.md new file mode 100644 index 000000000..2e6cf2a6d --- /dev/null +++ b/docs/help/contents/rich-text-editor/headings-and-collapsible-sections.md @@ -0,0 +1,123 @@ +--- +title: Headings +pageTitle: Headings and collapsible sections in the Notesnook editor +description: Apply headings 1 to 6 from the toolbar or with Ctrl+Alt+1..6, go back to a paragraph, and collapse everything under a heading to fold a long note. +keywords: + - notesnook headings + - collapsible headings notes + - fold sections in a note +--- + +# Headings and collapsible sections + +Headings give a note its structure. Notesnook supports six levels, each one available from the toolbar, from a keyboard shortcut, or by typing `#` characters. Every heading also acts as a fold: click the chevron beside it and everything underneath collapses out of the way. + +<!-- TODO: screenshot — a note with a collapsed Heading 2 showing the rotated chevron --> + +## Apply a heading + +:::tabs key:platform +== Desktop/Web + +1. Put the cursor on the line you want to turn into a heading, or select several lines. +2. Open the `{{headings}}` dropdown in the toolbar — it shows the current block, either `{{paragraph}}` or `Heading 1` to `Heading 6`. +3. Choose the level you want. + +Or skip the toolbar entirely: + +| Block | Shortcut | +| ------------------- | ------------ | +| Heading 1 | `Ctrl+Alt+1` | +| Heading 2 | `Ctrl+Alt+2` | +| Heading 3 | `Ctrl+Alt+3` | +| Heading 4 | `Ctrl+Alt+4` | +| Heading 5 | `Ctrl+Alt+5` | +| Heading 6 | `Ctrl+Alt+6` | +| Back to a paragraph | `Ctrl+Alt+0` | + +On macOS use `Command+Option` in place of `Ctrl+Alt`. + +== Mobile + +1. Tap the line you want to turn into a heading. +2. Open the `{{headings}}` dropdown in the toolbar at the bottom of the screen. On mobile the levels are labelled `H1` to `H6`. +3. Tap a level to apply it, or `{{paragraph}}` to turn a heading back into ordinary text. + +::: + +Applying a heading keeps the line's alignment and text direction, and clears any custom font size on the selection so the heading uses its own size. + +::: info Headings are unavailable inside a code block +The `{{headings}}` dropdown is disabled while the cursor is inside a [code block](/rich-text-editor/code-blocks), where `#` is an ordinary character. + +::: + +## Type a heading with Markdown <PlanTag plan="essential" /> + +With [Markdown shortcuts](/rich-text-editor/markdown-notes-editing) turned on, type one to six `#` characters followed by a space at the start of a line and it becomes a heading of that level — `# ` for Heading 1, `###### ` for Heading 6. Markdown shortcuts need the [Essential plan or higher](/plans-and-limits), and on desktop and web they're switched off until you turn them on in `{{settings}}` > `{{customization}}` > `{{editor}}`. + +The toolbar dropdown and the keyboard shortcuts work on every plan. + +## Collapse everything under a heading + +Every heading with text in it has a chevron at the end of the line. + +:::tabs key:platform +== Desktop/Web + +1. Hover over the heading — the chevron fades in immediately after the last word. +2. Click it. Everything below the heading is hidden and the chevron rotates to point right. +3. Click it again to unfold the section. + +== Mobile + +1. The chevron is always visible at the end of a heading line. +2. Tap it to collapse the section, tap it again to expand it. + +::: + +A collapsed heading hides everything after it **until the next heading of the same or a higher level**. So collapsing a `Heading 2` folds away the paragraphs, lists and any `Heading 3` blocks that belong to it, and stops at the next `Heading 2` or `Heading 1`. + +These block types are hidden when a section is collapsed: + +- paragraphs and headings +- bullet lists, numbered lists, check lists, [task lists](/rich-text-editor/task-and-todo-lists) and [outline lists](/rich-text-editor/outline-lists) +- [tables](/rich-text-editor/tables), [code blocks](/rich-text-editor/code-blocks), math blocks and [callouts](/rich-text-editor/callouts) +- quotes, horizontal rules, images, embeds and web clips + +Nested folds are remembered: if a `Heading 3` was already collapsed inside a section, expanding the parent heading leaves that inner section folded. + +::: info The fold is stored in the note +Collapsing a section is a change to the note's content, so the fold state is saved and syncs to your other devices. It doesn't delete or move anything — expanding the heading brings everything back exactly as it was. + +::: + +## Keep writing after a collapsed section + +Pressing `Enter` at the **end of a collapsed heading's text** doesn't push a new line into the hidden content. Notesnook adds a new paragraph _after_ the whole collapsed section and puts the cursor there, so you can carry on writing beneath a folded chapter without unfolding it first. + +Pressing `Enter` anywhere else in the heading behaves normally. + +## Navigate a long note + +Headings are what the table of contents is built from. + +:::tabs key:platform +== Desktop/Web +Click the table-of-contents button in the editor's top bar. The pane opens beside the note, lists every heading as a tree, follows along as you scroll, and jumps to a heading when you click it. A note with no headings shows `{{noHeadingsFound}}`. + +== Mobile + +Tap the `⋮` menu in the editor header and choose `Table of contents`. The entry only appears when the note actually has headings. `{{scrollToTop}}` and `{{scrollToBottom}}` in the same menu move you through the note quickly. + +::: + +[Find & replace](/rich-text-editor/search-and-replace) also expands collapsed headings automatically when a match is hidden inside one. + +## Related pages + +- [Editor toolbar](/rich-text-editor/rich-text-editor-toolbar) — every formatting tool and how to customize the toolbar +- [Markdown shortcuts](/rich-text-editor/markdown-notes-editing) — the full list of shortcuts, including `#` headings +- [Tabs & panes](/rich-text-editor/editor-tabs-and-panes) — the table of contents pane and focus mode +- [Find & replace](/rich-text-editor/search-and-replace) — searching inside a note, including folded sections +- [Plans & limits](/plans-and-limits) — what Essential, Pro and Believer unlock diff --git a/docs/help/contents/rich-text-editor/images-attachments-and-embeds.md b/docs/help/contents/rich-text-editor/images-attachments-and-embeds.md new file mode 100644 index 000000000..154078a66 --- /dev/null +++ b/docs/help/contents/rich-text-editor/images-attachments-and-embeds.md @@ -0,0 +1,147 @@ +--- +title: Images & embeds +pageTitle: Add images, files, audio and embeds to a note in Notesnook +description: Insert images from disk, camera or a URL, resize and align them, attach any file, play audio attachments, preview PDFs, and embed a video or a post in a note. +keywords: + - notesnook insert image + - notesnook attachments + - embed youtube in notes + - notesnook web clip +--- + +# Add images, files and embeds to a note + +Notes aren't only text. You can drop an image into a note, attach a file of any type, play back an audio recording, preview a PDF beside what you're writing, and embed a video or a post from the web. Everything you attach is encrypted before it leaves your device. + +::: info You need an account to attach anything +Attachments are uploaded to your encrypted storage, so Notesnook asks you to log in the first time you try to add one — the message reads `{{notLoggedIn}}` on desktop and web, and `{{loginRequired}}` on mobile. Storage and maximum file size depend on your plan; see [plans & limits](/plans-and-limits). + +::: + +<!-- TODO: screenshot — a note containing an image, a file attachment and an embedded video --> + +## Insert an image + +:::tabs key:platform +== Desktop/Web + +1. Put the cursor where the image should go. +2. Click the ![Toolbar plus](/toolbar-plus.png) button in the toolbar and choose `{{image}}`. +3. Pick `{{uploadFromDisk}}` (or press `Ctrl+Shift+I`) and select one or more image files, or pick `{{attachImageFromURL}}` and paste a link. +4. The `{{attachingFiles}}` dialog shows each file's progress; the image appears in the note when it's done. + +Two shortcuts skip the menu entirely: + +- **Drag and drop** — drag image files from your file manager straight onto the editor. +- **Paste** — paste an image from your clipboard. If the clipboard holds text _and_ a file, Notesnook pastes the text. + +== Mobile + +1. Tap where the image should go. +2. Tap the `+` button in the toolbar at the bottom of the screen and choose `{{image}}`. +3. Choose `{{uploadFromDisk}}` to pick from your gallery, `{{takePhotoUsingCamera}}` to shoot one now, or `{{attachImageFromURL}}` to paste a link. +4. Confirm in the sheet that appears; the image is encrypted and inserted into the note. + +::: + +::: info Images from a URL are downloaded, not hot-linked +When you use `{{attachImageFromURL}}`, Notesnook downloads the image and stores it as one of your attachments. The note never asks the original website for the file, so opening the note doesn't tell that site anything about you. + +::: + +## Keep images at full quality <PlanTag plan="pro" /> + +Images are compressed before upload by default, which keeps them small and fast to sync. Turning compression **off** — uploading the original, uncompressed file — is a Pro feature. + +:::tabs key:platform +== Desktop/Web +When the `{{attachingFiles}}` dialog is set to ask, each image has a `{{compress}}` toggle. Turn it off for full quality, then click `{{insert}}`. + +To change what happens by default, go to `{{settings}}` > `{{customization}}` > `{{behaviour}}` > `{{imageCompression}}` and choose `{{askEveryTime}}`, `{{enableRecommended}}` or `{{disable}}`. + +== Mobile + +The sheet shown when you attach an image has a `Compress (recommended)` checkbox. Clear it for full quality. + +To change the default, go to `{{settings}}` > `{{customization}}` > `{{behavior}}` > `{{imageCompression}}`. + +::: + +On a plan that doesn't support full quality images, the option is greyed out. Attempting to change it will ask you to upgrade your plan. + +## Resize and align an image + +1. Click (or tap) the image to select it. +2. Drag the handle in its **bottom-right corner**. The aspect ratio is locked, so the image never distorts, and it can't be dragged wider than the editor. +3. For exact numbers, open `{{imageProperties}}` from the image's toolbar and type a `width` or a `height` — the other value follows automatically. + +Alignment lives in the same toolbar, as three buttons: `{{alignLeft}}`, the centering button (its tooltip reads `{{alignCenter}}`) and `{{alignRight}}`. + +:::tabs key:platform +== Desktop/Web +Selecting an image floats a small toolbar above it with `{{previewAttachment}}`, `{{downloadAttachment}}`, the three alignment buttons and `{{imageProperties}}`. + +== Mobile + +Selecting an image adds an `{{imageSettings}}` button to the toolbar at the bottom. Tap it for `{{downloadAttachment}}`, alignment and `{{imageProperties}}`. `{{previewAttachment}}` is available directly in the toolbar. + +::: + +## Attach any other file + +1. Put the cursor where the attachment should go. +2. Open the ![Toolbar plus](/toolbar-plus.png) menu and choose `{{attachment}}` — on desktop and web the shortcut is `Ctrl+Shift+A`. +3. Select the file. It's encrypted on your device and uploaded to your storage. + +The attachment appears in the note as a block with its filename and size. Select it for `{{downloadAttachment}}`, and `{{previewAttachment}}` where the file type supports it. Dragging files onto the editor works for any file type, not only images. + +## Play an audio attachment + +Audio attachments render as a player with the filename, the file size and standard playback controls. Press play and Notesnook fetches and decrypts the audio before it starts — there's a short pause the first time. Selecting the player gives you `{{downloadAttachment}}` and, in an editable note, the option to remove it. + +## Preview an image or a PDF + +Select the attachment and choose `{{previewAttachment}}`. + +:::tabs key:platform +== Desktop/Web +Images open in a viewer. **PDFs open in a preview pane beside the editor**, so you can read the document and take notes on it at the same time. Drag the divider to resize the pane, and close it when you're done. See [tabs & panes](/rich-text-editor/editor-tabs-and-panes). + +== Mobile + +Images open in a full-screen image viewer and PDFs open in a full-screen PDF viewer. + +::: + +## Embed a video or a post + +1. Open the ![Toolbar plus](/toolbar-plus.png) menu and choose `{{embed}}`. +2. Use the `{{fromURL}}` tab and paste the address, setting `width` and `height` if you want, **or** use the `{{fromCode}}` tab and paste an embed snippet — the snippet has to contain an `iframe` with a `src`, and any width and height in it are used. +3. Click `{{save}}`. + +Notesnook converts common sharing URLs into their embeddable form for you, so a normal YouTube link works. YouTube embeds are loaded through a Notesnook proxy so the video service can't profile you from your note, and a link to X (formerly Twitter) is rendered as an embedded post rather than a bare frame. Embed code that tries to run `javascript:` is rejected. + +Select an embed to resize it with the bottom-right handle — embeds resize freely, without a locked aspect ratio — to align it left, center or right, or to open `{{embedProperties}}` and edit its source and exact size. On mobile the same buttons are grouped under `{{embedSettings}}` in the toolbar. + +::: warning Embeds load content from the internet +An embed is a live frame from another website, so opening a note that contains one makes a request to that site. Everything else in your note stays end-to-end encrypted; see [how your data is encrypted](/how-is-my-data-encrypted). + +::: + +## Read a web clip inside a note + +Pages saved with the [Notesnook Web Clipper](/web-clipper/clipping-your-first-web-page-with-web-clipper) appear in the note as a self-contained clip with the page title in its header. Select it for: + +- `{{fullscreen}}` — expand the clip to fill the screen; press `Esc` to come back +- `{{openLink}}` — open the saved copy of the page +- `{{openSource}}` — open the original page the clip came from + +On mobile these live under `{{webclipSettings}}` in the toolbar, which offers `{{fullscreen}}` and `{{openSource}}`. + +## Related pages + +- [Editor toolbar](/rich-text-editor/rich-text-editor-toolbar) — every formatting tool and how to customize the toolbar +- [Attachments and files](/attachments-and-files) — managing, downloading and cleaning up everything you've attached +- [Plans & limits](/plans-and-limits) — storage, maximum file size and full-quality images +- [Clipping your first web page](/web-clipper/clipping-your-first-web-page-with-web-clipper) — how clips get into a note +- [Tabs & panes](/rich-text-editor/editor-tabs-and-panes) — the PDF preview pane beside the editor diff --git a/docs/help/contents/rich-text-editor/markdown-notes-editing.md b/docs/help/contents/rich-text-editor/markdown-notes-editing.md index 37e1a1b3e..3945cd6d6 100644 --- a/docs/help/contents/rich-text-editor/markdown-notes-editing.md +++ b/docs/help/contents/rich-text-editor/markdown-notes-editing.md @@ -1,39 +1,105 @@ -# Markdown shortcuts in notes +--- +title: Markdown shortcuts +pageTitle: Markdown shortcuts in the Notesnook editor +description: Format notes as you type with Markdown shortcuts in Notesnook — headings, bold, lists, code blocks, tables and math, on desktop, web and mobile. +keywords: + - notesnook markdown + - markdown shortcuts notes app + - markdown note taking +schema: faq +faqs: + - q: Does Notesnook support Markdown editing? + a: Not as a raw editing mode. The Markdown shortcuts convert what you type into rich text blocks as you go, but the note itself is not stored or edited as raw Markdown. + - q: Can I import and export Markdown files in Notesnook? + a: Yes. You can import Markdown files and export any note as Markdown, with or without frontmatter. +--- -![Markdown notes editing with markdown shortcuts in notes](/markdown-editing.gif) +# Markdown shortcuts in notes <PlanTag plan="essential" /> + +Markdown shortcuts turn what you type into formatting. Type `# ` for a heading, `**bold**` for bold text, `- ` for a bullet list, and Notesnook applies the formatting the moment you finish the pattern — you never have to reach for the toolbar. + +![Typing markdown in the editor and watching it turn into formatting](/markdown-editing.gif) + +## Turn Markdown shortcuts on + +Markdown shortcuts are part of the [Essential plan and above](/plans-and-limits), and on the **web and desktop apps they are switched off until you turn them on**. On mobile they are on by default. + +:::tabs key:platform +== Desktop/Web + +1. Go to `{{settings}}`. +2. Open `{{customization}}` > `{{editor}}`. +3. Turn on `{{mardownShortcuts}}`. + +== Mobile + +1. Go to `{{settings}}`. +2. Open `{{customization}}` > `{{editor}}`. +3. Make sure `{{mardownShortcuts}}` is on. + +::: + +::: warning Nothing formats as you type until this is on +While Markdown shortcuts are off, **every** shortcut in the table below stops working — `#` headings, `**bold**`, list markers, code fences and math included. The toolbar and the keyboard shortcuts keep working either way. + +::: + +## Available shortcuts Notesnook supports the following (Markdown) shortcuts in the editor: -| Block | Markdown shortcut | -| --------------------------------- | --------------------------------------------------------------------- | -| Heading 1 | # | -| Heading 2 | ## | -| Heading 3 | ### | -| Heading 4 | #### | -| Heading 5 | ##### | -| Heading 6 | ###### | -| Bold | \*\*bold text\*\* | -| Italic | \_italicized text\_ | -| Strikethrough | \~\~strikethrough\~\~ | -| Blockquote | > blockquote | -| Ordered list | 1. First item<br>2. Second item<br>3. Third item | -| Unordered list | - First item<br>- Second item<br>- Third item | -| Task list | - \[x] Write the note<br>- [ ] Update the help<br>- [ ] Call the team | -| Outline list | -o Write the note<br>-o Update the help<br>-o Call the team | -| Inline code | \`inline code\` | -| Inline Math | \$\$2 + 2 = 4\$\$ | -| Horizontal rule | --- | -| Link | \[title](https://www.example.com) | -| Codeblock | \`\`\`javascript<br>function hello() { }<br>\`\`\` | -| Math block | $$$<br>2 + 2 = 4<br>$$$ | -| Current Date | `/date` | -| Current Day | `/day` | -| Date Time | `/time` | -| Current Date & Time | `/now` | -| Current Date & Time with timezone | `/nowz` | +| Block | Markdown shortcut | +| --------------------------------- | --------------------------------------------------------------- | +| Heading 1 | # | +| Heading 2 | ## | +| Heading 3 | ### | +| Heading 4 | #### | +| Heading 5 | ##### | +| Heading 6 | ###### | +| Bold | \*\*bold text\*\* | +| Italic | \_italicized text\_ | +| Strikethrough | \~\~strikethrough\~\~ | +| Blockquote | > blockquote | +| Ordered list | 1. First item<br>2. Second item<br>3. Third item | +| Unordered list | - First item<br>- Second item<br>- Third item | +| Task list | \[x] Write the note<br>[ ] Update the help<br>[ ] Call the team | +| Outline list | -o Write the note<br>-o Update the help<br>-o Call the team | +| Inline code | \`inline code\` | +| Inline Math | \$\$2 + 2 = 4\$\$ | +| Horizontal rule | --- | +| Link | \[title](https://www.example.com) | +| Codeblock | \`\`\`javascript<br>function hello() { }<br>\`\`\` | +| Math block | $$$ followed by a space | +| Current Date | `/date` | +| Current Day | `/day` | +| Current Time | `/time` | +| Current Date & Time | `/now` | +| Current Date & Time with timezone | `/nowz` | +| Callout | \>info Heads up<br>\>warn Careful<br>\>tip Try this | + +## Checklists and task lists share one shortcut + +`[] ` behaves differently depending on where you type it: + +- inside an existing bullet list, it turns those bullets into a **simple checklist**; +- on an empty line, it creates a full [task list](/rich-text-editor/task-and-todo-lists) with a title, a progress counter and sorting. + +Task lists, [outline lists](/rich-text-editor/outline-lists) and [callouts](/rich-text-editor/callouts) all need the [Essential plan or higher](/plans-and-limits). ## FAQs ### Does Notesnook support Markdown editing? -No. The Markdown shortcuts listed above are just that: shortcuts. They'll help you to quickly use the various formats & blocks in the editor but they aren't raw Markdown. +No. The Markdown shortcuts listed above are exactly that: shortcuts. They'll help you to quickly use the various formats & blocks in the editor but they aren't raw Markdown. + +### Can I import and export Markdown files? + +Yes. You can [import Markdown files](/importing-notes/import-notes-from-markdown-files) and [export any note as Markdown](/export-notes-from-notesnook), with or without frontmatter. + +## Related pages + +- [Editor toolbar](/rich-text-editor/rich-text-editor-toolbar) — every formatting tool and how to customize the toolbar +- [Code blocks](/rich-text-editor/code-blocks) — syntax highlighting for 297 languages +- [Math & formulas](/rich-text-editor/math-and-formulas) — writing LaTeX in a note +- [Personalizing the editor](/rich-text-editor/personalizing-rich-text-editor) — fonts, spacing and title formats +- [Plans & limits](/plans-and-limits) — what Essential, Pro and Believer unlock diff --git a/docs/help/contents/rich-text-editor/math-and-formulas.md b/docs/help/contents/rich-text-editor/math-and-formulas.md new file mode 100644 index 000000000..37098c9f2 --- /dev/null +++ b/docs/help/contents/rich-text-editor/math-and-formulas.md @@ -0,0 +1,99 @@ +--- +title: Math & formulas +pageTitle: How do I write math formulas in Notesnook? +description: Write LaTeX math in Notesnook — inline expressions inside a sentence, centered math blocks, and chemistry equations with mhchem, rendered by KaTeX. +keywords: + - notesnook latex + - notes app with math support + - katex notes + - write equations in notes +schema: howto +--- + +# Math & formulas + +Notesnook renders LaTeX math with [KaTeX](https://katex.org/), so you can write `\frac{a}{b}` in a note and see a real fraction. There are two kinds: **inline math**, which sits inside a line of text, and a **math block**, which is centered on its own line in display mode. + +## Insert inline math + +Inline math flows with the sentence around it, the way `$E = mc^2$` would in a paper. + +:::tabs key:platform +== Desktop/Web + +1. Put the cursor where the formula should go. +2. Click the `{{more}}` button in the first toolbar group (the one holding `{{bold}}`, `{{italic}}` and `{{underline}}`) and choose `{{mathInline}}`. +3. Type the LaTeX into the editor that opens under the formula. +4. Click anywhere outside it to render. + +There is no keyboard shortcut for inline math. With [Markdown shortcuts](/rich-text-editor/markdown-notes-editing) on, typing `$$2 + 2 = 4$$` converts to inline math as soon as you close the second pair of dollar signs. + +== Mobile + +1. Put the cursor where the formula should go. +2. Tap the `{{more}}` button in the bottom toolbar's first group (`{{bold}}`, `{{italic}}`, `{{underline}}`) and tap `{{mathInline}}`. +3. Type the LaTeX into the editor that opens under the formula. +4. Tap outside it to render. + +::: + +The `{{mathInline}}` button is disabled while the cursor is inside a [code block](/rich-text-editor/code-blocks). + +![The editor toolbar overflow menu, with the fx Math (inline) tool at the end of the row](/screenshots/editor-toolbar-more-menu.png) + +## Insert a math block + +A math block is rendered in display mode — centered, on its own line, with full-size operators. + +:::tabs key:platform +== Desktop/Web + +1. Place the cursor on an empty line. +2. Click the `+` (Insert) button in the toolbar. +3. Choose `{{mathAndFormulas}}`. +4. Type the LaTeX and click outside the block. + +`Ctrl+Shift+M` (`⌘+Shift+M` on macOS) inserts a math block from anywhere in the note. + +== Mobile + +1. Place the cursor on an empty line. +2. Tap the `+` (Insert) button in the bottom toolbar. +3. Choose `{{mathAndFormulas}}` from the `{{chooseBlockToInsert}}` sheet. +4. Type the LaTeX and tap outside the block. + +::: + +With Markdown shortcuts on, typing `$$$` followed by a space also creates a math block. + +::: info Markdown shortcuts need Essential +The `$$…$$` and `$$$` shortcuts are [Markdown shortcuts](/rich-text-editor/markdown-notes-editing), part of the [Essential plan and above](/plans-and-limits), and they are **off by default on web and desktop** — switch on `{{mardownShortcuts}}` in `{{settings}}` → `{{customization}}` → `{{editor}}`. They are on by default on mobile. The toolbar buttons and `Ctrl+Shift+M` work on every plan. + +::: + +## Edit a formula you already wrote + +Click (or tap) a rendered formula. It expands to show its LaTeX source in a small editor in place, with the rendered result above it. Change the source, then click outside the formula — or move the cursor away — and it re-renders immediately. + +An empty formula renders as an empty placeholder rather than disappearing, so you can always find it again. + +## Write chemistry equations + +The mhchem extension is loaded alongside KaTeX, so `\ce{...}` notation works out of the box: + +``` +\ce{2H2 + O2 -> 2H2O} +\ce{SO4^2- + Ba^2+ -> BaSO4 v} +``` + +## What happens when the LaTeX is invalid + +Notesnook never throws away your input over a typo. KaTeX renders unrecognized commands in red inside the formula and leaves everything it _could_ parse rendered normally, so a stray `\frac{1}` shows you exactly where the problem is. The raw LaTeX you typed is untouched — click the formula and fix it. + +## Related pages + +- [Editor toolbar](/rich-text-editor/rich-text-editor-toolbar) — every tool and block available in a note +- [Code blocks](/rich-text-editor/code-blocks) — syntax-highlighted code, with 297 languages +- [Markdown shortcuts](/rich-text-editor/markdown-notes-editing) — the full shortcut list and how to enable it +- [Plans & limits](/plans-and-limits) — which editor features need a paid plan +- [Personalizing the editor](/rich-text-editor/personalizing-rich-text-editor) — fonts and title formats diff --git a/docs/help/contents/rich-text-editor/outline-lists.md b/docs/help/contents/rich-text-editor/outline-lists.md new file mode 100644 index 000000000..6fec9e078 --- /dev/null +++ b/docs/help/contents/rich-text-editor/outline-lists.md @@ -0,0 +1,105 @@ +--- +title: Outline lists +pageTitle: How do I make a collapsible outline list in Notesnook? +description: Build collapsible, nested outlines inside a note in Notesnook — fold whole branches away, nest with Tab, and keep long structures readable. +keywords: + - notesnook outline list + - collapsible list notes app + - nested outline notes +schema: howto +--- + +# Outline lists <PlanTag plan="essential" /> + +An outline list is a nested list whose items **fold**. Any item with children gets a collapse arrow, so a hundred-line outline can sit in a note as five visible lines until you open the branch you need. + +That is the whole difference from a normal bullet list: a bullet list nests too, but everything in it is always visible. An outline list hides and shows branches, which makes it the better choice for meeting structures, project breakdowns, book outlines and anything else you scroll past more often than you read. + +## Create an outline list + +:::tabs key:platform +== Desktop/Web + +1. Place the cursor on an empty line, or select the lines you want to convert. +2. Click the `+` (Insert) button in the toolbar. +3. Choose `{{outlineList}}`. + +`Ctrl+Shift+O` (`⌘+Shift+O` on macOS) does the same thing, and toggles the list back to plain paragraphs if you press it inside one. + +== Mobile + +1. Place the cursor on an empty line, or select the lines you want to convert. +2. Tap the `+` (Insert) button in the bottom toolbar. +3. Choose `{{outlineList}}` from the `{{chooseBlockToInsert}}` sheet. + +::: + +Press `Enter` to start the next item, exactly as in any other list. + +![The insert block menu in the Notesnook editor, with Outline list near the top](/screenshots/editor-insert-block-menu.png) + +### Type `-o` instead + +On an empty line, type `-o` followed by a space and the line becomes the first item of an outline list. + +::: info Markdown shortcuts need to be enabled +`-o ` is a [Markdown shortcut.](/rich-text-editor/markdown-notes-editing) Markdown shortcuts are **off by default on web and desktop**: turn on `{{mardownShortcuts}}` in `{{settings}}` → `{{customization}}` → `{{editor}}`. On mobile they are on by default. The toolbar button and `Ctrl+Shift+O` do not depend on that setting. + +::: + +## Nest an item under another + +:::tabs key:platform +== Desktop/Web + +1. Put the cursor in the item you want to move in. +2. Press `Tab` to nest it under the item above. +3. Press `Shift+Tab` to move it back out one level. + +== Mobile + +1. Tap into the item you want to move in. +2. Tap `{{indent}}` in the bottom toolbar to nest it one level deeper. +3. Tap `{{outdent}}` to move it back out. + +These two buttons only appear while the cursor is inside a list item. + +::: + +As soon as an item has something nested under it, it becomes a parent and grows a collapse arrow. + +## Collapse and expand a branch + +:::tabs key:platform +== Desktop/Web + +1. Click the arrow in the margin to the left of a parent item — or put the cursor anywhere in that item and press `Ctrl+Space` (`⌘+Space` on macOS). +2. Everything nested under it folds away; the item itself stays visible. + +Repeat to expand it again. + +== Mobile + +1. Tap the arrow in the margin to the left of a parent item. +2. Everything nested under it folds away. + +Tap the arrow again to expand. + +::: + +Items with no children have nothing to fold, so no arrow appears on them. The collapsed state is saved with the note, so a branch you folded is still folded next time you open the note, on any device. + +<!-- TODO: screenshot — an outline list with one branch collapsed --> + +::: tip `⌘+Space` on macOS +macOS assigns `⌘+Space` to Spotlight by default. If nothing happens when you press it in the editor, use the collapse arrow instead, or rebind Spotlight in `System Settings` → `Keyboard` → `Keyboard Shortcuts`. + +::: + +## Related pages + +- [Editor toolbar](/rich-text-editor/rich-text-editor-toolbar) — every block you can insert into a note +- [Tasks and todo lists](/rich-text-editor/task-and-todo-lists) — checkable to-do blocks, also nestable +- [Callouts](/rich-text-editor/callouts) — the other collapsible block in the editor +- [Markdown shortcuts](/rich-text-editor/markdown-notes-editing) — the full shortcut list and how to switch it on +- [Plans & limits](/plans-and-limits) — what Essential unlocks, and everything else diff --git a/docs/help/contents/rich-text-editor/personalizing-rich-text-editor.md b/docs/help/contents/rich-text-editor/personalizing-rich-text-editor.md index 466c9491f..c7792fbf1 100644 --- a/docs/help/contents/rich-text-editor/personalizing-rich-text-editor.md +++ b/docs/help/contents/rich-text-editor/personalizing-rich-text-editor.md @@ -1,28 +1,70 @@ +--- +title: Personalizing the editor +pageTitle: Change the font, size and line spacing in the Notesnook editor +description: Set the default font and size in the Notesnook editor, adjust line height and paragraph spacing, turn on font ligatures, and change the note title format. +keywords: + - notesnook editor font + - notes app line spacing + - notesnook title format +schema: howto +--- + # Personalizing text editor Customize some common editor defaults to get a personalized editing experience. ## Default font size and font family -# [Desktop/Web](#/tab/web) +:::tabs key:platform +== Desktop/Web +The default font size and font family for all notes in the notes editor can be configured from `Settings > Customization > Editor`. -The default font size and font family for all notes in the notes editor can be configured from `Settings > Editor Settings`. - -# [Mobile](#/tab/mobile) +== Mobile The default font size and font family for all notes in the notes editor can be configured from `Settings > Customization > Editor`. ---- +::: -> info -> -> Custom fonts are not supported yet. +::: info +Custom fonts are not supported yet. + +::: + +## Line height + +`{{lineHeight}}` sets how much vertical space each line of text takes in the editor. The default is `1.2` and you can set anything between `1` and `10`. + +:::tabs key:platform +== Desktop/Web +Go to `{{settings}}` > `{{customization}}` > `{{editor}}` and set `{{lineHeight}}`. + +== Mobile + +Go to `{{settings}}` > `{{customization}}` > `{{editor}}` and tap `{{lineHeight}}`, then pick or type a value. + +::: + +## Font ligatures <PlanTag plan="pro" note="Web/desktop only" /> + +`{{fontLigatures}}` replaces common character sequences with a single symbol as you type — `->` becomes →, `<-` becomes ←, `<=` becomes ≤, `>=` becomes ≥, `!=` becomes ≠, `==>` becomes ⟹, `<==` becomes ⟸ and `--` becomes an em dash. + +:::tabs key:platform +== Desktop/Web +Go to `{{settings}}` > `{{customization}}` > `{{editor}}` and turn on `{{fontLigatures}}`. + +== Mobile + +Font ligatures are not available in the mobile editor. Turn them on in the desktop or web app — notes you write there keep the substituted symbols everywhere, because the substitution happens once as you type. + +::: + +Font ligatures require a Pro plan. See [Plans & limits](/plans-and-limits). ## Default note title format in rich text editor When you create a note in the text editor, a default title `Note $date$ $time$` is automatically set. You can change the default title format to better fit your needs. -Go to `Settings` > `Editor` > `Title format` to customize the title formatting. +Go to `{{settings}}` > `{{customization}}` > `{{editor}}` > `{{titleFormat}}` to customize the title formatting. ### Supported formatting templates @@ -40,8 +82,15 @@ Go to `Settings` > `Editor` > `Title format` to customize the title formatting. You can use a combination of above templates in the note title. For example `Note $count$ - $date$` will become `Note 150 - 06-22-2023`. -**$headline$**: Up to first 60 characters of the note's first paragraph or heading. This will keep updating the title as headline of the note changes until you manually edit the title. Shouldn't be used in combination with other templates. +**$headline$**: Up to first 60 characters of the note's first paragraph or heading. This will keep updating the title as headline of the note changes until you manually edit the title. This shouldn't be used in combination with other templates. ## Paragraph spacing -By default when you press enter on a line in the text editor, a new paragraph is created with double spacing. You can go to `Settings` > `Customization` > `Editor` to turn off `Double spaced lines`. +By default when you press enter on a line in the text editor, a new paragraph is created with double spacing. You can go to `{{settings}}` > `{{customization}}` > `{{editor}}` to turn off `{{doubleSpacedLines}}`. + +## Related pages + +- [Editor toolbar](/rich-text-editor/rich-text-editor-toolbar) — every formatting tool +- [Markdown shortcuts](/rich-text-editor/markdown-notes-editing) — formatting as you type +- [Customizing the app](/customizing-notesnook) — home screen, sidebar, sorting and formats +- [Spell checker](/desktop-integration/spell-checker) — dictionaries and languages diff --git a/docs/help/contents/rich-text-editor/rich-text-editor-toolbar.md b/docs/help/contents/rich-text-editor/rich-text-editor-toolbar.md index d936a6ebb..613631b2b 100644 --- a/docs/help/contents/rich-text-editor/rich-text-editor-toolbar.md +++ b/docs/help/contents/rich-text-editor/rich-text-editor-toolbar.md @@ -1,115 +1,174 @@ -# Editor Toolbar +--- +title: Editor toolbar +pageTitle: The Notesnook editor toolbar, and how to customize it +description: Insert blocks from the Notesnook editor toolbar, and rearrange its groups, subgroups and tools — or switch between the default, minimal and custom presets. +keywords: + - notesnook editor toolbar + - customize notes toolbar + - notesnook insert block +--- -The notes editor toolbar has all the basic tools for rich formatting of your notes. It also lets you add various blocks to your notes like task lists, images, videos etc. +# Editor toolbar -![Toolbar](/toolbar-editor.png) +The editor toolbar holds every formatting tool, and the `+` button on it inserts blocks — task lists, tables, images, code blocks and more. -## Adding blocks to a note +![The Notesnook editor toolbar, with its formatting tools grouped along the top of a note](/toolbar-editor.png) + +## Add a block to a note 1. Focus inside the note where you want to insert a block. -2. Click on the ![Toolbar plus](/toolbar-plus.png) button on the toolbar. +2. Click the ![Toolbar plus](/toolbar-plus.png) button on the toolbar. 3. Select the block you want to insert; for example a task list. -![Toolbar](/toolbar-blocks.png) +![The insert menu open in the editor, listing the blocks you can add to a note](/toolbar-blocks.png) -## Customzing editor toolbar +## Customize the editor toolbar <PlanTag plan="pro" /> -> info -> -> Toolbar configuration is automatically synced across all your devices. +An editor toolbar carries a lot of tools. Hiding the ones you never use, and keeping the ones you reach for at the front, leaves you with a toolbar that matches how you actually write. -One of the great features of the editor is the ability to customize the editor toolbar to fit your own needs. There's usually many tools in an editor toolbar and being able to hide the tools you never use and just keep what you use more frequently on top helps focus on your note taking. +::: info Desktop and mobile keep separate toolbars +Your toolbar layout syncs to your other devices, but desktop and mobile are stored separately — changing the toolbar on your laptop does not change the one on your phone, and the other way round. -# [Desktop/Web](#/tab/web) +::: -To customize the toolbar go to `Settings` > `Editor Settings` and click on `Configure Toolbar`. +On every platform the toolbar editor lives in the same place: `{{settings}}` > `{{customization}}` > `{{editor}}` > `{{customizeToolbar}}`. -![Configure editor toolbar](/config-toolbar-desktop.png) +![The Customize toolbar screen on desktop, showing the toolbar's groups and the tools inside each one](/config-toolbar-desktop.png) -# [Mobile](#/tab/mobile) +**Groups** — tools are distributed across groups. You can add, remove and reorder the groups in the toolbar. You can move tools between groups with drag and drop. -To customize the toolbar go to `Settings` > `Customization` > `Editor` and click on `Configure Toolbar`. +**Subgroups** — each group can have a single subgroup. Tools in a subgroup are collapsed into a drop down menu in the toolbar. ---- +:::tabs key:platform +== Desktop/Web +**Disabled items** — tools that are hidden from the toolbar. Drag a tool into this section to remove it from the toolbar. -**Groups** - Tools are distrubted across groups. You can add, remove and reorder the groups in the toolbar. You can move tools between groups with drag and drop. +== Mobile -**Subgroup** - Each group can have a single sub group. Tools in a subgroup are collapsed into a drop down menu in the toolbar. +**Disabled items** — tools that are hidden from the toolbar. Tap the `+` button on a group to see them and add them back. -# [Desktop/Web](#/tab/web) +::: -**Disabled Items** - Tools that are hidden from the toolbar. You can drag and drop a tool into this section to remove it from the toolbar. +### Choose a toolbar preset -# [Mobile](#/tab/mobile) +The toolbar always uses one of three presets, shown at the top of the `{{customizeToolbar}}` screen: -**Disabled Items** - Tools that are hidden from the toolbar. Click on the `+` button on a group to view disabled tools and add them back to the toolbar. +- `{{default}}` — the full set of groups and tools. +- `{{minimal}}` — a trimmed-down toolbar with only the most-used tools. +- `{{custom}}` <PlanTag plan="pro" /> — your own arrangement of groups, subgroups and tools. ---- +:::tabs key:platform +== Desktop/Web + +1. Go to `{{settings}}` > `{{customization}}` > `{{editor}}` > `{{customizeToolbar}}`. +2. Select `{{default}}`, `{{minimal}}` or `{{custom}}`. + +Editing groups or tools while `{{default}}` or `{{minimal}}` is selected switches you to `{{custom}}` automatically. + +== Mobile + +1. Go to `{{settings}}` > `{{customization}}` > `{{editor}}` > `{{customizeToolbar}}`. +2. Under `{{presets}}`, tap `{{default}}`, `{{minimal}}` or `{{custom}}`. + +::: + +Saving a `{{custom}}` preset requires a Pro plan — `{{default}}` and `{{minimal}}` are available on every plan. See [Plans & limits](/plans-and-limits). + +### Toolbar layouts on mobile are per device class + +Mobile keeps a separate toolbar layout for each device class — phone, small tablet and tablet — and picks the one that matches the current window size. Customizing the toolbar on your phone therefore does not change the layout you see on a tablet, and a tablet that switches between split-screen and full screen can move between the small tablet and tablet layouts. + +### Reset the toolbar + +:::tabs key:platform +== Desktop/Web +There is no reset action. Select the `{{default}}` preset on the `{{customizeToolbar}}` screen to go back to the stock toolbar. + +== Mobile + +1. Go to `{{settings}}` > `{{customization}}` > `{{editor}}`. +2. Tap `{{resetToolbar}}`. + +The toolbar goes back to the `{{default}}` preset and a `{{toolbarReset}}` toast confirms it. + +::: ### Add a new group -# [Desktop/Web](#/tab/web) +:::tabs key:platform +== Desktop/Web +To add a new group to the toolbar, click the `+` button in the header. -To add a new group to the toolbar, click on the `+` button in the header. +== Mobile -# [Mobile](#/tab/mobile) +Scroll to the bottom of the group list and tap `{{createAGroup}}`. -Scroll down the bottom of all groups. Click on `Create a group` button to add a new group. +::: ---- +### Add tools to a group -### Adding tools to a group +:::tabs key:platform +== Desktop/Web +Drag tools from other groups or from `Disabled items` into a group to add them. -# [Desktop/Web](#/tab/web) +== Mobile -Drag and drop tools from other groups or the `Disabled item` section into a group to add them to the group. +Tap the `+` button on a group header to add any disabled tools into the group. You can also drag tools in from other groups. -# [Mobile](#/tab/mobile) +::: -Click on the `+` button on a group header to add any disabled tools into the group. You can also drag and drop tools from other groups. +### Create a subgroup -### Creating a subgroup - -# [Desktop/Web](#/tab/web) +:::tabs key:platform +== Desktop/Web 1. Hover on a group header. -2. Click on the `+` button to add a subgroup. +2. Click the `+` button to add a subgroup. 3. Drag and drop tools into the subgroup. -4. Tools in the subgroup will be collapsed into a drop down. +4. Tools in the subgroup are collapsed into a drop down. -# [Mobile](#/tab/mobile) +== Mobile -You can create a subgroup by clicking on collapse button on a tool. Tools in the subgroup will be collapsed into a popup. +Create a subgroup by tapping the collapse button on a tool. Tools in the subgroup are collapsed into a popup. ---- +::: -### Deleting a group +### Delete a group -# [Desktop/Web](#/tab/web) - -You can remove a group and all it's tools from the toolbar. +:::tabs key:platform +== Desktop/Web +You can remove a group and all its tools from the toolbar. 1. Hover on a group header -2. Click on the trash icon to delete the group. -3. All the tools in the group will be moved to `Disabled items` section at the bottom. +2. Click the trash icon to delete the group. +3. All the tools in the group are moved to the `Disabled items` section at the bottom. -# [Mobile](#/tab/mobile) +== Mobile -1. Click on the `-` button on a group header to remove the group +1. Tap the `-` button on a group header to remove the group. 2. Tools removed from a group can be added back with the `+` button on the group header. ---- +::: ### Disable a tool -# [Desktop/Web](#/tab/web) +:::tabs key:platform +== Desktop/Web 1. Hover on a tool header -2. Click on the trash icon to disable the tool. -3. Deleted tools in the group will be moved to `Disabled items` section at the bottom. +2. Click the trash icon to disable the tool. +3. The tool is moved to the `Disabled items` section at the bottom. -# [Mobile](#/tab/mobile) +== Mobile -A tool can be disabled from the toolbar by clicking on the `-` button on the tool. +Tap the `-` button on a tool to disable it. ---- +::: + +## Related pages + +- [Markdown shortcuts](/rich-text-editor/markdown-notes-editing) — formatting as you type +- [Tables](/rich-text-editor/tables) — rows, columns, merging and CSV +- [Images & embeds](/rich-text-editor/images-attachments-and-embeds) — pictures, files and embedded content +- [Keyboard shortcuts](/keyboard-shortcuts) — every shortcut in one place +- [Plans & limits](/plans-and-limits) — what each plan unlocks and the exact limits diff --git a/docs/help/contents/rich-text-editor/search-and-replace.md b/docs/help/contents/rich-text-editor/search-and-replace.md new file mode 100644 index 000000000..5a9ef36d0 --- /dev/null +++ b/docs/help/contents/rich-text-editor/search-and-replace.md @@ -0,0 +1,101 @@ +--- +title: Find & replace +pageTitle: Find and replace text inside a note in Notesnook +description: Search inside the note you're editing with Ctrl+F, match case, whole words or a regular expression, and replace one match or all of them at once. +keywords: + - notesnook find and replace + - search inside a note + - notesnook regex search +schema: howto +--- + +# How do I find and replace text in a note? + +Press `Ctrl+F` while the editor is focused to search the note you're writing, or `Ctrl+Alt+F` to open the same box with a replace field. On macOS use `Command` instead of `Ctrl`. This searches **inside the open note only** — to search across every note, see [searching and navigating](/search-and-navigation). + +<!-- TODO: screenshot — the find and replace popup open over a note, with the match counter visible --> + +## Find text in the note + +:::tabs key:platform +== Desktop/Web + +1. Click into the note, then press `Ctrl+F`. You can also click the search button in the editor's top bar. +2. Type what you're looking for. Matches are highlighted as you type and the counter beside the field shows which match you're on, for example `3/12`. +3. Press `Enter` for the next match, `Shift+Enter` for the previous one — or use the `{{nextMatch}}` and `{{previousMatch}}` buttons. +4. Press `Escape`, or click `{{close}}`, when you're done. + +::: tip Start from a selection +If you select some text before pressing `Ctrl+F`, that text is put into the search field for you. + +::: + +== Mobile + +1. Tap the `⋮` menu in the editor header. +2. Tap the magnifying glass in the row at the top of the menu. +3. The find box opens as a sheet at the bottom of the screen. Type your search term; matches are highlighted and counted the same way. +4. Use `{{nextMatch}}` and `{{previousMatch}}` to step through the results, and `{{close}}` to dismiss the sheet. + +::: + +Notesnook scrolls to each match as you move through them, and reveals matches that are hidden inside a [collapsed heading](/rich-text-editor/headings-and-collapsible-sections), a collapsed [callout](/rich-text-editor/callouts) or a collapsed [outline list](/rich-text-editor/outline-lists) item. + +## Narrow the search with match case, whole word or regex + +The three matching options are folded away until you ask for them. + +1. Click the `{{expand}}` chevron inside the search field. +2. Turn on any combination of: + - `{{matchCase}}` — `{{note}}` no longer matches `note`. + - `{{matchWholeWord}}` — `cat` matches `cat` but not `catalogue`. + - `{{enableRegex}}` — your search term is treated as a regular expression instead of literal text. +3. The result count updates immediately. + +::: info About regular expressions +With `{{enableRegex}}` off, regular expression characters are escaped so the term is matched literally. With it on, the term is compiled as a JavaScript regular expression with the `g`, `u` and `m` flags, so patterns like `\d+` or `^Chapter` work and `^`/`$` anchor to each line. `.` does not match across line breaks. An expression that doesn't compile returns no matches. + +::: + +## Replace one match or all of them + +:::tabs key:platform +== Desktop/Web + +1. Press `Ctrl+Alt+F`, or press `Ctrl+F` and then click `{{toggleReplace}}`. +2. Type the search term in the first field and the replacement in the second. +3. Click `{{replace}}` to replace the match you're on — Notesnook then jumps to the next match, so you can work through the note by clicking `{{replace}}` repeatedly. +4. Click `{{replaceAll}}` to replace every match in the note in one step. + +== Mobile + +1. Tap the `⋮` menu, then the magnifying glass. +2. In the sheet, tap `{{toggleReplace}}` to reveal the replacement field. +3. Use `{{replace}}` for the current match, or `{{replaceAll}}` for every match in the note. + +::: + +::: warning Replace all cannot be undone from the search box +`{{replaceAll}}` rewrites every match at once. If it wasn't what you wanted, close the search box and press `Ctrl+Z` (`Command+Z`) in the editor to undo, or restore an earlier version from [note history](/note-version-history). + +::: + +## Why is there no replace field on this note? + +`{{toggleReplace}}`, `{{replace}}` and `{{replaceAll}}` only appear when the note can be edited. On a note in read-only mode you still get the full find experience — searching, match counting, and the matching options — but nothing can be rewritten until you turn read-only off. + +## Find & replace versus searching all your notes + +| You want to… | Use | +| -------------------------------------- | ------------------------------------------------------------------------- | +| Find a word in the note you're editing | `Ctrl+F` **inside** the editor | +| Find notes by their content or title | `Ctrl+F` outside the editor, which opens [search](/search-and-navigation) | +| Jump to a heading in a long note | The [table of contents pane](/rich-text-editor/editor-tabs-and-panes) | + +## Related pages + +- [Editor toolbar](/rich-text-editor/rich-text-editor-toolbar) — every formatting tool and how to customize the toolbar +- [Searching and navigating](/search-and-navigation) — finding notes across your whole account +- [Tabs & panes](/rich-text-editor/editor-tabs-and-panes) — the editor top bar, side panes and focus mode +- [Headings](/rich-text-editor/headings-and-collapsible-sections) — collapsing sections, and how search reveals them +- [Keyboard shortcuts](/keyboard-shortcuts) — the full list for desktop and web diff --git a/docs/help/contents/rich-text-editor/tables.md b/docs/help/contents/rich-text-editor/tables.md index 5bdea5597..3ad8995ba 100644 --- a/docs/help/contents/rich-text-editor/tables.md +++ b/docs/help/contents/rich-text-editor/tables.md @@ -1,107 +1,178 @@ +--- +title: Tables +pageTitle: How do I add a table to a note in Notesnook? +description: Insert a table in a Notesnook note and resize, move, merge and split its rows, columns and cells — plus importing and exporting tables as CSV. +keywords: + - notesnook table + - insert table in note + - notes app with tables + - import csv to note +schema: howto +--- + # Tables -![Notes editor with table example](/table-example-22.png) +![A table in the Notesnook editor with its row and column controls visible](/table-example-22.png) -Tables in Notesnook provide all the basic to advanced functionality. On the left side are the `Row properties` and `Insert a new row` buttons while on top of the table are `Table properties` and `Insert a new column` buttons. +Tables in Notesnook provide all the basic to advanced functionality. On the left side are the `{{rowProperties}}` and `{{insertRowBelow}}` buttons while on top of the table are `{{tableSettings}}` and `{{insertColumnRight}}` buttons. The first row of a newly created table is always a header. You can always delete this row if you do not like the header row formatting. ## Insert a table -1. Click on the ![Toolbar plus](/toolbar-plus.png) and select the table block. +1. Click the ![Toolbar plus](/toolbar-plus.png) and select the table block. 2. Select the size of the table grid. -![Create a table in rich text editor](/create-table.png) +![The table size grid in the insert menu](/create-table.png) ## Resizing table columns Table columns are resizable on all platforms. -# [Desktop](#/tab/desktop) +:::tabs key:platform +== Desktop 1. Hover on the separator between two columns, it will turn green 2. Click and hold separator to resize the column. ![Resize a table](/resize-table.gif) -# [Mobile](#/tab/mobile) +== Mobile -1. Tap on the separator between the two columns. +1. Tap the separator between the two columns. 2. Drag the separator left or right to resize. ![Resize a table on mobile](/resize-table-mobile.gif) ---- +::: ## Insert a row -1. Click on a cell below which you want to insert a new row. -2. Click on the `Insert row below` button to insert a new row. +1. Click a cell below which you want to insert a new row. +2. Click the `{{insertRowBelow}}` button to insert a new row. ![Insert row in the table](/insert-row-table.gif) ## Delete a row -1. Click on a cell of the row you want to delete -2. Click on the cell properties button and select `Delete row` +1. Click a cell of the row you want to delete +2. Click the row properties button and select `{{deleteRow}}` ![Delete a row from the table](/table-row-delete.png) ## Move row -1. Click on a cell of the row you want to move. -2. Click on the cell properties button and select `Move row up` to move the row up or `Move row down` to move the row down. +1. Click a cell of the row you want to move. +2. Click the row properties button and select `{{moveRowUp}}` to move the row up or `{{moveRowDown}}` to move the row down. ![Move a row in the table](/table-move-row.gif) ## Insert a column -1. Click on a cell in a column after which you want to insert a new column. -2. Click on the `Insert column right` button to insert a new column. +1. Click a cell in a column after which you want to insert a new column. +2. Click the `{{insertColumnRight}}` button to insert a new column. ![Insert a column in the table](/table-insert-column.gif) ## Delete a column -1. Click on a cell of the column you want to delete -2. Click on the table properties button and select `Delete column` +1. Click a cell of the column you want to delete +2. Click the column properties button and select `{{deleteColumn}}` ![Delete a column from the table](/table-delete-column.png) ## Move column -1. Click on a cell of the column you move. -2. Click on the table properties button on top and select `Move column right` to move the column right or `Move column left` to move the column left. +1. Click a cell of the column you move. +2. Click the column properties button on top and select `{{moveColumnRight}}` to move the column right or `{{moveColumnLeft}}` to move the column left. ![Move a column in the table](/table-move-column.gif) ## Merge cells 1. Drag and select the cells you want to merge -2. Click on table properties on top of table and select `Merge cells` +2. Click table properties on top of table and select `{{mergeCells}}` ![Merge table cells](/table-merge-cells.gif) ## Split cells 1. Double click to select the cell you want to split -2. Click on table properties on top of table and select `Split cells` +2. Click table properties on top of table and select `{{splitCells}}` ![Split table cells](/table-split-cell.gif) ## Cell Properties 1. Select the cell you want to customize -2. Click on the table properties button on top +2. Click the table properties button on top 3. Select Cell properties 4. You can now change cell background, text color and border color. ![Customize cell properties](/cell-properties.png) +## Import CSV <PlanTag plan="pro" /> + +`{{importCsv}}` turns a `.csv` file into a new table at the cursor, so you don't have to retype spreadsheet data. The first row of the file becomes the table's header row. + +:::tabs key:platform +== Desktop/Web + +1. Focus inside the note where you want the table. +2. Click the ![Toolbar plus](/toolbar-plus.png) button and open `{{table}}`. +3. Click `{{importCsv}}` and pick a `.csv` file. + +The table is inserted with one row per line and one column per field. + +== Mobile + +1. Focus inside the note where you want the table. +2. Tap the ![Toolbar plus](/toolbar-plus.png) button and open `{{table}}`. +3. Tap `{{importCsv}}` and pick a `.csv` file. + +::: + +<!-- TODO: screenshot — the Import CSV item in the toolbar's Table insert menu --> + +Importing a CSV into a table requires a Pro plan. See [Plans & limits](/plans-and-limits). + +## Export CSV <PlanTag plan="pro" /> + +`{{exportCsv}}` writes out the table you are in — and only that table — as a `.csv` file you can open in a spreadsheet. + +:::tabs key:platform +== Desktop/Web + +1. Click a cell in the table. +2. Click the `{{tableSettings}}` button on top of the table. +3. Click `{{exportCsv}}`. + +The file is saved as `table.csv`. + +== Mobile + +1. Tap a cell in the table. +2. Tap the `{{tableSettings}}` button in the toolbar at the bottom. +3. Tap `{{exportCsv}}`. + +On Android you are asked where to save `table.csv`. On iOS the file is saved inside the app and a `Table saved to csv` sheet lets you share it from there. + +::: + +<!-- TODO: screenshot — the Export CSV item in the table settings menu --> + +Exporting a table as CSV requires a Pro plan. See [Plans & limits](/plans-and-limits). + ## Delete table 1. Select the table -2. Click on table properties button on top. -3. Select `Delete table` from drop down menu +2. Click table properties button on top. +3. Select `{{deleteTable}}` from drop down menu ![Delete a table from the notes editor](/delete-table.png) + +## Related pages + +- [Editor toolbar](/rich-text-editor/rich-text-editor-toolbar) — every formatting tool +- [Markdown shortcuts](/rich-text-editor/markdown-notes-editing) — formatting as you type +- [Plans & limits](/plans-and-limits) — what each plan unlocks and the exact limits diff --git a/docs/help/contents/rich-text-editor/task-and-todo-lists.md b/docs/help/contents/rich-text-editor/task-and-todo-lists.md index ba6f69afa..425a917d6 100644 --- a/docs/help/contents/rich-text-editor/task-and-todo-lists.md +++ b/docs/help/contents/rich-text-editor/task-and-todo-lists.md @@ -1,51 +1,97 @@ --- title: Tasks and todo lists -description: Create todo lists and manage your tasks in Notesnook with ease using task lists. +pageTitle: Task lists and to-do lists in Notesnook +description: Build to-do lists inside any note in Notesnook — with titles, progress counts, subtasks, drag-and-drop reordering and one-click clearing of completed tasks. +keywords: + - notesnook task list + - encrypted to do list + - notes app with todo lists +schema: howto --- -# Task and todo lists +# Task and todo lists <PlanTag plan="essential" /> -Create todo lists and manage your tasks in Notesnook with ease using task lists. +Create todo lists and manage your tasks in Notesnook with ease using task lists. A task list lives inside a note, so your checklist sits alongside the notes that explain it — and it is [encrypted](/how-is-my-data-encrypted) like everything else. + +Task lists are part of the [Essential plan and above](/plans-and-limits). On the free plan you can still use a simple checklist: type `[] ` inside an existing bullet list, or pick `{{checklist}}` from the toolbar. + +## Add a task list to a note + +:::tabs key:platform +== Desktop/Web + +1. Place the cursor on an empty line. +2. Click the `+` (Insert) button in the toolbar. +3. Choose `{{taskList}}`. + +You can also press `Ctrl+Shift+T`, or type `[] ` on an empty line if you have [Markdown shortcuts](/rich-text-editor/markdown-notes-editing) turned on. + +== Mobile + +1. Place the cursor on an empty line. +2. Tap the `+` (Insert) button in the toolbar. +3. Choose `{{taskList}}`. + +Typing `[] ` on an empty line also works — Markdown shortcuts are on by default on mobile. + +::: + +## Track your progress + +Every task list carries a header showing how many of its items are done, with a progress bar that fills as you check things off. Checking a parent task checks all of its subtasks, and clearing the last subtask unchecks the parent. ## Adding a title to the task list When you add a task list to a note, a header is added on top of each task list. You can add a title to the task list. -![Add a heading to the todo list in notes editor](/task-header-title.png) +![A task list in the editor with a title typed into its header and a progress bar beneath it](/task-header-title.png) ## Sort completed tasks in task list -Sort completed tasks at the bottom of task list by clicking on the ![Sort completed task icon](/sort-task-icon.png) button on the task list header. +Sort completed tasks to the bottom of the list with the ![Sort completed tasks](/sort-task-icon.png) button in the task list header. ## Clear completed tasks from task list -Clear completed task items by clicking on the ![Clear completed task button](/sort-task-icon.png) button on the task list header. +Remove every completed item at once with the ![Clear completed tasks](/clear-task-icon.png) button in the task list header. ## Moving task items with drag and drop You can move task items and change the order by drag and drop using the drag handle at the start of each task item. -![Move todo item with drag and drop](/drag-drop.gif) +![Dragging a task by the handle at the start of the row to reorder it within the list](/drag-drop.gif) ## Adding a subtask to a parent task Notesnook supports unlimited subtasks under a single task item. -# [Desktop/Web](#/tab/web) +:::tabs key:platform +== Desktop/Web 1. Move selection to the end of the parent task item 2. Press `Enter` to create a new task item 3. Press `Tab` to indent it into a sub task -# [Mobile](#/tab/mobile) +== Mobile 1. Move selection to the end of the parent task item 2. Press `Enter` to create a new task item -3. Tap on the Indent tool button in the toolbar to indent it into a sub task +3. Tap the Indent tool button in the toolbar to indent it into a sub task ---- +::: Subtasks support the following features: 1. Completing a parent task will automatically complete all the sub tasks and vice versa. 2. You can select multiple sub tasks & mark them as completed/uncompleted together + +## Make a task list read-only + +Once a list is final, you can lock it against accidental edits with the `{{readonlyTaskList}}` button in the task list header — useful for a checklist you follow but don't change, like a packing list or a release checklist. The setting applies to nested task lists too, and you toggle it back off from the same button. + +## Related pages + +- [Editor toolbar](/rich-text-editor/rich-text-editor-toolbar) — where the insert menu lives, and how to customize it +- [Outline lists](/rich-text-editor/outline-lists) — collapsible nested lists for structuring longer notes +- [Markdown shortcuts](/rich-text-editor/markdown-notes-editing) — type `[] ` instead of using the menu +- [Reminders](/reminders) — get notified about a note at a specific time +- [Plans & limits](/plans-and-limits) — what the Essential plan unlocks diff --git a/docs/help/contents/search-and-navigation.md b/docs/help/contents/search-and-navigation.md new file mode 100644 index 000000000..d4719ba32 --- /dev/null +++ b/docs/help/contents/search-and-navigation.md @@ -0,0 +1,332 @@ +--- +title: Search & navigation +pageTitle: How to search your notes and move around Notesnook fast +description: Search your notes in Notesnook, narrow results with filters like tag, color, date and favorite, and jump anywhere with the command palette and quick open. +keywords: + - notesnook search notes + - notesnook search filters + - notesnook command palette + - search inside notes + - notesnook sort notes +--- + +# How do I search my notes in Notesnook? + +Every list view has a search box at the top of it. Type into it and Notesnook searches the notes in _that_ view — the whole notes list, one notebook, one tag, favorites, trash — matching both note titles and the text inside notes, and showing you the matching passages. + +Search runs on your device against the local database. Nothing about what you search for is sent anywhere. + +You can also [narrow a search with filters](#narrow-a-search-with-filters) — by tag, color, date, or whether a note is favorited, archived or filed in a notebook. + +## Search inside a view + +:::tabs key:platform +== Desktop/Web + +1. Click the search box at the top of the list. It's labelled after the view you're in — `Search in Notes`, `Search in Notebook`, `Search in Trash` and so on. +2. Type your query. Results appear as you type. +3. Press `Escape`, or click the ✕ in the box, to clear the search and go back to the full list. + +`Ctrl+F` (`⌘+F` on macOS) puts the cursor in that box whenever the editor isn't focused. If you're in a note, `Ctrl+F` opens the editor's own find bar instead. + +== Mobile + +1. Tap the bar at the top of the screen — it reads `Search in Notes`, `Search in Notebook` and so on, depending on the view. +2. Type your query. Results appear as you type. +3. Tap the back arrow to return to the list. + +::: + +## What is actually searched + +| You're searching | Matched on | +| ---------------- | ----------------------------------- | +| Notes | Title and the full text of the note | +| Notebooks | Title and description | +| Tags | Title | +| Reminders | Title and description | +| Attachments | Filename, file type and hash | +| Trash | Deleted notes and notebooks | + +::: info Locked notes +The content of a note in your [private vault](/lock-notes-with-private-vault) is encrypted, so it is never added to the search index. Locked notes are found by their titles only. This is a limitation of end-to-end encryption, not a bug. + +::: + +## Narrow a search with filters + +Search understands filters — `field:value` pairs you add to a search to cut the results down. Filters only work when you are **searching notes**. + +::: warning Put your words first, filters last +A word typed _after_ a filter is swallowed into it, and the whole search silently returns nothing: + +- `favorite:true meeting` — finds nothing at all +- `meeting favorite:true` — finds favorite notes containing "meeting" ✓ + +Always write what you're looking for, then the filters. + +::: + +### Filters you can use + +**Where to look** + +| Filter | Finds | +| ---------------- | --------------------------------- | +| `title:budget` | Notes whose **title** matches | +| `content:budget` | Notes whose **body text** matches | + +Without either of these, your words are matched against both `content` and `title`. + +**Tags and colors** + +| Filter | Finds | +| ----------- | -------------------------- | +| `tag:work` | Notes with the tag _work_ | +| `color:red` | Notes with the color _red_ | + +Values match the tag or color's exact title. Quote anything with a space: `tag:"work stuff"`. + +**Dates** + +| Filter | Finds | +| --------------------------- | ----------------------------- | +| `created_after:2026-01-01` | Notes created after that date | +| `created_before:2026-01-01` | Notes created before it | +| `edited_after:2026-01-01` | Notes edited after it | +| `edited_before:2026-01-01` | Notes edited before it | + +Write dates as `YYYY-MM-DD`. Words like `yesterday` are not understood and will make the search return nothing. + +**Yes / no filters** + +Each takes exactly `true` or `false`. + +| Filter | `true` finds | `false` finds | +| -------------- | ----------------------------------------------------- | --------------------------- | +| `favorite:` | Favorited notes | Notes that aren't favorited | +| `pinned:` | Pinned notes | Unpinned notes | +| `archived:` | Archived notes | Notes not archived | +| `readonly:` | Read-only notes | Editable notes | +| `locked:` | Notes in your [vault](/lock-notes-with-private-vault) | Notes outside it | +| `tagged:` | Notes with **any** tag | Notes with no tags at all | +| `colored:` | Notes with **any** color | Notes with no color | +| `in_notebook:` | Notes filed in **any** notebook | Notes in no notebook | + +The last three are the quickest way to find notes you never filed: `in_notebook:false` lists every loose note, `tagged:false` every untagged one. + +`locked:` only works once you have created a vault. + +### Combine filters + +Add as many as you like — a note has to satisfy all of them: + +``` +roadmap tag:work favorite:true edited_after:2026-06-01 +``` + +That reads: notes containing "roadmap", tagged _work_, favorited, and edited since 1 June 2026. + +You can also search with filters **and no words at all**, which lists everything that matches: + +``` +in_notebook:false archived:false +``` + +### Useful searches + +| Search | What it gives you | +| --------------------------------------- | ------------------------------------------ | +| `in_notebook:false` | Notes you never filed into a notebook | +| `tagged:false` | Notes with no tags | +| `favorite:true edited_after:2026-07-01` | Recently edited favorites | +| `tag:receipts created_after:2026-01-01` | This year's receipts | +| `budget content:quarterly` | "budget" anywhere, "quarterly" in the body | +| `locked:true` | Everything in your vault | + +### Things to watch out for + +- **`true` and `false` must be lowercase.** `favorite:TRUE` or `favorite:yes` makes the search return nothing. +- **A filter Notesnook doesn't recognise is treated as plain text.** `colour:red` searches for the literal words rather than filtering by color — the spelling is `color:`. +- Filter names are case-sensitive: `Tag:work` returns nothing. + +## Read the results and jump to a match + +A note that matched shows its title with the matching words highlighted, and the number of matches found inside the note on the right. + +:::tabs key:platform +== Desktop/Web + +1. Click the arrow next to a result to expand it. Each matching passage in the note is listed underneath, with the matched words highlighted. +2. Click a passage to open the note scrolled straight to that spot. +3. Middle-click a passage to open it in a new tab instead. + +Passages are only shown in the detailed list. Switching the notes list to compact view collapses results to titles. + +== Mobile + +1. Tap a result to open the note. + +Matching passages are highlighted in the result so you can see the context before opening it. + +::: + +<!-- TODO: screenshot — an expanded search result showing highlighted matches under the note title --> + +## Run a command from the keyboard + +The command palette is a desktop and web feature. Press `Ctrl+Shift+P` (`⌘+Shift+P` on macOS) — `Ctrl+Shift+:` works too — to open it. Start typing and it fuzzy-matches every command in the app: + +- **Navigate** — `Notes`, `{{notebooks}}`, `Tags`, `Favorites`, `{{reminders}}`, `{{monographs}}`, `{{trash}}`, `{{settings}}`, `{{helpAndSupport}}`, `Keyboard shortcuts`, `{{attachmentManager}}`. +- **Create** — `{{newNote}}`, `{{newNotebook}}`, `{{newTag}}`, `{{newReminder}}`, `{{newColor}}`. +- **Editor** — when a note is open: `{{newTab}}`, `{{nextTab}}`, `{{previousTab}}`, `{{closeCurrentTab}}`, `{{closeAllTabs}}`, `{{undo}}`, `{{redo}}`, `{{goBackInTab}}`, `{{goForwardInTab}}`, `{{toggleFocusMode}}`. +- **General** — `{{toggleTheme}}`. +- **Every action of whatever you have open** — the entire note menu for the note in the editor, and the notebook or tag menu for the notebook or tag you're viewing, appear as commands too. +- **Recents** — the commands you ran last, at the top. + +Move with `↑` and `↓`, run with `⏎`. Press `Delete` on an entry under recents, or click the ✕ on it, to drop it from the list. + +::: info Not on mobile +The command palette and quick open are only features of the **desktop and web apps**. On mobile, use the search bar and the side menu. + +::: + +## Jump to a note by name + +Quick open is a desktop and web feature. Press `Ctrl+P` (`⌘+P` on macOS) for **quick open**. It searches your notes, notebooks, tags and reminders by title and opens whatever you pick. With the box empty it lists your recent items and the notes already open in tabs. + +| Key | What it does | +| ---------------- | --------------------------------------------- | +| `⏎` | Open the highlighted item | +| `Ctrl+⏎` / `⌘+⏎` | Open the highlighted note in a new tab | +| `Shift+⏎` | Open a new tab titled with whatever you typed | + +`Shift+⏎` is the fast way to turn a search that found nothing into a new note: type the title you were looking for, press `Shift+⏎`, and start writing. + +## Search your settings + +:::tabs key:platform +== Desktop/Web + +1. Press `Ctrl+,` (`⌘+,` on macOS), or open `{{settings}}` from the side menu. +2. Type into the `{{search}}` box at the top of the settings sidebar. + +The search covers every section at once — section names, group headings, setting titles, their descriptions and their keywords — so you can find a setting without knowing which section it lives in. `{{noResultsFound}}` means nothing matched. + +== Mobile + +Settings on mobile has no search box. Open `{{settings}}` from the side menu and pick the section you need. + +::: + +## Filter notebooks and tags + +The notebooks and tags lists have their own filter box, separate from note search. + +:::tabs key:platform +== Desktop/Web + +1. Open `{{notebooks}}` or `Tags` from the side menu. +2. Type into the `Filter notebooks...` or `Filter tags...` box at the bottom of the list. + +== Mobile + +1. Open `{{notebooks}}` or `Tags` in the side menu. +2. Type into the `Filter notebooks...` or `Filter tags...` box at the bottom of the list. + +::: + +Clearing the box restores the full list. + +## Sort a list + +Sorting is set per view, and separately for each individual notebook, tag and color — so you can keep one notebook alphabetical and everything else newest-first. + +:::tabs key:platform +== Desktop/Web + +1. Click the sort icon in the group header at the top of the list. +2. Open `{{orderBy}}` and choose the direction. +3. Open `{{sortBy}}` and choose the key. + +== Mobile + +1. Tap the sort icon in the group header at the top of the list. +2. Tap the direction button next to `{{sortBy}}` to flip between ascending and descending. +3. Tap a key under `{{sortBy}}`. + +::: + +There are seven sort keys. Which ones are offered depends on the list you're in: + +| Sort by | Available in | +| --------------- | ------------------------------------------------------------------- | +| `Date created` | Everywhere except trash | +| `Date edited` | Everywhere except trash and tags — and, on mobile, except reminders | +| `Date modified` | Tags, and reminders on mobile | +| `Date deleted` | Trash | +| `Due date` | Reminders | +| `{{title}}` | Everywhere | +| `Relevance` | Search results | + +The direction labels change with the key: `{{aToZ}}` / `{{zToA}}` for `{{title}}`, `{{earliestFirst}}` / `{{latestFirst}}` for `Due date`, `{{mostRelevantFirst}}` / `{{leastRelevantFirst}}` for `Relevance`, and `{{oldestToNewest}}` / `{{newestToOldest}}` for the date keys. + +## Group a list + +Grouping splits the list into labelled sections. Six modes are available: + +| `{{groupBy}}` | Result | +| ------------- | -------------------------------------- | +| `{{default}}` | Today, Yesterday, This week, and so on | +| `{{none}}` | One flat list, no headers | +| `Abc` | One section per first letter | +| `Year` | One section per year | +| `{{month}}` | One section per month | +| `Week` | One section per week | + +:::tabs key:platform +== Desktop/Web + +1. Click the sort icon in the group header. +2. Open `{{groupBy}}` and pick a mode. + +Clicking the group header itself opens `{{jumpToGroup}}`, which scrolls the list straight to any section. + +== Mobile + +1. Tap the sort icon in the group header. +2. Scroll to `{{groupBy}}` and pick a mode. + +Tapping the group title opens the jump-to-group list. + +::: + +Grouping isn't offered for reminders or for search results — those are always sorted, never grouped. + +## Switch to compact mode + +Compact mode drops each row to a single line: title, plus small icons for locked, favorite, read-only and expiring notes, and the time. It fits far more notes on screen. + +:::tabs key:platform +== Desktop/Web + +1. Click the view icon next to the sort icon in the group header. + +It's available on the notes, favorites and notebooks lists, and it also collapses search results to their titles. + +== Mobile + +1. Tap the list-view icon next to the sort icon in the group header. + +Notes, notebooks and search results each remember their own setting. + +::: + +## Related pages + +- [Keyboard shortcuts](/keyboard-shortcuts) — the full list of shortcuts on desktop and web +- [Note links](/note-links-and-backlinks) — navigating between notes with internal links +- [Note actions](/notes/note-actions) — what you can do with a note once you've found it +- [Organize notes using notebooks](/organizing-notes/organize-notes-using-notebooks) — structure that makes search unnecessary +- [Organize notes using tags](/organizing-notes/organize-notes-using-tags) — filtering by tag instead of searching +- [Archive notes](/organizing-notes/archive-notes) — getting old notes out of your search results diff --git a/docs/help/contents/self-hosting.md b/docs/help/contents/self-hosting.md new file mode 100644 index 000000000..7fa131486 --- /dev/null +++ b/docs/help/contents/self-hosting.md @@ -0,0 +1,271 @@ +--- +title: Self-hosting +pageTitle: How do I self-host Notesnook? +description: Point the Notesnook apps at your own sync, auth, events and monograph servers. What each server does, and what Test connection actually checks. +keywords: + - self host notesnook + - notesnook sync server + - notesnook custom server url + - notesnook server configuration +--- + +# How do I self-host Notesnook? + +Every Notesnook app — web, desktop and mobile — lets you replace the servers it talks to with your own. You point the app at four URLs, test them, save, and the app restarts against your infrastructure. Your notes stay end-to-end encrypted either way; self-hosting means the encrypted data never touches Notesnook's machines. + +## Getting Started + +This guide assumes you are already familiar with the command line and basic systems security. Notesnook is not responsible for issues that may arise from improper configuration of the server. You are fully responsible for making adequate backups and for the security of your data and server. + +### Hardware requirements + +- Operating System: Linux. +- RAM: 1 Gigabyte. +- CPU: Any ARM or x86 cpu, as long as it supports AVX. +- Storage: 20 gigabytes. + +### Prerequisites + +1. Docker +2. Docker Compose +3. wget +4. curl +5. (optional) A reverse proxy, like Caddy or Ngnix. + +This guide assumes you already have a Linux server set up and ready to go. + +### Installation + +1. Create a directory where your configuration files will go. + +`mkdir notesnook-sync-server` + +2. Enter this directory. + +`cd notesnook-sync-server` + +3. Download the `docker-compose.yml` file. + +`wget https://raw.githubusercontent.com/streetwriters/notesnook-sync-server/master/docker-compose.yml` + +4. Download the `.env` file, this is where most (if not all) of your configuration belongs. + +`wget https://raw.githubusercontent.com/streetwriters/notesnook-sync-server/master/.env` + +You should now have two files in your directory: + +- `docker-compose.yml` +- `.env` + +### Configuration + +Open the `.env` file into an editor. This guide will go over the minimum you need to change. + +:::warning This guide does not cover setting up an SMTP server! +You **will have to** do this if you plan on using the password reset feature, or want to use email-based two factor auth (the default). If you don't change the two factor method after creating your account, you may become locked out of the account. You have been warned. + +::: + +#### `INSTANCE_NAME` + +This is used by the Notesnook clients to show which server you are connecting to on the login/signup pages. It should be unique to your server, something like `john-doe-notesnook-server` is adequate. The default value _also_ works, but we recommend you change it. + +#### `NOTESNOOK_API_SECRET` + +This is used by the server to validate access tokens. It should be a long, random value. If you need to create one, use this command. `openssl rand -hex 32` + +#### `DISABLE_SIGNUPS` + +This is a setting you should change after signing up, unless you want your server to be open registration. + +#### Public URLs + +Public URLs are how the servers can generate valid publicly accessible URLs for different things like email confirmation, password reset links etc. These URLs must be accessible from _outside_ of where you are hosting your servers (e.g. by using a reverse proxy like Nginx). + +| Variable | Description | Example | +| ------------------------------- | --------------------------------------------------------------------------------------------------- | -------------------------------------------------- | +| `NOTESNOOK_APP_PUBLIC_URL` | If you're self-hosting the web app too, you put the url to it here, otherwise, leave it alone. | [https://app.notesnook.com/](#public-urls) | +| `MONOGRAPH_PUBLIC_URL` | This is the url for the monograph server, it is also where published notes will be accessible from. | [https://monogr.ph/](#public-urls) | +| `AUTH_SERVER_PUBLIC_URL` | This is the url for the auth server. | [https://auth.streetwriters.co/](#public-urls) | +| `ATTACHMENTS_SERVER_PUBLIC_URL` | This is the url for the attachments server. It's where your attachments will be downloaded from. | [https://attachments.notesnook.com/](#public-urls) | + +You don't need to configure the sse/events server's public url in the `.env` file, but it is required to forward it through your reverse proxy. + +#### Starting the server + +Now that you've configured the server, let's take it for a test-drive! + +Run `docker compose up -d`, and Docker Compose will make the magic happen. + +Once everything is shown as started, wait a moment, and then run `docker compose ps` + +You should see something like this: + +``` +3c39da9194db streetwriters/sse:latest "./Streetwriters.Mes…" 38 minutes ago Up 38 minutes (healthy) 0.0.0.0:7264->7264/tcp, :::7264->7264/tcp notesnook-sse-server-1 +19c4a6536578 streetwriters/monograph:latest "docker-entrypoint.s…" 38 minutes ago Up 38 minutes (healthy) 0.0.0.0:6264->3000/tcp, [::]:6264->3000/tcp notesnook-monograph-server-1 +7b9db61b5d0d streetwriters/notesnook-sync:latest "./Notesnook.API" 38 minutes ago Up 38 minutes (healthy) 0.0.0.0:5264->5264/tcp, :::5264->5264/tcp notesnook-notesnook-server-1 +6491b172817e streetwriters/identity:latest "./Streetwriters.Ide…" 38 minutes ago Up 38 minutes (healthy) 0.0.0.0:8264->8264/tcp, :::8264->8264/tcp notesnook-identity-server-1 +bfb71f21e57b minio/minio:RELEASE.2024-07-29T22-14-52Z "/usr/bin/docker-ent…" 38 minutes ago Up 38 minutes (healthy) 0.0.0.0:9000->9000/tcp, :::9000->9000/tcp notesnook-notesnook-s3-1 +d27f6207fb93 mongo:7.0.12 "docker-entrypoint.s…" 38 minutes ago Up 38 minutes (healthy) 27017/tcp notesnook-notesnook-db-1 +2bde52e0102d willfarrell/autoheal:latest "/docker-entrypoint …" 38 minutes ago Up 38 minutes (healthy) notesnook-autoheal-1 +``` + +Everything should show as healthy, and there should be 7 containers listed at this point. If there are less than 7, or any show as unhealthy, something went wrong. Our [Discord community](https://go.notesnook.com/discord) may be able to assist you. + +#### Exposing to the internet + +Running the Docker containers on device is all well and good, but if you want to connect your other devices, sync your notes to them, you'll need to expose the servers over the internet. Even if you only require local access, it is recommended that you use something like Tailscale or Cloudflare Tunnels to securely & reliably expose the Notesnook servers. + +:::warning HTTPS is required. +**HTTPS is required by the browser and mobile apps**. Notesnook does not necessarily mandate this, but your browser and mobile operating system may. + +::: + +This guide will cover hosting Notesnook using a Cloudflare Tunnel, as we believe it is the easiest option, doesn't require port forwarding, and HTTPS is automatically set up. + +1. Log into the Cloudflare dashboard. We're assuming you already have your domain name set up and added to your Cloudflare account. If you don't, do that now. +2. In the dashboard, on the sidebar, find `Protect & connect`, open the drop down for `Networking`, and choose `Tunnels`. +3. On the top right of the page that loads, select `Create Tunnel`. +4. Name your tunnel, then select `Create tunnel` again. +5. Select `Docker` from the list of options and copy the command. We'll use values from it later. +6. Open up the `docker-compose.yml` file, and at the bottom of the `services:` section, add this: + +``` + cloudflare: + image: cloudflare/cloudflared:latest + networks: + - notesnook + depends_on: + - monograph-server + command: +``` + +7. Now, paste in the command you copied from the cloudflare dash, it should look like this: `docker run cloudflare/cloudflared:latest tunnel --no-autoupdate run --token eyJh...J9` + +8. Remove `docker run cloudflare/cloudflared:latest` from the beginning of the command, and save your changes to the file. + +9. Restart your Docker containers by running `docker compose down` and `docker compose up -d`. In a moment, everything should start back up, and the continue button on the cloudflare dash will light up, allowing you to proceed. + +10. Now you add your domains that you configured earlier to the newly created tunnel. To do this, click your new tunnel in the dashboard, then select `Routes` at the top. + +11. Click `Add route`, then select `Published application`. You'll configure your subdomain, and for the `Service URL` field you should see the table below. Repeat this for each service listed. + +:::tip What to do if you changed the port configuration +If you changed ports for a service, **use the configured port** instead of the default ones shown below. If you haven't already, you may additionally need to double check that your `docker-compose.yml` file doesn't use the defaults. + +::: + +| Service | Service URL | +| ------------------ | --------------------------------------------------------- | +| Sync server | [http://notesnook-server:5264](#exposing-to-the-internet) | +| Monograph server | [http://monograph-server:3000](#exposing-to-the-internet) | +| Events/SSE server | [http://sse-server:7264](#exposing-to-the-internet) | +| Attachments server | [http://notesnook-s3:9000](#exposing-to-the-internet) | +| Auth server | [http://identity-server:8264](#exposing-to-the-internet) | + +:::info +The attachments server doesn't get entered into the client, the public url is used by the sync server to generate signed S3 links. Those are scoped to a specific hostname. + +::: + +You should now [configure your client](#point-notesnook-at-your-own-servers) to ensure that everything is publicly accessible, everything should be now. The `{{testConnection}}` button is the easiest way to do this, as it will tell you which server is not reachable, should anything be wrong. + +## What servers do I need to configure in my client? + +Four, and all of them are required. + +| Server | What it does | +| --------------------- | ---------------------------------------------------------------- | +| `{{syncServer}}` | _"Server used to sync your notes & other data between devices."_ | +| `{{authServer}}` | _"Server used for login/sign up and authentication."_ | +| `{{sseServer}}` | _"Server used to receive important notifications & events."_ | +| `{{monographServer}}` | _"Server used to host your published notes."_ | + +By default these are `https://api.notesnook.com`, `https://auth.streetwriters.co`, `https://events.streetwriters.co` and `https://monogr.ph`. + +The apps validate all four together — you cannot self-host the sync server and leave the others pointing at Notesnook. `{{allServerUrlsRequired}}` + +## You must be logged out to change server URLs + +Every field and button on the servers screen is disabled while you are signed in, and the app tells you so: `{{logoutToChangeServerUrls}}` + +This is not an arbitrary restriction. Your account, your keys and your data live on whichever backend you were using; switching backends while logged in would leave the app holding a session the new server knows nothing about. + +::: warning Make a backup, then log out. +Take a [backup](/backup-and-restore-notes-in-notesnook) before logging out of notesnook to change your server configuration. An account on Notesnook's servers does not exist on your own. You'll have to sign up again on your instance, and you bring your notes over by restoring your backup. **Notesnook cannot move an account between backends for you.** + +::: + +## Point Notesnook at your own servers + +:::tabs key:platform +== Desktop/Web + +1. Log out. +2. Open `{{settings}}` → `{{customization}}` → `{{servers}}`. +3. Fill in all four URLs — `{{syncServer}}`, `{{authServer}}`, `{{sseServer}}` and `{{monographServer}}`. Each field shows an example such as `e.g. http://localhost:4326`. +4. Press `{{testConnection}}`. On success you see `{{connectedToServer}}` +5. Press `{{save}}`. + +`{{save}}` stays disabled until `{{testConnection}}` has passed. After saving, a dialog reads `App will reload in 5 seconds` — _"Your changes have been saved and will be reflected after the app has refreshed."_ — and the app reloads itself. + +== Mobile + +1. Log out. +2. Open `{{settings}}` → `{{customization}}` → `{{servers}}`. +3. Fill in all four URLs. Each field is labelled with the server id and an example, such as `notesnook-sync e.g. http://localhost:4326`. +4. Tap `{{testConnection}}`. On success you see `{{connectedToServer}}` +5. Tap `{{save}}`. + +Tapping `{{save}}` before testing shows `{{testConnectionBeforeSave}}`. After saving you get a `{{serverUrlChanged}}` dialog reading `{{restartAppToTakeEffect}}` — close the app fully and reopen it. + +::: + +<!-- TODO: screenshot — the Servers configuration screen with the four URL fields and the Test connection button --> + +## What does "Test connection" actually check? + +For each of the four servers in turn, the app requests that server's version endpoint — `/version`, or `/api/version` for the monograph server — and checks three things: + +1. **Is it reachable?** If the request fails or returns something that isn't JSON: `Could not connect to <server>.` +2. **Is it the right server?** The response identifies which server it is. If the sync URL answers with the auth server's identity, you get `The URL you have given (<url>) does not point to the <server>.` This catches the classic copy-paste mistake of putting the same host in every field. +3. **Does it speak this app's protocol version?** If the server's API version doesn't match what this build of the app expects: `The <server> at <url> is not compatible with this client.` Update the server, or use an app build from the matching release. + +Only when all four pass does the app report `{{connectedToServer}}` and let you save. + +## Go back to Notesnook's servers + +:::tabs key:platform +== Desktop/Web + +1. Log out. +2. Open `{{settings}}` → `{{customization}}` → `{{servers}}`. +3. Press `{{reset}}`. + +The app reloads after 5 seconds. + +== Mobile + +1. Log out. +2. Open `{{settings}}` → `{{customization}}` → `{{servers}}`. +3. Tap `{{resetServerUrls}}`. + +You get a `{{serverUrlsReset}}` dialog reading `{{restartAppToTakeEffect}}` — close and reopen the app. + +::: + +Your notes on your hosted server are untouched by the app reset, but the account you used on your own instance does not exist on Notesnook's servers. You'll have to log in (or sign up) again, and restore a backup to transfer your data back over. + +## Can I self-host the Inbox API too? + +Yes, and separately from the entire list of servers above. The inbox service, the one that accepts notes posted in from scripts and automations, can be hosted separately from the sync server. This means that you can host your own inbox server, even while using the official Notesnook server. See [self-hosting the Inbox API](/inbox-api/self-hosting-inbox-api) for more information. + +## Related pages + +- [How sync works](/sync/how-sync-works) — what the sync server actually receives from your device +- [Sync troubleshooting](/sync/troubleshooting-sync) — connection errors, including ones naming a specific server +- [Sync settings](/sync/sync-settings) — offline mode and sync controls, which work the same self-hosted +- [Self-hosting the Inbox API](/inbox-api/self-hosting-inbox-api) — running your own inbox endpoint +- [How is my data encrypted?](/how-is-my-data-encrypted) — why the server never sees your notes, hosted or not +- [Backup and restore](/backup-and-restore-notes-in-notesnook) — how you carry notes between backends diff --git a/docs/help/contents/sync/how-sync-works.md b/docs/help/contents/sync/how-sync-works.md new file mode 100644 index 000000000..ace9c0394 --- /dev/null +++ b/docs/help/contents/sync/how-sync-works.md @@ -0,0 +1,165 @@ +--- +title: How sync works +pageTitle: How does sync work in Notesnook? +description: How Notesnook syncs your notes across devices — when it runs, what the status indicator means, and how conflicting edits are resolved. +keywords: + - notesnook sync + - how does notesnook sync work + - notesnook encrypted sync + - notesnook sync between devices +schema: faq +faqs: + - q: Is sync free in Notesnook? + a: Yes. Sync is included on the free plan and works on an unlimited number of devices. There is no device cap on any plan. + - q: Can the Notesnook server read my notes while syncing? + a: No. Every note, notebook, tag and attachment is encrypted on your device with a key derived from your password before it is sent. The server only ever stores encrypted blobs. + - q: When does Notesnook sync? + a: Automatically a moment after you change something, in realtime while you type in an open note, when the app starts or comes back to the foreground, when the internet reconnects, and whenever you trigger a sync yourself. + - q: Why did I get a merge conflict instead of my edits merging? + a: If the same note is edited on two devices more than 60 seconds apart, Notesnook marks it as conflicted and asks you to choose. Edits closer together than that are merged silently, keeping the most recent version. +--- + +# How does sync work in Notesnook? + +Sync is free in Notesnook, on an unlimited number of devices, on every plan. Your notes are encrypted on your device _before_ they are sent, so the sync server stores nothing it can read — it only moves encrypted blobs between the devices you are logged in on. + +## Is sync free? + +Yes. Sync is on the free plan, and every plan — Free, Essential, Pro and Believer — allows **unlimited devices**. Nothing about syncing itself is behind a paywall. Only the [sync settings](/sync/sync-settings) that turn parts of syncing _off_, and full offline mode, need a paid plan. + +## What gets encrypted, and when + +Everything is encrypted on your device, with a key derived from your password, before it leaves it. That includes note content, titles, notebooks, tags, colors, reminders and attachments. The server receives ciphertext and hands the same ciphertext to your other devices, which decrypt it locally. + +This is why nobody at Notesnook can read your notes, and why nobody can recover them for you if you lose your password and your recovery key. See [how your data is encrypted](/how-is-my-data-encrypted) for the full picture. + +## When does Notesnook sync? + +Sync is not on a fixed timer. It runs when something actually happens: + +- **After a change.** Editing a note, creating a notebook, adding a tag or setting a reminder schedules a sync a moment later. Several quick changes are collapsed into one sync instead of one sync per keystroke. +- **In realtime.** While a note is open, changes arriving from your other devices are applied to the editor as they come in, so you can watch a note update on your laptop while you type on your phone. +- **On app start, and when the app comes back.** The app syncs when it starts, when you switch back to it, and when it detects that the internet came back after being offline. +- **Manually,** whenever you want to force the issue. + +::: info +Automatic and realtime sync can both be switched off individually on a paid plan — see [sync settings](/sync/sync-settings). + +::: + +### Sync now + +:::tabs key:platform +== Desktop/Web + +1. Look at the status bar along the bottom of the window. +2. Click the sync icon next to your account indicator. + +The icon starts spinning and its tooltip changes to `{{syncing}}` — or `{{downloading}}` / `{{uploading}}` — until it finishes. + +== Mobile + +1. Tap your profile picture — or the cog icon, if you have not set one — at the top of the side menu. +2. Tap `{{syncNow}}`. + +You can also pull down on any list of notes to start a sync. + +::: + +## What the sync status indicator means + +:::tabs key:platform +== Desktop/Web +Only the icon is drawn in the status bar at the bottom of the window — hover it and the tooltip tells you the state. There are seven: + +| Tooltip | What it means | +| --------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- | +| `Synced <time> ago` | Everything is up to date. | +| `{{syncing}}`, `{{downloading}}` or `{{uploading}}` | A sync is running right now. The number in brackets is how many items have been transferred. | +| `Merge conflicts` | Sync stopped because two versions of a note need your decision. The icon becomes a red alert triangle. | +| `Sync disabled`, with a red alert icon | Your email address is not confirmed yet. The status bar also shows `{{emailNotConfirmed}}` next to your account dot. | +| `{{syncFailed}}` | The last sync did not finish. | +| `Synced <time> ago (offline)` | You have no internet connection. | +| `Sync disabled`, with a greyed-out icon | You turned sync off in settings. | + +Clicking the icon starts a sync, unless sync is disabled. + +== Mobile + +Mobile does not have a status bar icon. Tap your profile picture — or the cog icon, if you have not set one — at the top of the side menu. Under your email you will see one of: + +- `{{syncing}}` — a sync is running, with the number of items transferred so far, and a spinner beside it +- `{{synced}}` followed by how long ago it finished +- `{{syncFailed}}` followed by how long ago it was last successful +- `{{never}}` — this device has not completed a sync yet +- `(Offline)` appended to any of the above when you have no connection + +A colored dot sits at the end of the line: green when the last sync passed, orange when you are offline, red when it failed or you are not logged in. + +::: + +<!-- TODO: screenshot — the sync status icon in the desktop status bar, showing "Synced 2m ago" --> + +## Sync while the app is closed + +On mobile there is an extra setting called `{{backgroundSync}}`: _"Sync your notes in the background even when the app is closed. This is an experimental feature. If you face any issues, please turn it off."_ + +With it on, the operating system wakes Notesnook up periodically — at most every 15 minutes, and only when the OS decides it is a good moment — to run a full sync, refresh your reminders and update note widgets. It also restarts after your phone reboots. + +Because the OS controls the schedule, background sync is best-effort: it is not a guarantee that your notes are current the second you open another device. Desktop and web have no equivalent — they sync for as long as the app is running, which on desktop includes when the window is closed to the system tray. + +::: info +`{{backgroundSync}}` lives under `{{settings}}` → `{{account}}` → `{{syncSettings}}`, on mobile only. It is available on every plan. The three `Disable …` switches next to it are not — see [sync settings](/sync/sync-settings). + +::: + +## Keep a single note off sync + +Any individual note can be excluded from sync entirely. This is useful for a scratchpad or something you want to exist on one device only. + +:::tabs key:platform +== Desktop/Web + +1. Right click the note in the notes list, or open its properties. +2. Choose `{{syncOff}}`. +3. Confirm — the dialog warns that the note _"will be automatically deleted from all other devices & any future changes won't get synced."_ + +The note now shows a crossed-out sync icon in the list. Choose `{{syncOff}}` again to turn syncing back on. + +== Mobile + +1. Tap the three dot menu on the note. +2. Tap `{{syncOff}}`. + +The note shows a crossed-out sync icon in the list. Tap `{{syncOff}}` again to re-enable syncing for it. + +::: + +::: warning This removes the note from your other devices +Turning `{{syncOff}}` on a note deletes it from every other device. Only the copy on the device where you switched it off remains, and it will not be in any backup taken on another device. + +::: + +## What happens when two devices edit the same note + +Notesnook never merges the text of two versions together and never silently throws one away. + +When a note comes in from another device, Notesnook compares when each side was last edited: + +- If the two edits are **less than 60 seconds apart**, or the content is identical, the more recent version wins and no conflict is raised. This is why typing on two devices at the same time, with sync working on both, does not create conflicts. +- If they are **more than 60 seconds apart**, the note is marked **conflicted**. It moves to the top of your notes list under a `Conflicted` group, and sync will keep flagging it until you pick a version. + +Resolving a conflict is a two-click job — keep one version, discard the other, or save both. See [what are merge conflicts?](/faqs/what-are-merge-conflicts) for the full walkthrough of the resolution screen. + +## Do I need an internet connection to use Notesnook? + +No. Notesnook is a local-first app: everything you write is saved to your device first and works with no connection at all. Sync catches up the moment you are online again. If you also want every attachment available offline, turn on [full offline mode](/sync/sync-settings). + +## Related pages + +- [Sync settings](/sync/sync-settings) — full offline mode, turning off automatic, realtime or all syncing, and force push/pull +- [Sync troubleshooting](/sync/troubleshooting-sync) — fixes for notes that won't appear on another device +- [What are merge conflicts?](/faqs/what-are-merge-conflicts) — resolving two versions of the same note +- [How is my data encrypted?](/how-is-my-data-encrypted) — what happens to a note before it is uploaded +- [Plans & limits](/plans-and-limits) — which sync-related features need a paid plan +- [Backup and restore](/backup-and-restore-notes-in-notesnook) — keeping your own copy alongside sync diff --git a/docs/help/contents/sync/sync-settings.md b/docs/help/contents/sync/sync-settings.md new file mode 100644 index 000000000..d442e9137 --- /dev/null +++ b/docs/help/contents/sync/sync-settings.md @@ -0,0 +1,153 @@ +--- +title: Sync settings +pageTitle: Notesnook sync settings — offline mode and sync controls +description: Turn on full offline mode, disable automatic, realtime or all syncing, and use force push and force pull to repair a device that is out of step. +keywords: + - notesnook full offline mode + - notesnook disable sync + - notesnook force push changes + - notesnook force pull changes + - notesnook offline attachments +--- + +# Notesnook sync settings + +Sync works out of the box with nothing to configure. These settings exist for the cases where you want more of your data kept on the device, less automatic network activity, or a way to repair a device that has fallen out of step with the server. + +## Where sync settings live + +:::tabs key:platform +== Desktop/Web + +1. Open `{{settings}}`. +2. Under `{{account}}`, select `{{sync}}`. + +Everything on this page is in the `{{sync}}` group. + +== Mobile + +1. Open `{{settings}}`. +2. Under `{{account}}`, tap `{{syncSettings}}` — _"Manage your sync settings here"_. + +::: + +<!-- TODO: screenshot — the Sync section of desktop settings showing all four toggles --> + +## Turn on full offline mode <PlanTag plan="essential" /> + +`{{fullOfflineMode}}` — _"Download everything including attachments on sync"_ — makes every sync also download your attachments, not only your notes. Without it, an image or file is fetched from the server the first time you open it, which needs a connection. + +Turn it on if you want your notes **and** every image, file and audio recording readable with no internet at all — on a flight, or on a laptop you deliberately keep offline. + +:::tabs key:platform +== Desktop/Web + +1. Open `{{settings}}` → `{{account}}` → `{{sync}}`. +2. Switch on `{{fullOfflineMode}}`. + +Notesnook immediately starts downloading everything you have not cached yet. Switching it back off cancels any download still in progress. + +== Mobile + +1. Open `{{settings}}` → `{{account}}` → `{{syncSettings}}`. +2. Switch on `{{fullOfflineMode}}`. + +A progress indicator appears at the top of the screen while attachments download. Switching it back off cancels the remaining downloads. + +::: + +::: info Full offline mode uses disk space +Your attachments are downloaded in full, so the app's storage footprint grows to roughly the size of everything you have uploaded. Attachments already downloaded stay downloaded when you turn the setting off. + +::: + +Full offline mode needs Essential or above — see [plans & limits](/plans-and-limits). + +## Turn off automatic, realtime or all syncing <PlanTag plan="pro" /> + +Three separate switches, from least to most drastic. All three need Pro or above. + +| Setting | What it does | +| ------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `{{disableAutoSync}}` | _"Turn off automatic syncing. Changes from this client will be synced only when you run sync manually."_ | +| `{{disableRealtimeSync}}` | _"Changes from other devices won't be updated in the editor in real-time."_ | +| `{{disableSync}}` | _"Turns off syncing completely on this device. Any changes made will remain local only and new changes from your other devices won't sync to this device."_ | + +Each is worded as a _disable_ switch: turning the switch **on** turns that piece of syncing **off**. + +- Use `{{disableAutoSync}}` on a metered or unreliable connection. You keep manual sync, so nothing is stranded permanently — you decide when it goes out. +- Use `{{disableRealtimeSync}}` if you find notes changing under your cursor distracting while someone else's device (or your own) is editing the same note. +- Use `{{disableSync}}` to make a device local-only for a while. When you switch it back on, everything queued up on that device syncs then. + +:::tabs key:platform +== Desktop/Web + +1. Open `{{settings}}` → `{{account}}` → `{{sync}}`. +2. Switch on `{{disableSync}}`, `{{disableAutoSync}}` or `{{disableRealtimeSync}}`. + +With `{{disableSync}}` on, the sync icon in the status bar greys out and its tooltip reads `Sync disabled`. Clicking it no longer starts a sync. + +== Mobile + +1. Open `{{settings}}` → `{{account}}` → `{{syncSettings}}`. +2. Switch on `{{disableAutoSync}}`, `{{disableRealtimeSync}}` or `{{disableSync}}`. + +::: + +::: warning Nothing leaves the device while sync is off +A device with `{{disableSync}}` on does not send changes anywhere, and does not receive them. If that device is lost or reset before you turn sync back on, the changes made on it are gone. Take a [backup](/backup-and-restore-notes-in-notesnook) if you plan to leave sync off for any length of time. + +::: + +## Sync in the background + +Mobile has one extra switch on the same screen, `{{backgroundSync}}` — _"Sync your notes in the background even when the app is closed. This is an experimental feature. If you face any issues, please turn it off."_ + +It is available on every plan, and it is **mobile only** — there is no equivalent on desktop or web, which sync while the app or tab is open. See [how sync works](/sync/how-sync-works) for what background sync can and cannot promise. + +## Force push or force pull your data + +These two buttons exist for one purpose: repairing a device whose data has drifted out of step with the server. They are available on every plan, and both overwrite data. + +| Button | What it does | +| ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `{{forcePushChanges}}` | _"Use this if changes made on this device are not appearing on other devices. This will overwrite the data on the server with the data from this device."_ | +| `{{forcePullChanges}}` | _"Use this if changes from other devices are not appearing on this device. This will overwrite the data on this device with the latest data from the server."_ | + +::: danger These are not a stronger "sync now" +From the app's own warning: _"This must only be used for troubleshooting. Using this regularly for sync is not recommended and will lead to unexpected data loss and other issues."_ + +A force push replaces what is on the server with this device's copy — anything on the server that this device never received can be lost. A force pull replaces this device's copy with the server's — anything on this device that was never uploaded can be lost. **Notesnook cannot recover data destroyed this way.** Take a [backup](/backup-and-restore-notes-in-notesnook) before you press either one. + +::: + +:::tabs key:platform +== Desktop/Web + +1. Open `{{settings}}` → `{{account}}` → `{{sync}}`. +2. Scroll to `{{havingProblemsWithSync}}`. +3. Press `{{forcePushChanges}}` or `{{forcePullChanges}}`. +4. Read the warning, tick `{{understand}}`, then press `{{continue}}`. + +The sync icon in the status bar shows the run in progress. Both buttons are styled in red — that is deliberate. + +== Mobile + +1. Open `{{settings}}` → `{{account}}` → `{{syncSettings}}`. +2. Tap `{{forcePullChanges}}` or `{{forcePushChanges}}`. +3. Read the warning in the dialog, then tap `{{start}}`. + +A progress sheet shows the run and closes when it finishes. + +::: + +If you are here because something is not syncing, try the ordinary fixes in [sync troubleshooting](/sync/troubleshooting-sync) first — a force push or pull is rarely the right first move. + +## Related pages + +- [How sync works](/sync/how-sync-works) — when Notesnook syncs and what the status indicator means +- [Sync troubleshooting](/sync/troubleshooting-sync) — what to try before forcing a push or pull +- [Plans & limits](/plans-and-limits) — full offline mode needs Essential, sync controls need Pro +- [Backup and restore](/backup-and-restore-notes-in-notesnook) — take one before any forced sync +- [What are merge conflicts?](/faqs/what-are-merge-conflicts) — resolving two versions of the same note +- [Self-hosting](/self-hosting) — pointing sync at your own server instead diff --git a/docs/help/contents/sync/troubleshooting-sync.md b/docs/help/contents/sync/troubleshooting-sync.md new file mode 100644 index 000000000..a455c205e --- /dev/null +++ b/docs/help/contents/sync/troubleshooting-sync.md @@ -0,0 +1,158 @@ +--- +title: Sync troubleshooting +pageTitle: Why is my note not syncing in Notesnook? +description: Notes not showing up on another device? Fix sync in Notesnook — login and email states, conflicts, rate limits, and when to force push or pull. +keywords: + - notesnook not syncing + - notesnook sync failed + - notesnook sync disabled + - notesnook note not appearing on other device + - notesnook attachment not downloading +schema: faq +faqs: + - q: Why is my note not syncing? + a: Most often the other device has not synced yet, sync is turned off on one of the two devices, the note itself has "Sync off" enabled, or your email address is not confirmed. Run a manual sync on both devices, then check those three settings in order. + - q: Why does Notesnook say sync is disabled? + a: Either you turned on "Disable sync" in sync settings, or your email address is not confirmed. Both show the tooltip "Sync disabled"; a greyed-out icon means the setting, a red alert icon means the email. + - q: What does "You are being rate limited" mean? + a: You have made too many requests to the server in a short period. Stop syncing manually, wait a few minutes, and let the app sync on its own. + - q: Should I use force push or force pull? + a: Force push when changes made on this device are missing everywhere else. Force pull when changes from your other devices are missing here. Both overwrite data, so take a backup first. +--- + +# Why is my note not syncing? + +Work through this page in order. Nearly every sync problem is one of four things: the other device has not synced, sync is switched off somewhere, your email is not confirmed, or a note is stuck as conflicted. Forcing a push or pull is the last resort, not the first. + +## Why is my note not syncing to my other device? + +Check these in order — the first three cover most cases. + +1. **Sync the other device too.** A note is only on your phone once your phone has fetched it. Open the other device and run a sync manually — click the sync icon in the desktop status bar, or tap your profile → `{{syncNow}}` on mobile. +2. **Confirm both devices are on the same account.** Open `{{settings}}` and check the email address shown on each device. +3. **Check the note is not set to `{{syncOff}}`.** A note with a crossed-out sync icon in the list has been deliberately excluded from sync, and turning that on **deletes it from your other devices**. Open the note's menu and toggle `{{syncOff}}` back off to bring it back into sync. +4. **Check sync is not disabled on either device.** See the next section. +5. **Check the note is not conflicted.** A conflicted note sits at the top of the notes list under the `Conflicted` group and blocks sync until you resolve it. + +If all five check out and the note is still missing on the other device only, a [force push](/sync/sync-settings) from the device that _has_ the note is the tool for it — read the warning there first. + +## Why does Notesnook say "Sync disabled"? + +There are two different causes, and the icon tells you which: + +:::tabs key:platform +== Desktop/Web +Both show the same tooltip, `Sync disabled` — the icon is what distinguishes them: + +- **Greyed-out sync-off icon** — you turned on `{{disableSync}}` in `{{settings}}` → `{{account}}` → `{{sync}}`. Turn that switch back off. +- **Red alert icon** — your email address is not confirmed. The status bar also shows `{{emailNotConfirmed}}` next to your account dot; click it to confirm your email. + +== Mobile + +- Open `{{settings}}` → `{{account}}` → `{{syncSettings}}` and check whether `{{disableSync}}` is switched on. If it is, switch it off. +- If your email is not confirmed, Notesnook shows `{{syncDisabled}}` with the message `{{syncDisabledActionText}}`. Tap it to resend the confirmation email. + +::: + +::: info If you already confirmed your email +Occasionally the server still thinks an already-confirmed address is unconfirmed. Notesnook detects this during sync and refreshes your login token automatically, so the next sync attempt fixes it. If it doesn't, log out and back in. + +::: + +## Why does it say "not logged in"? + +Sync only runs while you are logged in. On mobile, tapping the profile button at the top of the side menu opens a sheet that reads `{{notLoggedIn}}` when you are not; on desktop and web the account dot and sync icon disappear from the status bar. + +If you _were_ logged in and got signed out, your session expired. Log in again — your notes are still on the device, and nothing needs re-downloading. If you see `Unauthorized.` or `User encryption keys not generated. Please relogin.`, that is the same thing: log out and log back in. + +::: warning Do not delete the app to fix a login problem +Notes that were never uploaded live only on that device. Reinstalling deletes them. Log out and back in from inside the app instead, and take a [backup](/backup-and-restore-notes-in-notesnook) first. + +::: + +## What does "You are being rate limited" mean? + +The server refused the request because too many arrived from your account in a short window. It is temporary and nothing is lost. + +Stop pressing sync, wait a few minutes, and let the app sync on its own. If you have been repeatedly running `{{forcePullChanges}}` or `{{forcePushChanges}}`, that is the usual cause — those transfer your whole dataset every time and are not meant to be used routinely. + +## Why does sync say "Sync failed"? + +`{{syncFailed}}` means the last run did not complete. The error message in the toast tells you which stage failed: + +| Message | What it means | What to do | +| ------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------- | +| _(no message — only the status flips to `{{syncFailed}}`)_ | The app could not open a connection to the sync server within 30 seconds. Connection failures are written to the log as `Could not connect to the Sync server. Please try again.` but are deliberately not shown as a toast. | Check your connection, then sync again. Behind a strict firewall or VPN, try another network. | +| `Notesnook Sync Server is not responding. Please check your internet connection.` (the full message goes on to give a support address and a reference error) | The server did not answer at all. Other names you may see are `Authentication Server`, `Eventing Server` and `Monograph Server`. If you have pointed the app at your own servers you get the raw network error instead of this friendly one. | Check your connection. If you are [self-hosting](/self-hosting), check that server is up. | +| `You are being rate limited.` | Too many requests. | Wait a few minutes. | +| `Unauthorized.` | Your session is no longer valid. | Log out and log back in. | +| `Failed to send all items. Sent X out of Y.` | The upload stopped partway. | Sync again — the remaining items are still queued and go out on the next run. | + +A failed sync never loses local data. Everything you wrote is on the device and goes out on the next successful run. + +## Why is a note stuck as "conflicted"? + +A conflicted note stays conflicted until _you_ pick a version — Notesnook will not choose for you, and it will not merge two versions of your text together. Until it is resolved, the desktop status bar keeps showing a red alert icon whose tooltip reads `Merge conflicts` + +1. Go to `Notes`. +2. Open the note under the `Conflicted` group at the top of the list. +3. Keep one version, discard the other, or press `{{saveACopy}}` to keep both. +4. Run a sync. + +If a note re-conflicts every time you sync, the two devices are each holding an edit the other has not seen. Resolve it on one device, let that device sync fully to completion, _then_ sync the other one. + +Full instructions, including what the highlighted diff means, are in [what are merge conflicts?](/faqs/what-are-merge-conflicts). + +## Why won't my attachments download? + +Attachments sync separately from note text. A note can arrive on a device while its images are still on the server. + +- **Images load when you open the note.** By default an attachment is fetched the first time you view it, so it needs a connection at that moment. To have them all downloaded ahead of time, turn on [full offline mode](/sync/sync-settings). +- **Run a file check.** Open the attachments manager and use `{{fileCheck}}` on the affected files — it verifies the file actually exists on the server and is intact. + +:::tabs key:platform +== Desktop/Web + +1. Open `{{settings}}` → `{{profile}}`. +2. Next to `{{attachments}}` — _"Manage attachments"_ — press `{{open}}`. +3. Select the attachments and choose `{{fileCheck}}`. + +== Mobile + +1. Open `{{settings}}` → `{{account}}` → `{{manageAccount}}`. +2. Tap `{{manageAttachments}}`. +3. Select the attachments and tap `{{fileCheck}}`. + +::: + +- **Check the file was uploaded in the first place.** An attachment added while you were logged out or offline stays local until the device that holds it syncs successfully. Sync that device before looking for the file elsewhere. +- **Check your storage.** If your account is over its monthly storage allowance, new uploads are refused — existing attachments stay downloadable. See [plans & limits](/plans-and-limits). + +## When should I use force pull instead of force push? + +Match the direction to the symptom, and take a [backup](/backup-and-restore-notes-in-notesnook) first. + +| Symptom | Use | Effect | +| ------------------------------------------------------------------ | ---------------------- | ----------------------------------------------------------------------- | +| Changes made **on this device** are not appearing on other devices | `{{forcePushChanges}}` | Overwrites the data on the server with the data from this device | +| Changes **from other devices** are not appearing on this device | `{{forcePullChanges}}` | Overwrites the data on this device with the latest data from the server | + +::: danger Both of these overwrite data +The app's own warning: _"This must only be used for troubleshooting. Using this regularly for sync is not recommended and will lead to unexpected data loss and other issues."_ Anything that exists only on the side being overwritten is lost, and **Notesnook cannot recover it for you.** Never run both in sequence, and never use them as a routine "sync harder" button. + +::: + +Both buttons and the exact steps are documented in [sync settings](/sync/sync-settings). + +## Nothing here fixed it + +Send the details to support@streetwriters.co — which devices, what the status indicator says on each, and the exact error text. + +## Related pages + +- [How sync works](/sync/how-sync-works) — when sync runs and what each status state means +- [Sync settings](/sync/sync-settings) — disable switches, full offline mode, force push and force pull +- [What are merge conflicts?](/faqs/what-are-merge-conflicts) — resolving a conflicted note step by step +- [Backup and restore](/backup-and-restore-notes-in-notesnook) — take one before any forced sync +- [Plans & limits](/plans-and-limits) — storage allowances and which sync features need a paid plan +- [Self-hosting](/self-hosting) — sync errors when you run your own servers diff --git a/docs/help/contents/trash.md b/docs/help/contents/trash.md new file mode 100644 index 000000000..b509f5e33 --- /dev/null +++ b/docs/help/contents/trash.md @@ -0,0 +1,141 @@ +--- +title: Trash +pageTitle: How do I restore a deleted note in Notesnook? +description: Deleted notes and notebooks go to Trash. Restore them, delete them permanently, empty the trash, or change how long items are kept. +keywords: + - notesnook restore deleted note + - notesnook trash + - notesnook empty trash + - how long does notesnook keep deleted notes +schema: faq +faqs: + - q: How do I restore a deleted note in Notesnook? + a: Open Trash from the side menu, open the context menu on the note and choose Restore. It goes back where it was, with its content and notebook links intact. + - q: How long does Notesnook keep deleted notes? + a: Seven days by default. You can change the clear trash interval to Daily, 7 days, 30 days or 365 days, and Pro and Believer plans can set it to Never so nothing is ever cleared automatically. + - q: What goes to the trash in Notesnook? + a: Only notes and notebooks. Tags, colors, reminders and attachments are removed immediately when you delete them and do not pass through the trash. + - q: Does clearing the trash free up my storage? + a: No. Your storage limit counts attachments only, and attachments never go to the trash — so notes and notebooks sitting in the trash cost you nothing against it. +--- + +# How do I restore a deleted note in Notesnook? + +Deleting a note or a notebook moves it to `{{trash}}` instead of erasing it. Open `{{trash}}` from the side menu, open the item's menu and press `{{restore}}` to put it back. Items left in the trash are cleared automatically after **7 days** by default. + +## What goes to the trash + +Only two things: **notes** and **notebooks**. Deleting a notebook also moves its sub-notebooks with it. + +Tags, colors, reminders and attachments do not pass through the trash — deleting those removes them straight away. Notes that delete themselves on a date you set with [note expiry](/notes/note-expiry) land in the trash the same way manually deleted notes do. + +## Restore a note or notebook + +:::tabs key:platform +== Desktop/Web + +1. Open `{{trash}}` from the side menu. +2. Right click the item to open its menu. +3. Press `{{restore}}`. + +Restoring a notebook also restores every sub-notebook that went to the trash with it. + +== Mobile + +1. Open `{{trash}}` from the side menu. +2. Tap the ![Three dot button](/three-dot-button.png) button on the item. +3. Tap `{{restore}}`. + +Tapping a trashed **notebook** opens a `{{restore}}` prompt directly, with `{{restore}}` and `{{delete}}` as the two choices. + +::: + +Restored notes keep their content, their tags and their place in notebooks — nothing is re-created from scratch. + +### Restoring a notebook re-checks your notebook limit + +Free plans allow 50 notebooks and Essential allows 500; Pro and Believer are unlimited. On the desktop and web apps, restoring notebooks counts what you are about to restore against that limit, so a restore that would push you over is blocked until you free up notebooks or upgrade. See [Plans & limits](/plans-and-limits). + +## Delete a single item permanently + +:::tabs key:platform +== Desktop/Web + +1. Open `{{trash}}` from the side menu. +2. Right click the item and press `{{delete}}`, or select it and press the `{{delete}}` key. +3. Confirm the prompt. + +== Mobile + +1. Open `{{trash}}` from the side menu. +2. Tap the ![Three dot button](/three-dot-button.png) button on the item. +3. Tap `{{delete}}` and confirm. + +::: + +Permanently deleting a note also removes its content and its whole [version history](/note-version-history). + +## Clear the trash + +:::tabs key:platform +== Desktop/Web + +1. Open `{{trash}}` from the side menu. +2. Press the clear trash button on the list. +3. Read the prompt and press `{{clear}}`. + +You should see `{{trashCleared}}`. + +== Mobile + +1. Open `{{trash}}` from the side menu. +2. Tap the floating button at the bottom right. +3. Read the prompt and press `{{clear}}`. + +You should see `{{trashCleared}}`. + +::: + +::: danger This cannot be undone +`Clearing trash will permanently delete all the items in your trash. This action is IRREVERSIBLE.` Notesnook has no server-side copy to restore from — the only other copy is one you made yourself with a [backup](/backup-and-restore-notes-in-notesnook). + +::: + +## Change how long the trash keeps things + +The `{{clearTrashInterval}}` setting automatically clears trash after a certain period of time. The options are `{{daily}}`, `7 days`, `30 days`, `365 days` and `{{never}}`. **The default is `7 days`.** + +Cleanup measures from the start of the day an item was deleted, and runs against everything already in the trash, not only items deleted from now on. + +:::tabs key:platform +== Desktop/Web + +1. Go to `{{settings}}` → `{{behaviour}}`. +2. Under `{{trash}}`, open the `{{clearTrashInterval}}` dropdown. +3. Pick an interval. + +== Mobile + +1. Go to `{{settings}}` → `{{customization}}` → `{{behavior}}`. +2. Open `{{clearTrashInterval}}`. +3. Pick an interval. + +::: + +### Keep trash forever <PlanTag plan="pro" /> + +`{{never}}` turns automatic cleanup off entirely, so deleted notes stay in the trash until you remove them yourself. It is available on **Pro** and **Believer** — on free and Essential plans, choosing it shows an upgrade prompt. See [Plans & limits](/plans-and-limits). + +<!-- TODO: screenshot — the Clear trash interval dropdown in Settings → Behaviour --> + +## Does clearing the trash free up my storage? + +No. Storage limits count [attachments](/attachments-and-files) only, and attachments never go to the trash. Notes cost you nothing against your storage whether they are live or trashed, so emptying the trash does not change your storage figure. + +## Related pages + +- [Attachments and files](/attachments-and-files) — what actually counts against your storage +- [Note version history](/note-version-history) — recovering an earlier draft instead of a deleted note +- [Backup and restore](/backup-and-restore-notes-in-notesnook) — the only copy that survives a cleared trash +- [Notebooks](/organizing-notes/organize-notes-using-notebooks) — how deleting a notebook affects its notes +- [Plans & limits](/plans-and-limits) — notebook limits and the plans that unlock `{{never}}` diff --git a/docs/help/contents/two-factor-authentication.md b/docs/help/contents/two-factor-authentication.md new file mode 100644 index 000000000..a52a45c95 --- /dev/null +++ b/docs/help/contents/two-factor-authentication.md @@ -0,0 +1,170 @@ +--- +title: Two-factor authentication +pageTitle: How do I set up two-factor authentication in Notesnook? +description: Turn on 2FA for your Notesnook account with an authenticator app, email or SMS, add a fallback method, and save your recovery codes. +keywords: + - notesnook two factor authentication + - notesnook 2fa authenticator app + - notesnook 2fa recovery codes + - lost 2fa device notesnook +schema: howto +--- + +# How do I set up two-factor authentication in Notesnook? + +Two-factor authentication (2FA) asks for a 6-digit code in addition to your password every time you log in. You set it up from `{{settings}}`, choose one of three methods — an authenticator app, email or SMS — and save the recovery codes Notesnook shows you at the end. + +::: info 2FA protects your account, not your notes +Your notes are already end-to-end encrypted with a key derived from your password. 2FA stops someone from _logging in_ as you. It is a separate protection from [the encryption of your data.](/how-is-my-data-encrypted) + +::: + +## The three 2FA methods + +| Method | What it is | Plan | +| --------------------- | ------------------------------------------------------------------------- | ---------------- | +| `{{mfaAuthAppTitle}}` | Use an authenticator app to generate 2FA codes. Marked `{{recommended}}`. | All plans | +| `{{mfaEmailTitle}}` | Notesnook sends a 2FA code to your account email when prompted. | All plans | +| `{{mfaSmsTitle}}` | Notesnook sends an SMS with a 2FA code when prompted. | Pro and Believer | + +An authenticator app is the recommended option because it generates codes on your device and keeps working without a network connection. + +## Turn on two-factor authentication + +:::tabs key:platform +== Desktop/Web + +1. Go to `{{settings}}` → `{{authentication}}`. +2. Under `{{twoFactorAuth}}`, press `{{change}}` next to `{{change2faMethod}}`. +3. Confirm the `{{verifyItsYou}}` prompt with your account password. +4. Pick a method on the `{{select2faMethod}}` screen. +5. Follow the method's setup — scan the QR code, or press `{{sendCode}}` for email and SMS — and type the code into `{{enterSixDigitCode}}`. +6. Save the codes on the `{{saveRecoveryCodes}}` screen, then finish. + +You should now see `{{twoFactorAuthEnabled}}`. + +== Mobile + +1. Go to `{{settings}}` → `{{account}}` → `{{manageAccount}}`. +2. Open `{{twoFactorAuth}}`, then tap `{{change2faMethod}}`. +3. Confirm your identity with your account password. +4. Pick a method from the list. +5. Follow the method's setup — tap `{{copy}}` for the authenticator key, or `{{sendCode}}` for email and SMS — and type the code into the 6-digit field, then tap `{{next}}`. +6. Save the codes on the `{{saveRecoveryCodes}}` screen with `{{copyCodes}}` or `{{saveToFile}}`, then tap `{{next}}`. + +You should now see `{{twoFactorAuthEnabled}}`. + +::: + +### Set up an authenticator app + +:::tabs key:platform +== Desktop/Web +Notesnook shows a QR code with the instruction `{{mfaScanQrCode}}`. If your app cannot scan it, copy the text key shown underneath instead — spaces do not matter. Your app then displays a rotating 6-digit code to enter. + +== Mobile + +Notesnook shows the setup key in a field with a `{{copy}}` button. Tapping it copies the key and opens your installed authenticator app directly. Your app then displays a rotating 6-digit code to enter. + +::: + +### Set up email + +Notesnook pre-fills your account email and sends the code there when you press `{{sendCode}}`. You cannot enter a different address — email 2FA always uses your account email. + +### Set up SMS <PlanTag plan="pro" /> + +SMS 2FA is available on **Pro** and **Believer**. Enter your phone number **with the country code** (for example `+1234567890`), press `{{sendCode}}`, and enter the code from the SMS. On free and Essential plans, selecting `{{mfaSmsTitle}}` shows an upgrade prompt instead — see [Plans & limits](/plans-and-limits). + +## Wait 60 seconds between codes + +For email and SMS, the `{{sendCode}}` button becomes `Resend code in …` and counts down for **60 seconds** after each send. On mobile, requesting a new code too early shows `{{resendCodeWait}}`. The countdown exists both during setup and at login. + +## Add a fallback 2FA method + +A fallback is a second method you can use when your primary one is unavailable — for example email as a fallback when your authenticator app is on a phone you don't have. The method you already use as primary is not offered again in the list. + +:::tabs key:platform +== Desktop/Web + +1. Go to `{{settings}}` → `{{authentication}}`. +2. Press `{{addFallback2faMethod}}` (it reads `{{change2faFallbackMethod}}` once one exists). +3. Confirm the `{{verifyItsYou}}` prompt. +4. Pick a method and complete the same setup steps as above. + +You should now see `{{fallbackMethodEnabled}}`. + +== Mobile + +1. Go to `{{settings}}` → `{{account}}` → `{{manageAccount}}` → `{{twoFactorAuth}}`. +2. Tap `{{addFallback2faMethod}}` (it reads `{{change2faFallbackMethod}}` once one exists). +3. Confirm your identity. +4. Pick a method and complete the same setup steps as above. + +You should now see `{{fallbackMethodEnabled}}`. + +::: + +## View or regenerate your recovery codes + +Recovery codes are single-use codes that log you in when no 2FA method is reachable. Notesnook shows them once during setup, and you can pull them up again at any time. + +:::tabs key:platform +== Desktop/Web + +1. Go to `{{settings}}` → `{{authentication}}`. +2. Press `{{viewRecoveryCodes}}` and confirm the `{{verifyItsYou}}` prompt. +3. Use `{{print}}`, `{{copy}}` or `Download` to keep a copy. `Download` saves a `notesnook-recovery-codes.txt` file. +4. Press `{{regenerate}}` to replace the current set with a new one. + +== Mobile + +1. Go to `{{settings}}` → `{{account}}` → `{{manageAccount}}` → `{{twoFactorAuth}}`. +2. Tap `{{viewRecoveryCodes}}` and confirm your identity. +3. Use `{{copyCodes}}` or `{{saveToFile}}` — the file is saved as `notesnook_recoverycodes.txt`. + +Regenerating codes is available on the desktop and web apps. + +::: + +::: warning Regenerating invalidates the old codes +Once you regenerate, the previous set stops working. Replace any copy you printed or stored. + +::: + +<!-- TODO: screenshot — the Save recovery codes screen with the Print / Copy / Download / Regenerate buttons --> + +## What happens when you log in + +After you enter your email and password, Notesnook asks for a 6-digit code: + +- With an **authenticator app**, open the app and type the current code. +- With **email** or **SMS**, the code is sent automatically as the screen opens. `Resend code in …` is disabled for 60 seconds. +- The link at the bottom of the screen — `{{mfaAuthAppSelector}}`, `{{mfaEmailSelector}}` or `{{mfaSmsSelector}}` — opens `{{select2faMethod}}`, where you can switch to your fallback method or choose `{{recoveryCode}}`. + +Entering a recovery code instead of a 6-digit code logs you in the same way. + +## What if I lose my 2FA device? + +Work through these in order: + +1. **Use your fallback method.** On the code screen, follow the `Don't have access to …` link and pick your fallback. +2. **Use a recovery code.** From the same screen choose `{{recoveryCode}}` and enter one of the codes you saved. +3. **Log in on a device that is already signed in** and change your 2FA method from `{{settings}}` — an existing session does not need a fresh 2FA code. + +::: danger Notesnook cannot bypass 2FA for you +If you have no fallback method, no recovery codes and no logged-in device, support cannot unlock the account — the same way we cannot recover your password or decrypt your notes. Save your recovery codes somewhere outside the phone that holds your authenticator app. + +::: + +## Turn 2FA off + +The apps do not expose a switch to disable 2FA once it is enabled. What you can change is the primary method and the fallback method, from the same `{{twoFactorAuth}}` settings. + +## Related pages + +- [Plans & limits](/plans-and-limits) — which plans include SMS-based 2FA +- [Your account](/account-settings) — changing your email, password and recovery key +- [Recovering your account](/recovering-your-account) — what to do when you forget your password +- [How is my data encrypted?](/how-is-my-data-encrypted) — why 2FA and encryption protect different things +- [App lock](/app-lock) — locking the app itself on a device you already trust diff --git a/docs/help/contents/web-clipper/README.md b/docs/help/contents/web-clipper/README.md deleted file mode 100644 index 0fc038d2c..000000000 --- a/docs/help/contents/web-clipper/README.md +++ /dev/null @@ -1 +0,0 @@ -# Web clipper diff --git a/docs/help/contents/web-clipper/clipping-your-first-web-page-with-web-clipper.md b/docs/help/contents/web-clipper/clipping-your-first-web-page-with-web-clipper.md index d7d78f569..5dab88f25 100644 --- a/docs/help/contents/web-clipper/clipping-your-first-web-page-with-web-clipper.md +++ b/docs/help/contents/web-clipper/clipping-your-first-web-page-with-web-clipper.md @@ -1,46 +1,51 @@ --- title: Clipping your first webpage with web clipper -description: Clip web pages & save interesting things you find on the web with Notesnook web clipper in a private & secure way. +pageTitle: How do I clip a web page into Notesnook? +description: Connect the Notesnook Web Clipper to the web app, choose what part of a page to clip and in what mode, then file the clip into a note, notebook or tag. +keywords: + - notesnook web clipper + - clip web page to notes + - save article to notes app +schema: howto --- # Clipping your first webpage with web clipper -## Connecting the with the web app +## Connect the web clipper to the Notesnook app Before you can clip pages, you must connect the web clipper with the Notesnook web app. The web clipper works completely offline and relies on the web app to sync & save your clips. 1. Activate the web clipper by clicking on the Notesnook icon in your browser toolbar - > info Pin the Notesnook Web Clipper to toolbar - > - > Modern browsers group all extensions under their Extensions dropdown by default. It is recommended that you `Pin to toolbar` the Notesnook Web Clipper. - > - > # [Chrome](#/tab/chrome) - > - > ![How to pin the Notesnook Web Clipper to toolbar in Chrome](/static/web-clipper/chrome-pin-to-toolbar.gif) - > - > # [Firefox](#/tab/firefox) - > - > ![How to pin the Notesnook Web Clipper to toolbar in Firefox](/static/web-clipper/firefox-pin-to-toolbar.gif) - > - > *** + ::: info Pin the Notesnook Web Clipper to toolbar + Modern browsers group all extensions under their Extensions dropdown by default. It is recommended that you `Pin to toolbar` the Notesnook Web Clipper. -2. Click on `Connect to Notesnook` + :::tabs + == Chrome + ![How to pin the Notesnook Web Clipper to toolbar in Chrome](/static/web-clipper/chrome-pin-to-toolbar.gif) + == Firefox + ![How to pin the Notesnook Web Clipper to toolbar in Firefox](/static/web-clipper/firefox-pin-to-toolbar.gif) + + ::: + +2. Click `Connect with Notesnook` 3. Notesnook web app will open in a new tab in the background. Wait a few seconds and the web clipper should automatically connect. - > error What to do if the web clipper doesn't connect? - > - > There are a few things you can do to troubleshoot: - > - > 1. Make sure you are logged in on the Notesnook web app - > 2. Make sure you have the Notesnook web app opened in the background - > 3. The web clipper doesn't yet support multiple browser windows so make sure there aren't any additional browser windows opened in the background. - > 4. Try restarting the browser + + ::: details What to do if the web clipper doesn't connect? + There are a few things you can do to troubleshoot: + + 1. Make sure you are logged in on the Notesnook web app + 2. Make sure you have the Notesnook web app opened in the background + 3. The web clipper doesn't yet support multiple browser windows so make sure there aren't any additional browser windows opened in the background. + 4. Try restarting the browser + +::: ## Selecting the clipping area The [web clipper](https://notesnook.com/notesnook-web-clipper) provides a few options to help you clip exactly the part of the page you need: -![Notesnook Web Clipper clipping area options](/static/web-clipper/clipping-area.png) +![The clipping area options in the Notesnook Web Clipper](/static/web-clipper/clipping-area.png) ### Full page @@ -59,15 +64,15 @@ The `Visible area` mode clips only the nodes that fit in the viewport. Any nodes The `Selected nodes` mode allows you to select exactly which nodes you want to clip: 1. Select the `Selected nodes` mode from the Notesnook Web Clipper -2. You should now see a small popup in the bottom-right corner of the page - ![](/static/web-clipper/selected-nodes-popup.png) -3. Click on all the nodes you want to clip (they can be in any part of the screen). - > info - > - > The web clipper stacks all the selected nodes vertically during final processing. -4. Clicking again on the selected nodes will deselect them. -5. Once you are done, click on the Clip button -6. Activate the Notesnook Web Clipper and save your clip. +2. You should now see a small popup in the bottom-right corner of the page. + +![The selected-nodes popup shown in the bottom-right corner of the page](/static/web-clipper/selected-nodes-popup.png) + +3. Click all the nodes you want to clip (they can be in any part of the screen). + ::: info + The web clipper stacks all the selected nodes vertically during final processing. + +::: 4. Clicking again on the selected nodes will deselect them. 5. Once you are done, click the Clip button 6. Activate the Notesnook Web Clipper and save your clip. ## Selecting the clipping mode @@ -83,53 +88,59 @@ The clipping mode controls how the final clip should look. ### Screenshot -> info Uses attachment storage -> -> The `Screenshot` mode will use some of your monthly attachment storage for each page clipped. +::: info Requires a signed-in account +`Screenshot` and `Complete with styles` are offered only while you are **logged in** to the Notesnook web app. Clip while signed out and the clipper falls back to `Simplified`. Both modes use some of your [monthly attachment storage](/plans-and-limits) for every page you clip. + +::: `Screenshot` mode includes all the styles + images but the final result is saved as an image i.e. it is non-interactive. ### Complete with styles -> info Uses attachment storage -> -> The `Complete with styles` mode will use some of your monthly attachment storage for each page clipped. - `Complete with styles` mode saves all images, styles & everything on the page to retain the maximum amount of information. The final result appears as an embed in the Notesnook editor which is fully interactive. -![](/static/web-clipper/web-clip-embed.gif) +![A web clip embedded in a Notesnook note, scrollable and fully interactive](/static/web-clipper/web-clip-embed.gif) ## Organizing your web clip The Notesnook Web Clipper offers 3 easy ways to organize your web clips (all of which are completely optional): -![](/static/web-clipper/organize-web-clip.png) - -### [Append to note](#/tab/append-to-note) +![The Notesnook Web Clipper options for appending to a note, adding to a notebook, or assigning tags](/static/web-clipper/organize-web-clip.png) +:::tabs +== Append to note You can choose to append your web clip to an existing note and it'll be automatically added at the bottom of that note: -1. Click on `Select a note to append to` +1. Click `Select a note to append to` 2. Select the note you want to append to -### [Add to notebook](#/tab/add-to-notebook) +== Add to notebook -> info -> -> You can only assign the web clip to an existing notebook. Creating new notebooks is not supported from inside the web clipper. - -1. Click on `Select a notebook` +1. Click `Select a notebook` 2. Select the notebook you want to add the web clip to -### [Assign tags](#/tab/assign-tags) +::: info +You can only assign the web clip to an existing notebook. Creating new notebooks is not supported from inside the web clipper. -1. Click on `Assign a tag` +== Assign tags + +1. Click `Assign a tag` 2. Select the tag you want to assign (you can assign multiple tags) 3. You can also create & assign a new tag by typing in the search bar - ![](/static/web-clipper/assign-a-tag.gif) ---- + ![Assigning a tag to a web clip from the web clipper](/static/web-clipper/assign-a-tag.gif) + +::: ## Saving your web clip -1. Click on the `Save` button to save & sync your web clip. +1. Click the `{{save}}` button to save & sync your web clip. + +<GetNotesnook title="Clip the web into notes only you can read" text="The Notesnook Web Clipper saves pages straight into your encrypted notes — no third-party server sees what you save. It's free, open source, and works in Chrome, Firefox and Edge." /> + +## Related pages + +- [Installing the web clipper](/web-clipper/installation) — Chromium and Firefox setup +- [Web clipper troubleshooting](/web-clipper/troubleshooting) — when the clipper can't connect +- [Attachments & files](/attachments-and-files) — where clips are stored and what they count against +- [Plans & limits](/plans-and-limits) — monthly storage on each plan diff --git a/docs/help/contents/web-clipper/installation.md b/docs/help/contents/web-clipper/installation.md index 0fdb22499..d4f19c617 100644 --- a/docs/help/contents/web-clipper/installation.md +++ b/docs/help/contents/web-clipper/installation.md @@ -1,16 +1,28 @@ --- title: Installation -description: Notesnook Web Clipper is open source and available to download for Firefox and Chromium based browsers. +pageTitle: Install the Notesnook Web Clipper +description: Install the Notesnook Web Clipper extension in Chrome, Edge and other Chromium browsers, or in Firefox from the signed .xpi file. +keywords: + - notesnook web clipper install + - web clipper extension + - chrome notes clipper +schema: howto --- # Installation ## Chromium-based browsers -[Go to chrome webstore](https://chrome.google.com/webstore/detail/notesnook-web-clipper/kljhpemdlcnjohmfmkogahelkcidieaj) to get the latest version of [web clipper for Notesnook](https://notesnook.com/notesnook-web-clipper). +[Go to chrome webstore](https://chrome.google.com/webstore/detail/notesnook-web-clipper/kljhpemdlcnjohmfmkogahelkcidieaj) to get the latest version of the [web clipper for Notesnook](https://notesnook.com/notesnook-web-clipper). ## Firefox-based browsers 1. Download the .xpi file from [here](https://notesnook.com/notesnook-web-clipper) 2. A pop-up will appear, select "Continue to Installation". 3. Select "Add". + +## Related pages + +- [Clipping your first page](/web-clipper/clipping-your-first-web-page-with-web-clipper) — areas, modes and organizing clips +- [Web clipper troubleshooting](/web-clipper/troubleshooting) — when the clipper can't connect +- [Share from other apps](/mobile-integration/share-things-from-other-apps) — capturing from the share sheet diff --git a/docs/help/contents/web-clipper/troubleshooting.md b/docs/help/contents/web-clipper/troubleshooting.md index 217b65652..feff8f147 100644 --- a/docs/help/contents/web-clipper/troubleshooting.md +++ b/docs/help/contents/web-clipper/troubleshooting.md @@ -1,6 +1,11 @@ --- title: Troubleshooting web clipper -description: Common issues with the web clipper and how to fix them. +pageTitle: Notesnook Web Clipper won't connect — how do I fix it? +description: Fixes for the Notesnook Web Clipper when it will not connect to the web app, shows a connection error, or renders a clipped page incorrectly. +keywords: + - web clipper not connecting + - notesnook clipper error + - receiving end does not exist --- # Troubleshooting web clipper @@ -23,3 +28,9 @@ However, if you are seeing this on a website it is recommended that you trigger ## What to do if a website appears broken in the web clip? Since the [Notesnook Web Clipper](https://notesnook.com/notesnook-web-clipper) is still in alpha-beta stage, some rendering issues are expected in the web clips. If you notice any such problem, feel free to open a new issue on our [GitHub Issue Tracker](https://github.com/streetwriters/notesnook/issues/new/choose). + +## Related pages + +- [Installing the web clipper](/web-clipper/installation) — Chrome, Edge and Firefox +- [Clipping your first page](/web-clipper/clipping-your-first-web-page-with-web-clipper) — areas, modes and organizing clips +- [Attachments & files](/attachments-and-files) — managing the files in your notes diff --git a/docs/help/coverage-audit.md b/docs/help/coverage-audit.md new file mode 100644 index 000000000..1fe280389 --- /dev/null +++ b/docs/help/coverage-audit.md @@ -0,0 +1,140 @@ +# Help documentation coverage audit + +Notesnook **3.4.x** · help site **93 pages** · last run 2026-08-01. + +Method: mechanical sweeps over the whole `contents/` tree, plus targeted verification of every load-bearing claim against the monorepo source (`packages/common/src/utils/is-feature-available.ts`, `packages/crypto/src/`, `packages/theme/src/theme-engine/types.ts`, `packages/intl/src/strings.ts`, `apps/web/src/`, `apps/mobile/app/`). + +## Where it stands + +| | | +| --- | --- | +| Pages | 93 | +| Orphan pages / dead sidebar links | 0 / 0 | +| Pages with a meta description | 93 / 93 | +| Pages with `pageTitle` and `keywords` | 91 / 93 (`404`, `index` excluded) | +| Pages ending in a `## Related pages` cluster | 90 / 90 (`404`, `docs`, `index` excluded) | +| Internal links in body content | ~810 | +| Gated features (35) documented | 35 / 35 | +| Structured data | BreadcrumbList + TechArticle on all 93; HowTo on 57; FAQPage on 13 | +| Images with descriptive alt text | 100% | +| Outstanding screenshot TODOs | 24 | +| `npm run build` | passes — 0 dead internal links, 0 unresolved string keys | +| Legacy URLs still resolving | 71 / 71 (8 section indexes now 301) | + +## Verified against source this run + +These were re-derived from the source rather than taken on trust: + +| Claim | Source | Result | +| --- | --- | --- | +| All plan limits and every gated feature | `is-feature-available.ts` | 35 / 35 correct | +| All 35 `<PlanTag>` placements | `is-feature-available.ts` | all correct | +| Trash cleanup default of 7 days | `packages/core/src/collections/settings.ts:65` | correct | +| 297 code-block languages | `packages/editor/.../languages.json` | correct | +| Encryption primitives | `packages/crypto/src/` | corrected — see below | +| Theme scopes / variants / colors | `packages/theme/src/theme-engine/types.ts` | corrected — see below | +| Refund windows | `apps/web/src/dialogs/buy-dialog/plans.ts` | 7 / 14 / 30 days, now documented | +| Keyboard shortcut registry | `packages/common/src/utils/keybindings.ts` | page regenerates with zero diff | + +## Source bugs from earlier audits — all fixed in the app + +The four app-side bugs earlier runs surfaced have since been fixed in the source, and `keyboard-shortcuts.md` regenerates with **no diff**: + +| Bug | Status | +| --- | --- | +| `strings.none()` returned `"Cell border width"` | fixed — returns `None` | +| `strings.alignCenter()` returned `"Alignment"` | fixed — returns `Align center` | +| `sinkListItem` bound to `Mod-Shift-Down` | fixed — page reads `Tab` | +| Font-size shortcuts inverted, and `Ctrl-` macified on Mac | fixed — registry uses `Mod-[` / `Mod-]`, and `font-size.ts` binds from `tiptapKeys`, so labels and handlers cannot disagree | + +There are no known outstanding source-side bugs affecting the docs. + +## Errors found and fixed in this run + +**Contradictions and wrong facts** + +- `plans-and-limits.md` referred to a refund "window listed above" that was never stated. The real windows (7 / 14 / 30 days by billing period) are now documented in their own section and in the FAQ schema. +- Regional pricing was described as Pro-only in the body and as all-plans in the FAQPage schema. Both now say the same verifiable thing. +- The flat "all plans have a 14-day free trial" claim was not verifiable — trial length is server-driven and passed into `trialPlanConditions(duration)`. The page now says the length is shown on the plan before you start it. +- `attachments-and-files.md` and `trash.md` gave three different answers to "does deleting attachments free storage". All three now describe storage as a monthly allowance, consistent with the `50MB/mo` captions in `is-feature-available.ts`. **See open questions below.** +- `rich-text-editor-toolbar.md` said toolbar config "is automatically synced across all your devices" and then that it is not. +- `how-is-my-data-encrypted.md` named the cipher "XChaCha-Poly1305-IETF" (it is XChaCha**20**-Poly1305-IETF, `crypto_aead_xchacha20poly1305_ietf`) and called the KDF "PKDF". Both corrected; the page now also distinguishes `argon2i` (key derivation) from `argon2id` (password hashing), matching `keyutils.ts` and `password.ts`. +- `custom-themes/introduction.md` claimed 10 scopes (there are 11 — `titleBar` was undocumented), 5 variants (there are 6 — `disabled` was undocumented) and "12 colors" above a table of 11 (there are 13 — `shade` and `textSelection` were missing). The transparency column was also wrong for `background` and `placeholder`. +- `recovering-your-account.md` documented the first and third recovery options and skipped the second (`{{backupFileMethod}}`), had a truncated two-step Mobile tab, and carried an unresolved `<!--Needs Validation-->` comment. Mobile recovery is real (`apps/mobile/app/components/auth/forgot-password.tsx`) and is now documented. +- Two images were wrong: the "clear completed tasks" step pointed at `sort-task-icon.png`, and the notebook "create a note" steps used the desktop plus button in the mobile tab with "Three dot button" as alt text. +- `faqs/what-are-merge-conflicts.md` said "which version of the **name** you want to keep". + +**Structure** + +- The VitePress migration dropped the ten `README.md` section stubs the legacy docgen site served as directory landing pages, so `/organizing-notes`, `/rich-text-editor`, `/custom-themes`, `/faqs`, `/mobile-integration`, `/desktop-integration`, `/web-clipper` and `/inbox-api` started returning 404. Every *article* slug survived the migration unchanged; only these eight moved. They are now 301'd to their cluster hub from `contents/public/_redirects`. (`/` and `/importing-notes` were already covered by `index.md` and `importing-notes/index.md`.) +- `backup-and-restore-notes-in-notesnook.md` and `custom-themes/publish-a-theme.md` each had two `# H1`s, which hid a whole section from the page outline. Both now use one H1. +- `app-lock.md` had `###` headings **inside** both tab panels, so each appeared twice in the outline with duplicate anchor slugs, plus step numbering that ran across headings and six `alt="drawing"` images. Rewritten with headings outside the tabs and real UI string keys. +- `keyboard-shortcuts.md` started at `###`, leaving the page outline empty. The generator (`scripts/document-keyboard-shortcuts.mjs`) now emits `##` per category and a `## Related pages` block, and the page carries proper SEO frontmatter. +- `/self-hosting` was commented out of `sidebar.mjs` while remaining live, canonical and in the sitemap. It is now in the sidebar under Advanced. +- `faqs/what-are-merge-conflicts.md` had an `### Example:` with no H2 parent. +- `mobile-integration/pin-notes-to-notifications.md` rendered an empty `::: info` box. + +**Accessibility and SEO** + +- 82 images had useless or missing alt text: 37 reading `" in Notesnook"`, 27 reading `"Toolbar"` on theme screenshots, 9 `alt="drawing"`, 6 `"Step in Notesnook"`, 2 raw `<img>` tags with no `alt` at all, and 1 filename. All now describe what the reader should look for. +- 33 pages had no `pageTitle` or `keywords`. All now do. +- 5 pages had a body FAQ section but emitted only `TechArticle`. They now emit `FAQPage` (13 pages total, up from 5). +- 4 meta descriptions exceeded 160 characters. +- 32 uses of the banned words "simply", "just", "easily" across 30 files, and two version numbers in body copy ("Starting from v3", "Starting from v2.6.0"), both forbidden by `STYLE.md`. + +**Voice and editorial** + +- `faqs/is-there-an-eta.md` hotlinked an image from `imgs.xkcd.com` — a third-party request from a privacy product's help site — and told users that asking about ETAs "is annoying". Rewritten to point at the roadmap and issue tracker. +- First-person asides removed from `how-is-my-data-encrypted.md` ("that is when I found out"), `create-a-theme-with-theme-builder.md` ("like me") and `publish-a-theme.md`, which linked to a maintainer's personal fork. +- The two "login to … attachments" FAQs were 83-word near-duplicates with trailing whitespace in their titles. Both **keep their URLs** — `packages/intl/src/strings.ts:2625` and `:2741` link to them from inside the app — and are now distinct, question-shaped pages. +- `import-notes-from-standardnotes.md` warned that its own steps could not be completed, then presented them anyway. Restructured around the Markdown/plaintext route that actually works. + +## Open questions that need a product answer + +These could not be settled from this repo and are the main risk of a wrong claim shipping: + +1. **Storage accounting.** `is-feature-available.ts` captions the limit `50MB/mo`, `1GB/mo` and so on, and `storageUsed` / `totalStorage` arrive from the server. Whether the counter is a monthly upload allowance that resets, or a measure of bytes currently stored, is not determinable client-side. The docs now consistently describe it as a **monthly allowance that does not return when you delete a file** — this needs confirming, and correcting everywhere if it is wrong. +2. **Trial length per plan and period**, which is server-driven. +3. **Monograph 15 MB limit** and whether links-and-embeds gating is enforced anywhere client-side. +4. **Inbox API** 10 MB body cap and 60 req/min rate limit — both server-side. +5. **Per-provider "supported formats" checklists**, which depend on `@notesnook-importer/core` rather than this repo. + +## Screenshots + +**24 TODO markers** remain, in three groups: + +| Group | Why it isn't captured | Examples | +| --- | --- | --- | +| Needs a signed-in account | The capture harness runs logged out on purpose | attachment manager, sync status indicator, 2FA recovery codes, note links panel | +| Needs a paid plan | Feature is gated | the expiry badge on a note (Pro) | +| Needs a device or a date | Not reproducible in a browser | Android widgets, quick settings tile, Wrapped (December only) | + +Five screenshots in `contents/public/screenshots/` were captured from a real production build of the web app and are current. + +## Existing images are old + +**69 of 81 images date from 2023**, 9 from 2024 and 3 from 2026. The app has been through a major redesign since — editor tabs, a restructured settings dialog, the new side menu — so most screenshots predate the UI they illustrate. + +| Image | Age | Problem | +| --- | --- | --- | +| `config-toolbar-desktop.png` | 2023-06 | Dialog is titled **"Configure toolbar"**; the current label is **"Customize toolbar"** | +| `first-note-desktop.png` | 2023-02 | Toolbar predates the bi-directional note link tool | +| `desktop-enable-app-lock.png` | 2024 | Matches 3.4 except the new **Inbox** section is missing | + +The 2023 cohort covering tables (11 images), publishing themes (16), colors, backups and the first-note flow should be re-shot wholesale rather than audited one by one. + +## Remaining work, in priority order + +1. **Answer the five open questions above**, then correct any page that guessed wrong. +2. **Screenshots** — 25 TODOs, plus the 2023-era images. The account-gated ones need a throwaway account; the Android ones need a device or emulator. +3. **Thin coverage worth deepening**: debug logs (`other-settings.ts:400`, the first thing support asks for), desktop CLI arguments (`apps/desktop/src/cli.ts:38-83`), the `nn://` protocol handler on desktop, and subscription management detail (payment method, cancel trial, mobile restore purchase). + +## Notes for whoever writes here next + +- `docs/help/STYLE.md` is the contract: verification requirement, plan tags, platform tabs, SEO frontmatter, linking clusters. +- Plan tiers come from `packages/common/src/utils/is-feature-available.ts` and nowhere else. All 35 gated features are monotonic across tiers, so "Pro includes Essential" is provably true. +- Where `keybindings.ts` and an editor extension disagree about a shortcut, the extension wins. +- `keyboard-shortcuts.md` is generated. Edit `scripts/document-keyboard-shortcuts.mjs`, never the page. +- A frontmatter value containing `: ` must be quoted, or the YAML parser fails the build. +- Some help URLs are linked from inside the app via `packages/intl/src/strings.ts`. Grep it before renaming or deleting a page. +- `contents/v<version>/` is generated build output. Never edit it; edit the root copy, and use `npm run fork` to preserve old text for an archived version. diff --git a/docs/help/docgen.yaml b/docs/help/docgen.yaml deleted file mode 100644 index 290df796b..000000000 --- a/docs/help/docgen.yaml +++ /dev/null @@ -1,96 +0,0 @@ ---- -title: Notesnook -subtitle: HELP -docs_dir: ./contents -logo: logo.png -edit_root: https://github.com/streetwriters/notesnook/tree/master/docs/help -base_url: https://help.notesnook.com - -meta: - title: Notesnook Help - -footer: - copyright: Copyright © 2026 Streetwriters (Private) Limited - -navigation: - - path: create-a-note-in-notesnook.md - - path: organizing-notes - children: - - path: organizing-notes/archive-notes.md - - path: organizing-notes/organize-notes-using-colors.md - - path: organizing-notes/organize-notes-using-favorites.md - - path: organizing-notes/organize-notes-using-notebooks.md - - path: organizing-notes/organize-notes-using-tags.md - - path: organizing-notes/pin-notes.md - - path: organizing-notes/side-menu-shortcuts.md - - path: rich-text-editor - children: - - path: rich-text-editor/personalizing-rich-text-editor.md - - path: rich-text-editor/markdown-notes-editing.md - - path: rich-text-editor/rich-text-editor-toolbar.md - - path: rich-text-editor/tables.md - - path: rich-text-editor/task-and-todo-lists.md - - path: importing-notes - children: - - path: importing-notes/import-notes-from-evernote.md - - path: importing-notes/import-notes-from-googlekeep.md - - path: importing-notes/import-notes-from-joplin.md - - path: importing-notes/import-notes-from-simplenote.md - - path: importing-notes/import-notes-from-zoho-notebook.md - - path: importing-notes/import-notes-from-skiff-pages.md - - path: importing-notes/import-notes-from-obsidian.md - - path: importing-notes/import-notes-from-html-files.md - - path: importing-notes/import-notes-from-markdown-files.md - - path: importing-notes/import-notes-from-plaintext-files.md - - path: importing-notes/import-notes-from-colornote.md - - path: importing-notes/import-notes-from-upnote.md - - path: export-notes-from-notesnook.md - - path: backup-and-restore-notes-in-notesnook.md - - - path: lock-notes-with-private-vault.md - - path: note-version-history.md - - - path: publish-notes-with-monographs.md - - - path: how-is-my-data-encrypted.md - - path: recovering-your-account.md - - path: deleting-your-account.md - - path: app-lock.md - - path: gift-cards.md - - path: keyboard-shortcuts.md - - - path: privacy-mode.md - - path: reminders.md - - path: web-clipper - children: - - path: web-clipper/installation.md - - path: web-clipper/clipping-your-first-web-page-with-web-clipper.md - - path: web-clipper/troubleshooting.md - - path: mobile-integration - children: - - path: mobile-integration/home-screen-widgets.md - - path: mobile-integration/pin-notes-to-notifications.md - - path: mobile-integration/quick-note-from-notification.md - - path: mobile-integration/share-things-from-other-apps.md - - path: desktop-integration - children: - - path: desktop-integration/auto-start-on-system-startup.md - - path: desktop-integration/jumplist-and-dock-menu.md - - path: desktop-integration/spell-checker.md - - path: desktop-integration/system-tray-menu.md - - path: custom-themes - children: - - path: custom-themes/introduction.md - - path: custom-themes/create-a-theme-with-theme-builder.md - - path: custom-themes/install-a-theme-from-file.md - - path: custom-themes/publish-a-theme.md - - path: inbox-api - children: - - path: inbox-api/getting-started.md - - path: inbox-api/self-hosting-inbox-api.md - - path: faqs - children: - - path: faqs/what-are-merge-conflicts.md - - path: faqs/is-there-an-eta.md - - path: faqs/login-to-upload-attachments.md - - path: faqs/login-to-restore-attachments-in-backup.md diff --git a/docs/help/package-lock.json b/docs/help/package-lock.json index 8d1f812ea..0b40713f6 100644 --- a/docs/help/package-lock.json +++ b/docs/help/package-lock.json @@ -1,15 +1,20 @@ { - "name": "@notesnook/docs-help", + "name": "@notesnook/help", "version": "1.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "@notesnook/docs-help", + "name": "@notesnook/help", "version": "1.0.0", "license": "GPL-3.0-or-later", "devDependencies": { - "@notesnook/common": "file:../../packages/common" + "@lingui/core": "^5.2.0", + "@notesnook/common": "file:../../packages/common", + "@notesnook/intl": "file:../../packages/intl", + "markdown-it-task-lists": "^2.1.1", + "vitepress": "^1.6.4", + "vitepress-plugin-tabs": "^0.9.1" } }, "../../../packages/common": { @@ -21,6 +26,7 @@ "dev": true, "license": "GPL-3.0-or-later", "dependencies": { + "@notesnook/common": "^2.1.3", "@notesnook/core": "file:../core", "@readme/data-urls": "^3.0.0", "dayjs": "1.11.13", @@ -38,12 +44,2633 @@ "timeago.js": "4.0.2" } }, + "../../packages/intl": { + "name": "@notesnook/intl", + "version": "1.0.0", + "dev": true, + "hasInstallScript": true, + "license": "GPL-3.0-or-later", + "devDependencies": { + "@lingui/cli": "5.1.2", + "@lingui/core": "5.1.2", + "@lingui/swc-plugin": "5.0.2", + "@types/react": "18.3.5", + "babel-plugin-macros": "^3.1.0", + "nodemon": "^3.1.7", + "react": "18.3.1", + "rollup": "^4.24.4", + "vite": "5.4.11", + "vite-plugin-dts": "^4.2.3", + "vite-plugin-static-copy": "^2.0.0", + "vite-plugin-swc-transform": "^1.0.1" + }, + "peerDependencies": { + "@lingui/macro": "*", + "react": ">=18" + } + }, "../common": { "extraneous": true }, + "node_modules/@algolia/abtesting": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/@algolia/abtesting/-/abtesting-1.22.0.tgz", + "integrity": "sha512-BFR6zNowNKcY7Ou7TaJc9QWexES4YKPbmf/OTFofpdsdhz4x6q0lbxp3duO0EHnyrN7rE4ba/TSXuY+BDGu4+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.56.0", + "@algolia/requester-browser-xhr": "5.56.0", + "@algolia/requester-fetch": "5.56.0", + "@algolia/requester-node-http": "5.56.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/autocomplete-core": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-core/-/autocomplete-core-1.17.7.tgz", + "integrity": "sha512-BjiPOW6ks90UKl7TwMv7oNQMnzU+t/wk9mgIDi6b1tXpUek7MW0lbNOUHpvam9pe3lVCf4xPFT+lK7s+e+fs7Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/autocomplete-plugin-algolia-insights": "1.17.7", + "@algolia/autocomplete-shared": "1.17.7" + } + }, + "node_modules/@algolia/autocomplete-plugin-algolia-insights": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-plugin-algolia-insights/-/autocomplete-plugin-algolia-insights-1.17.7.tgz", + "integrity": "sha512-Jca5Ude6yUOuyzjnz57og7Et3aXjbwCSDf/8onLHSQgw1qW3ALl9mrMWaXb5FmPVkV3EtkD2F/+NkT6VHyPu9A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/autocomplete-shared": "1.17.7" + }, + "peerDependencies": { + "search-insights": ">= 1 < 3" + } + }, + "node_modules/@algolia/autocomplete-preset-algolia": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.17.7.tgz", + "integrity": "sha512-ggOQ950+nwbWROq2MOCIL71RE0DdQZsceqrg32UqnhDz8FlO9rL8ONHNsI2R1MH0tkgVIDKI/D0sMiUchsFdWA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/autocomplete-shared": "1.17.7" + }, + "peerDependencies": { + "@algolia/client-search": ">= 4.9.1 < 6", + "algoliasearch": ">= 4.9.1 < 6" + } + }, + "node_modules/@algolia/autocomplete-shared": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-shared/-/autocomplete-shared-1.17.7.tgz", + "integrity": "sha512-o/1Vurr42U/qskRSuhBH+VKxMvkkUVTLU6WZQr+L5lGZZLYWyhdzWjW0iGXY7EkwRTjBqvN2EsR81yCTGV/kmg==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@algolia/client-search": ">= 4.9.1 < 6", + "algoliasearch": ">= 4.9.1 < 6" + } + }, + "node_modules/@algolia/client-abtesting": { + "version": "5.56.0", + "resolved": "https://registry.npmjs.org/@algolia/client-abtesting/-/client-abtesting-5.56.0.tgz", + "integrity": "sha512-7r4Z3NC7yU1oAQVWJNA2HX7tX481F3pJvCGyLIXiTdBcthz4Q/o21jwcMYDFkuI92UWTNBQQmHYgwHo1zS5dzg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.56.0", + "@algolia/requester-browser-xhr": "5.56.0", + "@algolia/requester-fetch": "5.56.0", + "@algolia/requester-node-http": "5.56.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-analytics": { + "version": "5.56.0", + "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-5.56.0.tgz", + "integrity": "sha512-avmjXQSq+jadFO8Xl2em05/uQdQnEmHsJyOAdVbZkmVgpMfxL12aJwVVfGNwYr9nulcpuJN1X0lTaQ5wxuNGcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.56.0", + "@algolia/requester-browser-xhr": "5.56.0", + "@algolia/requester-fetch": "5.56.0", + "@algolia/requester-node-http": "5.56.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-common": { + "version": "5.56.0", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-5.56.0.tgz", + "integrity": "sha512-v2TPStUhY//ripPjIVclZ8AWc7DEGooXULZGFlFu37zNatgHjw34oZZ+OSbbc/YHO+xZwPl62I1k8xH1m4S2eg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-insights": { + "version": "5.56.0", + "resolved": "https://registry.npmjs.org/@algolia/client-insights/-/client-insights-5.56.0.tgz", + "integrity": "sha512-P0ehROpM4Sem3Sqo5x2cKPgj67D3G3jy0rh1Amwkcvsfr6tkvIcdCmerieanqTF7NxUMPNFLkpIFeMO8Rpa50w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.56.0", + "@algolia/requester-browser-xhr": "5.56.0", + "@algolia/requester-fetch": "5.56.0", + "@algolia/requester-node-http": "5.56.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-personalization": { + "version": "5.56.0", + "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-5.56.0.tgz", + "integrity": "sha512-SXK3Vn3WVxyzbm31oePZBJkp1wpOyuWdd4B/Pv7n0aXDxmeSWhC1R1FC1517mMrFAIaPH4Rt0x6RUe7ZNjz8FA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.56.0", + "@algolia/requester-browser-xhr": "5.56.0", + "@algolia/requester-fetch": "5.56.0", + "@algolia/requester-node-http": "5.56.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-query-suggestions": { + "version": "5.56.0", + "resolved": "https://registry.npmjs.org/@algolia/client-query-suggestions/-/client-query-suggestions-5.56.0.tgz", + "integrity": "sha512-5+ZdX8garFnmycnZgKhtXHePEaLj5zqDxI/0lkhhluzCcvTn0/PvvTirTg8hHYetQHvn7GDyeAiqTAieMvMW4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.56.0", + "@algolia/requester-browser-xhr": "5.56.0", + "@algolia/requester-fetch": "5.56.0", + "@algolia/requester-node-http": "5.56.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-search": { + "version": "5.56.0", + "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-5.56.0.tgz", + "integrity": "sha512-+mKUdYvqOi0BcvpAEyCEw49vSBptufIcfibtHz2bdr1pI789M46Yt0uQEk/sxtK3teh71OQvVFHaTDzShUWewQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.56.0", + "@algolia/requester-browser-xhr": "5.56.0", + "@algolia/requester-fetch": "5.56.0", + "@algolia/requester-node-http": "5.56.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/ingestion": { + "version": "1.56.0", + "resolved": "https://registry.npmjs.org/@algolia/ingestion/-/ingestion-1.56.0.tgz", + "integrity": "sha512-9g/zj+AZx5moFcdFIrYQoVrueXivjUcc3MQHtCYT8WhIuk1lUh1AyEhvJCS0XBZld09cLvd1AZ3BvDBpVpX2UA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.56.0", + "@algolia/requester-browser-xhr": "5.56.0", + "@algolia/requester-fetch": "5.56.0", + "@algolia/requester-node-http": "5.56.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/monitoring": { + "version": "1.56.0", + "resolved": "https://registry.npmjs.org/@algolia/monitoring/-/monitoring-1.56.0.tgz", + "integrity": "sha512-Qf3Sr6f9A9uxCZUf3MXS0d2b877uYzEB5yxqpVGXAhcJnBCQjrRRon0KvefpGkxy+BshrIJs96OUoMtGqXTFDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.56.0", + "@algolia/requester-browser-xhr": "5.56.0", + "@algolia/requester-fetch": "5.56.0", + "@algolia/requester-node-http": "5.56.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/recommend": { + "version": "5.56.0", + "resolved": "https://registry.npmjs.org/@algolia/recommend/-/recommend-5.56.0.tgz", + "integrity": "sha512-GXWG1rWc5wu8hY4N33Y3b6ernY6sAdAvmKWN/zHAiACOx40WnpG0TVX5YazCAr/9gOYGInSiM2A0y2jy2xbiDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.56.0", + "@algolia/requester-browser-xhr": "5.56.0", + "@algolia/requester-fetch": "5.56.0", + "@algolia/requester-node-http": "5.56.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/requester-browser-xhr": { + "version": "5.56.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.56.0.tgz", + "integrity": "sha512-7t24cBxaInS3mZb7ddEaZT/tp6q+/aR4YttsQVyP1/i+LmwPR34atO35KjaLFCcRVrlP7sYOAqkCfg6lIRB+ew==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.56.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/requester-fetch": { + "version": "5.56.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-fetch/-/requester-fetch-5.56.0.tgz", + "integrity": "sha512-R7ePHgVYmDFjZpvrsVAfbDz/d4RxKAYZ5/vgLfIsCVRZRryjWl/3INOxpOICzitehQ5FjNtNjcLQTrmHPTcHBQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.56.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/requester-node-http": { + "version": "5.56.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-5.56.0.tgz", + "integrity": "sha512-PIOUXlSnrqM0S+WOgDRb4RzotydJH7ZoT6tOyL7tAO7qJOfvX5wsEW8Pe+PMKMwvuI4/gIyK9cg2H7lJXqnc4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.56.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", + "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.7.tgz", + "integrity": "sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.7" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.7.tgz", + "integrity": "sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.7.tgz", + "integrity": "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@docsearch/css": { + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-3.8.2.tgz", + "integrity": "sha512-y05ayQFyUmCXze79+56v/4HpycYF3uFqB78pLPrSV5ZKAlDuIAAJNhaRi8tTdRNXh05yxX/TyNnzD6LwSM89vQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@docsearch/js": { + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/@docsearch/js/-/js-3.8.2.tgz", + "integrity": "sha512-Q5wY66qHn0SwA7Taa0aDbHiJvaFJLOJyHmooQ7y8hlwwQLQ/5WwCcoX0g7ii04Qi2DJlHsd0XXzJ8Ypw9+9YmQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@docsearch/react": "3.8.2", + "preact": "^10.0.0" + } + }, + "node_modules/@docsearch/react": { + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-3.8.2.tgz", + "integrity": "sha512-xCRrJQlTt8N9GU0DG4ptwHRkfnSnD/YpdeaXe02iKfqs97TkZJv60yE+1eq/tjPcVnTW8dP5qLP7itifFVV5eg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/autocomplete-core": "1.17.7", + "@algolia/autocomplete-preset-algolia": "1.17.7", + "@docsearch/css": "3.8.2", + "algoliasearch": "^5.14.2" + }, + "peerDependencies": { + "@types/react": ">= 16.8.0 < 19.0.0", + "react": ">= 16.8.0 < 19.0.0", + "react-dom": ">= 16.8.0 < 19.0.0", + "search-insights": ">= 1 < 3" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + }, + "search-insights": { + "optional": true + } + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@iconify-json/simple-icons": { + "version": "1.2.92", + "resolved": "https://registry.npmjs.org/@iconify-json/simple-icons/-/simple-icons-1.2.92.tgz", + "integrity": "sha512-hR0ozxR97t1dzWw+esoxFijZ15gagt7EIgF3CNifu2yICXhS7gnun4Y+j+odJQtNSl7wvqMdoLbViIShwe/fdw==", + "dev": true, + "license": "CC0-1.0", + "dependencies": { + "@iconify/types": "*" + } + }, + "node_modules/@iconify/types": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@iconify/types/-/types-2.0.0.tgz", + "integrity": "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@lingui/core": { + "version": "5.9.5", + "resolved": "https://registry.npmjs.org/@lingui/core/-/core-5.9.5.tgz", + "integrity": "sha512-Y+iZq9NqnqZOqHNgPomUFP21KH/zs4oTTizWoz0AKAkBbq9T9yb1DSz/ugtBRjF1YLtKMF9tq28v3thMHANSiQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.20.13", + "@lingui/message-utils": "5.9.5" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "@lingui/babel-plugin-lingui-macro": "5.9.5", + "babel-plugin-macros": "2 || 3" + }, + "peerDependenciesMeta": { + "@lingui/babel-plugin-lingui-macro": { + "optional": true + }, + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/@lingui/message-utils": { + "version": "5.9.5", + "resolved": "https://registry.npmjs.org/@lingui/message-utils/-/message-utils-5.9.5.tgz", + "integrity": "sha512-t3dNbjb1dWkvcpXGMXIEyBDO3l4B8J2ColZXi0NTG1ioAj+sDfFxFB8fepVgd3JAk+AwARlOLvF14oS0mAdgpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@messageformat/parser": "^5.0.0", + "js-sha256": "^0.10.1" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@messageformat/parser": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@messageformat/parser/-/parser-5.1.1.tgz", + "integrity": "sha512-3p0YRGCcTUCYvBKLIxtDDyrJ0YijGIwrTRu1DT8gIviIDZru8H23+FkY6MJBzM1n9n20CiM4VeDYuBsrrwnLjg==", + "dev": true, + "license": "MIT", + "dependencies": { + "moo": "^0.5.1" + } + }, "node_modules/@notesnook/common": { "resolved": "../../packages/common", "link": true + }, + "node_modules/@notesnook/intl": { + "resolved": "../../packages/intl", + "link": true + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.62.3.tgz", + "integrity": "sha512-c0wdcekXtQvvn5Tsrk/+op/gUArrbWaFduBnTLP2l1cKLSQs4diMWjJw3m6A0DdzT8dAAX95KpkJ3qynCePbmw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.62.3.tgz", + "integrity": "sha512-3YjElDdWN+qXAFbJ/CzPV+0wspLqh54k/I6GfdYtEJRqg7buSgc1yPM3B+93j1M4neobtkATHZTmxK2AMVGfnA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.62.3.tgz", + "integrity": "sha512-Pch2pFNOxxz1hTjypIdPyRTR6riiwRl84+VcN9djS680fw+Co1nAJINrdpqp7KV0NvyuU8ilZXZCjd7ykJl1GQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.62.3.tgz", + "integrity": "sha512-LEuncFUHFiF8t4yZVZvvZA1wk0pjAscRnsrn1EfTEmN4HXotBi2YtcnLRyaK6UbuczW7xZS5ES+81Rdz8Z0T6g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.62.3.tgz", + "integrity": "sha512-zvBUvsQUpOWALdDsk6qbS8bXf2VxmPisuudNDrY7x0p0jBdsoZl8HsHczIOgkQiZldmcacMKtBzpoGVNeIe2bQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.62.3.tgz", + "integrity": "sha512-C2KmNrcSem/AMg984H/dev+si0lieQGdXdR/lYGJnuumXnFb9Y7QdiI62obFdLlxRYLBv4P0eUVIDbD4c1vVvw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.62.3.tgz", + "integrity": "sha512-ggXnsTAEzNQx74XpunRsiZ9aBZDsI7XIa0hm2nzR9f4WzH5/f/d73ZSDaC5ejJ8YLY4NW+V3wr0tjOaeCq8hqA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.62.3.tgz", + "integrity": "sha512-2vng+FlzNUhKZxtej3IUqJgbZoQk2M/dwQM20+ULV0R/E/8tr9/P6uEf2iiGIk4HL0zMKh5Jry7mUHdUOvyGgA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.62.3.tgz", + "integrity": "sha512-LLLFZKt4/Nraf9rxDkhiU8QVgLF4WmCkfr0L4fj0fPfIZFBib0DeiFk1hhaYKd03LFAFJcxHslhDFlNJLylf5Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.62.3.tgz", + "integrity": "sha512-WJkdQCvS9sWNOUBJZfQRKpZGFBztRzcowI+nndmflKgU4XY+3a420FgTOSKTsVqJbnzSxeT4vaJalpOaPo2YCQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.62.3.tgz", + "integrity": "sha512-PwHXCCS2n64/1Ot6rP1YEYA02MGYBcQlr8CSZZyrUG2O7NH6NklYmvr9v3Jy+5e/eDeNchc/ukmKJi9LuflMIQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.62.3.tgz", + "integrity": "sha512-vUjxINQu3RC8NZS3ykk1gN65gIz8pAopOq2HXuZhiIxHdx7TFvDG+jgrdSgInu1Eza4/Rfi2VzZgyIgEH4WOaw==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.62.3.tgz", + "integrity": "sha512-wzko4aJ13+0G3kGnviCg5gnXFKd40izKsrf2uOw12US4XqprkDrmwOpeW14aSNa37V8bfPcz5Fkob6LZ3BAPmA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.62.3.tgz", + "integrity": "sha512-8120ue0JUMSwy11stlwnfdX3pPd+WZYGCDBwEHWtIHi6pOpZmsEF5QKB7a/UN+XFdqvobxz98kv8RTqikyCEBw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.62.3.tgz", + "integrity": "sha512-XLFHnR3tXMjbOCh2vtVJHmxt+995uJsTERQyseFDRA0xxMxyTZPLa3OIUlyFaO4mF/Lu0FjmWHCuPXJT1n/IOg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.62.3.tgz", + "integrity": "sha512-se6yXvNGMIl0f+RQzyh7XAmia8/9kplQx424wnG2w0C1oi6XgO6Y8otKhdXFHbHs88Ihavzmvh1NWjuovE76BQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.62.3.tgz", + "integrity": "sha512-gNoxRefktVIiGflpONuxWWXZAzIQG++z9qHO3xKwk4WdDMuQja3JHGfE1u0i3PfPDyvhypdk+WrgIJqLhGG7sg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.62.3.tgz", + "integrity": "sha512-V4KtWtQfAFMU7+9/A/VDps/VI8CHd3cYz0L8sgJzz8qK7eY7wI4ruFD82UYIYvW9Z4DtlTfhQcsl4XyPHW5uSg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.62.3.tgz", + "integrity": "sha512-LBx9LYXvj2CBkMkjLdNAWLwH0MLMin7do2VcVo9kVPibGLkY0BQQut2fv7NVqkXqZ/CrAu9LqDHVV1xHCMpCPw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.62.3.tgz", + "integrity": "sha512-ABVf3Q0RCu7NcyCCOZQI0pJ3GuSdfSl8EXcy88QtdceIMIoCUdfhsJChZ64L9zVM2aJHjde1Bhn5uqSRcX9ySA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.62.3.tgz", + "integrity": "sha512-+2Cy/ldweGBLlPIKsQLF8U5N44a0KDdbrk1rAjHOM9M2K+kGdIVjHLmmrZIcx+9Ny3ke/1JomCsDI1ocb11+sg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.62.3.tgz", + "integrity": "sha512-dtZvzc8BedpSaFNy75x6uiWwAGTH+aZHDtdrqP6qk+WcLJrfti6sGje1ZJ9UxyzDLF23d/mV+PaMwuC0hL7UVA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.62.3.tgz", + "integrity": "sha512-Rj8Ra4noo+aYy7sKBggCx0407mws34kAb1ySyWuq5DAtFBQdkSwnsjCgPrhPe9cvgBKZIukpE+CVHvORCS93kQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.62.3.tgz", + "integrity": "sha512-vp7N084ew/odXn2gi/mzm9mUkQu9l6AiN6dt4IeUM2Uvm9o+cVmP+YkqbMOteLbiGgqBBlJZjIMYVCfOOIVbVQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.62.3.tgz", + "integrity": "sha512-MOG/3gTOn4Fwf574RVOaY61I5o6P90legkFADiTyn1hyjNydT+cerU2rLUwPdZkKKyJ+iT+K9p7WXK4LM1Ka6g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@shikijs/core": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-2.5.0.tgz", + "integrity": "sha512-uu/8RExTKtavlpH7XqnVYBrfBkUc20ngXiX9NSrBhOVZYv/7XQRKUyhtkeflY5QsxC0GbJThCerruZfsUaSldg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/engine-javascript": "2.5.0", + "@shikijs/engine-oniguruma": "2.5.0", + "@shikijs/types": "2.5.0", + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.4", + "hast-util-to-html": "^9.0.4" + } + }, + "node_modules/@shikijs/engine-javascript": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-2.5.0.tgz", + "integrity": "sha512-VjnOpnQf8WuCEZtNUdjjwGUbtAVKuZkVQ/5cHy/tojVVRIRtlWMYVjyWhxOmIq05AlSOv72z7hRNRGVBgQOl0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/types": "2.5.0", + "@shikijs/vscode-textmate": "^10.0.2", + "oniguruma-to-es": "^3.1.0" + } + }, + "node_modules/@shikijs/engine-oniguruma": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-2.5.0.tgz", + "integrity": "sha512-pGd1wRATzbo/uatrCIILlAdFVKdxImWJGQ5rFiB5VZi2ve5xj3Ax9jny8QvkaV93btQEwR/rSz5ERFpC5mKNIw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/types": "2.5.0", + "@shikijs/vscode-textmate": "^10.0.2" + } + }, + "node_modules/@shikijs/langs": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-2.5.0.tgz", + "integrity": "sha512-Qfrrt5OsNH5R+5tJ/3uYBBZv3SuGmnRPejV9IlIbFH3HTGLDlkqgHymAlzklVmKBjAaVmkPkyikAV/sQ1wSL+w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/types": "2.5.0" + } + }, + "node_modules/@shikijs/themes": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-2.5.0.tgz", + "integrity": "sha512-wGrk+R8tJnO0VMzmUExHR+QdSaPUl/NKs+a4cQQRWyoc3YFbUzuLEi/KWK1hj+8BfHRKm2jNhhJck1dfstJpiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/types": "2.5.0" + } + }, + "node_modules/@shikijs/transformers": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@shikijs/transformers/-/transformers-2.5.0.tgz", + "integrity": "sha512-SI494W5X60CaUwgi8u4q4m4s3YAFSxln3tzNjOSYqq54wlVgz0/NbbXEb3mdLbqMBztcmS7bVTaEd2w0qMmfeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/core": "2.5.0", + "@shikijs/types": "2.5.0" + } + }, + "node_modules/@shikijs/types": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-2.5.0.tgz", + "integrity": "sha512-ygl5yhxki9ZLNuNpPitBWvcy9fsSKKaRuO4BAlMyagszQidxcpLAr0qiW/q43DtSIDxO6hEbtYLiFZNXO/hdGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.4" + } + }, + "node_modules/@shikijs/vscode-textmate": { + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-10.0.2.tgz", + "integrity": "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/estree": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/hast": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.5.tgz", + "integrity": "sha512-rp/ezSWaD1m44dPKICGhiskI13nVr7qTloFwDa/IYkhhf5nzwP+zIQcIJh3WIFSBOy/H1PzB40jPjMDksN4F+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/markdown-it": { + "version": "14.1.2", + "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.1.2.tgz", + "integrity": "sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/linkify-it": "^5", + "@types/mdurl": "^2" + } + }, + "node_modules/@types/mdast": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", + "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/unist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/web-bluetooth": { + "version": "0.0.21", + "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.21.tgz", + "integrity": "sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.3.tgz", + "integrity": "sha512-60YRaenCQcVjYEKOcG824+DRGGIQ3VKErcBoAEDJZz5bKIs2ZG+X/H9Nk+Q6EVkwJk5QNApxbrc5QtBSwtrXAg==", + "dev": true, + "license": "ISC" + }, + "node_modules/@vitejs/plugin-vue": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.2.4.tgz", + "integrity": "sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "peerDependencies": { + "vite": "^5.0.0 || ^6.0.0", + "vue": "^3.2.25" + } + }, + "node_modules/@vue/compiler-core": { + "version": "3.5.40", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.40.tgz", + "integrity": "sha512-39E8IgOhTbVDnoJFMKc2DvYnypcZwUqgUhQkccva/0m6FUwtIKSGV7n1hpVmYcFaoRAwf9pBcwnKlCEsN63ZEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.7", + "@vue/shared": "3.5.40", + "entities": "^7.0.1", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-dom": { + "version": "3.5.40", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.40.tgz", + "integrity": "sha512-pwkx4vqlqOspFstrcmzwkKLePVMD3PT65imRzLhanU2V1Fj4K13g6OXjanOyzw3aTAuRk84BOmY8f3rEHqPaVA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/compiler-core": "3.5.40", + "@vue/shared": "3.5.40" + } + }, + "node_modules/@vue/compiler-sfc": { + "version": "3.5.40", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.40.tgz", + "integrity": "sha512-gIf497P4kpuALcvs5n3AEg1Vdn0pSY4XbjASIfHNYF1/MP3T2Mf2STERTubysBxCRxzJGJYtF/O7vwJrxFB3Vw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.7", + "@vue/compiler-core": "3.5.40", + "@vue/compiler-dom": "3.5.40", + "@vue/compiler-ssr": "3.5.40", + "@vue/shared": "3.5.40", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.21", + "postcss": "^8.5.19", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-ssr": { + "version": "3.5.40", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.40.tgz", + "integrity": "sha512-rrE5xiXG663+vHCHa3J9p2z5OcBRjXmoqenprJxAFQxg5pSshzeBiCE6pu46axapRJ2Adk0YDA2BRZVjiHXnhg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.40", + "@vue/shared": "3.5.40" + } + }, + "node_modules/@vue/devtools-api": { + "version": "7.7.10", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-7.7.10.tgz", + "integrity": "sha512-KxtEpUOOpFz/qOGRrAwA36QF7DqIA+FXgCYit9mk9wjbaZt0sXOFz81ElOZtKA4HbWHUdwNjZHBFsFFyp5BZiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/devtools-kit": "^7.7.10" + } + }, + "node_modules/@vue/devtools-kit": { + "version": "7.7.10", + "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-7.7.10.tgz", + "integrity": "sha512-3WNi2Kq4tbpVbmhml7RiphmAt0279oh3fKNeWMQIrltfX8Q91b4i5PL8DtyNKdwmcsGrV4fg+erwWOmD05CLIw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/devtools-shared": "^7.7.10", + "birpc": "^2.3.0", + "hookable": "^5.5.3", + "mitt": "^3.0.1", + "perfect-debounce": "^1.0.0", + "speakingurl": "^14.0.1", + "superjson": "^2.2.2" + } + }, + "node_modules/@vue/devtools-shared": { + "version": "7.7.10", + "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-7.7.10.tgz", + "integrity": "sha512-wOPslzB8vTvpxwdaOcR2qAbwmuSP0L+rhpoC6Cf56V3Jip+HWb7PQQXOUPgBNQARpXsbQX/+mvi8kKucmBGRwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "rfdc": "^1.4.1" + } + }, + "node_modules/@vue/reactivity": { + "version": "3.5.40", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.40.tgz", + "integrity": "sha512-B7ot9UlUZOi1zbq61/LvE88ZLTV8IlajTdiZTAEiDQgrnIMIZoPr9kGw0Zw46ObW62O9+H/Be3kMbfb7kYPQZA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/shared": "3.5.40" + } + }, + "node_modules/@vue/runtime-core": { + "version": "3.5.40", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.40.tgz", + "integrity": "sha512-KAZLweuZ6uUJPK1PMSQPgBU5gCjgrrfjUhSglmU9NhH+Zjepa8cnwSydPWDWHDwOgY4g3VcZ+PljbiHlURNCbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.40", + "@vue/shared": "3.5.40" + } + }, + "node_modules/@vue/runtime-dom": { + "version": "3.5.40", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.40.tgz", + "integrity": "sha512-ZfrX8ssZQds900L9pr8AuK05ddnMsR4MPMZr8cPN9GoqoPWcXLhjvvbIA2SMv+7a97sJ1vv9pj/zxK0Cq/eEFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.40", + "@vue/runtime-core": "3.5.40", + "@vue/shared": "3.5.40", + "csstype": "^3.2.3" + } + }, + "node_modules/@vue/server-renderer": { + "version": "3.5.40", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.40.tgz", + "integrity": "sha512-XNJym9WpevhTVt1HuwOrCRJ5Q+9z4BjTMrDtjTrvx74SmUll8spNTw6whWJa9mEkO4PKn5TihI/bm/8ds2QVJw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/compiler-ssr": "3.5.40", + "@vue/runtime-dom": "3.5.40", + "@vue/shared": "3.5.40" + } + }, + "node_modules/@vue/shared": { + "version": "3.5.40", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.40.tgz", + "integrity": "sha512-WxnBtruIqOoV3rA4jeKDWzrYI5h7Cp4+pjwDi8kWGHz+IslhiN+wguLVVhtv2l8VoU02rzDCVfDjgCl1lNpZVg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@vueuse/core": { + "version": "12.8.2", + "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-12.8.2.tgz", + "integrity": "sha512-HbvCmZdzAu3VGi/pWYm5Ut+Kd9mn1ZHnn4L5G8kOQTPs/IwIAmJoBrmYk2ckLArgMXZj0AW3n5CAejLUO+PhdQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/web-bluetooth": "^0.0.21", + "@vueuse/metadata": "12.8.2", + "@vueuse/shared": "12.8.2", + "vue": "^3.5.13" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@vueuse/integrations": { + "version": "12.8.2", + "resolved": "https://registry.npmjs.org/@vueuse/integrations/-/integrations-12.8.2.tgz", + "integrity": "sha512-fbGYivgK5uBTRt7p5F3zy6VrETlV9RtZjBqd1/HxGdjdckBgBM4ugP8LHpjolqTj14TXTxSK1ZfgPbHYyGuH7g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vueuse/core": "12.8.2", + "@vueuse/shared": "12.8.2", + "vue": "^3.5.13" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "async-validator": "^4", + "axios": "^1", + "change-case": "^5", + "drauu": "^0.4", + "focus-trap": "^7", + "fuse.js": "^7", + "idb-keyval": "^6", + "jwt-decode": "^4", + "nprogress": "^0.2", + "qrcode": "^1.5", + "sortablejs": "^1", + "universal-cookie": "^7" + }, + "peerDependenciesMeta": { + "async-validator": { + "optional": true + }, + "axios": { + "optional": true + }, + "change-case": { + "optional": true + }, + "drauu": { + "optional": true + }, + "focus-trap": { + "optional": true + }, + "fuse.js": { + "optional": true + }, + "idb-keyval": { + "optional": true + }, + "jwt-decode": { + "optional": true + }, + "nprogress": { + "optional": true + }, + "qrcode": { + "optional": true + }, + "sortablejs": { + "optional": true + }, + "universal-cookie": { + "optional": true + } + } + }, + "node_modules/@vueuse/metadata": { + "version": "12.8.2", + "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-12.8.2.tgz", + "integrity": "sha512-rAyLGEuoBJ/Il5AmFHiziCPdQzRt88VxR+Y/A/QhJ1EWtWqPBBAxTAFaSkviwEuOEZNtW8pvkPgoCZQ+HxqW1A==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@vueuse/shared": { + "version": "12.8.2", + "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-12.8.2.tgz", + "integrity": "sha512-dznP38YzxZoNloI0qpEfpkms8knDtaoQ6Y/sfS0L7Yki4zh40LFHEhur0odJC6xTHG5dxWVPiUWBXn+wCG2s5w==", + "dev": true, + "license": "MIT", + "dependencies": { + "vue": "^3.5.13" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/algoliasearch": { + "version": "5.56.0", + "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-5.56.0.tgz", + "integrity": "sha512-PrqppUmhT4ENdas2pH9caE7efUcxy6EcSFhWzosiVuQBzu2tQ5yLTI6jwomT/1cuBnivzGfxiJCqDNN9FRRh+Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/abtesting": "1.22.0", + "@algolia/client-abtesting": "5.56.0", + "@algolia/client-analytics": "5.56.0", + "@algolia/client-common": "5.56.0", + "@algolia/client-insights": "5.56.0", + "@algolia/client-personalization": "5.56.0", + "@algolia/client-query-suggestions": "5.56.0", + "@algolia/client-search": "5.56.0", + "@algolia/ingestion": "1.56.0", + "@algolia/monitoring": "1.56.0", + "@algolia/recommend": "5.56.0", + "@algolia/requester-browser-xhr": "5.56.0", + "@algolia/requester-fetch": "5.56.0", + "@algolia/requester-node-http": "5.56.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/birpc": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/birpc/-/birpc-2.9.0.tgz", + "integrity": "sha512-KrayHS5pBi69Xi9JmvoqrIgYGDkD6mcSe/i6YKi3w5kekCLzrX4+nawcXqrj2tIp50Kw/mT/s3p+GVK0A0sKxw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/ccount": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", + "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-html4": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", + "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-legacy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", + "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/comma-separated-tokens": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", + "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/copy-anything": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-4.0.5.tgz", + "integrity": "sha512-7Vv6asjS4gMOuILabD3l739tsaxFQmC+a7pLZm02zyvs8p977bL3zEgq3yDk5rn9B0PbYgIv++jmHcuUab4RhA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-what": "^5.2.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/devlop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", + "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", + "dev": true, + "license": "MIT", + "dependencies": { + "dequal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/emoji-regex-xs": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex-xs/-/emoji-regex-xs-1.0.0.tgz", + "integrity": "sha512-LRlerrMYoIDrT6jgpeZ2YYl/L8EulRTt5hQcYjy5AInh7HWXKimpqx68aknBFpGL2+/IcogTcaydJEgaTmOpDg==", + "dev": true, + "license": "MIT" + }, + "node_modules/entities": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz", + "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/esbuild": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true, + "license": "MIT" + }, + "node_modules/focus-trap": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-7.8.0.tgz", + "integrity": "sha512-/yNdlIkpWbM0ptxno3ONTuf+2g318kh2ez3KSeZN5dZ8YC6AAmgeWz+GasYYiBJPFaYcSAPeu4GfhUaChzIJXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "tabbable": "^6.4.0" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/hast-util-to-html": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.5.tgz", + "integrity": "sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-whitespace": "^3.0.0", + "html-void-elements": "^3.0.0", + "mdast-util-to-hast": "^13.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0", + "stringify-entities": "^4.0.0", + "zwitch": "^2.0.4" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-whitespace": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", + "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hookable": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz", + "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/html-void-elements": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-3.0.0.tgz", + "integrity": "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-what": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/is-what/-/is-what-5.5.0.tgz", + "integrity": "sha512-oG7cgbmg5kLYae2N5IVd3jm2s+vldjxJzK1pcu9LfpGuQ93MQSzo0okvRna+7y5ifrD+20FE8FvjusyGaz14fw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, + "node_modules/js-sha256": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/js-sha256/-/js-sha256-0.10.1.tgz", + "integrity": "sha512-5obBtsz9301ULlsgggLg542s/jqtddfOpV5KJc4hajc9JV8GeY2gZHSVpYBn4nWqAUTJ9v+xwtbJ1mIBgIH5Vw==", + "dev": true, + "license": "MIT" + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/mark.js": { + "version": "8.11.1", + "resolved": "https://registry.npmjs.org/mark.js/-/mark.js-8.11.1.tgz", + "integrity": "sha512-1I+1qpDt4idfgLQG+BNWmrqku+7/2bi5nLf4YwF8y8zXvmfiTBY3PV3ZibfrjBueCByROpuBjLLFCajqkgYoLQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/markdown-it-task-lists": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/markdown-it-task-lists/-/markdown-it-task-lists-2.1.1.tgz", + "integrity": "sha512-TxFAc76Jnhb2OUu+n3yz9RMu4CwGfaT788br6HhEDlvWfdeJcLUsxk1Hgw2yJio0OXsxv7pyIPmvECY7bMbluA==", + "dev": true, + "license": "ISC" + }, + "node_modules/mdast-util-to-hast": { + "version": "13.2.1", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.1.tgz", + "integrity": "sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@ungap/structured-clone": "^1.0.0", + "devlop": "^1.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "trim-lines": "^3.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-encode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz", + "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-sanitize-uri": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz", + "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-types": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz", + "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/minisearch": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/minisearch/-/minisearch-7.2.0.tgz", + "integrity": "sha512-dqT2XBYUOZOiC5t2HRnwADjhNS2cecp9u+TJRiJ1Qp/f5qjkeT5APcGPjHw+bz89Ms8Jp+cG4AlE+QZ/QnDglg==", + "dev": true, + "license": "MIT" + }, + "node_modules/mitt": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", + "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", + "dev": true, + "license": "MIT" + }, + "node_modules/moo": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.3.tgz", + "integrity": "sha512-m2fmM2dDm7GZQsY7KK2cme8agi+AAljILjQnof7p1ZMDe6dQ4bdnSMx0cPppudoeNv5hEFQirN6u+O4fDE0IWA==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/nanoid": { + "version": "3.3.16", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.16.tgz", + "integrity": "sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/oniguruma-to-es": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/oniguruma-to-es/-/oniguruma-to-es-3.1.1.tgz", + "integrity": "sha512-bUH8SDvPkH3ho3dvwJwfonjlQ4R80vjyvrU8YpxuROddv55vAEJrTuCuCVUhhsHbtlD9tGGbaNApGQckXhS8iQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex-xs": "^1.0.0", + "regex": "^6.0.1", + "regex-recursion": "^6.0.2" + } + }, + "node_modules/perfect-debounce": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz", + "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==", + "dev": true, + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/postcss": { + "version": "8.5.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.23.tgz", + "integrity": "sha512-g50586zr4bZmwFiTlflMu8E0bDTb5I5gertgwAKmsdUlTQIhZtunzUlD1WSzwcVWPoAVpsrA6vlfCD7oXvRwgg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.16", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/preact": { + "version": "10.29.7", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.29.7.tgz", + "integrity": "sha512-DCHYrK/B10yUD3ZjLfhZ3WIE/9Vf9VFUODcRE2dRomTYDpJk6z6L9wecSfhfE6M9ZTHUdyQkoC46arIDhEV84Q==", + "dev": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/preact" + }, + "peerDependencies": { + "preact-render-to-string": ">=5" + }, + "peerDependenciesMeta": { + "preact-render-to-string": { + "optional": true + } + } + }, + "node_modules/property-information": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.2.0.tgz", + "integrity": "sha512-IAtzIB6sUiWaJYrX9smp3V46pBGbBeLFRGdh25kg1334VcBlD8HzhPeNIWQH9zhGmo2itIe25EHt9dQP7G5hmg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/regex/-/regex-6.1.0.tgz", + "integrity": "sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg==", + "dev": true, + "license": "MIT", + "dependencies": { + "regex-utilities": "^2.3.0" + } + }, + "node_modules/regex-recursion": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/regex-recursion/-/regex-recursion-6.0.2.tgz", + "integrity": "sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==", + "dev": true, + "license": "MIT", + "dependencies": { + "regex-utilities": "^2.3.0" + } + }, + "node_modules/regex-utilities": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/regex-utilities/-/regex-utilities-2.3.0.tgz", + "integrity": "sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==", + "dev": true, + "license": "MIT" + }, + "node_modules/rfdc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", + "dev": true, + "license": "MIT" + }, + "node_modules/rollup": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.62.3.tgz", + "integrity": "sha512-Gu0c0iH9FzgX1L1t7ByIbbS3Vmdz+6KHm/EsqmmC71gUQ82yvZRkTK6XzrFObSka91WUVdynqp6nsfilzr5k6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.9" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.62.3", + "@rollup/rollup-android-arm64": "4.62.3", + "@rollup/rollup-darwin-arm64": "4.62.3", + "@rollup/rollup-darwin-x64": "4.62.3", + "@rollup/rollup-freebsd-arm64": "4.62.3", + "@rollup/rollup-freebsd-x64": "4.62.3", + "@rollup/rollup-linux-arm-gnueabihf": "4.62.3", + "@rollup/rollup-linux-arm-musleabihf": "4.62.3", + "@rollup/rollup-linux-arm64-gnu": "4.62.3", + "@rollup/rollup-linux-arm64-musl": "4.62.3", + "@rollup/rollup-linux-loong64-gnu": "4.62.3", + "@rollup/rollup-linux-loong64-musl": "4.62.3", + "@rollup/rollup-linux-ppc64-gnu": "4.62.3", + "@rollup/rollup-linux-ppc64-musl": "4.62.3", + "@rollup/rollup-linux-riscv64-gnu": "4.62.3", + "@rollup/rollup-linux-riscv64-musl": "4.62.3", + "@rollup/rollup-linux-s390x-gnu": "4.62.3", + "@rollup/rollup-linux-x64-gnu": "4.62.3", + "@rollup/rollup-linux-x64-musl": "4.62.3", + "@rollup/rollup-openbsd-x64": "4.62.3", + "@rollup/rollup-openharmony-arm64": "4.62.3", + "@rollup/rollup-win32-arm64-msvc": "4.62.3", + "@rollup/rollup-win32-ia32-msvc": "4.62.3", + "@rollup/rollup-win32-x64-gnu": "4.62.3", + "@rollup/rollup-win32-x64-msvc": "4.62.3", + "fsevents": "~2.3.2" + } + }, + "node_modules/shiki": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-2.5.0.tgz", + "integrity": "sha512-mI//trrsaiCIPsja5CNfsyNOqgAZUb6VpJA+340toL42UpzQlXpwRV9nch69X6gaUxrr9kaOOa6e3y3uAkGFxQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/core": "2.5.0", + "@shikijs/engine-javascript": "2.5.0", + "@shikijs/engine-oniguruma": "2.5.0", + "@shikijs/langs": "2.5.0", + "@shikijs/themes": "2.5.0", + "@shikijs/types": "2.5.0", + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.4" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/space-separated-tokens": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", + "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/speakingurl": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/speakingurl/-/speakingurl-14.0.1.tgz", + "integrity": "sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stringify-entities": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", + "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==", + "dev": true, + "license": "MIT", + "dependencies": { + "character-entities-html4": "^2.0.0", + "character-entities-legacy": "^3.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/superjson": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/superjson/-/superjson-2.2.6.tgz", + "integrity": "sha512-H+ue8Zo4vJmV2nRjpx86P35lzwDT3nItnIsocgumgr0hHMQ+ZGq5vrERg9kJBo5AWGmxZDhzDo+WVIJqkB0cGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "copy-anything": "^4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/tabbable": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.5.0.tgz", + "integrity": "sha512-wieBHXygIm7OyQOu5hQlkk62/WyCFYGlWg7L6/ZCUZwx0o398Zkn4pVmMyfYhfMG8kGrj/Krt8eIk6UKC6VzwA==", + "dev": true, + "license": "MIT" + }, + "node_modules/trim-lines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", + "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/unist-util-is": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz", + "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-position": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", + "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.1.0.tgz", + "integrity": "sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit-parents": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz", + "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", + "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-message": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.3.tgz", + "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vite": { + "version": "5.4.21", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.21.tgz", + "integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.21.3", + "postcss": "^8.4.43", + "rollup": "^4.20.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/vitepress": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/vitepress/-/vitepress-1.6.4.tgz", + "integrity": "sha512-+2ym1/+0VVrbhNyRoFFesVvBvHAVMZMK0rw60E3X/5349M1GuVdKeazuksqopEdvkKwKGs21Q729jX81/bkBJg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@docsearch/css": "3.8.2", + "@docsearch/js": "3.8.2", + "@iconify-json/simple-icons": "^1.2.21", + "@shikijs/core": "^2.1.0", + "@shikijs/transformers": "^2.1.0", + "@shikijs/types": "^2.1.0", + "@types/markdown-it": "^14.1.2", + "@vitejs/plugin-vue": "^5.2.1", + "@vue/devtools-api": "^7.7.0", + "@vue/shared": "^3.5.13", + "@vueuse/core": "^12.4.0", + "@vueuse/integrations": "^12.4.0", + "focus-trap": "^7.6.4", + "mark.js": "8.11.1", + "minisearch": "^7.1.1", + "shiki": "^2.1.0", + "vite": "^5.4.14", + "vue": "^3.5.13" + }, + "bin": { + "vitepress": "bin/vitepress.js" + }, + "peerDependencies": { + "markdown-it-mathjax3": "^4", + "postcss": "^8" + }, + "peerDependenciesMeta": { + "markdown-it-mathjax3": { + "optional": true + }, + "postcss": { + "optional": true + } + } + }, + "node_modules/vitepress-plugin-tabs": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/vitepress-plugin-tabs/-/vitepress-plugin-tabs-0.9.1.tgz", + "integrity": "sha512-cRys9pWhyl5YnxXZ3BAdSDW8DriuXBewYhmUu4bBlnzksEDjzbKUwbNi30T74Vi1UXnY1a19Ap6DJDTOWJWdzA==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/sapphi-red" + }, + "peerDependencies": { + "vitepress": "^1.0.0 || ^2.0.0-alpha.17", + "vue": "^3.5.0" + } + }, + "node_modules/vue": { + "version": "3.5.40", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.40.tgz", + "integrity": "sha512-+8PJ4SJXdn/cHGImF4CKdxlWHIN5Dkt7DoufRREM6h6uVCx2m7QxgcEQmmzyOK8A9mcafg7sFbJFYsdFVubTig==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.40", + "@vue/compiler-sfc": "3.5.40", + "@vue/runtime-dom": "3.5.40", + "@vue/server-renderer": "3.5.40", + "@vue/shared": "3.5.40" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/zwitch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", + "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } } } } diff --git a/docs/help/package.json b/docs/help/package.json index a0c469466..a2d1f83eb 100644 --- a/docs/help/package.json +++ b/docs/help/package.json @@ -1,8 +1,17 @@ { - "name": "@notesnook/docs-help", + "name": "@notesnook/help", "version": "1.0.0", "scripts": { - "document-keyboard-shortcuts": "node scripts/document-keyboard-shortcuts.mjs" + "document-keyboard-shortcuts": "node scripts/document-keyboard-shortcuts.mjs", + "versions": "node scripts/check-strings-fresh.mjs && node scripts/build-versions.mjs", + "predev": "npm run versions", + "dev": "vitepress dev", + "prebuild": "npm run versions", + "build": "vitepress build", + "preview": "vitepress preview", + "version": "node scripts/new-version.mjs", + "fork": "node scripts/fork-page.mjs", + "strings": "node --experimental-strip-types scripts/check-strings.mjs" }, "repository": { "type": "git", @@ -20,6 +29,11 @@ }, "homepage": "https://github.com/streetwriters/notesnook#readme", "devDependencies": { - "@notesnook/common": "file:../../packages/common" + "@lingui/core": "^5.2.0", + "@notesnook/common": "file:../../packages/common", + "@notesnook/intl": "file:../../packages/intl", + "markdown-it-task-lists": "^2.1.1", + "vitepress": "^1.6.4", + "vitepress-plugin-tabs": "^0.9.1" } } diff --git a/docs/help/scripts/build-versions.mjs b/docs/help/scripts/build-versions.mjs new file mode 100644 index 000000000..bd359de39 --- /dev/null +++ b/docs/help/scripts/build-versions.mjs @@ -0,0 +1,205 @@ +/** + * Composes the `/v<version>/` doc trees before VitePress runs. + * + * Only *differences* are stored in the repo. `contents/_versions/<version>/` + * holds the pages whose content differs from the current docs, plus an optional + * `_excluded.txt` listing pages that did not exist in that version. Everything + * else is shared with the latest docs. + * + * For each archived version this writes a complete `contents/v<version>/` tree + * (gitignored, regenerated on every build) by layering: + * + * current docs ← newest version's overrides ← … ← this version's + * + * so a page forked once keeps applying to every older version until an older + * fork supersedes it. It also generates `.vitepress/sidebars/generated.mjs`, + * which the config imports. + * + * Run automatically by `predev` / `prebuild`. + */ +import { + copyFileSync, + existsSync, + mkdirSync, + readFileSync, + readdirSync, + rmSync, + statSync, + writeFileSync +} from "fs"; +import { dirname, join, relative } from "path"; +import { fileURLToPath, pathToFileURL } from "url"; + +const HELP = dirname(dirname(fileURLToPath(import.meta.url))); +const CONTENTS = join(HELP, "contents"); +const OVERRIDES = join(CONTENTS, "_versions"); +const SIDEBARS = join(HELP, ".vitepress", "sidebars"); + +const { LATEST, ARCHIVED } = await import( + pathToFileURL(join(HELP, ".vitepress", "versions.mjs")).href +); +const { sidebar } = await import( + pathToFileURL(join(HELP, ".vitepress", "sidebar.mjs")).href +); + +const isGeneratedVersionDir = (name) => /^v\d+\.\d+$/.test(name); + +/** Every page in the current docs, as paths relative to `contents/`. */ +function currentPages(dir = CONTENTS, out = []) { + for (const entry of readdirSync(dir)) { + if (dir === CONTENTS && (entry === "public" || entry === "_versions")) continue; + if (dir === CONTENTS && isGeneratedVersionDir(entry)) continue; + if (entry === ".vitepress" || entry === "node_modules") continue; + const p = join(dir, entry); + if (statSync(p).isDirectory()) currentPages(p, out); + else if (p.endsWith(".md")) out.push(relative(CONTENTS, p)); + } + return out; +} + +/** The overrides recorded for one version. */ +function overridesFor(version) { + const dir = join(OVERRIDES, version); + const pages = new Map(); + const excluded = new Set(); + if (!existsSync(dir)) return { pages, excluded }; + + const excludeFile = join(dir, "_excluded.txt"); + if (existsSync(excludeFile)) { + for (const line of readFileSync(excludeFile, "utf8").split("\n")) { + const page = line.trim(); + if (page && !page.startsWith("#")) excluded.add(page); + } + } + + (function walk(d) { + for (const entry of readdirSync(d)) { + const p = join(d, entry); + if (statSync(p).isDirectory()) walk(p); + else if (p.endsWith(".md")) pages.set(relative(dir, p), p); + } + })(dir); + + return { pages, excluded }; +} + +/* Internal page links must stay inside the version; asset links must not — + images and fonts are shared across versions. */ +const ASSET = /\.(png|jpe?g|gif|svg|webp|ico|css|js|woff2?|ttf|pdf|json|txt)$/i; +const scope = (href, version) => + ASSET.test(href) ? href : `/v${version}${href}`; + +function scopeLinks(markdown, version) { + const fm = markdown.match(/^---\n[\s\S]*?\n---\n/); + const head = fm + ? // Frontmatter carries links too — the home page's hero actions and + // feature cards are `link:` values, not markdown links. + fm[0].replace( + /^(\s*(?:-\s+)?link:\s*)(["']?)(\/[^\s"']*)\2\s*$/gm, + (_, prefix, quote, href) => `${prefix}${quote}${scope(href, version)}${quote}` + ) + : ""; + const body = fm ? markdown.slice(fm[0].length) : markdown; + return ( + head + + body.replace(/\]\((\/[^)\s]*)\)/g, (match, href) => + ASSET.test(href) ? match : `](${scope(href, version)})` + ) + ); +} + +/* ------------------------------------------------------------------ compose */ + +// Wipe previously generated trees so a removed version leaves nothing behind. +for (const entry of readdirSync(CONTENTS)) { + if (isGeneratedVersionDir(entry)) rmSync(join(CONTENTS, entry), { recursive: true }); +} + +const shared = currentPages(); +const summary = []; + +for (const version of ARCHIVED) { + // Layer overrides from the newest archived version down to this one. + const layers = ARCHIVED.slice(0, ARCHIVED.indexOf(version) + 1).map(overridesFor); + + const resolved = new Map(); // page -> source file (or null = use current docs) + for (const page of shared) resolved.set(page, null); + for (const layer of layers) { + for (const [page, file] of layer.pages) resolved.set(page, file); + for (const page of layer.excluded) resolved.delete(page); + } + + const outDir = join(CONTENTS, `v${version}`); + let forked = 0; + for (const [page, override] of resolved) { + const dest = join(outDir, page); + mkdirSync(dirname(dest), { recursive: true }); + const src = override ?? join(CONTENTS, page); + writeFileSync(dest, scopeLinks(readFileSync(src, "utf8"), version)); + if (override) forked++; + } + + summary.push( + ` v${version}: ${resolved.size} pages, ${forked} version-specific, ${ + resolved.size - forked + } shared` + ); +} + +/* ----------------------------------------------------------------- sidebars */ + +/** The current sidebar, re-pointed at a version and stripped of missing pages. */ +function sidebarFor(version) { + const present = new Set( + existsSync(join(CONTENTS, `v${version}`)) + ? (function walk(d, out = []) { + for (const entry of readdirSync(d)) { + const p = join(d, entry); + if (statSync(p).isDirectory()) walk(p, out); + else if (p.endsWith(".md")) + out.push("/" + relative(join(CONTENTS, `v${version}`), p).replace(/(index)?\.md$/, "").replace(/\/$/, "/")); + } + return out; + })(join(CONTENTS, `v${version}`)) + : [] + ); + + const exists = (link) => present.has(link) || present.has(link.replace(/\/$/, "/")); + + const rewrite = (items) => + items + .map((item) => { + const next = { ...item }; + if (next.items) next.items = rewrite(next.items); + if (next.link) { + if (!exists(next.link)) return null; + next.link = `/v${version}${next.link}`; + } + return next.items && !next.items.length && !next.link ? null : next; + }) + .filter(Boolean); + + return rewrite(sidebar); +} + +mkdirSync(SIDEBARS, { recursive: true }); +writeFileSync( + join(SIDEBARS, "generated.mjs"), + [ + "// Generated by scripts/build-versions.mjs — do not edit, do not commit.", + "export const archivedSidebars = {", + ...ARCHIVED.map( + (v) => ` "/v${v}/": ${JSON.stringify(sidebarFor(v), null, 2).replace(/\n/g, "\n ")},` + ), + "};", + "" + ].join("\n") +); + +console.log( + ARCHIVED.length + ? [`Composed ${ARCHIVED.length} archived version(s) (latest is v${LATEST}):`, ...summary].join( + "\n" + ) + : `No archived versions yet — the site serves v${LATEST} from the root.` +); diff --git a/docs/help/scripts/check-strings-fresh.mjs b/docs/help/scripts/check-strings-fresh.mjs new file mode 100644 index 000000000..6670afd5b --- /dev/null +++ b/docs/help/scripts/check-strings-fresh.mjs @@ -0,0 +1,89 @@ +/** + * Guards against stale generated inputs. + * + * Two packages feed the docs and both are consumed as *built* output: + * + * @notesnook/intl -> the `{{key}}` labels resolved at build time + * @notesnook/common -> the keybinding registry keyboard-shortcuts.md is generated from + * + * Edit either package's source without rebuilding it and the site quietly keeps + * rendering the previous version — the exact drift this setup exists to prevent. + * (Not hypothetical: a keybinding fix was regenerated once against a stale build + * and silently produced the old shortcut.) + * + * The check compares *content*, not timestamps: mtimes are rewritten by npm + * install, git checkouts and CI caches, so they produce false alarms. Instead we + * take a sample of values out of the source and confirm the build contains them. + */ +import { readFileSync, existsSync } from "node:fs"; +import { join, dirname } from "node:path"; +import { fileURLToPath } from "node:url"; + +const HELP = dirname(dirname(fileURLToPath(import.meta.url))); +const PACKAGES = join(HELP, "..", "..", "packages"); + +const problems = []; + +/* ------------------------------------------------- @notesnook/common (keys) */ + +const kbSource = join(PACKAGES, "common", "src", "utils", "keybindings.ts"); +const kbBuilt = join(PACKAGES, "common", "dist", "esm", "utils", "keybindings.js"); + +if (!existsSync(kbBuilt)) { + problems.push( + `@notesnook/common has not been built, and keyboard-shortcuts.md is generated from it.\n` + + ` cd packages/common && npm run build` + ); +} else { + const src = readFileSync(kbSource, "utf8"); + const built = readFileSync(kbBuilt, "utf8"); + const missing = [...src.matchAll(/keys:\s*"([^"]+)"/g)] + .map((m) => m[1]) + .filter((keys) => !built.includes(`"${keys}"`)); + if (missing.length) + problems.push( + `@notesnook/common is stale — these bindings exist in src but not in dist: ` + + `${[...new Set(missing)].slice(0, 5).join(", ")}.\n` + + `keyboard-shortcuts.md is generated from the build, so it would keep the old keys.\n` + + ` cd packages/common && npm run build && (cd ../../docs/help && npm run document-keyboard-shortcuts)` + ); +} + +/* --------------------------------------------------- @notesnook/intl (text) */ + +const intlSource = join(PACKAGES, "intl", "src", "strings.ts"); +const catalogue = join(PACKAGES, "intl", "dist", "locales", "$en.json"); + +if (!existsSync(catalogue)) { + problems.push( + `@notesnook/intl has not been built, and the docs resolve UI labels from it.\n` + + ` cd packages/intl && npm install && npm run build` + ); +} else { + const src = readFileSync(intlSource, "utf8"); + const messages = JSON.parse(readFileSync(catalogue, "utf8")).messages; + const known = new Set( + Object.values(messages).flatMap((v) => + typeof v === "string" ? [v] : Array.isArray(v) ? v.filter((p) => typeof p === "string") : [] + ) + ); + // Plain single-line `key: () => t`Some text`` entries, no interpolation. + const sourceTexts = [...src.matchAll(/^\s*[a-zA-Z0-9_]+: \(\) =>\s*t`([^`${]+)`/gm)].map( + (m) => m[1] + ); + const missing = sourceTexts.filter((text) => !known.has(text)); + if (missing.length > sourceTexts.length * 0.02) + problems.push( + `@notesnook/intl is stale — ${missing.length} strings exist in strings.ts but not in the ` + + `compiled catalogue (e.g. ${missing.slice(0, 3).map((s) => JSON.stringify(s)).join(", ")}).\n` + + `The docs would render the previous wording.\n` + + ` cd packages/intl && npm run build` + ); +} + +if (problems.length) { + console.error("\n" + problems.join("\n\n") + "\n"); + process.exit(1); +} + +console.log("Generated inputs (intl, common) match their source."); diff --git a/docs/help/scripts/check-strings.mjs b/docs/help/scripts/check-strings.mjs new file mode 100644 index 000000000..43acb0fb9 Binary files /dev/null and b/docs/help/scripts/check-strings.mjs differ diff --git a/docs/help/scripts/document-keyboard-shortcuts.mjs b/docs/help/scripts/document-keyboard-shortcuts.mjs index 6c530f77b..56d67d50e 100644 --- a/docs/help/scripts/document-keyboard-shortcuts.mjs +++ b/docs/help/scripts/document-keyboard-shortcuts.mjs @@ -30,20 +30,37 @@ console.log("Generating keyboard shortcuts documentation..."); const keyboardShortcutFilePath = "./contents/keyboard-shortcuts.md"; const frontmatter = `--- -title: Keyboard Shortcuts -description: Keyboard shortcuts for Notesnook +title: Keyboard shortcuts +pageTitle: Every keyboard shortcut in Notesnook +description: The complete list of Notesnook keyboard shortcuts for web, Windows, Linux and macOS — navigation, the editor, formatting and note actions. +keywords: + - notesnook keyboard shortcuts + - notesnook hotkeys + - notes app shortcuts --- `; const content = `# Keyboard shortcuts -The following keyboard shortcuts will help you navigate Notesnook faster.`; +These are every keyboard shortcut the Notesnook desktop and web apps respond to, grouped by what they do. Press \`Ctrl\` \`/\` (\`⌘\` \`/\` on macOS) inside the app to bring the same list up there. + +::: info This page is generated from the app +The tables below are generated straight from the app's own keybinding registry, so they cannot drift out of step with the shortcuts that actually fire. +:::`; + +const relatedPages = `## Related pages + +- [Editor toolbar](/rich-text-editor/rich-text-editor-toolbar) — the same actions as buttons, and how to rearrange them +- [Markdown shortcuts](/rich-text-editor/markdown-notes-editing) — formatting that triggers as you type +- [Find & replace](/rich-text-editor/search-and-replace) — searching inside the note you are editing +- [Search & navigation](/search-and-navigation) — the command palette and quick open +- [Tabs & panes](/rich-text-editor/editor-tabs-and-panes) — moving between open notes`; const markdownTable = getGroupedTableKeybindingsMarkdown(); writeFileSync( keyboardShortcutFilePath, - frontmatter + "\n" + content + "\n\n" + markdownTable, + frontmatter + "\n" + content + "\n\n" + markdownTable + "\n\n" + relatedPages + "\n", "utf-8" ); @@ -95,6 +112,6 @@ function getGroupedTableKeybindingsMarkdown() { }) .join("\n"); - return `### ${category}\n\n${header}\n${rows}`; + return `## ${category}\n\n${header}\n${rows}`; }).join("\n\n"); } diff --git a/docs/help/scripts/fork-page.mjs b/docs/help/scripts/fork-page.mjs new file mode 100644 index 000000000..a17458224 --- /dev/null +++ b/docs/help/scripts/fork-page.mjs @@ -0,0 +1,68 @@ +/** + * Preserves a page's current text for an older version, before you change it. + * + * npm run fork -- 3.3 organizing-notes/archive-notes + * npm run fork -- 3.3 app-lock.md + * + * Run this *before* editing the page at the root. It copies today's text into + * `contents/_versions/3.3/<page>`, so v3.3 keeps describing the old behaviour + * while the root moves on. Pages you never fork stay shared — there is exactly + * one copy of them in the repo. + * + * For a page that did not exist in an older version, add its path to + * `contents/_versions/<version>/_excluded.txt` instead. + */ +import { copyFileSync, existsSync, mkdirSync, readFileSync } from "fs"; +import { dirname, join, relative } from "path"; +import { fileURLToPath, pathToFileURL } from "url"; + +const HELP = dirname(dirname(fileURLToPath(import.meta.url))); +const CONTENTS = join(HELP, "contents"); + +const [version, rawPage] = process.argv.slice(2); +if (!version || !rawPage) { + console.error( + "Usage: npm run fork -- <version> <page>\n" + + " e.g. npm run fork -- 3.3 organizing-notes/archive-notes" + ); + process.exit(1); +} + +const { ARCHIVED } = await import( + pathToFileURL(join(HELP, ".vitepress", "versions.mjs")).href +); +if (!ARCHIVED.includes(version)) { + console.error( + `v${version} is not an archived version. Archived: ${ + ARCHIVED.length ? ARCHIVED.join(", ") : "(none yet)" + }` + ); + process.exit(1); +} + +const page = rawPage.replace(/^\/+/, "").replace(/\.md$/, "") + ".md"; +const source = join(CONTENTS, page); +if (!existsSync(source)) { + console.error(`No such page: contents/${page}`); + process.exit(1); +} + +const dest = join(CONTENTS, "_versions", version, page); +if (existsSync(dest)) { + console.error( + `contents/${relative(CONTENTS, dest)} already exists — v${version} already has its own copy of this page.` + ); + process.exit(1); +} + +mkdirSync(dirname(dest), { recursive: true }); +copyFileSync(source, dest); + +console.log( + [ + `Forked contents/${page} → contents/${relative(CONTENTS, dest)}`, + "", + `v${version} now keeps this text. Edit contents/${page} freely — your changes`, + "apply to the latest docs only." + ].join("\n") +); diff --git a/docs/help/scripts/new-version.mjs b/docs/help/scripts/new-version.mjs new file mode 100644 index 000000000..e32429c0e --- /dev/null +++ b/docs/help/scripts/new-version.mjs @@ -0,0 +1,73 @@ +/** + * Starts a new docs version. + * + * npm run version -- 3.4 + * + * Nothing is copied. The current docs simply become the newest archived version + * — they are shared with the root until a page actually changes, at which point + * `npm run fork` records the old text for that one page. + */ +import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs"; +import { dirname, join } from "path"; +import { fileURLToPath, pathToFileURL } from "url"; + +const HELP = dirname(dirname(fileURLToPath(import.meta.url))); +const versionsPath = join(HELP, ".vitepress", "versions.mjs"); + +const next = process.argv[2]; +if (!next || !/^\d+\.\d+$/.test(next)) { + console.error("Usage: npm run version -- <version> (e.g. 3.4)"); + process.exit(1); +} + +const { LATEST, ARCHIVED } = await import( + pathToFileURL(versionsPath).href + `?t=${Date.now()}` +); + +if (next === LATEST || ARCHIVED.includes(next)) { + console.error(`v${next} already exists.`); + process.exit(1); +} + +const overridesDir = join(HELP, "contents", "_versions", LATEST); +if (!existsSync(overridesDir)) { + mkdirSync(overridesDir, { recursive: true }); + writeFileSync( + join(overridesDir, "_excluded.txt"), + [ + `# Pages that do not exist in v${LATEST}.`, + "# One page path per line, relative to contents/, e.g.:", + "# organizing-notes/some-new-feature.md", + "" + ].join("\n") + ); +} + +writeFileSync( + versionsPath, + readFileSync(versionsPath, "utf8") + .replace(/export const LATEST = "[^"]+";/, `export const LATEST = "${next}";`) + .replace( + /export const ARCHIVED = \[[^\]]*\];/, + `export const ARCHIVED = [${[LATEST, ...ARCHIVED].map((v) => `"${v}"`).join(", ")}];` + ) + .replace(/npm run version -- [\d.]+/, `npm run version -- ${bumpMinor(next)}`) + .replace(/npm run fork -- [\d.]+ /, `npm run fork -- ${next} `) +); + +function bumpMinor(v) { + const [major, minor] = v.split(".").map(Number); + return `${major}.${minor + 1}`; +} + +console.log( + [ + `The site root now describes v${next}. v${LATEST} is archived at /v${LATEST}/.`, + "", + "No pages were copied — every page is shared until it changes. Before you", + `edit a page in a way that does not apply to v${LATEST}, run:`, + "", + ` npm run fork -- ${LATEST} <page>`, + "" + ].join("\n") +); diff --git a/package.json b/package.json index 2fc901a07..40eff89e6 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,7 @@ "clean": "node scripts/clean.mjs", "build": "npm run tx -- build --all --exclude=mobile,web,monograph,theme-builder,vericrypt", "build:web": "npm run tx web:build", + "build:help": "npm run tx help:build", "build:vericrypt": "npm run tx vericrypt:build", "build:test:web": "npm run tx web:build:test", "build:beta:web": "npm run tx web:build:beta", @@ -84,7 +85,8 @@ "packages/*", "apps/*", "extensions/*", - "servers/*" + "servers/*", + "docs/*" ], "tasks": [ { diff --git a/packages/common/package-lock.json b/packages/common/package-lock.json index db5ab9a52..69ac315aa 100644 --- a/packages/common/package-lock.json +++ b/packages/common/package-lock.json @@ -9,6 +9,7 @@ "version": "2.1.3", "license": "GPL-3.0-or-later", "dependencies": { + "@notesnook/common": "^2.1.3", "@notesnook/core": "file:../core", "@readme/data-urls": "^3.0.0", "dayjs": "1.11.13", @@ -29,7 +30,6 @@ "../core": { "name": "@notesnook/core", "version": "8.1.3", - "dev": true, "hasInstallScript": true, "license": "GPL-3.0-or-later", "dependencies": { @@ -237,12 +237,10 @@ }, "../core/node_modules/@leeoniya/ufuzzy": { "version": "1.0.14", - "dev": true, "license": "MIT" }, "../core/node_modules/@microsoft/signalr": { "version": "8.0.0", - "dev": true, "license": "MIT", "dependencies": { "abort-controller": "^3.0.0", @@ -254,7 +252,6 @@ }, "../core/node_modules/@microsoft/signalr/node_modules/ws": { "version": "7.5.9", - "dev": true, "license": "MIT", "engines": { "node": ">=8.3.0" @@ -333,7 +330,6 @@ }, "../core/node_modules/@readme/data-urls": { "version": "3.0.0", - "dev": true, "license": "ISC", "engines": { "node": ">=18" @@ -353,7 +349,6 @@ }, "../core/node_modules/@selderee/plugin-htmlparser2": { "version": "0.11.0", - "dev": true, "license": "MIT", "dependencies": { "domhandler": "^5.0.3", @@ -365,7 +360,6 @@ }, "../core/node_modules/@streetwriters/kysely": { "version": "0.27.4", - "dev": true, "license": "MIT", "engines": { "node": ">=14.0.0" @@ -373,7 +367,6 @@ }, "../core/node_modules/@streetwriters/showdown": { "version": "3.0.9-alpha", - "dev": true, "license": "MIT", "bin": { "showdown": "bin/showdown.js" @@ -426,7 +419,6 @@ }, "../core/node_modules/@types/mime-db": { "version": "1.43.5", - "dev": true, "license": "MIT" }, "../core/node_modules/@types/node": { @@ -595,7 +587,6 @@ }, "../core/node_modules/abort-controller": { "version": "3.0.0", - "dev": true, "license": "MIT", "dependencies": { "event-target-shim": "^5.0.0" @@ -641,7 +632,6 @@ }, "../core/node_modules/async-mutex": { "version": "0.5.0", - "dev": true, "license": "MIT", "dependencies": { "tslib": "^2.4.0" @@ -701,7 +691,6 @@ }, "../core/node_modules/boolbase": { "version": "1.0.0", - "dev": true, "license": "ISC" }, "../core/node_modules/brace-expansion": { @@ -851,7 +840,6 @@ }, "../core/node_modules/css-select": { "version": "5.1.0", - "dev": true, "license": "BSD-2-Clause", "dependencies": { "boolbase": "^1.0.0", @@ -866,7 +854,6 @@ }, "../core/node_modules/css-what": { "version": "6.1.0", - "dev": true, "license": "BSD-2-Clause", "engines": { "node": ">= 6" @@ -877,12 +864,10 @@ }, "../core/node_modules/cssom": { "version": "0.5.0", - "dev": true, "license": "MIT" }, "../core/node_modules/dayjs": { "version": "1.11.13", - "dev": true, "license": "MIT" }, "../core/node_modules/debug": { @@ -945,7 +930,6 @@ }, "../core/node_modules/deepmerge": { "version": "4.3.1", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -961,12 +945,10 @@ }, "../core/node_modules/discontinuous-range": { "version": "1.0.0", - "dev": true, "license": "MIT" }, "../core/node_modules/dom-serializer": { "version": "2.0.0", - "dev": true, "license": "MIT", "dependencies": { "domelementtype": "^2.3.0", @@ -979,7 +961,6 @@ }, "../core/node_modules/dom-serializer/node_modules/entities": { "version": "4.5.0", - "dev": true, "license": "BSD-2-Clause", "engines": { "node": ">=0.12" @@ -990,7 +971,6 @@ }, "../core/node_modules/domelementtype": { "version": "2.3.0", - "dev": true, "funding": [ { "type": "github", @@ -1001,7 +981,6 @@ }, "../core/node_modules/domhandler": { "version": "5.0.3", - "dev": true, "license": "BSD-2-Clause", "dependencies": { "domelementtype": "^2.3.0" @@ -1015,7 +994,6 @@ }, "../core/node_modules/domutils": { "version": "3.1.0", - "dev": true, "license": "BSD-2-Clause", "dependencies": { "dom-serializer": "^2.0.0", @@ -1057,7 +1035,6 @@ }, "../core/node_modules/entities": { "version": "5.0.0", - "dev": true, "license": "BSD-2-Clause", "engines": { "node": ">=0.12" @@ -1123,7 +1100,6 @@ }, "../core/node_modules/event-target-shim": { "version": "5.0.1", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -1131,7 +1107,6 @@ }, "../core/node_modules/eventsource": { "version": "2.0.2", - "dev": true, "license": "MIT", "engines": { "node": ">=12.0.0" @@ -1155,7 +1130,6 @@ }, "../core/node_modules/fetch-cookie": { "version": "2.1.0", - "dev": true, "license": "Unlicense", "dependencies": { "set-cookie-parser": "^2.4.8", @@ -1201,7 +1175,6 @@ }, "../core/node_modules/fuzzyjs": { "version": "5.0.1", - "dev": true, "license": "MIT", "engines": { "node": ">=8.0.0" @@ -1279,7 +1252,6 @@ }, "../core/node_modules/html-to-text": { "version": "9.0.5", - "dev": true, "license": "MIT", "dependencies": { "@selderee/plugin-htmlparser2": "^0.11.0", @@ -1294,7 +1266,6 @@ }, "../core/node_modules/htmlparser2": { "version": "8.0.1", - "dev": true, "funding": [ "https://github.com/fb55/htmlparser2?sponsor=1", { @@ -1312,7 +1283,6 @@ }, "../core/node_modules/htmlparser2/node_modules/entities": { "version": "4.5.0", - "dev": true, "license": "BSD-2-Clause", "engines": { "node": ">=0.12" @@ -1474,7 +1444,6 @@ }, "../core/node_modules/katex": { "version": "0.16.11", - "dev": true, "funding": [ "https://opencollective.com/katex", "https://github.com/sponsors/katex" @@ -1489,7 +1458,6 @@ }, "../core/node_modules/katex/node_modules/commander": { "version": "8.3.0", - "dev": true, "license": "MIT", "engines": { "node": ">= 12" @@ -1497,7 +1465,6 @@ }, "../core/node_modules/leac": { "version": "0.6.0", - "dev": true, "license": "MIT", "funding": { "url": "https://ko-fi.com/killymxi" @@ -1505,7 +1472,6 @@ }, "../core/node_modules/linkedom": { "version": "0.14.20", - "dev": true, "license": "ISC", "dependencies": { "css-select": "^5.1.0", @@ -1517,12 +1483,10 @@ }, "../core/node_modules/linkedom/node_modules/html-escaper": { "version": "3.0.3", - "dev": true, "license": "MIT" }, "../core/node_modules/liqe": { "version": "1.13.0", - "dev": true, "license": "BSD-3-Clause", "dependencies": { "nearley": "^2.20.1", @@ -1582,7 +1546,6 @@ }, "../core/node_modules/mime-db": { "version": "1.53.0", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.6" @@ -1641,7 +1604,6 @@ }, "../core/node_modules/moo": { "version": "0.5.2", - "dev": true, "license": "BSD-3-Clause" }, "../core/node_modules/ms": { @@ -1673,7 +1635,6 @@ }, "../core/node_modules/nearley": { "version": "2.20.1", - "dev": true, "license": "MIT", "dependencies": { "commander": "^2.19.0", @@ -1694,7 +1655,6 @@ }, "../core/node_modules/nearley/node_modules/commander": { "version": "2.20.3", - "dev": true, "license": "MIT" }, "../core/node_modules/node-abi": { @@ -1710,7 +1670,6 @@ }, "../core/node_modules/node-fetch": { "version": "2.6.7", - "dev": true, "license": "MIT", "dependencies": { "whatwg-url": "^5.0.0" @@ -1729,17 +1688,14 @@ }, "../core/node_modules/node-fetch/node_modules/tr46": { "version": "0.0.3", - "dev": true, "license": "MIT" }, "../core/node_modules/node-fetch/node_modules/webidl-conversions": { "version": "3.0.1", - "dev": true, "license": "BSD-2-Clause" }, "../core/node_modules/node-fetch/node_modules/whatwg-url": { "version": "5.0.0", - "dev": true, "license": "MIT", "dependencies": { "tr46": "~0.0.3", @@ -1748,7 +1704,6 @@ }, "../core/node_modules/nth-check": { "version": "2.1.1", - "dev": true, "license": "BSD-2-Clause", "dependencies": { "boolbase": "^1.0.0" @@ -1806,7 +1761,6 @@ }, "../core/node_modules/parseley": { "version": "0.12.0", - "dev": true, "license": "MIT", "dependencies": { "leac": "^0.6.0", @@ -1859,7 +1813,6 @@ }, "../core/node_modules/peberminta": { "version": "0.9.0", - "dev": true, "license": "MIT", "funding": { "url": "https://ko-fi.com/killymxi" @@ -1941,7 +1894,6 @@ }, "../core/node_modules/prismjs": { "version": "1.29.0", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -1958,7 +1910,6 @@ }, "../core/node_modules/psl": { "version": "1.9.0", - "dev": true, "license": "MIT" }, "../core/node_modules/pump": { @@ -1972,7 +1923,6 @@ }, "../core/node_modules/punycode": { "version": "2.3.1", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -1980,22 +1930,18 @@ }, "../core/node_modules/qclone": { "version": "1.2.0", - "dev": true, "license": "MIT" }, "../core/node_modules/querystringify": { "version": "2.2.0", - "dev": true, "license": "MIT" }, "../core/node_modules/railroad-diagrams": { "version": "1.0.0", - "dev": true, "license": "CC0-1.0" }, "../core/node_modules/randexp": { "version": "0.4.6", - "dev": true, "license": "MIT", "dependencies": { "discontinuous-range": "1.0.0", @@ -2049,12 +1995,10 @@ }, "../core/node_modules/requires-port": { "version": "1.0.0", - "dev": true, "license": "MIT" }, "../core/node_modules/ret": { "version": "0.1.15", - "dev": true, "license": "MIT", "engines": { "node": ">=0.12" @@ -2062,7 +2006,6 @@ }, "../core/node_modules/rfdc": { "version": "1.3.1", - "dev": true, "license": "MIT" }, "../core/node_modules/rollup": { @@ -2123,7 +2066,6 @@ }, "../core/node_modules/selderee": { "version": "0.11.0", - "dev": true, "license": "MIT", "dependencies": { "parseley": "^0.12.0" @@ -2148,7 +2090,6 @@ }, "../core/node_modules/set-cookie-parser": { "version": "2.6.0", - "dev": true, "license": "MIT" }, "../core/node_modules/shebang-command": { @@ -2248,7 +2189,6 @@ }, "../core/node_modules/spark-md5": { "version": "3.0.2", - "dev": true, "license": "(WTFPL OR MIT)" }, "../core/node_modules/sqlite-better-trigram": { @@ -2483,7 +2423,6 @@ }, "../core/node_modules/tough-cookie": { "version": "4.1.3", - "dev": true, "license": "BSD-3-Clause", "dependencies": { "psl": "^1.1.33", @@ -2497,12 +2436,10 @@ }, "../core/node_modules/ts-error": { "version": "1.0.6", - "dev": true, "license": "MIT" }, "../core/node_modules/tslib": { "version": "2.4.1", - "dev": true, "license": "0BSD" }, "../core/node_modules/tunnel-agent": { @@ -2518,12 +2455,10 @@ }, "../core/node_modules/uhyphen": { "version": "0.1.0", - "dev": true, "license": "ISC" }, "../core/node_modules/universalify": { "version": "0.2.0", - "dev": true, "license": "MIT", "engines": { "node": ">= 4.0.0" @@ -2531,7 +2466,6 @@ }, "../core/node_modules/url-parse": { "version": "1.5.10", - "dev": true, "license": "MIT", "dependencies": { "querystringify": "^2.1.1", @@ -2865,7 +2799,6 @@ "../logger": { "name": "@notesnook/logger", "version": "2.1.3", - "dev": true, "license": "GPL-3.0-or-later", "devDependencies": {} }, @@ -4097,6 +4030,23 @@ "dev": true, "license": "MIT" }, + "node_modules/@notesnook/common": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@notesnook/common/-/common-2.1.3.tgz", + "integrity": "sha512-5t1LYIzXMmlOgS/5LeSFngR77NPMQA0TnM6kCe0S1rzDbB1b31jqh2XGiNn1qD7ebbewTPanC4g7klYC8UhoPQ==", + "license": "GPL-3.0-or-later", + "dependencies": { + "@notesnook/core": "^8.1.3", + "@readme/data-urls": "^3.0.0", + "dayjs": "^1.11.13", + "pathe": "^1.1.2", + "timeago.js": "4.0.2" + }, + "peerDependencies": { + "react": ">=18", + "timeago.js": "4.0.2" + } + }, "node_modules/@notesnook/core": { "resolved": "../core", "link": true @@ -4382,12 +4332,10 @@ }, "node_modules/js-tokens": { "version": "4.0.0", - "dev": true, "license": "MIT" }, "node_modules/loose-envify": { "version": "1.4.0", - "dev": true, "license": "MIT", "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" @@ -4477,7 +4425,6 @@ }, "node_modules/react": { "version": "18.3.1", - "dev": true, "license": "MIT", "dependencies": { "loose-envify": "^1.1.0" diff --git a/packages/common/package.json b/packages/common/package.json index 372b52342..722062c17 100644 --- a/packages/common/package.json +++ b/packages/common/package.json @@ -41,10 +41,11 @@ "timeago.js": "4.0.2" }, "dependencies": { + "@notesnook/common": "^2.1.3", "@notesnook/core": "file:../core", "@readme/data-urls": "^3.0.0", "dayjs": "1.11.13", "pathe": "^1.1.2", "timeago.js": "4.0.2" } -} \ No newline at end of file +} diff --git a/packages/common/src/utils/keybindings.ts b/packages/common/src/utils/keybindings.ts index 73c1296a7..8a469ea3c 100644 --- a/packages/common/src/utils/keybindings.ts +++ b/packages/common/src/utils/keybindings.ts @@ -168,7 +168,7 @@ export const tiptapKeys = { type: "tiptap" }, sinkListItem: { - keys: "Mod-Shift-Down", + keys: "Tab", description: "Sink list item", category: "Editor", type: "tiptap" @@ -210,13 +210,13 @@ export const tiptapKeys = { type: "tiptap" }, increaseFontSize: { - keys: "Ctrl-[", + keys: "Mod-[", description: "Increase font size", category: "Editor", type: "tiptap" }, decreaseFontSize: { - keys: "Ctrl-]", + keys: "Mod-]", description: "Decrease font size", category: "Editor", type: "tiptap" diff --git a/packages/editor/src/extensions/font-size/font-size.ts b/packages/editor/src/extensions/font-size/font-size.ts index 199b61d2c..ecaa01ed7 100644 --- a/packages/editor/src/extensions/font-size/font-size.ts +++ b/packages/editor/src/extensions/font-size/font-size.ts @@ -87,7 +87,7 @@ export const FontSize = Extension.create<FontSizeOptions>({ }, addKeyboardShortcuts() { return { - [tiptapKeys.decreaseFontSize.keys]: ({ editor }) => { + [tiptapKeys.increaseFontSize.keys]: ({ editor }) => { editor .chain() .focus() @@ -95,7 +95,7 @@ export const FontSize = Extension.create<FontSizeOptions>({ .run(); return true; }, - [tiptapKeys.increaseFontSize.keys]: ({ editor }) => { + [tiptapKeys.decreaseFontSize.keys]: ({ editor }) => { editor .chain() .focus() diff --git a/packages/editor/src/toolbar/tool-definitions.ts b/packages/editor/src/toolbar/tool-definitions.ts index edf1ff35a..9541d05ba 100644 --- a/packages/editor/src/toolbar/tool-definitions.ts +++ b/packages/editor/src/toolbar/tool-definitions.ts @@ -127,7 +127,7 @@ const tools = (): Record<ToolId, ToolDefinition> => ({ }, alignment: { icon: "alignCenter", - title: strings.alignCenter() + title: strings.alignment() }, textDirection: { icon: "ltr", diff --git a/packages/intl/locale/en.po b/packages/intl/locale/en.po index 71ead12cb..6d8c86931 100644 --- a/packages/intl/locale/en.po +++ b/packages/intl/locale/en.po @@ -800,6 +800,10 @@ msgstr "Advanced" msgid "After scanning the QR code image, the app will display a code that you can enter below." msgstr "After scanning the QR code image, the app will display a code that you can enter below." +#: src/strings.ts:2292 +msgid "Align center" +msgstr "Align center" + #: src/strings.ts:2322 msgid "Align left" msgstr "Align left" @@ -808,7 +812,7 @@ msgstr "Align left" msgid "Align right" msgstr "Align right" -#: src/strings.ts:2292 +#: src/strings.ts:2813 msgid "Alignment" msgstr "Alignment" @@ -1419,7 +1423,6 @@ msgid "Cell border color" msgstr "Cell border color" #: src/strings.ts:2318 -#: src/strings.ts:2319 msgid "Cell border width" msgstr "Cell border width" @@ -4553,6 +4556,7 @@ msgid "No updates available" msgstr "No updates available" #: src/strings.ts:661 +#: src/strings.ts:2319 msgid "None" msgstr "None" diff --git a/packages/intl/locale/pseudo-LOCALE.po b/packages/intl/locale/pseudo-LOCALE.po index f686dc3e0..b6fc68c14 100644 --- a/packages/intl/locale/pseudo-LOCALE.po +++ b/packages/intl/locale/pseudo-LOCALE.po @@ -800,6 +800,10 @@ msgstr "" msgid "After scanning the QR code image, the app will display a code that you can enter below." msgstr "" +#: src/strings.ts:2292 +msgid "Align center" +msgstr "" + #: src/strings.ts:2322 msgid "Align left" msgstr "" @@ -808,7 +812,7 @@ msgstr "" msgid "Align right" msgstr "" -#: src/strings.ts:2292 +#: src/strings.ts:2813 msgid "Alignment" msgstr "" @@ -1419,7 +1423,6 @@ msgid "Cell border color" msgstr "" #: src/strings.ts:2318 -#: src/strings.ts:2319 msgid "Cell border width" msgstr "" @@ -4533,6 +4536,7 @@ msgid "No updates available" msgstr "" #: src/strings.ts:661 +#: src/strings.ts:2319 msgid "None" msgstr "" diff --git a/packages/intl/src/strings.ts b/packages/intl/src/strings.ts index 46a8cf681..2597de848 100644 --- a/packages/intl/src/strings.ts +++ b/packages/intl/src/strings.ts @@ -2289,7 +2289,7 @@ Use this if changes from other devices are not appearing on this device. This wi fontFamily: () => t`Font family`, fontSize: () => t`Font size`, headings: () => t`Headings`, - alignCenter: () => t`Alignment`, + alignCenter: () => t`Align center`, ltr: () => t`Text direction`, highlight: () => t`Highlight`, textColor: () => t`Text color`, @@ -2316,7 +2316,7 @@ Use this if changes from other devices are not appearing on this device. This wi cellBorderColor: () => t`Cell border color`, cellTextColor: () => t`Cell text color`, cellBorderWidth: () => t`Cell border width`, - none: () => t`Cell border width`, + none: () => t`None`, imageSettings: () => t`Image settings`, // alignCenter: () => t`Align center`, alignLeft: () => t`Align left`, @@ -2809,5 +2809,6 @@ Continue without attachments?`, versionDeleted: () => actions.deleted.version(1), offlineMode: () => t`Offline mode`, offlineModeDesc: () => - t`Using Notesnook without an account will NOT sync your notes across devices and could result in data loss if you lose access to your device or uninstall the app. Make sure to backup your notes regularly.` + t`Using Notesnook without an account will **NOT** sync your notes across devices and could result in data loss if you lose access to your device or uninstall the app. Make sure to backup your notes regularly.`, + alignment: () => t`Alignment` }; diff --git a/scripts/bootstrap.mjs b/scripts/bootstrap.mjs index 5232096ad..230bab476 100644 --- a/scripts/bootstrap.mjs +++ b/scripts/bootstrap.mjs @@ -38,7 +38,8 @@ const scopes = { core: "packages/core", editor: "packages/editor", themes: "servers/themes", - themebuilder: "apps/theme-builder" + themebuilder: "apps/theme-builder", + help: "docs/help" }; // packages that we should run npm rebuild for const POSTINSTALL_WHITELIST = [